Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

365
drivers/media/rc/Kconfig Normal file
View file

@ -0,0 +1,365 @@
config RC_CORE
tristate
depends on MEDIA_RC_SUPPORT
depends on INPUT
default y
source "drivers/media/rc/keymaps/Kconfig"
menuconfig RC_DECODERS
bool "Remote controller decoders"
depends on RC_CORE
default y
if RC_DECODERS
config LIRC
tristate "LIRC interface driver"
depends on RC_CORE
---help---
Enable this option to build the Linux Infrared Remote
Control (LIRC) core device interface driver. The LIRC
interface passes raw IR to and from userspace, where the
LIRC daemon handles protocol decoding for IR reception and
encoding for IR transmitting (aka "blasting").
config IR_LIRC_CODEC
tristate "Enable IR to LIRC bridge"
depends on RC_CORE
depends on LIRC
default y
---help---
Enable this option to pass raw IR to and from userspace via
the LIRC interface.
config IR_NEC_DECODER
tristate "Enable IR raw decoder for the NEC protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have IR with NEC protocol, and
if the IR is decoded in software
config IR_RC5_DECODER
tristate "Enable IR raw decoder for the RC-5 protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have IR with RC-5 protocol, and
if the IR is decoded in software
config IR_RC6_DECODER
tristate "Enable IR raw decoder for the RC6 protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have an infrared remote control which
uses the RC6 protocol, and you need software decoding support.
config IR_JVC_DECODER
tristate "Enable IR raw decoder for the JVC protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have an infrared remote control which
uses the JVC protocol, and you need software decoding support.
config IR_SONY_DECODER
tristate "Enable IR raw decoder for the Sony protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have an infrared remote control which
uses the Sony protocol, and you need software decoding support.
config IR_SANYO_DECODER
tristate "Enable IR raw decoder for the Sanyo protocol"
depends on RC_CORE
default y
---help---
Enable this option if you have an infrared remote control which
uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes),
and you need software decoding support.
config IR_SHARP_DECODER
tristate "Enable IR raw decoder for the Sharp protocol"
depends on RC_CORE
default y
---help---
Enable this option if you have an infrared remote control which
uses the Sharp protocol, and you need software decoding support.
config IR_MCE_KBD_DECODER
tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have a Microsoft Remote Keyboard for
Windows Media Center Edition, which you would like to use with
a raw IR receiver in your system.
config IR_XMP_DECODER
tristate "Enable IR raw decoder for the XMP protocol"
depends on RC_CORE
select BITREVERSE
default y
---help---
Enable this option if you have IR with XMP protocol, and
if the IR is decoded in software
endif #RC_DECODERS
menuconfig RC_DEVICES
bool "Remote Controller devices"
depends on RC_CORE
if RC_DEVICES
config RC_ATI_REMOTE
tristate "ATI / X10 based USB RF remote controls"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
help
Say Y here if you want to use an X10 based USB remote control.
These are RF remotes with USB receivers.
Such devices include the ATI remote that comes with many of ATI's
All-In-Wonder video cards, the X10 "Lola" remote, NVIDIA RF remote,
Medion RF remote, and SnapStream FireFly remote.
This driver provides mouse pointer, left and right mouse buttons,
and maps all the other remote buttons to keypress events.
To compile this driver as a module, choose M here: the module will be
called ati_remote.
config IR_ENE
tristate "ENE eHome Receiver/Transceiver (pnp id: ENE0100/ENE02xxx)"
depends on PNP
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
/transceiver made by ENE.
You can see if you have it by looking at lspnp output.
Output should include ENE0100 ENE0200 or something similar.
To compile this driver as a module, choose M here: the
module will be called ene_ir.
config IR_HIX5HD2
tristate "Hisilicon hix5hd2 IR remote control"
depends on RC_CORE
help
Say Y here if you want to use hisilicon hix5hd2 remote control.
To compile this driver as a module, choose M here: the module will be
called ir-hix5hd2.
If you're not sure, select N here
config IR_IMON
tristate "SoundGraph iMON Receiver and Display"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
---help---
Say Y here if you want to use a SoundGraph iMON (aka Antec Veris)
IR Receiver and/or LCD/VFD/VGA display.
To compile this driver as a module, choose M here: the
module will be called imon.
config IR_MCEUSB
tristate "Windows Media Center Ed. eHome Infrared Transceiver"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
---help---
Say Y here if you want to use a Windows Media Center Edition
eHome Infrared Transceiver.
To compile this driver as a module, choose M here: the
module will be called mceusb.
config IR_ITE_CIR
tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
depends on PNP
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receivers
/transceivers made by ITE Tech Inc. These are found in
several ASUS devices, like the ASUS Digimatrix or the ASUS
EEEBox 1501U.
To compile this driver as a module, choose M here: the
module will be called ite-cir.
config IR_FINTEK
tristate "Fintek Consumer Infrared Transceiver"
depends on PNP
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
/transciever made by Fintek. This chip is found on assorted
Jetway motherboards (and of course, possibly others).
To compile this driver as a module, choose M here: the
module will be called fintek-cir.
config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
depends on PNP
depends on RC_CORE
---help---
Say Y here to enable support for integrated infrared receiver
/transciever made by Nuvoton (formerly Winbond). This chip is
found in the ASRock ION 330HT, as well as assorted Intel
DP55-series motherboards (and of course, possibly others).
To compile this driver as a module, choose M here: the
module will be called nuvoton-cir.
config IR_REDRAT3
tristate "RedRat3 IR Transceiver"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select NEW_LEDS
select LEDS_CLASS
select USB
---help---
Say Y here if you want to use a RedRat3 Infrared Transceiver.
To compile this driver as a module, choose M here: the
module will be called redrat3.
config IR_STREAMZAP
tristate "Streamzap PC Remote IR Receiver"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
---help---
Say Y here if you want to use a Streamzap PC Remote
Infrared Receiver.
To compile this driver as a module, choose M here: the
module will be called streamzap.
config IR_WINBOND_CIR
tristate "Winbond IR remote control"
depends on X86 && PNP
depends on RC_CORE
select NEW_LEDS
select LEDS_CLASS
select BITREVERSE
---help---
Say Y here if you want to use the IR remote functionality found
in some Winbond SuperI/O chips. Currently only the WPCD376I
chip is supported (included in some Intel Media series
motherboards).
To compile this driver as a module, choose M here: the module will
be called winbond_cir.
config IR_IGUANA
tristate "IguanaWorks USB IR Transceiver"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
---help---
Say Y here if you want to use the IguanaWorks USB IR Transceiver.
Both infrared receive and send are supported. If you want to
change the ID or the pin config, use the user space driver from
IguanaWorks.
Only firmware 0x0205 and later is supported.
To compile this driver as a module, choose M here: the module will
be called iguanair.
config IR_TTUSBIR
tristate "TechnoTrend USB IR Receiver"
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
select USB
select NEW_LEDS
select LEDS_CLASS
---help---
Say Y here if you want to use the TechnoTrend USB IR Receiver. The
driver can control the led.
To compile this driver as a module, choose M here: the module will
be called ttusbir.
config IR_RX51
tristate "Nokia N900 IR transmitter diode"
depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM
---help---
Say Y or M here if you want to enable support for the IR
transmitter diode built in the Nokia N900 (RX51) device.
The driver uses omap DM timers for generating the carrier
wave and pulses.
source "drivers/media/rc/img-ir/Kconfig"
config RC_LOOPBACK
tristate "Remote Control Loopback Driver"
depends on RC_CORE
---help---
Say Y here if you want support for the remote control loopback
driver which allows TX data to be sent back as RX data.
This is mostly useful for debugging purposes.
If you're not sure, select N here.
To compile this driver as a module, choose M here: the module will
be called rc_loopback.
config IR_GPIO_CIR
tristate "GPIO IR remote control"
depends on RC_CORE
---help---
Say Y if you want to use GPIO based IR Receiver.
To compile this driver as a module, choose M here: the module will
be called gpio-ir-recv.
config RC_ST
tristate "ST remote control receiver"
depends on RC_CORE
depends on ARCH_STI || COMPILE_TEST
help
Say Y here if you want support for ST remote control driver
which allows both IR and UHF RX.
The driver passes raw pulse and space information to the LIRC decoder.
If you're not sure, select N here.
config IR_SUNXI
tristate "SUNXI IR remote control"
depends on RC_CORE
depends on ARCH_SUNXI || COMPILE_TEST
---help---
Say Y if you want to use sunXi internal IR Controller
To compile this driver as a module, choose M here: the module will
be called sunxi-ir.
endif #RC_DEVICES

37
drivers/media/rc/Makefile Normal file
View file

@ -0,0 +1,37 @@
rc-core-objs := rc-main.o rc-ir-raw.o
obj-y += keymaps/
obj-$(CONFIG_RC_CORE) += rc-core.o
obj-$(CONFIG_LIRC) += lirc_dev.o
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
obj-$(CONFIG_IR_XMP_DECODER) += ir-xmp-decoder.o
# stand-alone IR receivers/transmitters
obj-$(CONFIG_RC_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_IR_HIX5HD2) += ir-hix5hd2.o
obj-$(CONFIG_IR_IMON) += imon.o
obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CONFIG_IR_ENE) += ene_ir.o
obj-$(CONFIG_IR_REDRAT3) += redrat3.o
obj-$(CONFIG_IR_RX51) += ir-rx51.o
obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
obj-$(CONFIG_IR_IGUANA) += iguanair.o
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
obj-$(CONFIG_RC_ST) += st_rc.o
obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
obj-$(CONFIG_IR_IMG) += img-ir/

View file

@ -0,0 +1,982 @@
/*
* USB ATI Remote support
*
* Copyright (c) 2011, 2012 Anssi Hannula <anssi.hannula@iki.fi>
* Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
* Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev
*
* This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including
* porting to the 2.6 kernel interfaces, along with other modification
* to better match the style of the existing usb/input drivers. However, the
* protocol and hardware handling is essentially unchanged from 2.1.1.
*
* The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by
* Vojtech Pavlik.
*
* Changes:
*
* Feb 2004: Torrey Hoffman <thoffman@arnor.net>
* Version 2.2.0
* Jun 2004: Torrey Hoffman <thoffman@arnor.net>
* Version 2.2.1
* Added key repeat support contributed by:
* Vincent Vanackere <vanackere@lif.univ-mrs.fr>
* Added support for the "Lola" remote contributed by:
* Seth Cohn <sethcohn@yahoo.com>
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Hardware & software notes
*
* These remote controls are distributed by ATI as part of their
* "All-In-Wonder" video card packages. The receiver self-identifies as a
* "USB Receiver" with manufacturer "X10 Wireless Technology Inc".
*
* The "Lola" remote is available from X10. See:
* http://www.x10.com/products/lola_sg1.htm
* The Lola is similar to the ATI remote but has no mouse support, and slightly
* different keys.
*
* It is possible to use multiple receivers and remotes on multiple computers
* simultaneously by configuring them to use specific channels.
*
* The RF protocol used by the remote supports 16 distinct channels, 1 to 16.
* Actually, it may even support more, at least in some revisions of the
* hardware.
*
* Each remote can be configured to transmit on one channel as follows:
* - Press and hold the "hand icon" button.
* - When the red LED starts to blink, let go of the "hand icon" button.
* - When it stops blinking, input the channel code as two digits, from 01
* to 16, and press the hand icon again.
*
* The timing can be a little tricky. Try loading the module with debug=1
* to have the kernel print out messages about the remote control number
* and mask. Note: debugging prints remote numbers as zero-based hexadecimal.
*
* The driver has a "channel_mask" parameter. This bitmask specifies which
* channels will be ignored by the module. To mask out channels, just add
* all the 2^channel_number values together.
*
* For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote
* ignore signals coming from remote controls transmitting on channel 4, but
* accept all other channels.
*
* Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be
* ignored.
*
* The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this
* parameter are unused.
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/usb/input.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <media/rc-core.h>
/*
* Module and Version Information, Module Parameters
*/
#define ATI_REMOTE_VENDOR_ID 0x0bc7
#define LOLA_REMOTE_PRODUCT_ID 0x0002
#define LOLA2_REMOTE_PRODUCT_ID 0x0003
#define ATI_REMOTE_PRODUCT_ID 0x0004
#define NVIDIA_REMOTE_PRODUCT_ID 0x0005
#define MEDION_REMOTE_PRODUCT_ID 0x0006
#define FIREFLY_REMOTE_PRODUCT_ID 0x0008
#define DRIVER_VERSION "2.2.1"
#define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>"
#define DRIVER_DESC "ATI/X10 RF USB Remote Control"
#define NAME_BUFSIZE 80 /* size of product name, path buffers */
#define DATA_BUFSIZE 63 /* size of URB data buffers */
/*
* Duplicate event filtering time.
* Sequential, identical KIND_FILTERED inputs with less than
* FILTER_TIME milliseconds between them are considered as repeat
* events. The hardware generates 5 events for the first keypress
* and we have to take this into account for an accurate repeat
* behaviour.
*/
#define FILTER_TIME 60 /* msec */
#define REPEAT_DELAY 500 /* msec */
static unsigned long channel_mask;
module_param(channel_mask, ulong, 0644);
MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore");
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Enable extra debug messages and information");
static int repeat_filter = FILTER_TIME;
module_param(repeat_filter, int, 0644);
MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec");
static int repeat_delay = REPEAT_DELAY;
module_param(repeat_delay, int, 0644);
MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec");
static bool mouse = true;
module_param(mouse, bool, 0444);
MODULE_PARM_DESC(mouse, "Enable mouse device, default = yes");
#define dbginfo(dev, format, arg...) \
do { if (debug) dev_info(dev , format , ## arg); } while (0)
#undef err
#define err(format, arg...) printk(KERN_ERR format , ## arg)
struct ati_receiver_type {
/* either default_keymap or get_default_keymap should be set */
const char *default_keymap;
const char *(*get_default_keymap)(struct usb_interface *interface);
};
static const char *get_medion_keymap(struct usb_interface *interface)
{
struct usb_device *udev = interface_to_usbdev(interface);
/*
* There are many different Medion remotes shipped with a receiver
* with the same usb id, but the receivers have subtle differences
* in the USB descriptors allowing us to detect them.
*/
if (udev->manufacturer && udev->product) {
if (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP) {
if (!strcmp(udev->manufacturer, "X10 Wireless Technology Inc")
&& !strcmp(udev->product, "USB Receiver"))
return RC_MAP_MEDION_X10_DIGITAINER;
if (!strcmp(udev->manufacturer, "X10 WTI")
&& !strcmp(udev->product, "RF receiver"))
return RC_MAP_MEDION_X10_OR2X;
} else {
if (!strcmp(udev->manufacturer, "X10 Wireless Technology Inc")
&& !strcmp(udev->product, "USB Receiver"))
return RC_MAP_MEDION_X10;
}
}
dev_info(&interface->dev,
"Unknown Medion X10 receiver, using default ati_remote Medion keymap\n");
return RC_MAP_MEDION_X10;
}
static const struct ati_receiver_type type_ati = {
.default_keymap = RC_MAP_ATI_X10
};
static const struct ati_receiver_type type_medion = {
.get_default_keymap = get_medion_keymap
};
static const struct ati_receiver_type type_firefly = {
.default_keymap = RC_MAP_SNAPSTREAM_FIREFLY
};
static struct usb_device_id ati_remote_table[] = {
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_ati
},
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_ati
},
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_ati
},
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_ati
},
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_medion
},
{
USB_DEVICE(ATI_REMOTE_VENDOR_ID, FIREFLY_REMOTE_PRODUCT_ID),
.driver_info = (unsigned long)&type_firefly
},
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, ati_remote_table);
/* Get hi and low bytes of a 16-bits int */
#define HI(a) ((unsigned char)((a) >> 8))
#define LO(a) ((unsigned char)((a) & 0xff))
#define SEND_FLAG_IN_PROGRESS 1
#define SEND_FLAG_COMPLETE 2
/* Device initialization strings */
static char init1[] = { 0x01, 0x00, 0x20, 0x14 };
static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 };
struct ati_remote {
struct input_dev *idev;
struct rc_dev *rdev;
struct usb_device *udev;
struct usb_interface *interface;
struct urb *irq_urb;
struct urb *out_urb;
struct usb_endpoint_descriptor *endpoint_in;
struct usb_endpoint_descriptor *endpoint_out;
unsigned char *inbuf;
unsigned char *outbuf;
dma_addr_t inbuf_dma;
dma_addr_t outbuf_dma;
unsigned char old_data; /* Detect duplicate events */
unsigned long old_jiffies;
unsigned long acc_jiffies; /* handle acceleration */
unsigned long first_jiffies;
unsigned int repeat_count;
char rc_name[NAME_BUFSIZE];
char rc_phys[NAME_BUFSIZE];
char mouse_name[NAME_BUFSIZE];
char mouse_phys[NAME_BUFSIZE];
wait_queue_head_t wait;
int send_flags;
int users; /* 0-2, users are rc and input */
struct mutex open_mutex;
};
/* "Kinds" of messages sent from the hardware to the driver. */
#define KIND_END 0
#define KIND_LITERAL 1 /* Simply pass to input system as EV_KEY */
#define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */
#define KIND_ACCEL 3 /* Translate to EV_REL mouse-move events */
/* Translation table from hardware messages to input events. */
static const struct {
unsigned char kind;
unsigned char data; /* Raw key code from remote */
unsigned short code; /* Input layer translation */
} ati_remote_tbl[] = {
/* Directional control pad axes. Code is xxyy */
{KIND_ACCEL, 0x70, 0xff00}, /* left */
{KIND_ACCEL, 0x71, 0x0100}, /* right */
{KIND_ACCEL, 0x72, 0x00ff}, /* up */
{KIND_ACCEL, 0x73, 0x0001}, /* down */
/* Directional control pad diagonals */
{KIND_ACCEL, 0x74, 0xffff}, /* left up */
{KIND_ACCEL, 0x75, 0x01ff}, /* right up */
{KIND_ACCEL, 0x77, 0xff01}, /* left down */
{KIND_ACCEL, 0x76, 0x0101}, /* right down */
/* "Mouse button" buttons. The code below uses the fact that the
* lsbit of the raw code is a down/up indicator. */
{KIND_LITERAL, 0x78, BTN_LEFT}, /* left btn down */
{KIND_LITERAL, 0x79, BTN_LEFT}, /* left btn up */
{KIND_LITERAL, 0x7c, BTN_RIGHT},/* right btn down */
{KIND_LITERAL, 0x7d, BTN_RIGHT},/* right btn up */
/* Artificial "doubleclick" events are generated by the hardware.
* They are mapped to the "side" and "extra" mouse buttons here. */
{KIND_FILTERED, 0x7a, BTN_SIDE}, /* left dblclick */
{KIND_FILTERED, 0x7e, BTN_EXTRA},/* right dblclick */
/* Non-mouse events are handled by rc-core */
{KIND_END, 0x00, 0}
};
/*
* ati_remote_dump_input
*/
static void ati_remote_dump(struct device *dev, unsigned char *data,
unsigned int len)
{
if (len == 1) {
if (data[0] != (unsigned char)0xff && data[0] != 0x00)
dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
} else if (len == 4)
dev_warn(dev, "Weird key %*ph\n", 4, data);
else
dev_warn(dev, "Weird data, len=%d %*ph ...\n", len, 6, data);
}
/*
* ati_remote_open
*/
static int ati_remote_open(struct ati_remote *ati_remote)
{
int err = 0;
mutex_lock(&ati_remote->open_mutex);
if (ati_remote->users++ != 0)
goto out; /* one was already active */
/* On first open, submit the read urb which was set up previously. */
ati_remote->irq_urb->dev = ati_remote->udev;
if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) {
dev_err(&ati_remote->interface->dev,
"%s: usb_submit_urb failed!\n", __func__);
err = -EIO;
}
out: mutex_unlock(&ati_remote->open_mutex);
return err;
}
/*
* ati_remote_close
*/
static void ati_remote_close(struct ati_remote *ati_remote)
{
mutex_lock(&ati_remote->open_mutex);
if (--ati_remote->users == 0)
usb_kill_urb(ati_remote->irq_urb);
mutex_unlock(&ati_remote->open_mutex);
}
static int ati_remote_input_open(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = input_get_drvdata(inputdev);
return ati_remote_open(ati_remote);
}
static void ati_remote_input_close(struct input_dev *inputdev)
{
struct ati_remote *ati_remote = input_get_drvdata(inputdev);
ati_remote_close(ati_remote);
}
static int ati_remote_rc_open(struct rc_dev *rdev)
{
struct ati_remote *ati_remote = rdev->priv;
return ati_remote_open(ati_remote);
}
static void ati_remote_rc_close(struct rc_dev *rdev)
{
struct ati_remote *ati_remote = rdev->priv;
ati_remote_close(ati_remote);
}
/*
* ati_remote_irq_out
*/
static void ati_remote_irq_out(struct urb *urb)
{
struct ati_remote *ati_remote = urb->context;
if (urb->status) {
dev_dbg(&ati_remote->interface->dev, "%s: status %d\n",
__func__, urb->status);
return;
}
ati_remote->send_flags |= SEND_FLAG_COMPLETE;
wmb();
wake_up(&ati_remote->wait);
}
/*
* ati_remote_sendpacket
*
* Used to send device initialization strings
*/
static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd,
unsigned char *data)
{
int retval = 0;
/* Set up out_urb */
memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd));
((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd);
ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1;
ati_remote->out_urb->dev = ati_remote->udev;
ati_remote->send_flags = SEND_FLAG_IN_PROGRESS;
retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC);
if (retval) {
dev_dbg(&ati_remote->interface->dev,
"sendpacket: usb_submit_urb failed: %d\n", retval);
return retval;
}
wait_event_timeout(ati_remote->wait,
((ati_remote->out_urb->status != -EINPROGRESS) ||
(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
HZ);
usb_kill_urb(ati_remote->out_urb);
return retval;
}
/*
* ati_remote_compute_accel
*
* Implements acceleration curve for directional control pad
* If elapsed time since last event is > 1/4 second, user "stopped",
* so reset acceleration. Otherwise, user is probably holding the control
* pad down, so we increase acceleration, ramping up over two seconds to
* a maximum speed.
*/
static int ati_remote_compute_accel(struct ati_remote *ati_remote)
{
static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 };
unsigned long now = jiffies;
int acc;
if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) {
acc = 1;
ati_remote->acc_jiffies = now;
}
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125)))
acc = accel[0];
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250)))
acc = accel[1];
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500)))
acc = accel[2];
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000)))
acc = accel[3];
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500)))
acc = accel[4];
else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000)))
acc = accel[5];
else
acc = accel[6];
return acc;
}
/*
* ati_remote_report_input
*/
static void ati_remote_input_report(struct urb *urb)
{
struct ati_remote *ati_remote = urb->context;
unsigned char *data= ati_remote->inbuf;
struct input_dev *dev = ati_remote->idev;
int index = -1;
int remote_num;
unsigned char scancode;
u32 wheel_keycode = KEY_RESERVED;
int i;
/*
* data[0] = 0x14
* data[1] = data[2] + data[3] + 0xd5 (a checksum byte)
* data[2] = the key code (with toggle bit in MSB with some models)
* data[3] = channel << 4 (the low 4 bits must be zero)
*/
/* Deal with strange looking inputs */
if ( urb->actual_length != 4 || data[0] != 0x14 ||
data[1] != (unsigned char)(data[2] + data[3] + 0xD5) ||
(data[3] & 0x0f) != 0x00) {
ati_remote_dump(&urb->dev->dev, data, urb->actual_length);
return;
}
if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
dbginfo(&ati_remote->interface->dev,
"wrong checksum in input: %*ph\n", 4, data);
return;
}
/* Mask unwanted remote channels. */
/* note: remote_num is 0-based, channel 1 on remote == 0 here */
remote_num = (data[3] >> 4) & 0x0f;
if (channel_mask & (1 << (remote_num + 1))) {
dbginfo(&ati_remote->interface->dev,
"Masked input from channel 0x%02x: data %02x, "
"mask= 0x%02lx\n",
remote_num, data[2], channel_mask);
return;
}
/*
* MSB is a toggle code, though only used by some devices
* (e.g. SnapStream Firefly)
*/
scancode = data[2] & 0x7f;
dbginfo(&ati_remote->interface->dev,
"channel 0x%02x; key data %02x, scancode %02x\n",
remote_num, data[2], scancode);
if (scancode >= 0x70) {
/*
* This is either a mouse or scrollwheel event, depending on
* the remote/keymap.
* Get the keycode assigned to scancode 0x78/0x70. If it is
* set, assume this is a scrollwheel up/down event.
*/
wheel_keycode = rc_g_keycode_from_table(ati_remote->rdev,
scancode & 0x78);
if (wheel_keycode == KEY_RESERVED) {
/* scrollwheel was not mapped, assume mouse */
/* Look up event code index in the mouse translation
* table.
*/
for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) {
if (scancode == ati_remote_tbl[i].data) {
index = i;
break;
}
}
}
}
if (index >= 0 && ati_remote_tbl[index].kind == KIND_LITERAL) {
/*
* The lsbit of the raw key code is a down/up flag.
* Invert it to match the input layer's conventions.
*/
input_event(dev, EV_KEY, ati_remote_tbl[index].code,
!(data[2] & 1));
ati_remote->old_jiffies = jiffies;
} else if (index < 0 || ati_remote_tbl[index].kind == KIND_FILTERED) {
unsigned long now = jiffies;
/* Filter duplicate events which happen "too close" together. */
if (ati_remote->old_data == data[2] &&
time_before(now, ati_remote->old_jiffies +
msecs_to_jiffies(repeat_filter))) {
ati_remote->repeat_count++;
} else {
ati_remote->repeat_count = 0;
ati_remote->first_jiffies = now;
}
ati_remote->old_jiffies = now;
/* Ensure we skip at least the 4 first duplicate events
* (generated by a single keypress), and continue skipping
* until repeat_delay msecs have passed.
*/
if (ati_remote->repeat_count > 0 &&
(ati_remote->repeat_count < 5 ||
time_before(now, ati_remote->first_jiffies +
msecs_to_jiffies(repeat_delay))))
return;
if (index >= 0) {
input_event(dev, EV_KEY, ati_remote_tbl[index].code, 1);
input_event(dev, EV_KEY, ati_remote_tbl[index].code, 0);
} else {
/* Not a mouse event, hand it to rc-core. */
int count = 1;
if (wheel_keycode != KEY_RESERVED) {
/*
* This is a scrollwheel event, send the
* scroll up (0x78) / down (0x70) scancode
* repeatedly as many times as indicated by
* rest of the scancode.
*/
count = (scancode & 0x07) + 1;
scancode &= 0x78;
}
while (count--) {
/*
* We don't use the rc-core repeat handling yet as
* it would cause ghost repeats which would be a
* regression for this driver.
*/
rc_keydown_notimeout(ati_remote->rdev, RC_TYPE_OTHER,
scancode, data[2]);
rc_keyup(ati_remote->rdev);
}
goto nosync;
}
} else if (ati_remote_tbl[index].kind == KIND_ACCEL) {
signed char dx = ati_remote_tbl[index].code >> 8;
signed char dy = ati_remote_tbl[index].code & 255;
/*
* Other event kinds are from the directional control pad, and
* have an acceleration factor applied to them. Without this
* acceleration, the control pad is mostly unusable.
*/
int acc = ati_remote_compute_accel(ati_remote);
if (dx)
input_report_rel(dev, REL_X, dx * acc);
if (dy)
input_report_rel(dev, REL_Y, dy * acc);
ati_remote->old_jiffies = jiffies;
} else {
dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n",
ati_remote_tbl[index].kind);
return;
}
input_sync(dev);
nosync:
ati_remote->old_data = data[2];
}
/*
* ati_remote_irq_in
*/
static void ati_remote_irq_in(struct urb *urb)
{
struct ati_remote *ati_remote = urb->context;
int retval;
switch (urb->status) {
case 0: /* success */
ati_remote_input_report(urb);
break;
case -ECONNRESET: /* unlink */
case -ENOENT:
case -ESHUTDOWN:
dev_dbg(&ati_remote->interface->dev,
"%s: urb error status, unlink?\n",
__func__);
return;
default: /* error */
dev_dbg(&ati_remote->interface->dev,
"%s: Nonzero urb status %d\n",
__func__, urb->status);
}
retval = usb_submit_urb(urb, GFP_ATOMIC);
if (retval)
dev_err(&ati_remote->interface->dev,
"%s: usb_submit_urb()=%d\n",
__func__, retval);
}
/*
* ati_remote_alloc_buffers
*/
static int ati_remote_alloc_buffers(struct usb_device *udev,
struct ati_remote *ati_remote)
{
ati_remote->inbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->inbuf_dma);
if (!ati_remote->inbuf)
return -1;
ati_remote->outbuf = usb_alloc_coherent(udev, DATA_BUFSIZE, GFP_ATOMIC,
&ati_remote->outbuf_dma);
if (!ati_remote->outbuf)
return -1;
ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ati_remote->irq_urb)
return -1;
ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ati_remote->out_urb)
return -1;
return 0;
}
/*
* ati_remote_free_buffers
*/
static void ati_remote_free_buffers(struct ati_remote *ati_remote)
{
usb_free_urb(ati_remote->irq_urb);
usb_free_urb(ati_remote->out_urb);
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->inbuf, ati_remote->inbuf_dma);
usb_free_coherent(ati_remote->udev, DATA_BUFSIZE,
ati_remote->outbuf, ati_remote->outbuf_dma);
}
static void ati_remote_input_init(struct ati_remote *ati_remote)
{
struct input_dev *idev = ati_remote->idev;
int i;
idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
idev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA);
idev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++)
if (ati_remote_tbl[i].kind == KIND_LITERAL ||
ati_remote_tbl[i].kind == KIND_FILTERED)
__set_bit(ati_remote_tbl[i].code, idev->keybit);
input_set_drvdata(idev, ati_remote);
idev->open = ati_remote_input_open;
idev->close = ati_remote_input_close;
idev->name = ati_remote->mouse_name;
idev->phys = ati_remote->mouse_phys;
usb_to_input_id(ati_remote->udev, &idev->id);
idev->dev.parent = &ati_remote->interface->dev;
}
static void ati_remote_rc_init(struct ati_remote *ati_remote)
{
struct rc_dev *rdev = ati_remote->rdev;
rdev->priv = ati_remote;
rdev->driver_type = RC_DRIVER_SCANCODE;
rdev->allowed_protocols = RC_BIT_OTHER;
rdev->driver_name = "ati_remote";
rdev->open = ati_remote_rc_open;
rdev->close = ati_remote_rc_close;
rdev->input_name = ati_remote->rc_name;
rdev->input_phys = ati_remote->rc_phys;
usb_to_input_id(ati_remote->udev, &rdev->input_id);
rdev->dev.parent = &ati_remote->interface->dev;
}
static int ati_remote_initialize(struct ati_remote *ati_remote)
{
struct usb_device *udev = ati_remote->udev;
int pipe, maxp;
init_waitqueue_head(&ati_remote->wait);
/* Set up irq_urb */
pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf,
maxp, ati_remote_irq_in, ati_remote,
ati_remote->endpoint_in->bInterval);
ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma;
ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* Set up out_urb */
pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress);
maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp;
usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf,
maxp, ati_remote_irq_out, ati_remote,
ati_remote->endpoint_out->bInterval);
ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma;
ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
/* send initialization strings */
if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) ||
(ati_remote_sendpacket(ati_remote, 0x8007, init2))) {
dev_err(&ati_remote->interface->dev,
"Initializing ati_remote hardware failed.\n");
return -EIO;
}
return 0;
}
/*
* ati_remote_probe
*/
static int ati_remote_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(interface);
struct usb_host_interface *iface_host = interface->cur_altsetting;
struct usb_endpoint_descriptor *endpoint_in, *endpoint_out;
struct ati_receiver_type *type = (struct ati_receiver_type *)id->driver_info;
struct ati_remote *ati_remote;
struct input_dev *input_dev;
struct rc_dev *rc_dev;
int err = -ENOMEM;
if (iface_host->desc.bNumEndpoints != 2) {
err("%s: Unexpected desc.bNumEndpoints\n", __func__);
return -ENODEV;
}
endpoint_in = &iface_host->endpoint[0].desc;
endpoint_out = &iface_host->endpoint[1].desc;
if (!usb_endpoint_is_int_in(endpoint_in)) {
err("%s: Unexpected endpoint_in\n", __func__);
return -ENODEV;
}
if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) {
err("%s: endpoint_in message size==0? \n", __func__);
return -ENODEV;
}
ati_remote = kzalloc(sizeof (struct ati_remote), GFP_KERNEL);
rc_dev = rc_allocate_device();
if (!ati_remote || !rc_dev)
goto exit_free_dev_rdev;
/* Allocate URB buffers, URBs */
if (ati_remote_alloc_buffers(udev, ati_remote))
goto exit_free_buffers;
ati_remote->endpoint_in = endpoint_in;
ati_remote->endpoint_out = endpoint_out;
ati_remote->udev = udev;
ati_remote->rdev = rc_dev;
ati_remote->interface = interface;
usb_make_path(udev, ati_remote->rc_phys, sizeof(ati_remote->rc_phys));
strlcpy(ati_remote->mouse_phys, ati_remote->rc_phys,
sizeof(ati_remote->mouse_phys));
strlcat(ati_remote->rc_phys, "/input0", sizeof(ati_remote->rc_phys));
strlcat(ati_remote->mouse_phys, "/input1", sizeof(ati_remote->mouse_phys));
if (udev->manufacturer)
strlcpy(ati_remote->rc_name, udev->manufacturer,
sizeof(ati_remote->rc_name));
if (udev->product)
snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
"%s %s", ati_remote->rc_name, udev->product);
if (!strlen(ati_remote->rc_name))
snprintf(ati_remote->rc_name, sizeof(ati_remote->rc_name),
DRIVER_DESC "(%04x,%04x)",
le16_to_cpu(ati_remote->udev->descriptor.idVendor),
le16_to_cpu(ati_remote->udev->descriptor.idProduct));
snprintf(ati_remote->mouse_name, sizeof(ati_remote->mouse_name),
"%s mouse", ati_remote->rc_name);
rc_dev->map_name = RC_MAP_ATI_X10; /* default map */
/* set default keymap according to receiver model */
if (type) {
if (type->default_keymap)
rc_dev->map_name = type->default_keymap;
else if (type->get_default_keymap)
rc_dev->map_name = type->get_default_keymap(interface);
}
ati_remote_rc_init(ati_remote);
mutex_init(&ati_remote->open_mutex);
/* Device Hardware Initialization - fills in ati_remote->idev from udev. */
err = ati_remote_initialize(ati_remote);
if (err)
goto exit_kill_urbs;
/* Set up and register rc device */
err = rc_register_device(ati_remote->rdev);
if (err)
goto exit_kill_urbs;
/* use our delay for rc_dev */
ati_remote->rdev->input_dev->rep[REP_DELAY] = repeat_delay;
/* Set up and register mouse input device */
if (mouse) {
input_dev = input_allocate_device();
if (!input_dev) {
err = -ENOMEM;
goto exit_unregister_device;
}
ati_remote->idev = input_dev;
ati_remote_input_init(ati_remote);
err = input_register_device(input_dev);
if (err)
goto exit_free_input_device;
}
usb_set_intfdata(interface, ati_remote);
return 0;
exit_free_input_device:
input_free_device(input_dev);
exit_unregister_device:
rc_unregister_device(rc_dev);
rc_dev = NULL;
exit_kill_urbs:
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
exit_free_buffers:
ati_remote_free_buffers(ati_remote);
exit_free_dev_rdev:
rc_free_device(rc_dev);
kfree(ati_remote);
return err;
}
/*
* ati_remote_disconnect
*/
static void ati_remote_disconnect(struct usb_interface *interface)
{
struct ati_remote *ati_remote;
ati_remote = usb_get_intfdata(interface);
usb_set_intfdata(interface, NULL);
if (!ati_remote) {
dev_warn(&interface->dev, "%s - null device?\n", __func__);
return;
}
usb_kill_urb(ati_remote->irq_urb);
usb_kill_urb(ati_remote->out_urb);
if (ati_remote->idev)
input_unregister_device(ati_remote->idev);
rc_unregister_device(ati_remote->rdev);
ati_remote_free_buffers(ati_remote);
kfree(ati_remote);
}
/* usb specific object to register with the usb subsystem */
static struct usb_driver ati_remote_driver = {
.name = "ati_remote",
.probe = ati_remote_probe,
.disconnect = ati_remote_disconnect,
.id_table = ati_remote_table,
};
module_usb_driver(ati_remote_driver);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");

1230
drivers/media/rc/ene_ir.c Normal file

File diff suppressed because it is too large Load diff

250
drivers/media/rc/ene_ir.h Normal file
View file

@ -0,0 +1,250 @@
/*
* driver for ENE KB3926 B/C/D/E/F CIR (also known as ENE0XXX)
*
* Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <linux/spinlock.h>
/* hardware address */
#define ENE_STATUS 0 /* hardware status - unused */
#define ENE_ADDR_HI 1 /* hi byte of register address */
#define ENE_ADDR_LO 2 /* low byte of register address */
#define ENE_IO 3 /* read/write window */
#define ENE_IO_SIZE 4
/* 8 bytes of samples, divided in 2 packets*/
#define ENE_FW_SAMPLE_BUFFER 0xF8F0 /* sample buffer */
#define ENE_FW_SAMPLE_SPACE 0x80 /* sample is space */
#define ENE_FW_PACKET_SIZE 4
/* first firmware flag register */
#define ENE_FW1 0xF8F8 /* flagr */
#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
#define ENE_FW1_HAS_EXTRA_BUF 0x04 /* fw uses extra buffer*/
#define ENE_FW1_EXTRA_BUF_HND 0x08 /* extra buffer handshake bit*/
#define ENE_FW1_LED_ON 0x10 /* turn on a led */
#define ENE_FW1_WPATTERN 0x20 /* enable wake pattern */
#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
#define ENE_FW1_IRQ 0x80 /* enable interrupt */
/* second firmware flag register */
#define ENE_FW2 0xF8F9 /* flagw */
#define ENE_FW2_BUF_WPTR 0x01 /* which half of the buffer to read */
#define ENE_FW2_RXIRQ 0x04 /* RX IRQ pending*/
#define ENE_FW2_GP0A 0x08 /* Use GPIO0A for demodulated input */
#define ENE_FW2_EMMITER1_CONN 0x10 /* TX emmiter 1 connected */
#define ENE_FW2_EMMITER2_CONN 0x20 /* TX emmiter 2 connected */
#define ENE_FW2_FAN_INPUT 0x40 /* fan input used for demodulated data*/
#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
/* firmware RX pointer for new style buffer */
#define ENE_FW_RX_POINTER 0xF8FA
/* high parts of samples for fan input (8 samples)*/
#define ENE_FW_SMPL_BUF_FAN 0xF8FB
#define ENE_FW_SMPL_BUF_FAN_PLS 0x8000 /* combined sample is pulse */
#define ENE_FW_SMPL_BUF_FAN_MSK 0x0FFF /* combined sample maximum value */
#define ENE_FW_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
/* transmitter ports */
#define ENE_GPIOFS1 0xFC01
#define ENE_GPIOFS1_GPIO0D 0x20 /* enable tx output on GPIO0D */
#define ENE_GPIOFS8 0xFC08
#define ENE_GPIOFS8_GPIO41 0x02 /* enable tx output on GPIO40 */
/* IRQ registers block (for revision B) */
#define ENEB_IRQ 0xFD09 /* IRQ number */
#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
/* fan as input settings */
#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
#define ENE_FAN_AS_IN1_EN 0xCD
#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
#define ENE_FAN_AS_IN2_EN 0x03
/* IRQ registers block (for revision C,D) */
#define ENE_IRQ 0xFE9B /* new irq settings register */
#define ENE_IRQ_MASK 0x0F /* irq number mask */
#define ENE_IRQ_UNK_EN 0x10 /* always enabled */
#define ENE_IRQ_STATUS 0x20 /* irq status and ACK */
/* CIR Config register #1 */
#define ENE_CIRCFG 0xFEC0
#define ENE_CIRCFG_RX_EN 0x01 /* RX enable */
#define ENE_CIRCFG_RX_IRQ 0x02 /* Enable hardware interrupt */
#define ENE_CIRCFG_REV_POL 0x04 /* Input polarity reversed */
#define ENE_CIRCFG_CARR_DEMOD 0x08 /* Enable carrier demodulator */
#define ENE_CIRCFG_TX_EN 0x10 /* TX enable */
#define ENE_CIRCFG_TX_IRQ 0x20 /* Send interrupt on TX done */
#define ENE_CIRCFG_TX_POL_REV 0x40 /* TX polarity reversed */
#define ENE_CIRCFG_TX_CARR 0x80 /* send TX carrier or not */
/* CIR config register #2 */
#define ENE_CIRCFG2 0xFEC1
#define ENE_CIRCFG2_RLC 0x00
#define ENE_CIRCFG2_RC5 0x01
#define ENE_CIRCFG2_RC6 0x02
#define ENE_CIRCFG2_NEC 0x03
#define ENE_CIRCFG2_CARR_DETECT 0x10 /* Enable carrier detection */
#define ENE_CIRCFG2_GPIO0A 0x20 /* Use GPIO0A instead of GPIO40 for input */
#define ENE_CIRCFG2_FAST_SAMPL1 0x40 /* Fast leading pulse detection for RC6 */
#define ENE_CIRCFG2_FAST_SAMPL2 0x80 /* Fast data detection for RC6 */
/* Knobs for protocol decoding - will document when/if will use them */
#define ENE_CIRPF 0xFEC2
#define ENE_CIRHIGH 0xFEC3
#define ENE_CIRBIT 0xFEC4
#define ENE_CIRSTART 0xFEC5
#define ENE_CIRSTART2 0xFEC6
/* Actual register which contains RLC RX data - read by firmware */
#define ENE_CIRDAT_IN 0xFEC7
/* RLC configuration - sample period (1us resulution) + idle mode */
#define ENE_CIRRLC_CFG 0xFEC8
#define ENE_CIRRLC_CFG_OVERFLOW 0x80 /* interrupt on overflows if set */
#define ENE_DEFAULT_SAMPLE_PERIOD 50
/* Two byte RLC TX buffer */
#define ENE_CIRRLC_OUT0 0xFEC9
#define ENE_CIRRLC_OUT1 0xFECA
#define ENE_CIRRLC_OUT_PULSE 0x80 /* Transmitted sample is pulse */
#define ENE_CIRRLC_OUT_MASK 0x7F
/* Carrier detect setting
* Low nibble - number of carrier pulses to average
* High nibble - number of initial carrier pulses to discard
*/
#define ENE_CIRCAR_PULS 0xFECB
/* detected RX carrier period (resolution: 500 ns) */
#define ENE_CIRCAR_PRD 0xFECC
#define ENE_CIRCAR_PRD_VALID 0x80 /* data valid content valid */
/* detected RX carrier pulse width (resolution: 500 ns) */
#define ENE_CIRCAR_HPRD 0xFECD
/* TX period (resolution: 500 ns, minimum 2)*/
#define ENE_CIRMOD_PRD 0xFECE
#define ENE_CIRMOD_PRD_POL 0x80 /* TX carrier polarity*/
#define ENE_CIRMOD_PRD_MAX 0x7F /* 15.87 kHz */
#define ENE_CIRMOD_PRD_MIN 0x02 /* 1 Mhz */
/* TX pulse width (resolution: 500 ns)*/
#define ENE_CIRMOD_HPRD 0xFECF
/* Hardware versions */
#define ENE_ECHV 0xFF00 /* hardware revision */
#define ENE_PLLFRH 0xFF16
#define ENE_PLLFRL 0xFF17
#define ENE_DEFAULT_PLL_FREQ 1000
#define ENE_ECSTS 0xFF1D
#define ENE_ECSTS_RSRVD 0x04
#define ENE_ECVER_MAJOR 0xFF1E /* chip version */
#define ENE_ECVER_MINOR 0xFF1F
#define ENE_HW_VER_OLD 0xFD00
/******************************************************************************/
#define ENE_DRIVER_NAME "ene_ir"
#define ENE_IRQ_RX 1
#define ENE_IRQ_TX 2
#define ENE_HW_B 1 /* 3926B */
#define ENE_HW_C 2 /* 3926C */
#define ENE_HW_D 3 /* 3926D or later */
#define __dbg(level, format, ...) \
do { \
if (debug >= level) \
pr_info(format "\n", ## __VA_ARGS__); \
} while (0)
#define dbg(format, ...) __dbg(1, format, ## __VA_ARGS__)
#define dbg_verbose(format, ...) __dbg(2, format, ## __VA_ARGS__)
#define dbg_regs(format, ...) __dbg(3, format, ## __VA_ARGS__)
struct ene_device {
struct pnp_dev *pnp_dev;
struct rc_dev *rdev;
/* hw IO settings */
long hw_io;
int irq;
spinlock_t hw_lock;
/* HW features */
int hw_revision; /* hardware revision */
bool hw_use_gpio_0a; /* gpio0a is demodulated input*/
bool hw_extra_buffer; /* hardware has 'extra buffer' */
bool hw_fan_input; /* fan input is IR data source */
bool hw_learning_and_tx_capable; /* learning & tx capable */
int pll_freq;
int buffer_len;
/* Extra RX buffer location */
int extra_buf1_address;
int extra_buf1_len;
int extra_buf2_address;
int extra_buf2_len;
/* HW state*/
int r_pointer; /* pointer to next sample to read */
int w_pointer; /* pointer to next sample hw will write */
bool rx_fan_input_inuse; /* is fan input in use for rx*/
int tx_reg; /* current reg used for TX */
u8 saved_conf1; /* saved FEC0 reg */
unsigned int tx_sample; /* current sample for TX */
bool tx_sample_pulse; /* current sample is pulse */
/* TX buffer */
unsigned *tx_buffer; /* input samples buffer*/
int tx_pos; /* position in that buffer */
int tx_len; /* current len of tx buffer */
int tx_done; /* done transmitting */
/* one more sample pending*/
struct completion tx_complete; /* TX completion */
struct timer_list tx_sim_timer;
/* TX settings */
int tx_period;
int tx_duty_cycle;
int transmitter_mask;
/* RX settings */
bool learning_mode_enabled; /* learning input enabled */
bool carrier_detect_enabled; /* carrier detect enabled */
int rx_period_adjust;
bool rx_enabled;
};
static int ene_irq_status(struct ene_device *dev);
static void ene_rx_read_hw_pointer(struct ene_device *dev);

View file

@ -0,0 +1,707 @@
/*
* Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR
*
* Copyright (C) 2011 Jarod Wilson <jarod@redhat.com>
*
* Special thanks to Fintek for providing hardware and spec sheets.
* This driver is based upon the nuvoton, ite and ene drivers for
* similar hardware.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pnp.h>
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <media/rc-core.h>
#include <linux/pci_ids.h>
#include "fintek-cir.h"
/* write val to config reg */
static inline void fintek_cr_write(struct fintek_dev *fintek, u8 val, u8 reg)
{
fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)",
__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
outb(reg, fintek->cr_ip);
outb(val, fintek->cr_dp);
}
/* read val from config reg */
static inline u8 fintek_cr_read(struct fintek_dev *fintek, u8 reg)
{
u8 val;
outb(reg, fintek->cr_ip);
val = inb(fintek->cr_dp);
fit_dbg("%s: reg 0x%02x, val 0x%02x (ip/dp: %02x/%02x)",
__func__, reg, val, fintek->cr_ip, fintek->cr_dp);
return val;
}
/* update config register bit without changing other bits */
static inline void fintek_set_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)
{
u8 tmp = fintek_cr_read(fintek, reg) | val;
fintek_cr_write(fintek, tmp, reg);
}
/* clear config register bit without changing other bits */
static inline void fintek_clear_reg_bit(struct fintek_dev *fintek, u8 val, u8 reg)
{
u8 tmp = fintek_cr_read(fintek, reg) & ~val;
fintek_cr_write(fintek, tmp, reg);
}
/* enter config mode */
static inline void fintek_config_mode_enable(struct fintek_dev *fintek)
{
/* Enabling Config Mode explicitly requires writing 2x */
outb(CONFIG_REG_ENABLE, fintek->cr_ip);
outb(CONFIG_REG_ENABLE, fintek->cr_ip);
}
/* exit config mode */
static inline void fintek_config_mode_disable(struct fintek_dev *fintek)
{
outb(CONFIG_REG_DISABLE, fintek->cr_ip);
}
/*
* When you want to address a specific logical device, write its logical
* device number to GCR_LOGICAL_DEV_NO
*/
static inline void fintek_select_logical_dev(struct fintek_dev *fintek, u8 ldev)
{
fintek_cr_write(fintek, ldev, GCR_LOGICAL_DEV_NO);
}
/* write val to cir config register */
static inline void fintek_cir_reg_write(struct fintek_dev *fintek, u8 val, u8 offset)
{
outb(val, fintek->cir_addr + offset);
}
/* read val from cir config register */
static u8 fintek_cir_reg_read(struct fintek_dev *fintek, u8 offset)
{
u8 val;
val = inb(fintek->cir_addr + offset);
return val;
}
/* dump current cir register contents */
static void cir_dump_regs(struct fintek_dev *fintek)
{
fintek_config_mode_enable(fintek);
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
pr_info("%s: Dump CIR logical device registers:\n", FINTEK_DRIVER_NAME);
pr_info(" * CR CIR BASE ADDR: 0x%x\n",
(fintek_cr_read(fintek, CIR_CR_BASE_ADDR_HI) << 8) |
fintek_cr_read(fintek, CIR_CR_BASE_ADDR_LO));
pr_info(" * CR CIR IRQ NUM: 0x%x\n",
fintek_cr_read(fintek, CIR_CR_IRQ_SEL));
fintek_config_mode_disable(fintek);
pr_info("%s: Dump CIR registers:\n", FINTEK_DRIVER_NAME);
pr_info(" * STATUS: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_STATUS));
pr_info(" * CONTROL: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_CONTROL));
pr_info(" * RX_DATA: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_RX_DATA));
pr_info(" * TX_CONTROL: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_TX_CONTROL));
pr_info(" * TX_DATA: 0x%x\n",
fintek_cir_reg_read(fintek, CIR_TX_DATA));
}
/* detect hardware features */
static int fintek_hw_detect(struct fintek_dev *fintek)
{
unsigned long flags;
u8 chip_major, chip_minor;
u8 vendor_major, vendor_minor;
u8 portsel, ir_class;
u16 vendor, chip;
fintek_config_mode_enable(fintek);
/* Check if we're using config port 0x4e or 0x2e */
portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
if (portsel == 0xff) {
fit_pr(KERN_INFO, "first portsel read was bunk, trying alt");
fintek_config_mode_disable(fintek);
fintek->cr_ip = CR_INDEX_PORT2;
fintek->cr_dp = CR_DATA_PORT2;
fintek_config_mode_enable(fintek);
portsel = fintek_cr_read(fintek, GCR_CONFIG_PORT_SEL);
}
fit_dbg("portsel reg: 0x%02x", portsel);
ir_class = fintek_cir_reg_read(fintek, CIR_CR_CLASS);
fit_dbg("ir_class reg: 0x%02x", ir_class);
switch (ir_class) {
case CLASS_RX_2TX:
case CLASS_RX_1TX:
fintek->hw_tx_capable = true;
break;
case CLASS_RX_ONLY:
default:
fintek->hw_tx_capable = false;
break;
}
chip_major = fintek_cr_read(fintek, GCR_CHIP_ID_HI);
chip_minor = fintek_cr_read(fintek, GCR_CHIP_ID_LO);
chip = chip_major << 8 | chip_minor;
vendor_major = fintek_cr_read(fintek, GCR_VENDOR_ID_HI);
vendor_minor = fintek_cr_read(fintek, GCR_VENDOR_ID_LO);
vendor = vendor_major << 8 | vendor_minor;
if (vendor != VENDOR_ID_FINTEK)
fit_pr(KERN_WARNING, "Unknown vendor ID: 0x%04x", vendor);
else
fit_dbg("Read Fintek vendor ID from chip");
fintek_config_mode_disable(fintek);
spin_lock_irqsave(&fintek->fintek_lock, flags);
fintek->chip_major = chip_major;
fintek->chip_minor = chip_minor;
fintek->chip_vendor = vendor;
/*
* Newer reviews of this chipset uses port 8 instead of 5
*/
if ((chip != 0x0408) && (chip != 0x0804))
fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV2;
else
fintek->logical_dev_cir = LOGICAL_DEV_CIR_REV1;
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
return 0;
}
static void fintek_cir_ldev_init(struct fintek_dev *fintek)
{
/* Select CIR logical device and enable */
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
/* Write allocated CIR address and IRQ information to hardware */
fintek_cr_write(fintek, fintek->cir_addr >> 8, CIR_CR_BASE_ADDR_HI);
fintek_cr_write(fintek, fintek->cir_addr & 0xff, CIR_CR_BASE_ADDR_LO);
fintek_cr_write(fintek, fintek->cir_irq, CIR_CR_IRQ_SEL);
fit_dbg("CIR initialized, base io address: 0x%lx, irq: %d (len: %d)",
fintek->cir_addr, fintek->cir_irq, fintek->cir_port_len);
}
/* enable CIR interrupts */
static void fintek_enable_cir_irq(struct fintek_dev *fintek)
{
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
}
static void fintek_cir_regs_init(struct fintek_dev *fintek)
{
/* clear any and all stray interrupts */
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
/* and finally, enable interrupts */
fintek_enable_cir_irq(fintek);
}
static void fintek_enable_wake(struct fintek_dev *fintek)
{
fintek_config_mode_enable(fintek);
fintek_select_logical_dev(fintek, LOGICAL_DEV_ACPI);
/* Allow CIR PME's to wake system */
fintek_set_reg_bit(fintek, ACPI_WAKE_EN_CIR_BIT, LDEV_ACPI_WAKE_EN_REG);
/* Enable CIR PME's */
fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_EN_REG);
/* Clear CIR PME status register */
fintek_set_reg_bit(fintek, ACPI_PME_CIR_BIT, LDEV_ACPI_PME_CLR_REG);
/* Save state */
fintek_set_reg_bit(fintek, ACPI_STATE_CIR_BIT, LDEV_ACPI_STATE_REG);
fintek_config_mode_disable(fintek);
}
static int fintek_cmdsize(u8 cmd, u8 subcmd)
{
int datasize = 0;
switch (cmd) {
case BUF_COMMAND_NULL:
if (subcmd == BUF_HW_CMD_HEADER)
datasize = 1;
break;
case BUF_HW_CMD_HEADER:
if (subcmd == BUF_CMD_G_REVISION)
datasize = 2;
break;
case BUF_COMMAND_HEADER:
switch (subcmd) {
case BUF_CMD_S_CARRIER:
case BUF_CMD_S_TIMEOUT:
case BUF_RSP_PULSE_COUNT:
datasize = 2;
break;
case BUF_CMD_SIG_END:
case BUF_CMD_S_TXMASK:
case BUF_CMD_S_RXSENSOR:
datasize = 1;
break;
}
}
return datasize;
}
/* process ir data stored in driver buffer */
static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
{
DEFINE_IR_RAW_EVENT(rawir);
u8 sample;
bool event = false;
int i;
for (i = 0; i < fintek->pkts; i++) {
sample = fintek->buf[i];
switch (fintek->parser_state) {
case CMD_HEADER:
fintek->cmd = sample;
if ((fintek->cmd == BUF_COMMAND_HEADER) ||
((fintek->cmd & BUF_COMMAND_MASK) !=
BUF_PULSE_BIT)) {
fintek->parser_state = SUBCMD;
continue;
}
fintek->rem = (fintek->cmd & BUF_LEN_MASK);
fit_dbg("%s: rem: 0x%02x", __func__, fintek->rem);
if (fintek->rem)
fintek->parser_state = PARSE_IRDATA;
else
ir_raw_event_reset(fintek->rdev);
break;
case SUBCMD:
fintek->rem = fintek_cmdsize(fintek->cmd, sample);
fintek->parser_state = CMD_DATA;
break;
case CMD_DATA:
fintek->rem--;
break;
case PARSE_IRDATA:
fintek->rem--;
init_ir_raw_event(&rawir);
rawir.pulse = ((sample & BUF_PULSE_BIT) != 0);
rawir.duration = US_TO_NS((sample & BUF_SAMPLE_MASK)
* CIR_SAMPLE_PERIOD);
fit_dbg("Storing %s with duration %d",
rawir.pulse ? "pulse" : "space",
rawir.duration);
if (ir_raw_event_store_with_filter(fintek->rdev,
&rawir))
event = true;
break;
}
if ((fintek->parser_state != CMD_HEADER) && !fintek->rem)
fintek->parser_state = CMD_HEADER;
}
fintek->pkts = 0;
if (event) {
fit_dbg("Calling ir_raw_event_handle");
ir_raw_event_handle(fintek->rdev);
}
}
/* copy data from hardware rx register into driver buffer */
static void fintek_get_rx_ir_data(struct fintek_dev *fintek, u8 rx_irqs)
{
unsigned long flags;
u8 sample, status;
spin_lock_irqsave(&fintek->fintek_lock, flags);
/*
* We must read data from CIR_RX_DATA until the hardware IR buffer
* is empty and clears the RX_TIMEOUT and/or RX_RECEIVE flags in
* the CIR_STATUS register
*/
do {
sample = fintek_cir_reg_read(fintek, CIR_RX_DATA);
fit_dbg("%s: sample: 0x%02x", __func__, sample);
fintek->buf[fintek->pkts] = sample;
fintek->pkts++;
status = fintek_cir_reg_read(fintek, CIR_STATUS);
if (!(status & CIR_STATUS_IRQ_EN))
break;
} while (status & rx_irqs);
fintek_process_rx_ir_data(fintek);
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
}
static void fintek_cir_log_irqs(u8 status)
{
fit_pr(KERN_INFO, "IRQ 0x%02x:%s%s%s%s%s", status,
status & CIR_STATUS_IRQ_EN ? " IRQEN" : "",
status & CIR_STATUS_TX_FINISH ? " TXF" : "",
status & CIR_STATUS_TX_UNDERRUN ? " TXU" : "",
status & CIR_STATUS_RX_TIMEOUT ? " RXTO" : "",
status & CIR_STATUS_RX_RECEIVE ? " RXOK" : "");
}
/* interrupt service routine for incoming and outgoing CIR data */
static irqreturn_t fintek_cir_isr(int irq, void *data)
{
struct fintek_dev *fintek = data;
u8 status, rx_irqs;
fit_dbg_verbose("%s firing", __func__);
fintek_config_mode_enable(fintek);
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_config_mode_disable(fintek);
/*
* Get IR Status register contents. Write 1 to ack/clear
*
* bit: reg name - description
* 3: TX_FINISH - TX is finished
* 2: TX_UNDERRUN - TX underrun
* 1: RX_TIMEOUT - RX data timeout
* 0: RX_RECEIVE - RX data received
*/
status = fintek_cir_reg_read(fintek, CIR_STATUS);
if (!(status & CIR_STATUS_IRQ_MASK) || status == 0xff) {
fit_dbg_verbose("%s exiting, IRSTS 0x%02x", __func__, status);
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
return IRQ_RETVAL(IRQ_NONE);
}
if (debug)
fintek_cir_log_irqs(status);
rx_irqs = status & (CIR_STATUS_RX_RECEIVE | CIR_STATUS_RX_TIMEOUT);
if (rx_irqs)
fintek_get_rx_ir_data(fintek, rx_irqs);
/* ack/clear all irq flags we've got */
fintek_cir_reg_write(fintek, status, CIR_STATUS);
fit_dbg_verbose("%s done", __func__);
return IRQ_RETVAL(IRQ_HANDLED);
}
static void fintek_enable_cir(struct fintek_dev *fintek)
{
/* set IRQ enabled */
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_EN, CIR_STATUS);
fintek_config_mode_enable(fintek);
/* enable the CIR logical device */
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
fintek_config_mode_disable(fintek);
/* clear all pending interrupts */
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
/* enable interrupts */
fintek_enable_cir_irq(fintek);
}
static void fintek_disable_cir(struct fintek_dev *fintek)
{
fintek_config_mode_enable(fintek);
/* disable the CIR logical device */
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
fintek_config_mode_disable(fintek);
}
static int fintek_open(struct rc_dev *dev)
{
struct fintek_dev *fintek = dev->priv;
unsigned long flags;
spin_lock_irqsave(&fintek->fintek_lock, flags);
fintek_enable_cir(fintek);
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
return 0;
}
static void fintek_close(struct rc_dev *dev)
{
struct fintek_dev *fintek = dev->priv;
unsigned long flags;
spin_lock_irqsave(&fintek->fintek_lock, flags);
fintek_disable_cir(fintek);
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
}
/* Allocate memory, probe hardware, and initialize everything */
static int fintek_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
{
struct fintek_dev *fintek;
struct rc_dev *rdev;
int ret = -ENOMEM;
fintek = kzalloc(sizeof(struct fintek_dev), GFP_KERNEL);
if (!fintek)
return ret;
/* input device for IR remote (and tx) */
rdev = rc_allocate_device();
if (!rdev)
goto exit_free_dev_rdev;
ret = -ENODEV;
/* validate pnp resources */
if (!pnp_port_valid(pdev, 0)) {
dev_err(&pdev->dev, "IR PNP Port not valid!\n");
goto exit_free_dev_rdev;
}
if (!pnp_irq_valid(pdev, 0)) {
dev_err(&pdev->dev, "IR PNP IRQ not valid!\n");
goto exit_free_dev_rdev;
}
fintek->cir_addr = pnp_port_start(pdev, 0);
fintek->cir_irq = pnp_irq(pdev, 0);
fintek->cir_port_len = pnp_port_len(pdev, 0);
fintek->cr_ip = CR_INDEX_PORT;
fintek->cr_dp = CR_DATA_PORT;
spin_lock_init(&fintek->fintek_lock);
pnp_set_drvdata(pdev, fintek);
fintek->pdev = pdev;
ret = fintek_hw_detect(fintek);
if (ret)
goto exit_free_dev_rdev;
/* Initialize CIR & CIR Wake Logical Devices */
fintek_config_mode_enable(fintek);
fintek_cir_ldev_init(fintek);
fintek_config_mode_disable(fintek);
/* Initialize CIR & CIR Wake Config Registers */
fintek_cir_regs_init(fintek);
/* Set up the rc device */
rdev->priv = fintek;
rdev->driver_type = RC_DRIVER_IR_RAW;
rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = fintek_open;
rdev->close = fintek_close;
rdev->input_name = FINTEK_DESCRIPTION;
rdev->input_phys = "fintek/cir0";
rdev->input_id.bustype = BUS_HOST;
rdev->input_id.vendor = VENDOR_ID_FINTEK;
rdev->input_id.product = fintek->chip_major;
rdev->input_id.version = fintek->chip_minor;
rdev->dev.parent = &pdev->dev;
rdev->driver_name = FINTEK_DRIVER_NAME;
rdev->map_name = RC_MAP_RC6_MCE;
rdev->timeout = US_TO_NS(1000);
/* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */
rdev->rx_resolution = US_TO_NS(CIR_SAMPLE_PERIOD);
fintek->rdev = rdev;
ret = -EBUSY;
/* now claim resources */
if (!request_region(fintek->cir_addr,
fintek->cir_port_len, FINTEK_DRIVER_NAME))
goto exit_free_dev_rdev;
if (request_irq(fintek->cir_irq, fintek_cir_isr, IRQF_SHARED,
FINTEK_DRIVER_NAME, (void *)fintek))
goto exit_free_cir_addr;
ret = rc_register_device(rdev);
if (ret)
goto exit_free_irq;
device_init_wakeup(&pdev->dev, true);
fit_pr(KERN_NOTICE, "driver has been successfully loaded\n");
if (debug)
cir_dump_regs(fintek);
return 0;
exit_free_irq:
free_irq(fintek->cir_irq, fintek);
exit_free_cir_addr:
release_region(fintek->cir_addr, fintek->cir_port_len);
exit_free_dev_rdev:
rc_free_device(rdev);
kfree(fintek);
return ret;
}
static void fintek_remove(struct pnp_dev *pdev)
{
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
unsigned long flags;
spin_lock_irqsave(&fintek->fintek_lock, flags);
/* disable CIR */
fintek_disable_cir(fintek);
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
/* enable CIR Wake (for IR power-on) */
fintek_enable_wake(fintek);
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
/* free resources */
free_irq(fintek->cir_irq, fintek);
release_region(fintek->cir_addr, fintek->cir_port_len);
rc_unregister_device(fintek->rdev);
kfree(fintek);
}
static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
{
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
unsigned long flags;
fit_dbg("%s called", __func__);
spin_lock_irqsave(&fintek->fintek_lock, flags);
/* disable all CIR interrupts */
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
fintek_config_mode_enable(fintek);
/* disable cir logical dev */
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_cr_write(fintek, LOGICAL_DEV_DISABLE, CIR_CR_DEV_EN);
fintek_config_mode_disable(fintek);
/* make sure wake is enabled */
fintek_enable_wake(fintek);
return 0;
}
static int fintek_resume(struct pnp_dev *pdev)
{
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
fit_dbg("%s called", __func__);
/* open interrupt */
fintek_enable_cir_irq(fintek);
/* Enable CIR logical device */
fintek_config_mode_enable(fintek);
fintek_select_logical_dev(fintek, fintek->logical_dev_cir);
fintek_cr_write(fintek, LOGICAL_DEV_ENABLE, CIR_CR_DEV_EN);
fintek_config_mode_disable(fintek);
fintek_cir_regs_init(fintek);
return 0;
}
static void fintek_shutdown(struct pnp_dev *pdev)
{
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
fintek_enable_wake(fintek);
}
static const struct pnp_device_id fintek_ids[] = {
{ "FIT0002", 0 }, /* CIR */
{ "", 0 },
};
static struct pnp_driver fintek_driver = {
.name = FINTEK_DRIVER_NAME,
.id_table = fintek_ids,
.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
.probe = fintek_probe,
.remove = fintek_remove,
.suspend = fintek_suspend,
.resume = fintek_resume,
.shutdown = fintek_shutdown,
};
static int __init fintek_init(void)
{
return pnp_register_driver(&fintek_driver);
}
static void __exit fintek_exit(void)
{
pnp_unregister_driver(&fintek_driver);
}
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable debugging output");
MODULE_DEVICE_TABLE(pnp, fintek_ids);
MODULE_DESCRIPTION(FINTEK_DESCRIPTION " driver");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
MODULE_LICENSE("GPL");
module_init(fintek_init);
module_exit(fintek_exit);

View file

@ -0,0 +1,245 @@
/*
* Driver for Feature Integration Technology Inc. (aka Fintek) LPC CIR
*
* Copyright (C) 2011 Jarod Wilson <jarod@redhat.com>
*
* Special thanks to Fintek for providing hardware and spec sheets.
* This driver is based upon the nuvoton, ite and ene drivers for
* similar hardware.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <linux/spinlock.h>
#include <linux/ioctl.h>
/* platform driver name to register */
#define FINTEK_DRIVER_NAME "fintek-cir"
#define FINTEK_DESCRIPTION "Fintek LPC SuperIO Consumer IR Transceiver"
#define VENDOR_ID_FINTEK 0x1934
/* debugging module parameter */
static int debug;
#define fit_pr(level, text, ...) \
printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
#define fit_dbg(text, ...) \
if (debug) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define fit_dbg_verbose(text, ...) \
if (debug > 1) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define fit_dbg_wake(text, ...) \
if (debug > 2) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__)
#define TX_BUF_LEN 256
#define RX_BUF_LEN 32
struct fintek_dev {
struct pnp_dev *pdev;
struct rc_dev *rdev;
spinlock_t fintek_lock;
/* for rx */
u8 buf[RX_BUF_LEN];
unsigned int pkts;
struct {
spinlock_t lock;
u8 buf[TX_BUF_LEN];
unsigned int buf_count;
unsigned int cur_buf_num;
wait_queue_head_t queue;
} tx;
/* Config register index/data port pair */
u32 cr_ip;
u32 cr_dp;
/* hardware I/O settings */
unsigned long cir_addr;
int cir_irq;
int cir_port_len;
/* hardware id */
u8 chip_major;
u8 chip_minor;
u16 chip_vendor;
u8 logical_dev_cir;
/* hardware features */
bool hw_learning_capable;
bool hw_tx_capable;
/* rx settings */
bool learning_enabled;
bool carrier_detect_enabled;
enum {
CMD_HEADER = 0,
SUBCMD,
CMD_DATA,
PARSE_IRDATA,
} parser_state;
u8 cmd, rem;
/* carrier period = 1 / frequency */
u32 carrier;
};
/* buffer packet constants, largely identical to mceusb.c */
#define BUF_PULSE_BIT 0x80
#define BUF_LEN_MASK 0x1f
#define BUF_SAMPLE_MASK 0x7f
#define BUF_COMMAND_HEADER 0x9f
#define BUF_COMMAND_MASK 0xe0
#define BUF_COMMAND_NULL 0x00
#define BUF_HW_CMD_HEADER 0xff
#define BUF_CMD_G_REVISION 0x0b
#define BUF_CMD_S_CARRIER 0x06
#define BUF_CMD_S_TIMEOUT 0x0c
#define BUF_CMD_SIG_END 0x01
#define BUF_CMD_S_TXMASK 0x08
#define BUF_CMD_S_RXSENSOR 0x14
#define BUF_RSP_PULSE_COUNT 0x15
#define CIR_SAMPLE_PERIOD 50
/*
* Configuration Register:
* Index Port
* Data Port
*/
#define CR_INDEX_PORT 0x2e
#define CR_DATA_PORT 0x2f
/* Possible alternate values, depends on how the chip is wired */
#define CR_INDEX_PORT2 0x4e
#define CR_DATA_PORT2 0x4f
/*
* GCR_CONFIG_PORT_SEL bit 4 specifies which Index Port value is
* active. 1 = 0x4e, 0 = 0x2e
*/
#define PORT_SEL_PORT_4E_EN 0x10
/* Extended Function Mode enable/disable magic values */
#define CONFIG_REG_ENABLE 0x87
#define CONFIG_REG_DISABLE 0xaa
/* Chip IDs found in CR_CHIP_ID_{HI,LO} */
#define CHIP_ID_HIGH_F71809U 0x04
#define CHIP_ID_LOW_F71809U 0x08
/*
* Global control regs we need to care about:
* Global Control def.
* Register name addr val. */
#define GCR_SOFTWARE_RESET 0x02 /* 0x00 */
#define GCR_LOGICAL_DEV_NO 0x07 /* 0x00 */
#define GCR_CHIP_ID_HI 0x20 /* 0x04 */
#define GCR_CHIP_ID_LO 0x21 /* 0x08 */
#define GCR_VENDOR_ID_HI 0x23 /* 0x19 */
#define GCR_VENDOR_ID_LO 0x24 /* 0x34 */
#define GCR_CONFIG_PORT_SEL 0x25 /* 0x01 */
#define GCR_KBMOUSE_WAKEUP 0x27
#define LOGICAL_DEV_DISABLE 0x00
#define LOGICAL_DEV_ENABLE 0x01
/* Logical device number of the CIR function */
#define LOGICAL_DEV_CIR_REV1 0x05
#define LOGICAL_DEV_CIR_REV2 0x08
/* CIR Logical Device (LDN 0x08) config registers */
#define CIR_CR_COMMAND_INDEX 0x04
#define CIR_CR_IRCS 0x05 /* Before host writes command to IR, host
must set to 1. When host finshes write
command to IR, host must clear to 0. */
#define CIR_CR_COMMAND_DATA 0x06 /* Host read or write comand data */
#define CIR_CR_CLASS 0x07 /* 0xff = rx-only, 0x66 = rx + 2 tx,
0x33 = rx + 1 tx */
#define CIR_CR_DEV_EN 0x30 /* bit0 = 1 enables CIR */
#define CIR_CR_BASE_ADDR_HI 0x60 /* MSB of CIR IO base addr */
#define CIR_CR_BASE_ADDR_LO 0x61 /* LSB of CIR IO base addr */
#define CIR_CR_IRQ_SEL 0x70 /* bits3-0 store CIR IRQ */
#define CIR_CR_PSOUT_STATUS 0xf1
#define CIR_CR_WAKE_KEY3_ADDR 0xf8
#define CIR_CR_WAKE_KEY3_CODE 0xf9
#define CIR_CR_WAKE_KEY3_DC 0xfa
#define CIR_CR_WAKE_CONTROL 0xfb
#define CIR_CR_WAKE_KEY12_ADDR 0xfc
#define CIR_CR_WAKE_KEY4_ADDR 0xfd
#define CIR_CR_WAKE_KEY5_ADDR 0xfe
#define CLASS_RX_ONLY 0xff
#define CLASS_RX_2TX 0x66
#define CLASS_RX_1TX 0x33
/* CIR device registers */
#define CIR_STATUS 0x00
#define CIR_RX_DATA 0x01
#define CIR_TX_CONTROL 0x02
#define CIR_TX_DATA 0x03
#define CIR_CONTROL 0x04
/* Bits to enable CIR wake */
#define LOGICAL_DEV_ACPI 0x01
#define LDEV_ACPI_WAKE_EN_REG 0xe8
#define ACPI_WAKE_EN_CIR_BIT 0x04
#define LDEV_ACPI_PME_EN_REG 0xf0
#define LDEV_ACPI_PME_CLR_REG 0xf1
#define ACPI_PME_CIR_BIT 0x02
#define LDEV_ACPI_STATE_REG 0xf4
#define ACPI_STATE_CIR_BIT 0x20
/*
* CIR status register (0x00):
* 7 - CIR_IRQ_EN (1 = enable CIR IRQ, 0 = disable)
* 3 - TX_FINISH (1 when TX finished, write 1 to clear)
* 2 - TX_UNDERRUN (1 on TX underrun, write 1 to clear)
* 1 - RX_TIMEOUT (1 on RX timeout, write 1 to clear)
* 0 - RX_RECEIVE (1 on RX receive, write 1 to clear)
*/
#define CIR_STATUS_IRQ_EN 0x80
#define CIR_STATUS_TX_FINISH 0x08
#define CIR_STATUS_TX_UNDERRUN 0x04
#define CIR_STATUS_RX_TIMEOUT 0x02
#define CIR_STATUS_RX_RECEIVE 0x01
#define CIR_STATUS_IRQ_MASK 0x0f
/*
* CIR TX control register (0x02):
* 7 - TX_START (1 to indicate TX start, auto-cleared when done)
* 6 - TX_END (1 to indicate TX data written to TX fifo)
*/
#define CIR_TX_CONTROL_TX_START 0x80
#define CIR_TX_CONTROL_TX_END 0x40

View file

@ -0,0 +1,253 @@
/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <media/rc-core.h>
#include <media/gpio-ir-recv.h>
#define GPIO_IR_DRIVER_NAME "gpio-rc-recv"
#define GPIO_IR_DEVICE_NAME "gpio_ir_recv"
struct gpio_rc_dev {
struct rc_dev *rcdev;
int gpio_nr;
bool active_low;
};
#ifdef CONFIG_OF
/*
* Translate OpenFirmware node properties into platform_data
*/
static int gpio_ir_recv_get_devtree_pdata(struct device *dev,
struct gpio_ir_recv_platform_data *pdata)
{
struct device_node *np = dev->of_node;
enum of_gpio_flags flags;
int gpio;
gpio = of_get_gpio_flags(np, 0, &flags);
if (gpio < 0) {
if (gpio != -EPROBE_DEFER)
dev_err(dev, "Failed to get gpio flags (%d)\n", gpio);
return gpio;
}
pdata->gpio_nr = gpio;
pdata->active_low = (flags & OF_GPIO_ACTIVE_LOW);
/* probe() takes care of map_name == NULL or allowed_protos == 0 */
pdata->map_name = of_get_property(np, "linux,rc-map-name", NULL);
pdata->allowed_protos = 0;
return 0;
}
static struct of_device_id gpio_ir_recv_of_match[] = {
{ .compatible = "gpio-ir-receiver", },
{ },
};
MODULE_DEVICE_TABLE(of, gpio_ir_recv_of_match);
#else /* !CONFIG_OF */
#define gpio_ir_recv_get_devtree_pdata(dev, pdata) (-ENOSYS)
#endif
static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
{
struct gpio_rc_dev *gpio_dev = dev_id;
int gval;
int rc = 0;
enum raw_event_type type = IR_SPACE;
gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
if (gval < 0)
goto err_get_value;
if (gpio_dev->active_low)
gval = !gval;
if (gval == 1)
type = IR_PULSE;
rc = ir_raw_event_store_edge(gpio_dev->rcdev, type);
if (rc < 0)
goto err_get_value;
ir_raw_event_handle(gpio_dev->rcdev);
err_get_value:
return IRQ_HANDLED;
}
static int gpio_ir_recv_probe(struct platform_device *pdev)
{
struct gpio_rc_dev *gpio_dev;
struct rc_dev *rcdev;
const struct gpio_ir_recv_platform_data *pdata =
pdev->dev.platform_data;
int rc;
if (pdev->dev.of_node) {
struct gpio_ir_recv_platform_data *dtpdata =
devm_kzalloc(&pdev->dev, sizeof(*dtpdata), GFP_KERNEL);
if (!dtpdata)
return -ENOMEM;
rc = gpio_ir_recv_get_devtree_pdata(&pdev->dev, dtpdata);
if (rc)
return rc;
pdata = dtpdata;
}
if (!pdata)
return -EINVAL;
if (pdata->gpio_nr < 0)
return -EINVAL;
gpio_dev = kzalloc(sizeof(struct gpio_rc_dev), GFP_KERNEL);
if (!gpio_dev)
return -ENOMEM;
rcdev = rc_allocate_device();
if (!rcdev) {
rc = -ENOMEM;
goto err_allocate_device;
}
rcdev->priv = gpio_dev;
rcdev->driver_type = RC_DRIVER_IR_RAW;
rcdev->input_name = GPIO_IR_DEVICE_NAME;
rcdev->input_phys = GPIO_IR_DEVICE_NAME "/input0";
rcdev->input_id.bustype = BUS_HOST;
rcdev->input_id.vendor = 0x0001;
rcdev->input_id.product = 0x0001;
rcdev->input_id.version = 0x0100;
rcdev->dev.parent = &pdev->dev;
rcdev->driver_name = GPIO_IR_DRIVER_NAME;
if (pdata->allowed_protos)
rcdev->allowed_protocols = pdata->allowed_protos;
else
rcdev->allowed_protocols = RC_BIT_ALL;
rcdev->map_name = pdata->map_name ?: RC_MAP_EMPTY;
gpio_dev->rcdev = rcdev;
gpio_dev->gpio_nr = pdata->gpio_nr;
gpio_dev->active_low = pdata->active_low;
rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
if (rc < 0)
goto err_gpio_request;
rc = gpio_direction_input(pdata->gpio_nr);
if (rc < 0)
goto err_gpio_direction_input;
rc = rc_register_device(rcdev);
if (rc < 0) {
dev_err(&pdev->dev, "failed to register rc device\n");
goto err_register_rc_device;
}
platform_set_drvdata(pdev, gpio_dev);
rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),
gpio_ir_recv_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
"gpio-ir-recv-irq", gpio_dev);
if (rc < 0)
goto err_request_irq;
return 0;
err_request_irq:
rc_unregister_device(rcdev);
rcdev = NULL;
err_register_rc_device:
err_gpio_direction_input:
gpio_free(pdata->gpio_nr);
err_gpio_request:
rc_free_device(rcdev);
err_allocate_device:
kfree(gpio_dev);
return rc;
}
static int gpio_ir_recv_remove(struct platform_device *pdev)
{
struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
rc_unregister_device(gpio_dev->rcdev);
gpio_free(gpio_dev->gpio_nr);
kfree(gpio_dev);
return 0;
}
#ifdef CONFIG_PM
static int gpio_ir_recv_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
if (device_may_wakeup(dev))
enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
else
disable_irq(gpio_to_irq(gpio_dev->gpio_nr));
return 0;
}
static int gpio_ir_recv_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
if (device_may_wakeup(dev))
disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
else
enable_irq(gpio_to_irq(gpio_dev->gpio_nr));
return 0;
}
static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
.suspend = gpio_ir_recv_suspend,
.resume = gpio_ir_recv_resume,
};
#endif
static struct platform_driver gpio_ir_recv_driver = {
.probe = gpio_ir_recv_probe,
.remove = gpio_ir_recv_remove,
.driver = {
.name = GPIO_IR_DRIVER_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpio_ir_recv_of_match),
#ifdef CONFIG_PM
.pm = &gpio_ir_recv_pm_ops,
#endif
},
};
module_platform_driver(gpio_ir_recv_driver);
MODULE_DESCRIPTION("GPIO IR Receiver driver");
MODULE_LICENSE("GPL v2");

618
drivers/media/rc/iguanair.c Normal file
View file

@ -0,0 +1,618 @@
/*
* IguanaWorks USB IR Transceiver support
*
* Copyright (C) 2012 Sean Young <sean@mess.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <media/rc-core.h>
#define DRIVER_NAME "iguanair"
#define BUF_SIZE 152
struct iguanair {
struct rc_dev *rc;
struct device *dev;
struct usb_device *udev;
uint16_t version;
uint8_t bufsize;
uint8_t cycle_overhead;
struct mutex lock;
/* receiver support */
bool receiver_on;
dma_addr_t dma_in, dma_out;
uint8_t *buf_in;
struct urb *urb_in, *urb_out;
struct completion completion;
/* transmit support */
bool tx_overflow;
uint32_t carrier;
struct send_packet *packet;
char name[64];
char phys[64];
};
#define CMD_NOP 0x00
#define CMD_GET_VERSION 0x01
#define CMD_GET_BUFSIZE 0x11
#define CMD_GET_FEATURES 0x10
#define CMD_SEND 0x15
#define CMD_EXECUTE 0x1f
#define CMD_RX_OVERFLOW 0x31
#define CMD_TX_OVERFLOW 0x32
#define CMD_RECEIVER_ON 0x12
#define CMD_RECEIVER_OFF 0x14
#define DIR_IN 0xdc
#define DIR_OUT 0xcd
#define MAX_IN_PACKET 8u
#define MAX_OUT_PACKET (sizeof(struct send_packet) + BUF_SIZE)
#define TIMEOUT 1000
#define RX_RESOLUTION 21333
struct packet {
uint16_t start;
uint8_t direction;
uint8_t cmd;
};
struct send_packet {
struct packet header;
uint8_t length;
uint8_t channels;
uint8_t busy7;
uint8_t busy4;
uint8_t payload[0];
};
static void process_ir_data(struct iguanair *ir, unsigned len)
{
if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
switch (ir->buf_in[3]) {
case CMD_GET_VERSION:
if (len == 6) {
ir->version = (ir->buf_in[5] << 8) |
ir->buf_in[4];
complete(&ir->completion);
}
break;
case CMD_GET_BUFSIZE:
if (len >= 5) {
ir->bufsize = ir->buf_in[4];
complete(&ir->completion);
}
break;
case CMD_GET_FEATURES:
if (len > 5) {
ir->cycle_overhead = ir->buf_in[5];
complete(&ir->completion);
}
break;
case CMD_TX_OVERFLOW:
ir->tx_overflow = true;
case CMD_RECEIVER_OFF:
case CMD_RECEIVER_ON:
case CMD_SEND:
complete(&ir->completion);
break;
case CMD_RX_OVERFLOW:
dev_warn(ir->dev, "receive overflow\n");
ir_raw_event_reset(ir->rc);
break;
default:
dev_warn(ir->dev, "control code %02x received\n",
ir->buf_in[3]);
break;
}
} else if (len >= 7) {
DEFINE_IR_RAW_EVENT(rawir);
unsigned i;
bool event = false;
init_ir_raw_event(&rawir);
for (i = 0; i < 7; i++) {
if (ir->buf_in[i] == 0x80) {
rawir.pulse = false;
rawir.duration = US_TO_NS(21845);
} else {
rawir.pulse = (ir->buf_in[i] & 0x80) == 0;
rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) *
RX_RESOLUTION;
}
if (ir_raw_event_store_with_filter(ir->rc, &rawir))
event = true;
}
if (event)
ir_raw_event_handle(ir->rc);
}
}
static void iguanair_rx(struct urb *urb)
{
struct iguanair *ir;
int rc;
if (!urb)
return;
ir = urb->context;
if (!ir) {
usb_unlink_urb(urb);
return;
}
switch (urb->status) {
case 0:
process_ir_data(ir, urb->actual_length);
break;
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
usb_unlink_urb(urb);
return;
case -EPIPE:
default:
dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
break;
}
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc && rc != -ENODEV)
dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
}
static void iguanair_irq_out(struct urb *urb)
{
struct iguanair *ir = urb->context;
if (urb->status)
dev_dbg(ir->dev, "Error: out urb status = %d\n", urb->status);
/* if we sent an nop packet, do not expect a response */
if (urb->status == 0 && ir->packet->header.cmd == CMD_NOP)
complete(&ir->completion);
}
static int iguanair_send(struct iguanair *ir, unsigned size)
{
int rc;
reinit_completion(&ir->completion);
ir->urb_out->transfer_buffer_length = size;
rc = usb_submit_urb(ir->urb_out, GFP_KERNEL);
if (rc)
return rc;
if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
return -ETIMEDOUT;
return rc;
}
static int iguanair_get_features(struct iguanair *ir)
{
int rc;
/*
* On cold boot, the iguanair initializes on the first packet
* received but does not process that packet. Send an empty
* packet.
*/
ir->packet->header.start = 0;
ir->packet->header.direction = DIR_OUT;
ir->packet->header.cmd = CMD_NOP;
iguanair_send(ir, sizeof(ir->packet->header));
ir->packet->header.cmd = CMD_GET_VERSION;
rc = iguanair_send(ir, sizeof(ir->packet->header));
if (rc) {
dev_info(ir->dev, "failed to get version\n");
goto out;
}
if (ir->version < 0x205) {
dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
rc = -ENODEV;
goto out;
}
ir->bufsize = 150;
ir->cycle_overhead = 65;
ir->packet->header.cmd = CMD_GET_BUFSIZE;
rc = iguanair_send(ir, sizeof(ir->packet->header));
if (rc) {
dev_info(ir->dev, "failed to get buffer size\n");
goto out;
}
if (ir->bufsize > BUF_SIZE) {
dev_info(ir->dev, "buffer size %u larger than expected\n",
ir->bufsize);
ir->bufsize = BUF_SIZE;
}
ir->packet->header.cmd = CMD_GET_FEATURES;
rc = iguanair_send(ir, sizeof(ir->packet->header));
if (rc)
dev_info(ir->dev, "failed to get features\n");
out:
return rc;
}
static int iguanair_receiver(struct iguanair *ir, bool enable)
{
ir->packet->header.start = 0;
ir->packet->header.direction = DIR_OUT;
ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;
if (enable)
ir_raw_event_reset(ir->rc);
return iguanair_send(ir, sizeof(ir->packet->header));
}
/*
* The iguanair creates the carrier by busy spinning after each half period.
* This is counted in CPU cycles, with the CPU running at 24MHz. It is
* broken down into 7-cycles and 4-cyles delays, with a preference for
* 4-cycle delays, minus the overhead of the loop itself (cycle_overhead).
*/
static int iguanair_set_tx_carrier(struct rc_dev *dev, uint32_t carrier)
{
struct iguanair *ir = dev->priv;
if (carrier < 25000 || carrier > 150000)
return -EINVAL;
mutex_lock(&ir->lock);
if (carrier != ir->carrier) {
uint32_t cycles, fours, sevens;
ir->carrier = carrier;
cycles = DIV_ROUND_CLOSEST(24000000, carrier * 2) -
ir->cycle_overhead;
/*
* Calculate minimum number of 7 cycles needed so
* we are left with a multiple of 4; so we want to have
* (sevens * 7) & 3 == cycles & 3
*/
sevens = (4 - cycles) & 3;
fours = (cycles - sevens * 7) / 4;
/*
* The firmware interprets these values as a relative offset
* for a branch. Immediately following the branches, there
* 4 instructions of 7 cycles (2 bytes each) and 110
* instructions of 4 cycles (1 byte each). A relative branch
* of 0 will execute all of them, branch further for less
* cycle burning.
*/
ir->packet->busy7 = (4 - sevens) * 2;
ir->packet->busy4 = 110 - fours;
}
mutex_unlock(&ir->lock);
return carrier;
}
static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
{
struct iguanair *ir = dev->priv;
if (mask > 15)
return 4;
mutex_lock(&ir->lock);
ir->packet->channels = mask << 4;
mutex_unlock(&ir->lock);
return 0;
}
static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
{
struct iguanair *ir = dev->priv;
uint8_t space;
unsigned i, size, periods, bytes;
int rc;
mutex_lock(&ir->lock);
/* convert from us to carrier periods */
for (i = space = size = 0; i < count; i++) {
periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
bytes = DIV_ROUND_UP(periods, 127);
if (size + bytes > ir->bufsize) {
rc = -EINVAL;
goto out;
}
while (periods) {
unsigned p = min(periods, 127u);
ir->packet->payload[size++] = p | space;
periods -= p;
}
space ^= 0x80;
}
ir->packet->header.start = 0;
ir->packet->header.direction = DIR_OUT;
ir->packet->header.cmd = CMD_SEND;
ir->packet->length = size;
ir->tx_overflow = false;
rc = iguanair_send(ir, sizeof(*ir->packet) + size);
if (rc == 0 && ir->tx_overflow)
rc = -EOVERFLOW;
out:
mutex_unlock(&ir->lock);
return rc ? rc : count;
}
static int iguanair_open(struct rc_dev *rdev)
{
struct iguanair *ir = rdev->priv;
int rc;
mutex_lock(&ir->lock);
rc = iguanair_receiver(ir, true);
if (rc == 0)
ir->receiver_on = true;
mutex_unlock(&ir->lock);
return rc;
}
static void iguanair_close(struct rc_dev *rdev)
{
struct iguanair *ir = rdev->priv;
int rc;
mutex_lock(&ir->lock);
rc = iguanair_receiver(ir, false);
ir->receiver_on = false;
if (rc && rc != -ENODEV)
dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
mutex_unlock(&ir->lock);
}
static int iguanair_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct iguanair *ir;
struct rc_dev *rc;
int ret, pipein, pipeout;
struct usb_host_interface *idesc;
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
rc = rc_allocate_device();
if (!ir || !rc) {
ret = -ENOMEM;
goto out;
}
ir->buf_in = usb_alloc_coherent(udev, MAX_IN_PACKET, GFP_KERNEL,
&ir->dma_in);
ir->packet = usb_alloc_coherent(udev, MAX_OUT_PACKET, GFP_KERNEL,
&ir->dma_out);
ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
ir->urb_out = usb_alloc_urb(0, GFP_KERNEL);
if (!ir->buf_in || !ir->packet || !ir->urb_in || !ir->urb_out) {
ret = -ENOMEM;
goto out;
}
idesc = intf->altsetting;
if (idesc->desc.bNumEndpoints < 2) {
ret = -ENODEV;
goto out;
}
ir->rc = rc;
ir->dev = &intf->dev;
ir->udev = udev;
mutex_init(&ir->lock);
init_completion(&ir->completion);
pipeout = usb_sndintpipe(udev,
idesc->endpoint[1].desc.bEndpointAddress);
usb_fill_int_urb(ir->urb_out, udev, pipeout, ir->packet, MAX_OUT_PACKET,
iguanair_irq_out, ir, 1);
ir->urb_out->transfer_dma = ir->dma_out;
ir->urb_out->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_IN_PACKET,
iguanair_rx, ir, 1);
ir->urb_in->transfer_dma = ir->dma_in;
ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
ret = usb_submit_urb(ir->urb_in, GFP_KERNEL);
if (ret) {
dev_warn(&intf->dev, "failed to submit urb: %d\n", ret);
goto out;
}
ret = iguanair_get_features(ir);
if (ret)
goto out2;
snprintf(ir->name, sizeof(ir->name),
"IguanaWorks USB IR Transceiver version 0x%04x", ir->version);
usb_make_path(ir->udev, ir->phys, sizeof(ir->phys));
rc->input_name = ir->name;
rc->input_phys = ir->phys;
usb_to_input_id(ir->udev, &rc->input_id);
rc->dev.parent = &intf->dev;
rc->driver_type = RC_DRIVER_IR_RAW;
rc->allowed_protocols = RC_BIT_ALL;
rc->priv = ir;
rc->open = iguanair_open;
rc->close = iguanair_close;
rc->s_tx_mask = iguanair_set_tx_mask;
rc->s_tx_carrier = iguanair_set_tx_carrier;
rc->tx_ir = iguanair_tx;
rc->driver_name = DRIVER_NAME;
rc->map_name = RC_MAP_RC6_MCE;
rc->timeout = MS_TO_NS(100);
rc->rx_resolution = RX_RESOLUTION;
iguanair_set_tx_carrier(rc, 38000);
iguanair_set_tx_mask(rc, 0);
ret = rc_register_device(rc);
if (ret < 0) {
dev_err(&intf->dev, "failed to register rc device %d", ret);
goto out2;
}
usb_set_intfdata(intf, ir);
return 0;
out2:
usb_kill_urb(ir->urb_in);
usb_kill_urb(ir->urb_out);
out:
if (ir) {
usb_free_urb(ir->urb_in);
usb_free_urb(ir->urb_out);
usb_free_coherent(udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
usb_free_coherent(udev, MAX_OUT_PACKET, ir->packet,
ir->dma_out);
}
rc_free_device(rc);
kfree(ir);
return ret;
}
static void iguanair_disconnect(struct usb_interface *intf)
{
struct iguanair *ir = usb_get_intfdata(intf);
rc_unregister_device(ir->rc);
usb_set_intfdata(intf, NULL);
usb_kill_urb(ir->urb_in);
usb_kill_urb(ir->urb_out);
usb_free_urb(ir->urb_in);
usb_free_urb(ir->urb_out);
usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
usb_free_coherent(ir->udev, MAX_OUT_PACKET, ir->packet, ir->dma_out);
kfree(ir);
}
static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
{
struct iguanair *ir = usb_get_intfdata(intf);
int rc = 0;
mutex_lock(&ir->lock);
if (ir->receiver_on) {
rc = iguanair_receiver(ir, false);
if (rc)
dev_warn(ir->dev, "failed to disable receiver for suspend\n");
}
usb_kill_urb(ir->urb_in);
usb_kill_urb(ir->urb_out);
mutex_unlock(&ir->lock);
return rc;
}
static int iguanair_resume(struct usb_interface *intf)
{
struct iguanair *ir = usb_get_intfdata(intf);
int rc = 0;
mutex_lock(&ir->lock);
rc = usb_submit_urb(ir->urb_in, GFP_KERNEL);
if (rc)
dev_warn(&intf->dev, "failed to submit urb: %d\n", rc);
if (ir->receiver_on) {
rc = iguanair_receiver(ir, true);
if (rc)
dev_warn(ir->dev, "failed to enable receiver after resume\n");
}
mutex_unlock(&ir->lock);
return rc;
}
static const struct usb_device_id iguanair_table[] = {
{ USB_DEVICE(0x1781, 0x0938) },
{ }
};
static struct usb_driver iguanair_driver = {
.name = DRIVER_NAME,
.probe = iguanair_probe,
.disconnect = iguanair_disconnect,
.suspend = iguanair_suspend,
.resume = iguanair_resume,
.reset_resume = iguanair_resume,
.id_table = iguanair_table,
.soft_unbind = 1 /* we want to disable receiver on unbind */
};
module_usb_driver(iguanair_driver);
MODULE_DESCRIPTION("IguanaWorks USB IR Transceiver");
MODULE_AUTHOR("Sean Young <sean@mess.org>");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(usb, iguanair_table);

View file

@ -0,0 +1,61 @@
config IR_IMG
tristate "ImgTec IR Decoder"
depends on RC_CORE
select IR_IMG_HW if !IR_IMG_RAW
help
Say Y or M here if you want to use the ImgTec infrared decoder
functionality found in SoCs such as TZ1090.
config IR_IMG_RAW
bool "Raw decoder"
depends on IR_IMG
help
Say Y here to enable the raw mode driver which passes raw IR signal
changes to the IR raw decoders for software decoding. This is much
less reliable (due to lack of timestamps) and consumes more
processing power than using hardware decode, but can be useful for
testing, debug, and to make more protocols available.
config IR_IMG_HW
bool "Hardware decoder"
depends on IR_IMG
help
Say Y here to enable the hardware decode driver which decodes the IR
signals in hardware. This is more reliable, consumes less processing
power since only a single interrupt is received for each scancode,
and allows an IR scancode to be used as a wake event.
config IR_IMG_NEC
bool "NEC protocol support"
depends on IR_IMG_HW
help
Say Y here to enable support for the NEC, extended NEC, and 32-bit
NEC protocols in the ImgTec infrared decoder block.
config IR_IMG_JVC
bool "JVC protocol support"
depends on IR_IMG_HW
help
Say Y here to enable support for the JVC protocol in the ImgTec
infrared decoder block.
config IR_IMG_SONY
bool "Sony protocol support"
depends on IR_IMG_HW
help
Say Y here to enable support for the Sony protocol in the ImgTec
infrared decoder block.
config IR_IMG_SHARP
bool "Sharp protocol support"
depends on IR_IMG_HW
help
Say Y here to enable support for the Sharp protocol in the ImgTec
infrared decoder block.
config IR_IMG_SANYO
bool "Sanyo protocol support"
depends on IR_IMG_HW
help
Say Y here to enable support for the Sanyo protocol (used by Sanyo,
Aiwa, Chinon remotes) in the ImgTec infrared decoder block.

View file

@ -0,0 +1,11 @@
img-ir-y := img-ir-core.o
img-ir-$(CONFIG_IR_IMG_RAW) += img-ir-raw.o
img-ir-$(CONFIG_IR_IMG_HW) += img-ir-hw.o
img-ir-$(CONFIG_IR_IMG_NEC) += img-ir-nec.o
img-ir-$(CONFIG_IR_IMG_JVC) += img-ir-jvc.o
img-ir-$(CONFIG_IR_IMG_SONY) += img-ir-sony.o
img-ir-$(CONFIG_IR_IMG_SHARP) += img-ir-sharp.o
img-ir-$(CONFIG_IR_IMG_SANYO) += img-ir-sanyo.o
img-ir-objs := $(img-ir-y)
obj-$(CONFIG_IR_IMG) += img-ir.o

View file

@ -0,0 +1,181 @@
/*
* ImgTec IR Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This contains core img-ir code for setting up the driver. The two interfaces
* (raw and hardware decode) are handled separately.
*/
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include "img-ir.h"
static irqreturn_t img_ir_isr(int irq, void *dev_id)
{
struct img_ir_priv *priv = dev_id;
u32 irq_status;
spin_lock(&priv->lock);
/* we have to clear irqs before reading */
irq_status = img_ir_read(priv, IMG_IR_IRQ_STATUS);
img_ir_write(priv, IMG_IR_IRQ_CLEAR, irq_status);
/* don't handle valid data irqs if we're only interested in matches */
irq_status &= img_ir_read(priv, IMG_IR_IRQ_ENABLE);
/* hand off edge interrupts to raw decode handler */
if (irq_status & IMG_IR_IRQ_EDGE && img_ir_raw_enabled(&priv->raw))
img_ir_isr_raw(priv, irq_status);
/* hand off hardware match interrupts to hardware decode handler */
if (irq_status & (IMG_IR_IRQ_DATA_MATCH |
IMG_IR_IRQ_DATA_VALID |
IMG_IR_IRQ_DATA2_VALID) &&
img_ir_hw_enabled(&priv->hw))
img_ir_isr_hw(priv, irq_status);
spin_unlock(&priv->lock);
return IRQ_HANDLED;
}
static void img_ir_setup(struct img_ir_priv *priv)
{
/* start off with interrupts disabled */
img_ir_write(priv, IMG_IR_IRQ_ENABLE, 0);
img_ir_setup_raw(priv);
img_ir_setup_hw(priv);
if (!IS_ERR(priv->clk))
clk_prepare_enable(priv->clk);
}
static void img_ir_ident(struct img_ir_priv *priv)
{
u32 core_rev = img_ir_read(priv, IMG_IR_CORE_REV);
dev_info(priv->dev,
"IMG IR Decoder (%d.%d.%d.%d) probed successfully\n",
(core_rev & IMG_IR_DESIGNER) >> IMG_IR_DESIGNER_SHIFT,
(core_rev & IMG_IR_MAJOR_REV) >> IMG_IR_MAJOR_REV_SHIFT,
(core_rev & IMG_IR_MINOR_REV) >> IMG_IR_MINOR_REV_SHIFT,
(core_rev & IMG_IR_MAINT_REV) >> IMG_IR_MAINT_REV_SHIFT);
dev_info(priv->dev, "Modes:%s%s\n",
img_ir_hw_enabled(&priv->hw) ? " hardware" : "",
img_ir_raw_enabled(&priv->raw) ? " raw" : "");
}
static int img_ir_probe(struct platform_device *pdev)
{
struct img_ir_priv *priv;
struct resource *res_regs;
int irq, error, error2;
/* Get resources from platform device */
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_err(&pdev->dev, "cannot find IRQ resource\n");
return irq;
}
/* Private driver data */
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
dev_err(&pdev->dev, "cannot allocate device data\n");
return -ENOMEM;
}
platform_set_drvdata(pdev, priv);
priv->dev = &pdev->dev;
spin_lock_init(&priv->lock);
/* Ioremap the registers */
res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->reg_base = devm_ioremap_resource(&pdev->dev, res_regs);
if (IS_ERR(priv->reg_base))
return PTR_ERR(priv->reg_base);
/* Get core clock */
priv->clk = devm_clk_get(&pdev->dev, "core");
if (IS_ERR(priv->clk))
dev_warn(&pdev->dev, "cannot get core clock resource\n");
/*
* The driver doesn't need to know about the system ("sys") or power
* modulation ("mod") clocks yet
*/
/* Set up raw & hw decoder */
error = img_ir_probe_raw(priv);
error2 = img_ir_probe_hw(priv);
if (error && error2)
return (error == -ENODEV) ? error2 : error;
/* Get the IRQ */
priv->irq = irq;
error = request_irq(priv->irq, img_ir_isr, 0, "img-ir", priv);
if (error) {
dev_err(&pdev->dev, "cannot register IRQ %u\n",
priv->irq);
error = -EIO;
goto err_irq;
}
img_ir_ident(priv);
img_ir_setup(priv);
return 0;
err_irq:
img_ir_remove_hw(priv);
img_ir_remove_raw(priv);
return error;
}
static int img_ir_remove(struct platform_device *pdev)
{
struct img_ir_priv *priv = platform_get_drvdata(pdev);
free_irq(priv->irq, priv);
img_ir_remove_hw(priv);
img_ir_remove_raw(priv);
if (!IS_ERR(priv->clk))
clk_disable_unprepare(priv->clk);
return 0;
}
static SIMPLE_DEV_PM_OPS(img_ir_pmops, img_ir_suspend, img_ir_resume);
static const struct of_device_id img_ir_match[] = {
{ .compatible = "img,ir-rev1" },
{}
};
MODULE_DEVICE_TABLE(of, img_ir_match);
static struct platform_driver img_ir_driver = {
.driver = {
.name = "img-ir",
.owner = THIS_MODULE,
.of_match_table = img_ir_match,
.pm = &img_ir_pmops,
},
.probe = img_ir_probe,
.remove = img_ir_remove,
};
module_platform_driver(img_ir_driver);
MODULE_AUTHOR("Imagination Technologies Ltd.");
MODULE_DESCRIPTION("ImgTec IR");
MODULE_LICENSE("GPL");

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,284 @@
/*
* ImgTec IR Hardware Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _IMG_IR_HW_H_
#define _IMG_IR_HW_H_
#include <linux/kernel.h>
#include <media/rc-core.h>
/* constants */
#define IMG_IR_CODETYPE_PULSELEN 0x0 /* Sony */
#define IMG_IR_CODETYPE_PULSEDIST 0x1 /* NEC, Toshiba, Micom, Sharp */
#define IMG_IR_CODETYPE_BIPHASE 0x2 /* RC-5/6 */
#define IMG_IR_CODETYPE_2BITPULSEPOS 0x3 /* RC-MM */
/* Timing information */
/**
* struct img_ir_control - Decoder control settings
* @decoden: Primary decoder enable
* @code_type: Decode type (see IMG_IR_CODETYPE_*)
* @hdrtog: Detect header toggle symbol after leader symbol
* @ldrdec: Don't discard leader if maximum width reached
* @decodinpol: Decoder input polarity (1=active high)
* @bitorien: Bit orientation (1=MSB first)
* @d1validsel: Decoder 2 takes over if it detects valid data
* @bitinv: Bit inversion switch (1=don't invert)
* @decodend2: Secondary decoder enable (no leader symbol)
* @bitoriend2: Bit orientation (1=MSB first)
* @bitinvd2: Secondary decoder bit inversion switch (1=don't invert)
*/
struct img_ir_control {
unsigned decoden:1;
unsigned code_type:2;
unsigned hdrtog:1;
unsigned ldrdec:1;
unsigned decodinpol:1;
unsigned bitorien:1;
unsigned d1validsel:1;
unsigned bitinv:1;
unsigned decodend2:1;
unsigned bitoriend2:1;
unsigned bitinvd2:1;
};
/**
* struct img_ir_timing_range - range of timing values
* @min: Minimum timing value
* @max: Maximum timing value (if < @min, this will be set to @min during
* preprocessing step, so it is normally not explicitly initialised
* and is taken care of by the tolerance)
*/
struct img_ir_timing_range {
u16 min;
u16 max;
};
/**
* struct img_ir_symbol_timing - timing data for a symbol
* @pulse: Timing range for the length of the pulse in this symbol
* @space: Timing range for the length of the space in this symbol
*/
struct img_ir_symbol_timing {
struct img_ir_timing_range pulse;
struct img_ir_timing_range space;
};
/**
* struct img_ir_free_timing - timing data for free time symbol
* @minlen: Minimum number of bits of data
* @maxlen: Maximum number of bits of data
* @ft_min: Minimum free time after message
*/
struct img_ir_free_timing {
/* measured in bits */
u8 minlen;
u8 maxlen;
u16 ft_min;
};
/**
* struct img_ir_timings - Timing values.
* @ldr: Leader symbol timing data
* @s00: Zero symbol timing data for primary decoder
* @s01: One symbol timing data for primary decoder
* @s10: Zero symbol timing data for secondary (no leader symbol) decoder
* @s11: One symbol timing data for secondary (no leader symbol) decoder
* @ft: Free time symbol timing data
*/
struct img_ir_timings {
struct img_ir_symbol_timing ldr, s00, s01, s10, s11;
struct img_ir_free_timing ft;
};
/**
* struct img_ir_filter - Filter IR events.
* @data: Data to match.
* @mask: Mask of bits to compare.
* @minlen: Additional minimum number of bits.
* @maxlen: Additional maximum number of bits.
*/
struct img_ir_filter {
u64 data;
u64 mask;
u8 minlen;
u8 maxlen;
};
/**
* struct img_ir_timing_regvals - Calculated timing register values.
* @ldr: Leader symbol timing register value
* @s00: Zero symbol timing register value for primary decoder
* @s01: One symbol timing register value for primary decoder
* @s10: Zero symbol timing register value for secondary decoder
* @s11: One symbol timing register value for secondary decoder
* @ft: Free time symbol timing register value
*/
struct img_ir_timing_regvals {
u32 ldr, s00, s01, s10, s11, ft;
};
#define IMG_IR_SCANCODE 0 /* new scancode */
#define IMG_IR_REPEATCODE 1 /* repeat the previous code */
/**
* struct img_ir_decoder - Decoder settings for an IR protocol.
* @type: Protocol types bitmap.
* @tolerance: Timing tolerance as a percentage (default 10%).
* @unit: Unit of timings in nanoseconds (default 1 us).
* @timings: Primary timings
* @rtimings: Additional override timings while waiting for repeats.
* @repeat: Maximum repeat interval (always in milliseconds).
* @control: Control flags.
*
* @scancode: Pointer to function to convert the IR data into a scancode (it
* must be safe to execute in interrupt context).
* Returns IMG_IR_SCANCODE to emit new scancode.
* Returns IMG_IR_REPEATCODE to repeat previous code.
* Returns -errno (e.g. -EINVAL) on error.
* @filter: Pointer to function to convert scancode filter to raw hardware
* filter. The minlen and maxlen fields will have been initialised
* to the maximum range.
*/
struct img_ir_decoder {
/* core description */
u64 type;
unsigned int tolerance;
unsigned int unit;
struct img_ir_timings timings;
struct img_ir_timings rtimings;
unsigned int repeat;
struct img_ir_control control;
/* scancode logic */
int (*scancode)(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols);
int (*filter)(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols);
};
extern struct img_ir_decoder img_ir_nec;
extern struct img_ir_decoder img_ir_jvc;
extern struct img_ir_decoder img_ir_sony;
extern struct img_ir_decoder img_ir_sharp;
extern struct img_ir_decoder img_ir_sanyo;
/**
* struct img_ir_reg_timings - Reg values for decoder timings at clock rate.
* @ctrl: Processed control register value.
* @timings: Processed primary timings.
* @rtimings: Processed repeat timings.
*/
struct img_ir_reg_timings {
u32 ctrl;
struct img_ir_timing_regvals timings;
struct img_ir_timing_regvals rtimings;
};
int img_ir_register_decoder(struct img_ir_decoder *dec);
void img_ir_unregister_decoder(struct img_ir_decoder *dec);
struct img_ir_priv;
#ifdef CONFIG_IR_IMG_HW
enum img_ir_mode {
IMG_IR_M_NORMAL,
IMG_IR_M_REPEATING,
#ifdef CONFIG_PM_SLEEP
IMG_IR_M_WAKE,
#endif
};
/**
* struct img_ir_priv_hw - Private driver data for hardware decoder.
* @ct_quirks: Quirk bits for each code type.
* @rdev: Remote control device
* @clk_nb: Notifier block for clock notify events.
* @end_timer: Timer until repeat timeout.
* @decoder: Current decoder settings.
* @enabled_protocols: Currently enabled protocols.
* @clk_hz: Current core clock rate in Hz.
* @reg_timings: Timing reg values for decoder at clock rate.
* @flags: IMG_IR_F_*.
* @filters: HW filters (derived from scancode filters).
* @mode: Current decode mode.
* @stopping: Indicates that decoder is being taken down and timers
* should not be restarted.
* @suspend_irqen: Saved IRQ enable mask over suspend.
*/
struct img_ir_priv_hw {
unsigned int ct_quirks[4];
struct rc_dev *rdev;
struct notifier_block clk_nb;
struct timer_list end_timer;
const struct img_ir_decoder *decoder;
u64 enabled_protocols;
unsigned long clk_hz;
struct img_ir_reg_timings reg_timings;
unsigned int flags;
struct img_ir_filter filters[RC_FILTER_MAX];
enum img_ir_mode mode;
bool stopping;
u32 suspend_irqen;
};
static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
{
return hw->rdev;
};
void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status);
void img_ir_setup_hw(struct img_ir_priv *priv);
int img_ir_probe_hw(struct img_ir_priv *priv);
void img_ir_remove_hw(struct img_ir_priv *priv);
#ifdef CONFIG_PM_SLEEP
int img_ir_suspend(struct device *dev);
int img_ir_resume(struct device *dev);
#else
#define img_ir_suspend NULL
#define img_ir_resume NULL
#endif
#else
struct img_ir_priv_hw {
};
static inline bool img_ir_hw_enabled(struct img_ir_priv_hw *hw)
{
return false;
};
static inline void img_ir_isr_hw(struct img_ir_priv *priv, u32 irq_status)
{
}
static inline void img_ir_setup_hw(struct img_ir_priv *priv)
{
}
static inline int img_ir_probe_hw(struct img_ir_priv *priv)
{
return -ENODEV;
}
static inline void img_ir_remove_hw(struct img_ir_priv *priv)
{
}
#define img_ir_suspend NULL
#define img_ir_resume NULL
#endif /* CONFIG_IR_IMG_HW */
#endif /* _IMG_IR_HW_H_ */

View file

@ -0,0 +1,88 @@
/*
* ImgTec IR Decoder setup for JVC protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "img-ir-hw.h"
/* Convert JVC data to a scancode */
static int img_ir_jvc_scancode(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols)
{
unsigned int cust, data;
if (len != 16)
return -EINVAL;
cust = (raw >> 0) & 0xff;
data = (raw >> 8) & 0xff;
*protocol = RC_TYPE_JVC;
*scancode = cust << 8 | data;
return IMG_IR_SCANCODE;
}
/* Convert JVC scancode to JVC data filter */
static int img_ir_jvc_filter(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols)
{
unsigned int cust, data;
unsigned int cust_m, data_m;
cust = (in->data >> 8) & 0xff;
cust_m = (in->mask >> 8) & 0xff;
data = (in->data >> 0) & 0xff;
data_m = (in->mask >> 0) & 0xff;
out->data = cust | data << 8;
out->mask = cust_m | data_m << 8;
return 0;
}
/*
* JVC decoder
* See also http://www.sbprojects.com/knowledge/ir/jvc.php
* http://support.jvc.com/consumer/support/documents/RemoteCodes.pdf
*/
struct img_ir_decoder img_ir_jvc = {
.type = RC_BIT_JVC,
.control = {
.decoden = 1,
.code_type = IMG_IR_CODETYPE_PULSEDIST,
},
/* main timings */
.unit = 527500, /* 527.5 us */
.timings = {
/* leader symbol */
.ldr = {
.pulse = { 16 /* 8.44 ms */ },
.space = { 8 /* 4.22 ms */ },
},
/* 0 symbol */
.s00 = {
.pulse = { 1 /* 527.5 us +-60 us */ },
.space = { 1 /* 527.5 us */ },
},
/* 1 symbol */
.s01 = {
.pulse = { 1 /* 527.5 us +-60 us */ },
.space = { 3 /* 1.5825 ms +-40 us */ },
},
/* free time */
.ft = {
.minlen = 16,
.maxlen = 16,
.ft_min = 10, /* 5.275 ms */
},
},
/* scancode logic */
.scancode = img_ir_jvc_scancode,
.filter = img_ir_jvc_filter,
};

View file

@ -0,0 +1,158 @@
/*
* ImgTec IR Decoder setup for NEC protocol.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "img-ir-hw.h"
#include <linux/bitrev.h>
/* Convert NEC data to a scancode */
static int img_ir_nec_scancode(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
if (!len)
return IMG_IR_REPEATCODE;
if (len != 32)
return -EINVAL;
/* raw encoding: ddDDaaAA */
addr = (raw >> 0) & 0xff;
addr_inv = (raw >> 8) & 0xff;
data = (raw >> 16) & 0xff;
data_inv = (raw >> 24) & 0xff;
if ((data_inv ^ data) != 0xff) {
/* 32-bit NEC (used by Apple and TiVo remotes) */
/* scan encoding: as transmitted, MSBit = first received bit */
*scancode = bitrev8(addr) << 24 |
bitrev8(addr_inv) << 16 |
bitrev8(data) << 8 |
bitrev8(data_inv);
} else if ((addr_inv ^ addr) != 0xff) {
/* Extended NEC */
/* scan encoding: AAaaDD */
*scancode = addr << 16 |
addr_inv << 8 |
data;
} else {
/* Normal NEC */
/* scan encoding: AADD */
*scancode = addr << 8 |
data;
}
*protocol = RC_TYPE_NEC;
return IMG_IR_SCANCODE;
}
/* Convert NEC scancode to NEC data filter */
static int img_ir_nec_filter(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols)
{
unsigned int addr, addr_inv, data, data_inv;
unsigned int addr_m, addr_inv_m, data_m, data_inv_m;
data = in->data & 0xff;
data_m = in->mask & 0xff;
if ((in->data | in->mask) & 0xff000000) {
/* 32-bit NEC (used by Apple and TiVo remotes) */
/* scan encoding: as transmitted, MSBit = first received bit */
addr = bitrev8(in->data >> 24);
addr_m = bitrev8(in->mask >> 24);
addr_inv = bitrev8(in->data >> 16);
addr_inv_m = bitrev8(in->mask >> 16);
data = bitrev8(in->data >> 8);
data_m = bitrev8(in->mask >> 8);
data_inv = bitrev8(in->data >> 0);
data_inv_m = bitrev8(in->mask >> 0);
} else if ((in->data | in->mask) & 0x00ff0000) {
/* Extended NEC */
/* scan encoding AAaaDD */
addr = (in->data >> 16) & 0xff;
addr_m = (in->mask >> 16) & 0xff;
addr_inv = (in->data >> 8) & 0xff;
addr_inv_m = (in->mask >> 8) & 0xff;
data_inv = data ^ 0xff;
data_inv_m = data_m;
} else {
/* Normal NEC */
/* scan encoding: AADD */
addr = (in->data >> 8) & 0xff;
addr_m = (in->mask >> 8) & 0xff;
addr_inv = addr ^ 0xff;
addr_inv_m = addr_m;
data_inv = data ^ 0xff;
data_inv_m = data_m;
}
/* raw encoding: ddDDaaAA */
out->data = data_inv << 24 |
data << 16 |
addr_inv << 8 |
addr;
out->mask = data_inv_m << 24 |
data_m << 16 |
addr_inv_m << 8 |
addr_m;
return 0;
}
/*
* NEC decoder
* See also http://www.sbprojects.com/knowledge/ir/nec.php
* http://wiki.altium.com/display/ADOH/NEC+Infrared+Transmission+Protocol
*/
struct img_ir_decoder img_ir_nec = {
.type = RC_BIT_NEC,
.control = {
.decoden = 1,
.code_type = IMG_IR_CODETYPE_PULSEDIST,
},
/* main timings */
.unit = 562500, /* 562.5 us */
.timings = {
/* leader symbol */
.ldr = {
.pulse = { 16 /* 9ms */ },
.space = { 8 /* 4.5ms */ },
},
/* 0 symbol */
.s00 = {
.pulse = { 1 /* 562.5 us */ },
.space = { 1 /* 562.5 us */ },
},
/* 1 symbol */
.s01 = {
.pulse = { 1 /* 562.5 us */ },
.space = { 3 /* 1687.5 us */ },
},
/* free time */
.ft = {
.minlen = 32,
.maxlen = 32,
.ft_min = 10, /* 5.625 ms */
},
},
/* repeat codes */
.repeat = 108, /* 108 ms */
.rtimings = {
/* leader symbol */
.ldr = {
.space = { 4 /* 2.25 ms */ },
},
/* free time */
.ft = {
.minlen = 0, /* repeat code has no data */
.maxlen = 0,
},
},
/* scancode logic */
.scancode = img_ir_nec_scancode,
.filter = img_ir_nec_filter,
};

View file

@ -0,0 +1,156 @@
/*
* ImgTec IR Raw Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This ties into the input subsystem using the RC-core in raw mode. Raw IR
* signal edges are reported and decoded by generic software decoders.
*/
#include <linux/spinlock.h>
#include <media/rc-core.h>
#include "img-ir.h"
#define ECHO_TIMEOUT_MS 150 /* ms between echos */
/* must be called with priv->lock held */
static void img_ir_refresh_raw(struct img_ir_priv *priv, u32 irq_status)
{
struct img_ir_priv_raw *raw = &priv->raw;
struct rc_dev *rc_dev = priv->raw.rdev;
int multiple;
u32 ir_status;
/* find whether both rise and fall was detected */
multiple = ((irq_status & IMG_IR_IRQ_EDGE) == IMG_IR_IRQ_EDGE);
/*
* If so, we need to see if the level has actually changed.
* If it's just noise that we didn't have time to process,
* there's no point reporting it.
*/
ir_status = img_ir_read(priv, IMG_IR_STATUS) & IMG_IR_IRRXD;
if (multiple && ir_status == raw->last_status)
return;
raw->last_status = ir_status;
/* report the edge to the IR raw decoders */
if (ir_status) /* low */
ir_raw_event_store_edge(rc_dev, IR_SPACE);
else /* high */
ir_raw_event_store_edge(rc_dev, IR_PULSE);
ir_raw_event_handle(rc_dev);
}
/* called with priv->lock held */
void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
{
struct img_ir_priv_raw *raw = &priv->raw;
/* check not removing */
if (!raw->rdev)
return;
img_ir_refresh_raw(priv, irq_status);
/* start / push back the echo timer */
mod_timer(&raw->timer, jiffies + msecs_to_jiffies(ECHO_TIMEOUT_MS));
}
/*
* Echo timer callback function.
* The raw decoders expect to get a final sample even if there are no edges, in
* order to be assured of the final space. If there are no edges for a certain
* time we use this timer to emit a final sample to satisfy them.
*/
static void img_ir_echo_timer(unsigned long arg)
{
struct img_ir_priv *priv = (struct img_ir_priv *)arg;
spin_lock_irq(&priv->lock);
/* check not removing */
if (priv->raw.rdev)
/*
* It's safe to pass irq_status=0 since it's only used to check
* for double edges.
*/
img_ir_refresh_raw(priv, 0);
spin_unlock_irq(&priv->lock);
}
void img_ir_setup_raw(struct img_ir_priv *priv)
{
u32 irq_en;
if (!priv->raw.rdev)
return;
/* clear and enable edge interrupts */
spin_lock_irq(&priv->lock);
irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
irq_en |= IMG_IR_IRQ_EDGE;
img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
spin_unlock_irq(&priv->lock);
}
int img_ir_probe_raw(struct img_ir_priv *priv)
{
struct img_ir_priv_raw *raw = &priv->raw;
struct rc_dev *rdev;
int error;
/* Set up the echo timer */
setup_timer(&raw->timer, img_ir_echo_timer, (unsigned long)priv);
/* Allocate raw decoder */
raw->rdev = rdev = rc_allocate_device();
if (!rdev) {
dev_err(priv->dev, "cannot allocate raw input device\n");
return -ENOMEM;
}
rdev->priv = priv;
rdev->map_name = RC_MAP_EMPTY;
rdev->input_name = "IMG Infrared Decoder Raw";
rdev->driver_type = RC_DRIVER_IR_RAW;
/* Register raw decoder */
error = rc_register_device(rdev);
if (error) {
dev_err(priv->dev, "failed to register raw IR input device\n");
rc_free_device(rdev);
raw->rdev = NULL;
return error;
}
return 0;
}
void img_ir_remove_raw(struct img_ir_priv *priv)
{
struct img_ir_priv_raw *raw = &priv->raw;
struct rc_dev *rdev = raw->rdev;
u32 irq_en;
if (!rdev)
return;
/* switch off and disable raw (edge) interrupts */
spin_lock_irq(&priv->lock);
raw->rdev = NULL;
irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
irq_en &= ~IMG_IR_IRQ_EDGE;
img_ir_write(priv, IMG_IR_IRQ_ENABLE, irq_en);
img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
spin_unlock_irq(&priv->lock);
rc_unregister_device(rdev);
del_timer_sync(&raw->timer);
}

View file

@ -0,0 +1,65 @@
/*
* ImgTec IR Raw Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _IMG_IR_RAW_H_
#define _IMG_IR_RAW_H_
struct img_ir_priv;
#ifdef CONFIG_IR_IMG_RAW
/**
* struct img_ir_priv_raw - Private driver data for raw decoder.
* @rdev: Raw remote control device
* @timer: Timer to echo samples to keep soft decoders happy.
* @last_status: Last raw status bits.
*/
struct img_ir_priv_raw {
struct rc_dev *rdev;
struct timer_list timer;
u32 last_status;
};
static inline bool img_ir_raw_enabled(struct img_ir_priv_raw *raw)
{
return raw->rdev;
};
void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status);
void img_ir_setup_raw(struct img_ir_priv *priv);
int img_ir_probe_raw(struct img_ir_priv *priv);
void img_ir_remove_raw(struct img_ir_priv *priv);
#else
struct img_ir_priv_raw {
};
static inline bool img_ir_raw_enabled(struct img_ir_priv_raw *raw)
{
return false;
};
static inline void img_ir_isr_raw(struct img_ir_priv *priv, u32 irq_status)
{
}
static inline void img_ir_setup_raw(struct img_ir_priv *priv)
{
}
static inline int img_ir_probe_raw(struct img_ir_priv *priv)
{
return -ENODEV;
}
static inline void img_ir_remove_raw(struct img_ir_priv *priv)
{
}
#endif /* CONFIG_IR_IMG_RAW */
#endif /* _IMG_IR_RAW_H_ */

View file

@ -0,0 +1,129 @@
/*
* ImgTec IR Decoder setup for Sanyo protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* From ir-sanyo-decoder.c:
*
* This protocol uses the NEC protocol timings. However, data is formatted as:
* 13 bits Custom Code
* 13 bits NOT(Custom Code)
* 8 bits Key data
* 8 bits NOT(Key data)
*
* According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
* Information for this protocol is available at the Sanyo LC7461 datasheet.
*/
#include "img-ir-hw.h"
/* Convert Sanyo data to a scancode */
static int img_ir_sanyo_scancode(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, addr_inv, data, data_inv;
/* a repeat code has no data */
if (!len)
return IMG_IR_REPEATCODE;
if (len != 42)
return -EINVAL;
addr = (raw >> 0) & 0x1fff;
addr_inv = (raw >> 13) & 0x1fff;
data = (raw >> 26) & 0xff;
data_inv = (raw >> 34) & 0xff;
/* Validate data */
if ((data_inv ^ data) != 0xff)
return -EINVAL;
/* Validate address */
if ((addr_inv ^ addr) != 0x1fff)
return -EINVAL;
/* Normal Sanyo */
*protocol = RC_TYPE_SANYO;
*scancode = addr << 8 | data;
return IMG_IR_SCANCODE;
}
/* Convert Sanyo scancode to Sanyo data filter */
static int img_ir_sanyo_filter(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols)
{
unsigned int addr, addr_inv, data, data_inv;
unsigned int addr_m, data_m;
data = in->data & 0xff;
data_m = in->mask & 0xff;
data_inv = data ^ 0xff;
if (in->data & 0xff700000)
return -EINVAL;
addr = (in->data >> 8) & 0x1fff;
addr_m = (in->mask >> 8) & 0x1fff;
addr_inv = addr ^ 0x1fff;
out->data = (u64)data_inv << 34 |
(u64)data << 26 |
addr_inv << 13 |
addr;
out->mask = (u64)data_m << 34 |
(u64)data_m << 26 |
addr_m << 13 |
addr_m;
return 0;
}
/* Sanyo decoder */
struct img_ir_decoder img_ir_sanyo = {
.type = RC_BIT_SANYO,
.control = {
.decoden = 1,
.code_type = IMG_IR_CODETYPE_PULSEDIST,
},
/* main timings */
.unit = 562500, /* 562.5 us */
.timings = {
/* leader symbol */
.ldr = {
.pulse = { 16 /* 9ms */ },
.space = { 8 /* 4.5ms */ },
},
/* 0 symbol */
.s00 = {
.pulse = { 1 /* 562.5 us */ },
.space = { 1 /* 562.5 us */ },
},
/* 1 symbol */
.s01 = {
.pulse = { 1 /* 562.5 us */ },
.space = { 3 /* 1687.5 us */ },
},
/* free time */
.ft = {
.minlen = 42,
.maxlen = 42,
.ft_min = 10, /* 5.625 ms */
},
},
/* repeat codes */
.repeat = 108, /* 108 ms */
.rtimings = {
/* leader symbol */
.ldr = {
.space = { 4 /* 2.25 ms */ },
},
/* free time */
.ft = {
.minlen = 0, /* repeat code has no data */
.maxlen = 0,
},
},
/* scancode logic */
.scancode = img_ir_sanyo_scancode,
.filter = img_ir_sanyo_filter,
};

View file

@ -0,0 +1,106 @@
/*
* ImgTec IR Decoder setup for Sharp protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sharp data to a scancode */
static int img_ir_sharp_scancode(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols)
{
unsigned int addr, cmd, exp, chk;
if (len != 15)
return -EINVAL;
addr = (raw >> 0) & 0x1f;
cmd = (raw >> 5) & 0xff;
exp = (raw >> 13) & 0x1;
chk = (raw >> 14) & 0x1;
/* validate data */
if (!exp)
return -EINVAL;
if (chk)
/* probably the second half of the message */
return -EINVAL;
*protocol = RC_TYPE_SHARP;
*scancode = addr << 8 | cmd;
return IMG_IR_SCANCODE;
}
/* Convert Sharp scancode to Sharp data filter */
static int img_ir_sharp_filter(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols)
{
unsigned int addr, cmd, exp = 0, chk = 0;
unsigned int addr_m, cmd_m, exp_m = 0, chk_m = 0;
addr = (in->data >> 8) & 0x1f;
addr_m = (in->mask >> 8) & 0x1f;
cmd = (in->data >> 0) & 0xff;
cmd_m = (in->mask >> 0) & 0xff;
if (cmd_m) {
/* if filtering commands, we can only match the first part */
exp = 1;
exp_m = 1;
chk = 0;
chk_m = 1;
}
out->data = addr |
cmd << 5 |
exp << 13 |
chk << 14;
out->mask = addr_m |
cmd_m << 5 |
exp_m << 13 |
chk_m << 14;
return 0;
}
/*
* Sharp decoder
* See also http://www.sbprojects.com/knowledge/ir/sharp.php
*/
struct img_ir_decoder img_ir_sharp = {
.type = RC_BIT_SHARP,
.control = {
.decoden = 0,
.decodend2 = 1,
.code_type = IMG_IR_CODETYPE_PULSEDIST,
.d1validsel = 1,
},
/* main timings */
.tolerance = 20, /* 20% */
.timings = {
/* 0 symbol */
.s10 = {
.pulse = { 320 /* 320 us */ },
.space = { 680 /* 1 ms period */ },
},
/* 1 symbol */
.s11 = {
.pulse = { 320 /* 320 us */ },
.space = { 1680 /* 2 ms period */ },
},
/* free time */
.ft = {
.minlen = 15,
.maxlen = 15,
.ft_min = 5000, /* 5 ms */
},
},
/* scancode logic */
.scancode = img_ir_sharp_scancode,
.filter = img_ir_sharp_filter,
};

View file

@ -0,0 +1,154 @@
/*
* ImgTec IR Decoder setup for Sony (SIRC) protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include "img-ir-hw.h"
/* Convert Sony data to a scancode */
static int img_ir_sony_scancode(int len, u64 raw, enum rc_type *protocol,
u32 *scancode, u64 enabled_protocols)
{
unsigned int dev, subdev, func;
switch (len) {
case 12:
if (!(enabled_protocols & RC_BIT_SONY12))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
subdev = 0;
*protocol = RC_TYPE_SONY12;
break;
case 15:
if (!(enabled_protocols & RC_BIT_SONY15))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0xff; /* next 8 bits */
subdev = 0;
*protocol = RC_TYPE_SONY15;
break;
case 20:
if (!(enabled_protocols & RC_BIT_SONY20))
return -EINVAL;
func = raw & 0x7f; /* first 7 bits */
raw >>= 7;
dev = raw & 0x1f; /* next 5 bits */
raw >>= 5;
subdev = raw & 0xff; /* next 8 bits */
*protocol = RC_TYPE_SONY20;
break;
default:
return -EINVAL;
}
*scancode = dev << 16 | subdev << 8 | func;
return IMG_IR_SCANCODE;
}
/* Convert NEC scancode to NEC data filter */
static int img_ir_sony_filter(const struct rc_scancode_filter *in,
struct img_ir_filter *out, u64 protocols)
{
unsigned int dev, subdev, func;
unsigned int dev_m, subdev_m, func_m;
unsigned int len = 0;
dev = (in->data >> 16) & 0xff;
dev_m = (in->mask >> 16) & 0xff;
subdev = (in->data >> 8) & 0xff;
subdev_m = (in->mask >> 8) & 0xff;
func = (in->data >> 0) & 0x7f;
func_m = (in->mask >> 0) & 0x7f;
if (subdev & subdev_m) {
/* can't encode subdev and higher device bits */
if (dev & dev_m & 0xe0)
return -EINVAL;
/* subdevice (extended) bits only in 20 bit encoding */
if (!(protocols & RC_BIT_SONY20))
return -EINVAL;
len = 20;
dev_m &= 0x1f;
} else if (dev & dev_m & 0xe0) {
/* upper device bits only in 15 bit encoding */
if (!(protocols & RC_BIT_SONY15))
return -EINVAL;
len = 15;
subdev_m = 0;
} else {
/*
* The hardware mask cannot distinguish high device bits and low
* extended bits, so logically AND those bits of the masks
* together.
*/
subdev_m &= (dev_m >> 5) | 0xf8;
dev_m &= 0x1f;
}
/* ensure there aren't any bits straying between fields */
dev &= dev_m;
subdev &= subdev_m;
/* write the hardware filter */
out->data = func |
dev << 7 |
subdev << 15;
out->mask = func_m |
dev_m << 7 |
subdev_m << 15;
if (len) {
out->minlen = len;
out->maxlen = len;
}
return 0;
}
/*
* Sony SIRC decoder
* See also http://www.sbprojects.com/knowledge/ir/sirc.php
* http://picprojects.org.uk/projects/sirc/sonysirc.pdf
*/
struct img_ir_decoder img_ir_sony = {
.type = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
.control = {
.decoden = 1,
.code_type = IMG_IR_CODETYPE_PULSELEN,
},
/* main timings */
.unit = 600000, /* 600 us */
.timings = {
/* leader symbol */
.ldr = {
.pulse = { 4 /* 2.4 ms */ },
.space = { 1 /* 600 us */ },
},
/* 0 symbol */
.s00 = {
.pulse = { 1 /* 600 us */ },
.space = { 1 /* 600 us */ },
},
/* 1 symbol */
.s01 = {
.pulse = { 2 /* 1.2 ms */ },
.space = { 1 /* 600 us */ },
},
/* free time */
.ft = {
.minlen = 12,
.maxlen = 20,
.ft_min = 10, /* 6 ms */
},
},
/* scancode logic */
.scancode = img_ir_sony_scancode,
.filter = img_ir_sony_filter,
};

View file

@ -0,0 +1,171 @@
/*
* ImgTec IR Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef _IMG_IR_H_
#define _IMG_IR_H_
#include <linux/io.h>
#include <linux/spinlock.h>
#include "img-ir-raw.h"
#include "img-ir-hw.h"
/* registers */
/* relative to the start of the IR block of registers */
#define IMG_IR_CONTROL 0x00
#define IMG_IR_STATUS 0x04
#define IMG_IR_DATA_LW 0x08
#define IMG_IR_DATA_UP 0x0c
#define IMG_IR_LEAD_SYMB_TIMING 0x10
#define IMG_IR_S00_SYMB_TIMING 0x14
#define IMG_IR_S01_SYMB_TIMING 0x18
#define IMG_IR_S10_SYMB_TIMING 0x1c
#define IMG_IR_S11_SYMB_TIMING 0x20
#define IMG_IR_FREE_SYMB_TIMING 0x24
#define IMG_IR_POW_MOD_PARAMS 0x28
#define IMG_IR_POW_MOD_ENABLE 0x2c
#define IMG_IR_IRQ_MSG_DATA_LW 0x30
#define IMG_IR_IRQ_MSG_DATA_UP 0x34
#define IMG_IR_IRQ_MSG_MASK_LW 0x38
#define IMG_IR_IRQ_MSG_MASK_UP 0x3c
#define IMG_IR_IRQ_ENABLE 0x40
#define IMG_IR_IRQ_STATUS 0x44
#define IMG_IR_IRQ_CLEAR 0x48
#define IMG_IR_IRCORE_ID 0xf0
#define IMG_IR_CORE_REV 0xf4
#define IMG_IR_CORE_DES1 0xf8
#define IMG_IR_CORE_DES2 0xfc
/* field masks */
/* IMG_IR_CONTROL */
#define IMG_IR_DECODEN 0x40000000
#define IMG_IR_CODETYPE 0x30000000
#define IMG_IR_CODETYPE_SHIFT 28
#define IMG_IR_HDRTOG 0x08000000
#define IMG_IR_LDRDEC 0x04000000
#define IMG_IR_DECODINPOL 0x02000000 /* active high */
#define IMG_IR_BITORIEN 0x01000000 /* MSB first */
#define IMG_IR_D1VALIDSEL 0x00008000
#define IMG_IR_BITINV 0x00000040 /* don't invert */
#define IMG_IR_DECODEND2 0x00000010
#define IMG_IR_BITORIEND2 0x00000002 /* MSB first */
#define IMG_IR_BITINVD2 0x00000001 /* don't invert */
/* IMG_IR_STATUS */
#define IMG_IR_RXDVALD2 0x00001000
#define IMG_IR_IRRXD 0x00000400
#define IMG_IR_TOGSTATE 0x00000200
#define IMG_IR_RXDVAL 0x00000040
#define IMG_IR_RXDLEN 0x0000003f
#define IMG_IR_RXDLEN_SHIFT 0
/* IMG_IR_LEAD_SYMB_TIMING, IMG_IR_Sxx_SYMB_TIMING */
#define IMG_IR_PD_MAX 0xff000000
#define IMG_IR_PD_MAX_SHIFT 24
#define IMG_IR_PD_MIN 0x00ff0000
#define IMG_IR_PD_MIN_SHIFT 16
#define IMG_IR_W_MAX 0x0000ff00
#define IMG_IR_W_MAX_SHIFT 8
#define IMG_IR_W_MIN 0x000000ff
#define IMG_IR_W_MIN_SHIFT 0
/* IMG_IR_FREE_SYMB_TIMING */
#define IMG_IR_MAXLEN 0x0007e000
#define IMG_IR_MAXLEN_SHIFT 13
#define IMG_IR_MINLEN 0x00001f00
#define IMG_IR_MINLEN_SHIFT 8
#define IMG_IR_FT_MIN 0x000000ff
#define IMG_IR_FT_MIN_SHIFT 0
/* IMG_IR_POW_MOD_PARAMS */
#define IMG_IR_PERIOD_LEN 0x3f000000
#define IMG_IR_PERIOD_LEN_SHIFT 24
#define IMG_IR_PERIOD_DUTY 0x003f0000
#define IMG_IR_PERIOD_DUTY_SHIFT 16
#define IMG_IR_STABLE_STOP 0x00003f00
#define IMG_IR_STABLE_STOP_SHIFT 8
#define IMG_IR_STABLE_START 0x0000003f
#define IMG_IR_STABLE_START_SHIFT 0
/* IMG_IR_POW_MOD_ENABLE */
#define IMG_IR_POWER_OUT_EN 0x00000002
#define IMG_IR_POWER_MOD_EN 0x00000001
/* IMG_IR_IRQ_ENABLE, IMG_IR_IRQ_STATUS, IMG_IR_IRQ_CLEAR */
#define IMG_IR_IRQ_DEC2_ERR 0x00000080
#define IMG_IR_IRQ_DEC_ERR 0x00000040
#define IMG_IR_IRQ_ACT_LEVEL 0x00000020
#define IMG_IR_IRQ_FALL_EDGE 0x00000010
#define IMG_IR_IRQ_RISE_EDGE 0x00000008
#define IMG_IR_IRQ_DATA_MATCH 0x00000004
#define IMG_IR_IRQ_DATA2_VALID 0x00000002
#define IMG_IR_IRQ_DATA_VALID 0x00000001
#define IMG_IR_IRQ_ALL 0x000000ff
#define IMG_IR_IRQ_EDGE (IMG_IR_IRQ_FALL_EDGE | IMG_IR_IRQ_RISE_EDGE)
/* IMG_IR_CORE_ID */
#define IMG_IR_CORE_ID 0x00ff0000
#define IMG_IR_CORE_ID_SHIFT 16
#define IMG_IR_CORE_CONFIG 0x0000ffff
#define IMG_IR_CORE_CONFIG_SHIFT 0
/* IMG_IR_CORE_REV */
#define IMG_IR_DESIGNER 0xff000000
#define IMG_IR_DESIGNER_SHIFT 24
#define IMG_IR_MAJOR_REV 0x00ff0000
#define IMG_IR_MAJOR_REV_SHIFT 16
#define IMG_IR_MINOR_REV 0x0000ff00
#define IMG_IR_MINOR_REV_SHIFT 8
#define IMG_IR_MAINT_REV 0x000000ff
#define IMG_IR_MAINT_REV_SHIFT 0
struct device;
struct clk;
/**
* struct img_ir_priv - Private driver data.
* @dev: Platform device.
* @irq: IRQ number.
* @clk: Input clock.
* @reg_base: Iomem base address of IR register block.
* @lock: Protects IR registers and variables in this struct.
* @raw: Driver data for raw decoder.
* @hw: Driver data for hardware decoder.
*/
struct img_ir_priv {
struct device *dev;
int irq;
struct clk *clk;
void __iomem *reg_base;
spinlock_t lock;
struct img_ir_priv_raw raw;
struct img_ir_priv_hw hw;
};
/* Hardware access */
static inline void img_ir_write(struct img_ir_priv *priv,
unsigned int reg_offs, unsigned int data)
{
iowrite32(data, priv->reg_base + reg_offs);
}
static inline unsigned int img_ir_read(struct img_ir_priv *priv,
unsigned int reg_offs)
{
return ioread32(priv->reg_base + reg_offs);
}
#endif /* _IMG_IR_H_ */

2591
drivers/media/rc/imon.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,351 @@
/*
* Copyright (c) 2014 Linaro Ltd.
* Copyright (c) 2014 Hisilicon Limited.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <media/rc-core.h>
/* Allow the driver to compile on all architectures */
#ifndef writel_relaxed
# define writel_relaxed writel
#endif
#ifndef readl_relaxed
# define readl_relaxed readl
#endif
#define IR_ENABLE 0x00
#define IR_CONFIG 0x04
#define CNT_LEADS 0x08
#define CNT_LEADE 0x0c
#define CNT_SLEADE 0x10
#define CNT0_B 0x14
#define CNT1_B 0x18
#define IR_BUSY 0x1c
#define IR_DATAH 0x20
#define IR_DATAL 0x24
#define IR_INTM 0x28
#define IR_INTS 0x2c
#define IR_INTC 0x30
#define IR_START 0x34
/* interrupt mask */
#define INTMS_SYMBRCV (BIT(24) | BIT(8))
#define INTMS_TIMEOUT (BIT(25) | BIT(9))
#define INTMS_OVERFLOW (BIT(26) | BIT(10))
#define INT_CLR_OVERFLOW BIT(18)
#define INT_CLR_TIMEOUT BIT(17)
#define INT_CLR_RCV BIT(16)
#define INT_CLR_RCVTIMEOUT (BIT(16) | BIT(17))
#define IR_CLK 0x48
#define IR_CLK_ENABLE BIT(4)
#define IR_CLK_RESET BIT(5)
#define IR_CFG_WIDTH_MASK 0xffff
#define IR_CFG_WIDTH_SHIFT 16
#define IR_CFG_FORMAT_MASK 0x3
#define IR_CFG_FORMAT_SHIFT 14
#define IR_CFG_INT_LEVEL_MASK 0x3f
#define IR_CFG_INT_LEVEL_SHIFT 8
/* only support raw mode */
#define IR_CFG_MODE_RAW BIT(7)
#define IR_CFG_FREQ_MASK 0x7f
#define IR_CFG_FREQ_SHIFT 0
#define IR_CFG_INT_THRESHOLD 1
/* symbol start from low to high, symbol stream end at high*/
#define IR_CFG_SYMBOL_FMT 0
#define IR_CFG_SYMBOL_MAXWIDTH 0x3e80
#define IR_HIX5HD2_NAME "hix5hd2-ir"
struct hix5hd2_ir_priv {
int irq;
void volatile __iomem *base;
struct device *dev;
struct rc_dev *rdev;
struct regmap *regmap;
struct clk *clock;
unsigned long rate;
};
static void hix5hd2_ir_enable(struct hix5hd2_ir_priv *dev, bool on)
{
u32 val;
regmap_read(dev->regmap, IR_CLK, &val);
if (on) {
val &= ~IR_CLK_RESET;
val |= IR_CLK_ENABLE;
} else {
val &= ~IR_CLK_ENABLE;
val |= IR_CLK_RESET;
}
regmap_write(dev->regmap, IR_CLK, val);
}
static int hix5hd2_ir_config(struct hix5hd2_ir_priv *priv)
{
int timeout = 10000;
u32 val, rate;
writel_relaxed(0x01, priv->base + IR_ENABLE);
while (readl_relaxed(priv->base + IR_BUSY)) {
if (timeout--) {
udelay(1);
} else {
dev_err(priv->dev, "IR_BUSY timeout\n");
return -ETIMEDOUT;
}
}
/* Now only support raw mode, with symbol start from low to high */
rate = DIV_ROUND_CLOSEST(priv->rate, 1000000);
val = IR_CFG_SYMBOL_MAXWIDTH & IR_CFG_WIDTH_MASK << IR_CFG_WIDTH_SHIFT;
val |= IR_CFG_SYMBOL_FMT & IR_CFG_FORMAT_MASK << IR_CFG_FORMAT_SHIFT;
val |= (IR_CFG_INT_THRESHOLD - 1) & IR_CFG_INT_LEVEL_MASK
<< IR_CFG_INT_LEVEL_SHIFT;
val |= IR_CFG_MODE_RAW;
val |= (rate - 1) & IR_CFG_FREQ_MASK << IR_CFG_FREQ_SHIFT;
writel_relaxed(val, priv->base + IR_CONFIG);
writel_relaxed(0x00, priv->base + IR_INTM);
/* write arbitrary value to start */
writel_relaxed(0x01, priv->base + IR_START);
return 0;
}
static int hix5hd2_ir_open(struct rc_dev *rdev)
{
struct hix5hd2_ir_priv *priv = rdev->priv;
hix5hd2_ir_enable(priv, true);
return hix5hd2_ir_config(priv);
}
static void hix5hd2_ir_close(struct rc_dev *rdev)
{
struct hix5hd2_ir_priv *priv = rdev->priv;
hix5hd2_ir_enable(priv, false);
}
static irqreturn_t hix5hd2_ir_rx_interrupt(int irq, void *data)
{
u32 symb_num, symb_val, symb_time;
u32 data_l, data_h;
u32 irq_sr, i;
struct hix5hd2_ir_priv *priv = data;
irq_sr = readl_relaxed(priv->base + IR_INTS);
if (irq_sr & INTMS_OVERFLOW) {
/*
* we must read IR_DATAL first, then we can clean up
* IR_INTS availably since logic would not clear
* fifo when overflow, drv do the job
*/
ir_raw_event_reset(priv->rdev);
symb_num = readl_relaxed(priv->base + IR_DATAH);
for (i = 0; i < symb_num; i++)
readl_relaxed(priv->base + IR_DATAL);
writel_relaxed(INT_CLR_OVERFLOW, priv->base + IR_INTC);
dev_info(priv->dev, "overflow, level=%d\n",
IR_CFG_INT_THRESHOLD);
}
if ((irq_sr & INTMS_SYMBRCV) || (irq_sr & INTMS_TIMEOUT)) {
DEFINE_IR_RAW_EVENT(ev);
symb_num = readl_relaxed(priv->base + IR_DATAH);
for (i = 0; i < symb_num; i++) {
symb_val = readl_relaxed(priv->base + IR_DATAL);
data_l = ((symb_val & 0xffff) * 10);
data_h = ((symb_val >> 16) & 0xffff) * 10;
symb_time = (data_l + data_h) / 10;
ev.duration = US_TO_NS(data_l);
ev.pulse = true;
ir_raw_event_store(priv->rdev, &ev);
if (symb_time < IR_CFG_SYMBOL_MAXWIDTH) {
ev.duration = US_TO_NS(data_h);
ev.pulse = false;
ir_raw_event_store(priv->rdev, &ev);
} else {
ir_raw_event_set_idle(priv->rdev, true);
}
}
if (irq_sr & INTMS_SYMBRCV)
writel_relaxed(INT_CLR_RCV, priv->base + IR_INTC);
if (irq_sr & INTMS_TIMEOUT)
writel_relaxed(INT_CLR_TIMEOUT, priv->base + IR_INTC);
}
/* Empty software fifo */
ir_raw_event_handle(priv->rdev);
return IRQ_HANDLED;
}
static int hix5hd2_ir_probe(struct platform_device *pdev)
{
struct rc_dev *rdev;
struct device *dev = &pdev->dev;
struct resource *res;
struct hix5hd2_ir_priv *priv;
struct device_node *node = pdev->dev.of_node;
const char *map_name;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->regmap = syscon_regmap_lookup_by_phandle(node,
"hisilicon,power-syscon");
if (IS_ERR(priv->regmap)) {
dev_err(dev, "no power-reg\n");
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
if (IS_ERR((__force void *)priv->base))
return PTR_ERR((__force void *)priv->base);
priv->irq = platform_get_irq(pdev, 0);
if (priv->irq < 0) {
dev_err(dev, "irq can not get\n");
return priv->irq;
}
rdev = rc_allocate_device();
if (!rdev)
return -ENOMEM;
priv->clock = devm_clk_get(dev, NULL);
if (IS_ERR(priv->clock)) {
dev_err(dev, "clock not found\n");
ret = PTR_ERR(priv->clock);
goto err;
}
clk_prepare_enable(priv->clock);
priv->rate = clk_get_rate(priv->clock);
rdev->driver_type = RC_DRIVER_IR_RAW;
rdev->allowed_protocols = RC_BIT_ALL;
rdev->priv = priv;
rdev->open = hix5hd2_ir_open;
rdev->close = hix5hd2_ir_close;
rdev->driver_name = IR_HIX5HD2_NAME;
map_name = of_get_property(node, "linux,rc-map-name", NULL);
rdev->map_name = map_name ?: RC_MAP_EMPTY;
rdev->input_name = IR_HIX5HD2_NAME;
rdev->input_phys = IR_HIX5HD2_NAME "/input0";
rdev->input_id.bustype = BUS_HOST;
rdev->input_id.vendor = 0x0001;
rdev->input_id.product = 0x0001;
rdev->input_id.version = 0x0100;
rdev->rx_resolution = US_TO_NS(10);
rdev->timeout = US_TO_NS(IR_CFG_SYMBOL_MAXWIDTH * 10);
ret = rc_register_device(rdev);
if (ret < 0)
goto clkerr;
if (devm_request_irq(dev, priv->irq, hix5hd2_ir_rx_interrupt,
IRQF_NO_SUSPEND, pdev->name, priv) < 0) {
dev_err(dev, "IRQ %d register failed\n", priv->irq);
ret = -EINVAL;
goto regerr;
}
priv->rdev = rdev;
priv->dev = dev;
platform_set_drvdata(pdev, priv);
return ret;
regerr:
rc_unregister_device(rdev);
rdev = NULL;
clkerr:
clk_disable_unprepare(priv->clock);
err:
rc_free_device(rdev);
dev_err(dev, "Unable to register device (%d)\n", ret);
return ret;
}
static int hix5hd2_ir_remove(struct platform_device *pdev)
{
struct hix5hd2_ir_priv *priv = platform_get_drvdata(pdev);
clk_disable_unprepare(priv->clock);
rc_unregister_device(priv->rdev);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int hix5hd2_ir_suspend(struct device *dev)
{
struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
clk_disable_unprepare(priv->clock);
hix5hd2_ir_enable(priv, false);
return 0;
}
static int hix5hd2_ir_resume(struct device *dev)
{
struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
hix5hd2_ir_enable(priv, true);
clk_prepare_enable(priv->clock);
writel_relaxed(0x01, priv->base + IR_ENABLE);
writel_relaxed(0x00, priv->base + IR_INTM);
writel_relaxed(0xff, priv->base + IR_INTC);
writel_relaxed(0x01, priv->base + IR_START);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(hix5hd2_ir_pm_ops, hix5hd2_ir_suspend,
hix5hd2_ir_resume);
static struct of_device_id hix5hd2_ir_table[] = {
{ .compatible = "hisilicon,hix5hd2-ir", },
{},
};
MODULE_DEVICE_TABLE(of, hix5hd2_ir_table);
static struct platform_driver hix5hd2_ir_driver = {
.driver = {
.name = IR_HIX5HD2_NAME,
.of_match_table = hix5hd2_ir_table,
.pm = &hix5hd2_ir_pm_ops,
},
.probe = hix5hd2_ir_probe,
.remove = hix5hd2_ir_remove,
};
module_platform_driver(hix5hd2_ir_driver);
MODULE_DESCRIPTION("IR controller driver for hix5hd2 platforms");
MODULE_AUTHOR("Guoxiong Yan <yanguoxiong@huawei.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:hix5hd2-ir");

View file

@ -0,0 +1,199 @@
/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
*
* Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"
#define JVC_NBITS 16 /* dev(8) + func(8) */
#define JVC_UNIT 525000 /* ns */
#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */
#define JVC_HEADER_SPACE (8 * JVC_UNIT)
#define JVC_BIT_PULSE (1 * JVC_UNIT)
#define JVC_BIT_0_SPACE (1 * JVC_UNIT)
#define JVC_BIT_1_SPACE (3 * JVC_UNIT)
#define JVC_TRAILER_PULSE (1 * JVC_UNIT)
#define JVC_TRAILER_SPACE (35 * JVC_UNIT)
enum jvc_state {
STATE_INACTIVE,
STATE_HEADER_SPACE,
STATE_BIT_PULSE,
STATE_BIT_SPACE,
STATE_TRAILER_PULSE,
STATE_TRAILER_SPACE,
STATE_CHECK_REPEAT,
};
/**
* ir_jvc_decode() - Decode one JVC pulse or space
* @dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_jvc_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct jvc_dec *data = &dev->raw->jvc;
if (!(dev->enabled_protocols & RC_BIT_JVC))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
goto out;
IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
again:
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
break;
data->count = 0;
data->first = true;
data->toggle = !data->toggle;
data->state = STATE_HEADER_SPACE;
return 0;
case STATE_HEADER_SPACE:
if (ev.pulse)
break;
if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
break;
data->state = STATE_BIT_PULSE;
return 0;
case STATE_BIT_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
break;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_SPACE:
if (ev.pulse)
break;
data->bits <<= 1;
if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
data->bits |= 1;
decrease_duration(&ev, JVC_BIT_1_SPACE);
} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
decrease_duration(&ev, JVC_BIT_0_SPACE);
else
break;
data->count++;
if (data->count == JVC_NBITS)
data->state = STATE_TRAILER_PULSE;
else
data->state = STATE_BIT_PULSE;
return 0;
case STATE_TRAILER_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
break;
data->state = STATE_TRAILER_SPACE;
return 0;
case STATE_TRAILER_SPACE:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
break;
if (data->first) {
u32 scancode;
scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
(bitrev8((data->bits >> 0) & 0xff) << 0);
IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
rc_keydown(dev, RC_TYPE_JVC, scancode, data->toggle);
data->first = false;
data->old_bits = data->bits;
} else if (data->bits == data->old_bits) {
IR_dprintk(1, "JVC repeat\n");
rc_repeat(dev);
} else {
IR_dprintk(1, "JVC invalid repeat msg\n");
break;
}
data->count = 0;
data->state = STATE_CHECK_REPEAT;
return 0;
case STATE_CHECK_REPEAT:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
data->state = STATE_INACTIVE;
else
data->state = STATE_BIT_PULSE;
goto again;
}
out:
IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler jvc_handler = {
.protocols = RC_BIT_JVC,
.decode = ir_jvc_decode,
};
static int __init ir_jvc_decode_init(void)
{
ir_raw_handler_register(&jvc_handler);
printk(KERN_INFO "IR JVC protocol handler initialized\n");
return 0;
}
static void __exit ir_jvc_decode_exit(void)
{
ir_raw_handler_unregister(&jvc_handler);
}
module_init(ir_jvc_decode_init);
module_exit(ir_jvc_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
MODULE_DESCRIPTION("JVC IR protocol decoder");

View file

@ -0,0 +1,452 @@
/* ir-lirc-codec.c - rc-core to classic lirc interface bridge
*
* Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/module.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
#include <media/rc-core.h>
#include "rc-core-priv.h"
#define LIRCBUF_SIZE 256
/**
* ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
* lircd userspace daemon for decoding.
* @input_dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the lirc interfaces aren't wired up.
*/
static int ir_lirc_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct lirc_codec *lirc = &dev->raw->lirc;
int sample;
if (!(dev->enabled_protocols & RC_BIT_LIRC))
return 0;
if (!dev->raw->lirc.drv || !dev->raw->lirc.drv->rbuf)
return -EINVAL;
/* Packet start */
if (ev.reset) {
/* Userspace expects a long space event before the start of
* the signal to use as a sync. This may be done with repeat
* packets and normal samples. But if a reset has been sent
* then we assume that a long time has passed, so we send a
* space with the maximum time value. */
sample = LIRC_SPACE(LIRC_VALUE_MASK);
IR_dprintk(2, "delivering reset sync space to lirc_dev\n");
/* Carrier reports */
} else if (ev.carrier_report) {
sample = LIRC_FREQUENCY(ev.carrier);
IR_dprintk(2, "carrier report (freq: %d)\n", sample);
/* Packet end */
} else if (ev.timeout) {
if (lirc->gap)
return 0;
lirc->gap_start = ktime_get();
lirc->gap = true;
lirc->gap_duration = ev.duration;
if (!lirc->send_timeout_reports)
return 0;
sample = LIRC_TIMEOUT(ev.duration / 1000);
IR_dprintk(2, "timeout report (duration: %d)\n", sample);
/* Normal sample */
} else {
if (lirc->gap) {
int gap_sample;
lirc->gap_duration += ktime_to_ns(ktime_sub(ktime_get(),
lirc->gap_start));
/* Convert to ms and cap by LIRC_VALUE_MASK */
do_div(lirc->gap_duration, 1000);
lirc->gap_duration = min(lirc->gap_duration,
(u64)LIRC_VALUE_MASK);
gap_sample = LIRC_SPACE(lirc->gap_duration);
lirc_buffer_write(dev->raw->lirc.drv->rbuf,
(unsigned char *) &gap_sample);
lirc->gap = false;
}
sample = ev.pulse ? LIRC_PULSE(ev.duration / 1000) :
LIRC_SPACE(ev.duration / 1000);
IR_dprintk(2, "delivering %uus %s to lirc_dev\n",
TO_US(ev.duration), TO_STR(ev.pulse));
}
lirc_buffer_write(dev->raw->lirc.drv->rbuf,
(unsigned char *) &sample);
wake_up(&dev->raw->lirc.drv->rbuf->wait_poll);
return 0;
}
static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
size_t n, loff_t *ppos)
{
struct lirc_codec *lirc;
struct rc_dev *dev;
unsigned int *txbuf; /* buffer with values to transmit */
ssize_t ret = -EINVAL;
size_t count;
ktime_t start;
s64 towait;
unsigned int duration = 0; /* signal duration in us */
int i;
start = ktime_get();
lirc = lirc_get_pdata(file);
if (!lirc)
return -EFAULT;
if (n < sizeof(unsigned) || n % sizeof(unsigned))
return -EINVAL;
count = n / sizeof(unsigned);
if (count > LIRCBUF_SIZE || count % 2 == 0)
return -EINVAL;
txbuf = memdup_user(buf, n);
if (IS_ERR(txbuf))
return PTR_ERR(txbuf);
dev = lirc->dev;
if (!dev) {
ret = -EFAULT;
goto out;
}
if (!dev->tx_ir) {
ret = -ENOSYS;
goto out;
}
for (i = 0; i < count; i++) {
if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) {
ret = -EINVAL;
goto out;
}
duration += txbuf[i];
}
ret = dev->tx_ir(dev, txbuf, count);
if (ret < 0)
goto out;
for (duration = i = 0; i < ret; i++)
duration += txbuf[i];
ret *= sizeof(unsigned int);
/*
* The lircd gap calculation expects the write function to
* wait for the actual IR signal to be transmitted before
* returning.
*/
towait = ktime_us_delta(ktime_add_us(start, duration), ktime_get());
if (towait > 0) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(usecs_to_jiffies(towait));
}
out:
kfree(txbuf);
return ret;
}
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
unsigned long arg)
{
struct lirc_codec *lirc;
struct rc_dev *dev;
u32 __user *argp = (u32 __user *)(arg);
int ret = 0;
__u32 val = 0, tmp;
lirc = lirc_get_pdata(filep);
if (!lirc)
return -EFAULT;
dev = lirc->dev;
if (!dev)
return -EFAULT;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
ret = get_user(val, argp);
if (ret)
return ret;
}
switch (cmd) {
/* legacy support */
case LIRC_GET_SEND_MODE:
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
break;
case LIRC_SET_SEND_MODE:
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
return -EINVAL;
return 0;
/* TX settings */
case LIRC_SET_TRANSMITTER_MASK:
if (!dev->s_tx_mask)
return -ENOSYS;
return dev->s_tx_mask(dev, val);
case LIRC_SET_SEND_CARRIER:
if (!dev->s_tx_carrier)
return -ENOSYS;
return dev->s_tx_carrier(dev, val);
case LIRC_SET_SEND_DUTY_CYCLE:
if (!dev->s_tx_duty_cycle)
return -ENOSYS;
if (val <= 0 || val >= 100)
return -EINVAL;
return dev->s_tx_duty_cycle(dev, val);
/* RX settings */
case LIRC_SET_REC_CARRIER:
if (!dev->s_rx_carrier_range)
return -ENOSYS;
if (val <= 0)
return -EINVAL;
return dev->s_rx_carrier_range(dev,
dev->raw->lirc.carrier_low,
val);
case LIRC_SET_REC_CARRIER_RANGE:
if (val <= 0)
return -EINVAL;
dev->raw->lirc.carrier_low = val;
return 0;
case LIRC_GET_REC_RESOLUTION:
val = dev->rx_resolution;
break;
case LIRC_SET_WIDEBAND_RECEIVER:
if (!dev->s_learning_mode)
return -ENOSYS;
return dev->s_learning_mode(dev, !!val);
case LIRC_SET_MEASURE_CARRIER_MODE:
if (!dev->s_carrier_report)
return -ENOSYS;
return dev->s_carrier_report(dev, !!val);
/* Generic timeout support */
case LIRC_GET_MIN_TIMEOUT:
if (!dev->max_timeout)
return -ENOSYS;
val = dev->min_timeout / 1000;
break;
case LIRC_GET_MAX_TIMEOUT:
if (!dev->max_timeout)
return -ENOSYS;
val = dev->max_timeout / 1000;
break;
case LIRC_SET_REC_TIMEOUT:
if (!dev->max_timeout)
return -ENOSYS;
tmp = val * 1000;
if (tmp < dev->min_timeout ||
tmp > dev->max_timeout)
return -EINVAL;
dev->timeout = tmp;
break;
case LIRC_SET_REC_TIMEOUT_REPORTS:
lirc->send_timeout_reports = !!val;
break;
default:
return lirc_dev_fop_ioctl(filep, cmd, arg);
}
if (_IOC_DIR(cmd) & _IOC_READ)
ret = put_user(val, argp);
return ret;
}
static int ir_lirc_open(void *data)
{
return 0;
}
static void ir_lirc_close(void *data)
{
return;
}
static const struct file_operations lirc_fops = {
.owner = THIS_MODULE,
.write = ir_lirc_transmit_ir,
.unlocked_ioctl = ir_lirc_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ir_lirc_ioctl,
#endif
.read = lirc_dev_fop_read,
.poll = lirc_dev_fop_poll,
.open = lirc_dev_fop_open,
.release = lirc_dev_fop_close,
.llseek = no_llseek,
};
static int ir_lirc_register(struct rc_dev *dev)
{
struct lirc_driver *drv;
struct lirc_buffer *rbuf;
int rc = -ENOMEM;
unsigned long features;
drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
if (!drv)
return rc;
rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
if (!rbuf)
goto rbuf_alloc_failed;
rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
if (rc)
goto rbuf_init_failed;
features = LIRC_CAN_REC_MODE2;
if (dev->tx_ir) {
features |= LIRC_CAN_SEND_PULSE;
if (dev->s_tx_mask)
features |= LIRC_CAN_SET_TRANSMITTER_MASK;
if (dev->s_tx_carrier)
features |= LIRC_CAN_SET_SEND_CARRIER;
if (dev->s_tx_duty_cycle)
features |= LIRC_CAN_SET_SEND_DUTY_CYCLE;
}
if (dev->s_rx_carrier_range)
features |= LIRC_CAN_SET_REC_CARRIER |
LIRC_CAN_SET_REC_CARRIER_RANGE;
if (dev->s_learning_mode)
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
if (dev->s_carrier_report)
features |= LIRC_CAN_MEASURE_CARRIER;
if (dev->max_timeout)
features |= LIRC_CAN_SET_REC_TIMEOUT;
snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
dev->driver_name);
drv->minor = -1;
drv->features = features;
drv->data = &dev->raw->lirc;
drv->rbuf = rbuf;
drv->set_use_inc = &ir_lirc_open;
drv->set_use_dec = &ir_lirc_close;
drv->code_length = sizeof(struct ir_raw_event) * 8;
drv->fops = &lirc_fops;
drv->dev = &dev->dev;
drv->rdev = dev;
drv->owner = THIS_MODULE;
drv->minor = lirc_register_driver(drv);
if (drv->minor < 0) {
rc = -ENODEV;
goto lirc_register_failed;
}
dev->raw->lirc.drv = drv;
dev->raw->lirc.dev = dev;
return 0;
lirc_register_failed:
rbuf_init_failed:
kfree(rbuf);
rbuf_alloc_failed:
kfree(drv);
return rc;
}
static int ir_lirc_unregister(struct rc_dev *dev)
{
struct lirc_codec *lirc = &dev->raw->lirc;
lirc_unregister_driver(lirc->drv->minor);
lirc_buffer_free(lirc->drv->rbuf);
kfree(lirc->drv);
return 0;
}
static struct ir_raw_handler lirc_handler = {
.protocols = RC_BIT_LIRC,
.decode = ir_lirc_decode,
.raw_register = ir_lirc_register,
.raw_unregister = ir_lirc_unregister,
};
static int __init ir_lirc_codec_init(void)
{
ir_raw_handler_register(&lirc_handler);
printk(KERN_INFO "IR LIRC bridge handler initialized\n");
return 0;
}
static void __exit ir_lirc_codec_exit(void)
{
ir_raw_handler_unregister(&lirc_handler);
}
module_init(ir_lirc_codec_init);
module_exit(ir_lirc_codec_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("LIRC IR handler bridge");

View file

@ -0,0 +1,449 @@
/* ir-mce_kbd-decoder.c - A decoder for the RC6-ish keyboard/mouse IR protocol
* used by the Microsoft Remote Keyboard for Windows Media Center Edition,
* referred to by Microsoft's Windows Media Center remote specification docs
* as "an internal protocol called MCIR-2".
*
* Copyright (C) 2011 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/module.h>
#include "rc-core-priv.h"
/*
* This decoder currently supports:
* - MCIR-2 29-bit IR signals used for mouse movement and buttons
* - MCIR-2 32-bit IR signals used for standard keyboard keys
*
* The media keys on the keyboard send RC-6 signals that are inditinguishable
* from the keys of the same name on the stock MCE remote, and will be handled
* by the standard RC-6 decoder, and be made available to the system via the
* input device for the remote, rather than the keyboard/mouse one.
*/
#define MCIR2_UNIT 333333 /* ns */
#define MCIR2_HEADER_NBITS 5
#define MCIR2_MOUSE_NBITS 29
#define MCIR2_KEYBOARD_NBITS 32
#define MCIR2_PREFIX_PULSE (8 * MCIR2_UNIT)
#define MCIR2_PREFIX_SPACE (1 * MCIR2_UNIT)
#define MCIR2_MAX_LEN (3 * MCIR2_UNIT)
#define MCIR2_BIT_START (1 * MCIR2_UNIT)
#define MCIR2_BIT_END (1 * MCIR2_UNIT)
#define MCIR2_BIT_0 (1 * MCIR2_UNIT)
#define MCIR2_BIT_SET (2 * MCIR2_UNIT)
#define MCIR2_MODE_MASK 0xf /* for the header bits */
#define MCIR2_KEYBOARD_HEADER 0x4
#define MCIR2_MOUSE_HEADER 0x1
#define MCIR2_MASK_KEYS_START 0xe0
enum mce_kbd_mode {
MCIR2_MODE_KEYBOARD,
MCIR2_MODE_MOUSE,
MCIR2_MODE_UNKNOWN,
};
enum mce_kbd_state {
STATE_INACTIVE,
STATE_HEADER_BIT_START,
STATE_HEADER_BIT_END,
STATE_BODY_BIT_START,
STATE_BODY_BIT_END,
STATE_FINISHED,
};
static unsigned char kbd_keycodes[256] = {
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_A,
KEY_B, KEY_C, KEY_D, KEY_E, KEY_F,
KEY_G, KEY_H, KEY_I, KEY_J, KEY_K,
KEY_L, KEY_M, KEY_N, KEY_O, KEY_P,
KEY_Q, KEY_R, KEY_S, KEY_T, KEY_U,
KEY_V, KEY_W, KEY_X, KEY_Y, KEY_Z,
KEY_1, KEY_2, KEY_3, KEY_4, KEY_5,
KEY_6, KEY_7, KEY_8, KEY_9, KEY_0,
KEY_ENTER, KEY_ESC, KEY_BACKSPACE, KEY_TAB, KEY_SPACE,
KEY_MINUS, KEY_EQUAL, KEY_LEFTBRACE, KEY_RIGHTBRACE, KEY_BACKSLASH,
KEY_RESERVED, KEY_SEMICOLON, KEY_APOSTROPHE, KEY_GRAVE, KEY_COMMA,
KEY_DOT, KEY_SLASH, KEY_CAPSLOCK, KEY_F1, KEY_F2,
KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7,
KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_F12,
KEY_SYSRQ, KEY_SCROLLLOCK, KEY_PAUSE, KEY_INSERT, KEY_HOME,
KEY_PAGEUP, KEY_DELETE, KEY_END, KEY_PAGEDOWN, KEY_RIGHT,
KEY_LEFT, KEY_DOWN, KEY_UP, KEY_NUMLOCK, KEY_KPSLASH,
KEY_KPASTERISK, KEY_KPMINUS, KEY_KPPLUS, KEY_KPENTER, KEY_KP1,
KEY_KP2, KEY_KP3, KEY_KP4, KEY_KP5, KEY_KP6,
KEY_KP7, KEY_KP8, KEY_KP9, KEY_KP0, KEY_KPDOT,
KEY_102ND, KEY_COMPOSE, KEY_POWER, KEY_KPEQUAL, KEY_F13,
KEY_F14, KEY_F15, KEY_F16, KEY_F17, KEY_F18,
KEY_F19, KEY_F20, KEY_F21, KEY_F22, KEY_F23,
KEY_F24, KEY_OPEN, KEY_HELP, KEY_PROPS, KEY_FRONT,
KEY_STOP, KEY_AGAIN, KEY_UNDO, KEY_CUT, KEY_COPY,
KEY_PASTE, KEY_FIND, KEY_MUTE, KEY_VOLUMEUP, KEY_VOLUMEDOWN,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_KPCOMMA, KEY_RESERVED,
KEY_RO, KEY_KATAKANAHIRAGANA, KEY_YEN, KEY_HENKAN, KEY_MUHENKAN,
KEY_KPJPCOMMA, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_HANGUEL,
KEY_HANJA, KEY_KATAKANA, KEY_HIRAGANA, KEY_ZENKAKUHANKAKU, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED, KEY_LEFTCTRL,
KEY_LEFTSHIFT, KEY_LEFTALT, KEY_LEFTMETA, KEY_RIGHTCTRL, KEY_RIGHTSHIFT,
KEY_RIGHTALT, KEY_RIGHTMETA, KEY_PLAYPAUSE, KEY_STOPCD, KEY_PREVIOUSSONG,
KEY_NEXTSONG, KEY_EJECTCD, KEY_VOLUMEUP, KEY_VOLUMEDOWN, KEY_MUTE,
KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND,
KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_COFFEE,
KEY_REFRESH, KEY_CALC, KEY_RESERVED, KEY_RESERVED, KEY_RESERVED,
KEY_RESERVED
};
static void mce_kbd_rx_timeout(unsigned long data)
{
struct mce_kbd_dec *mce_kbd = (struct mce_kbd_dec *)data;
int i;
unsigned char maskcode;
IR_dprintk(2, "timer callback clearing all keys\n");
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
input_report_key(mce_kbd->idev, maskcode, 0);
}
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(mce_kbd->idev, kbd_keycodes[i], 0);
}
static enum mce_kbd_mode mce_kbd_mode(struct mce_kbd_dec *data)
{
switch (data->header & MCIR2_MODE_MASK) {
case MCIR2_KEYBOARD_HEADER:
return MCIR2_MODE_KEYBOARD;
case MCIR2_MOUSE_HEADER:
return MCIR2_MODE_MOUSE;
default:
return MCIR2_MODE_UNKNOWN;
}
}
static void ir_mce_kbd_process_keyboard_data(struct input_dev *idev,
u32 scancode)
{
u8 keydata = (scancode >> 8) & 0xff;
u8 shiftmask = scancode & 0xff;
unsigned char keycode, maskcode;
int i, keystate;
IR_dprintk(1, "keyboard: keydata = 0x%02x, shiftmask = 0x%02x\n",
keydata, shiftmask);
for (i = 0; i < 7; i++) {
maskcode = kbd_keycodes[MCIR2_MASK_KEYS_START + i];
if (shiftmask & (1 << i))
keystate = 1;
else
keystate = 0;
input_report_key(idev, maskcode, keystate);
}
if (keydata) {
keycode = kbd_keycodes[keydata];
input_report_key(idev, keycode, 1);
} else {
for (i = 0; i < MCIR2_MASK_KEYS_START; i++)
input_report_key(idev, kbd_keycodes[i], 0);
}
}
static void ir_mce_kbd_process_mouse_data(struct input_dev *idev, u32 scancode)
{
/* raw mouse coordinates */
u8 xdata = (scancode >> 7) & 0x7f;
u8 ydata = (scancode >> 14) & 0x7f;
int x, y;
/* mouse buttons */
bool right = scancode & 0x40;
bool left = scancode & 0x20;
if (xdata & 0x40)
x = -((~xdata & 0x7f) + 1);
else
x = xdata;
if (ydata & 0x40)
y = -((~ydata & 0x7f) + 1);
else
y = ydata;
IR_dprintk(1, "mouse: x = %d, y = %d, btns = %s%s\n",
x, y, left ? "L" : "", right ? "R" : "");
input_report_rel(idev, REL_X, x);
input_report_rel(idev, REL_Y, y);
input_report_key(idev, BTN_LEFT, left);
input_report_key(idev, BTN_RIGHT, right);
}
/**
* ir_mce_kbd_decode() - Decode one mce_kbd pulse or space
* @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_mce_kbd_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct mce_kbd_dec *data = &dev->raw->mce_kbd;
u32 scancode;
unsigned long delay;
if (!(dev->enabled_protocols & RC_BIT_MCE_KBD))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
goto out;
again:
IR_dprintk(2, "started at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
if (!geq_margin(ev.duration, MCIR2_UNIT, MCIR2_UNIT / 2))
return 0;
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
/* Note: larger margin on first pulse since each MCIR2_UNIT
is quite short and some hardware takes some time to
adjust to the signal */
if (!eq_margin(ev.duration, MCIR2_PREFIX_PULSE, MCIR2_UNIT))
break;
data->state = STATE_HEADER_BIT_START;
data->count = 0;
data->header = 0;
return 0;
case STATE_HEADER_BIT_START:
if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
break;
data->header <<= 1;
if (ev.pulse)
data->header |= 1;
data->count++;
data->state = STATE_HEADER_BIT_END;
return 0;
case STATE_HEADER_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
decrease_duration(&ev, MCIR2_BIT_END);
if (data->count != MCIR2_HEADER_NBITS) {
data->state = STATE_HEADER_BIT_START;
goto again;
}
switch (mce_kbd_mode(data)) {
case MCIR2_MODE_KEYBOARD:
data->wanted_bits = MCIR2_KEYBOARD_NBITS;
break;
case MCIR2_MODE_MOUSE:
data->wanted_bits = MCIR2_MOUSE_NBITS;
break;
default:
IR_dprintk(1, "not keyboard or mouse data\n");
goto out;
}
data->count = 0;
data->body = 0;
data->state = STATE_BODY_BIT_START;
goto again;
case STATE_BODY_BIT_START:
if (geq_margin(ev.duration, MCIR2_MAX_LEN, MCIR2_UNIT / 2))
break;
data->body <<= 1;
if (ev.pulse)
data->body |= 1;
data->count++;
data->state = STATE_BODY_BIT_END;
return 0;
case STATE_BODY_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
if (data->count == data->wanted_bits)
data->state = STATE_FINISHED;
else
data->state = STATE_BODY_BIT_START;
decrease_duration(&ev, MCIR2_BIT_END);
goto again;
case STATE_FINISHED:
if (ev.pulse)
break;
switch (data->wanted_bits) {
case MCIR2_KEYBOARD_NBITS:
scancode = data->body & 0xffff;
IR_dprintk(1, "keyboard data 0x%08x\n", data->body);
if (dev->timeout)
delay = usecs_to_jiffies(dev->timeout / 1000);
else
delay = msecs_to_jiffies(100);
mod_timer(&data->rx_timeout, jiffies + delay);
/* Pass data to keyboard buffer parser */
ir_mce_kbd_process_keyboard_data(data->idev, scancode);
break;
case MCIR2_MOUSE_NBITS:
scancode = data->body & 0x1fffff;
IR_dprintk(1, "mouse data 0x%06x\n", scancode);
/* Pass data to mouse buffer parser */
ir_mce_kbd_process_mouse_data(data->idev, scancode);
break;
default:
IR_dprintk(1, "not keyboard or mouse data\n");
goto out;
}
data->state = STATE_INACTIVE;
input_sync(data->idev);
return 0;
}
out:
IR_dprintk(1, "failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
input_sync(data->idev);
return -EINVAL;
}
static int ir_mce_kbd_register(struct rc_dev *dev)
{
struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
struct input_dev *idev;
int i, ret;
idev = input_allocate_device();
if (!idev)
return -ENOMEM;
snprintf(mce_kbd->name, sizeof(mce_kbd->name),
"MCE IR Keyboard/Mouse (%s)", dev->driver_name);
strlcat(mce_kbd->phys, "/input0", sizeof(mce_kbd->phys));
idev->name = mce_kbd->name;
idev->phys = mce_kbd->phys;
/* Keyboard bits */
set_bit(EV_KEY, idev->evbit);
set_bit(EV_REP, idev->evbit);
for (i = 0; i < sizeof(kbd_keycodes); i++)
set_bit(kbd_keycodes[i], idev->keybit);
/* Mouse bits */
set_bit(EV_REL, idev->evbit);
set_bit(REL_X, idev->relbit);
set_bit(REL_Y, idev->relbit);
set_bit(BTN_LEFT, idev->keybit);
set_bit(BTN_RIGHT, idev->keybit);
/* Report scancodes too */
set_bit(EV_MSC, idev->evbit);
set_bit(MSC_SCAN, idev->mscbit);
setup_timer(&mce_kbd->rx_timeout, mce_kbd_rx_timeout,
(unsigned long)mce_kbd);
input_set_drvdata(idev, mce_kbd);
#if 0
/* Adding this reference means two input devices are associated with
* this rc-core device, which ir-keytable doesn't cope with yet */
idev->dev.parent = &dev->dev;
#endif
ret = input_register_device(idev);
if (ret < 0) {
input_free_device(idev);
return -EIO;
}
mce_kbd->idev = idev;
return 0;
}
static int ir_mce_kbd_unregister(struct rc_dev *dev)
{
struct mce_kbd_dec *mce_kbd = &dev->raw->mce_kbd;
struct input_dev *idev = mce_kbd->idev;
del_timer_sync(&mce_kbd->rx_timeout);
input_unregister_device(idev);
return 0;
}
static struct ir_raw_handler mce_kbd_handler = {
.protocols = RC_BIT_MCE_KBD,
.decode = ir_mce_kbd_decode,
.raw_register = ir_mce_kbd_register,
.raw_unregister = ir_mce_kbd_unregister,
};
static int __init ir_mce_kbd_decode_init(void)
{
ir_raw_handler_register(&mce_kbd_handler);
printk(KERN_INFO "IR MCE Keyboard/mouse protocol handler initialized\n");
return 0;
}
static void __exit ir_mce_kbd_decode_exit(void)
{
ir_raw_handler_unregister(&mce_kbd_handler);
}
module_init(ir_mce_kbd_decode_init);
module_exit(ir_mce_kbd_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
MODULE_DESCRIPTION("MCE Keyboard/mouse IR protocol decoder");

View file

@ -0,0 +1,227 @@
/* ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"
#define NEC_NBITS 32
#define NEC_UNIT 562500 /* ns */
#define NEC_HEADER_PULSE (16 * NEC_UNIT)
#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
#define NEC_HEADER_SPACE (8 * NEC_UNIT)
#define NEC_REPEAT_SPACE (4 * NEC_UNIT)
#define NEC_BIT_PULSE (1 * NEC_UNIT)
#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
#define NECX_REPEAT_BITS 1
enum nec_state {
STATE_INACTIVE,
STATE_HEADER_SPACE,
STATE_BIT_PULSE,
STATE_BIT_SPACE,
STATE_TRAILER_PULSE,
STATE_TRAILER_SPACE,
};
/**
* ir_nec_decode() - Decode one NEC pulse or space
* @dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct nec_dec *data = &dev->raw->nec;
u32 scancode;
u8 address, not_address, command, not_command;
bool send_32bits = false;
if (!(dev->enabled_protocols & RC_BIT_NEC))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) {
data->is_nec_x = false;
data->necx_repeat = false;
} else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
data->is_nec_x = true;
else
break;
data->count = 0;
data->state = STATE_HEADER_SPACE;
return 0;
case STATE_HEADER_SPACE:
if (ev.pulse)
break;
if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) {
data->state = STATE_BIT_PULSE;
return 0;
} else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
if (!dev->keypressed) {
IR_dprintk(1, "Discarding last key repeat: event after key up\n");
} else {
rc_repeat(dev);
IR_dprintk(1, "Repeat last key\n");
data->state = STATE_TRAILER_PULSE;
}
return 0;
}
break;
case STATE_BIT_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
break;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_SPACE:
if (ev.pulse)
break;
if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
geq_margin(ev.duration,
NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
IR_dprintk(1, "Repeat last key\n");
rc_repeat(dev);
data->state = STATE_INACTIVE;
return 0;
} else if (data->count > NECX_REPEAT_BITS)
data->necx_repeat = false;
data->bits <<= 1;
if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
data->bits |= 1;
else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
break;
data->count++;
if (data->count == NEC_NBITS)
data->state = STATE_TRAILER_PULSE;
else
data->state = STATE_BIT_PULSE;
return 0;
case STATE_TRAILER_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
break;
data->state = STATE_TRAILER_SPACE;
return 0;
case STATE_TRAILER_SPACE:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
break;
address = bitrev8((data->bits >> 24) & 0xff);
not_address = bitrev8((data->bits >> 16) & 0xff);
command = bitrev8((data->bits >> 8) & 0xff);
not_command = bitrev8((data->bits >> 0) & 0xff);
if ((command ^ not_command) != 0xff) {
IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
data->bits);
send_32bits = true;
}
if (send_32bits) {
/* NEC transport, but modified protocol, used by at
* least Apple and TiVo remotes */
scancode = data->bits;
IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);
} else if ((address ^ not_address) != 0xff) {
/* Extended NEC */
scancode = address << 16 |
not_address << 8 |
command;
IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
} else {
/* Normal NEC */
scancode = address << 8 | command;
IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
}
if (data->is_nec_x)
data->necx_repeat = true;
rc_keydown(dev, RC_TYPE_NEC, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",
data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler nec_handler = {
.protocols = RC_BIT_NEC,
.decode = ir_nec_decode,
};
static int __init ir_nec_decode_init(void)
{
ir_raw_handler_register(&nec_handler);
printk(KERN_INFO "IR NEC protocol handler initialized\n");
return 0;
}
static void __exit ir_nec_decode_exit(void)
{
ir_raw_handler_unregister(&nec_handler);
}
module_init(ir_nec_decode_init);
module_exit(ir_nec_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("NEC IR protocol decoder");

View file

@ -0,0 +1,211 @@
/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
* Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*
* This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
* and 20 bit RC5x protocol.
*/
#include "rc-core-priv.h"
#include <linux/module.h>
#define RC5_NBITS 14
#define RC5_SZ_NBITS 15
#define RC5X_NBITS 20
#define CHECK_RC5X_NBITS 8
#define RC5_UNIT 888888 /* ns */
#define RC5_BIT_START (1 * RC5_UNIT)
#define RC5_BIT_END (1 * RC5_UNIT)
#define RC5X_SPACE (4 * RC5_UNIT)
#define RC5_TRAILER (10 * RC5_UNIT) /* In reality, approx 100 */
enum rc5_state {
STATE_INACTIVE,
STATE_BIT_START,
STATE_BIT_END,
STATE_CHECK_RC5X,
STATE_FINISHED,
};
/**
* ir_rc5_decode() - Decode one RC-5 pulse or space
* @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct rc5_dec *data = &dev->raw->rc5;
u8 toggle;
u32 scancode;
enum rc_type protocol;
if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ)))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
goto out;
again:
IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
return 0;
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
data->state = STATE_BIT_START;
data->count = 1;
decrease_duration(&ev, RC5_BIT_START);
goto again;
case STATE_BIT_START:
if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
data->state = STATE_FINISHED;
goto again;
}
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
break;
data->bits <<= 1;
if (!ev.pulse)
data->bits |= 1;
data->count++;
data->state = STATE_BIT_END;
return 0;
case STATE_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
if (data->count == CHECK_RC5X_NBITS)
data->state = STATE_CHECK_RC5X;
else
data->state = STATE_BIT_START;
decrease_duration(&ev, RC5_BIT_END);
goto again;
case STATE_CHECK_RC5X:
if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
data->is_rc5x = true;
decrease_duration(&ev, RC5X_SPACE);
} else
data->is_rc5x = false;
data->state = STATE_BIT_START;
goto again;
case STATE_FINISHED:
if (ev.pulse)
break;
if (data->is_rc5x && data->count == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
data->state = STATE_INACTIVE;
return 0;
}
xdata = (data->bits & 0x0003F) >> 0;
command = (data->bits & 0x00FC0) >> 6;
system = (data->bits & 0x1F000) >> 12;
toggle = (data->bits & 0x20000) ? 1 : 0;
command += (data->bits & 0x01000) ? 0 : 0x40;
scancode = system << 16 | command << 8 | xdata;
protocol = RC_TYPE_RC5X;
} else if (!data->is_rc5x && data->count == RC5_NBITS) {
/* RC5 */
u8 command, system;
if (!(dev->enabled_protocols & RC_BIT_RC5)) {
data->state = STATE_INACTIVE;
return 0;
}
command = (data->bits & 0x0003F) >> 0;
system = (data->bits & 0x007C0) >> 6;
toggle = (data->bits & 0x00800) ? 1 : 0;
command += (data->bits & 0x01000) ? 0 : 0x40;
scancode = system << 8 | command;
protocol = RC_TYPE_RC5;
} else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
/* RC5 StreamZap */
u8 command, system;
if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
data->state = STATE_INACTIVE;
return 0;
}
command = (data->bits & 0x0003F) >> 0;
system = (data->bits & 0x02FC0) >> 6;
toggle = (data->bits & 0x01000) ? 1 : 0;
scancode = system << 6 | command;
protocol = RC_TYPE_RC5_SZ;
} else
break;
IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
scancode, protocol, toggle);
rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
return 0;
}
out:
IR_dprintk(1, "RC5(x/sz) decode failed at state %i count %d (%uus %s)\n",
data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler rc5_handler = {
.protocols = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
.decode = ir_rc5_decode,
};
static int __init ir_rc5_decode_init(void)
{
ir_raw_handler_register(&rc5_handler);
printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
return 0;
}
static void __exit ir_rc5_decode_exit(void)
{
ir_raw_handler_unregister(&rc5_handler);
}
module_init(ir_rc5_decode_init);
module_exit(ir_rc5_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("RC5(x/sz) IR protocol decoder");

View file

@ -0,0 +1,319 @@
/* ir-rc6-decoder.c - A decoder for the RC6 IR protocol
*
* Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "rc-core-priv.h"
#include <linux/module.h>
/*
* This decoder currently supports:
* RC6-0-16 (standard toggle bit in header)
* RC6-6A-20 (no toggle bit)
* RC6-6A-24 (no toggle bit)
* RC6-6A-32 (MCE version with toggle bit in body)
*/
#define RC6_UNIT 444444 /* nanosecs */
#define RC6_HEADER_NBITS 4 /* not including toggle bit */
#define RC6_0_NBITS 16
#define RC6_6A_32_NBITS 32
#define RC6_6A_NBITS 128 /* Variable 8..128 */
#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
#define RC6_BIT_START (1 * RC6_UNIT)
#define RC6_BIT_END (1 * RC6_UNIT)
#define RC6_TOGGLE_START (2 * RC6_UNIT)
#define RC6_TOGGLE_END (2 * RC6_UNIT)
#define RC6_SUFFIX_SPACE (6 * RC6_UNIT)
#define RC6_MODE_MASK 0x07 /* for the header bits */
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
#define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */
#define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */
#ifndef CHAR_BIT
#define CHAR_BIT 8 /* Normally in <limits.h> */
#endif
enum rc6_mode {
RC6_MODE_0,
RC6_MODE_6A,
RC6_MODE_UNKNOWN,
};
enum rc6_state {
STATE_INACTIVE,
STATE_PREFIX_SPACE,
STATE_HEADER_BIT_START,
STATE_HEADER_BIT_END,
STATE_TOGGLE_START,
STATE_TOGGLE_END,
STATE_BODY_BIT_START,
STATE_BODY_BIT_END,
STATE_FINISHED,
};
static enum rc6_mode rc6_mode(struct rc6_dec *data)
{
switch (data->header & RC6_MODE_MASK) {
case 0:
return RC6_MODE_0;
case 6:
if (!data->toggle)
return RC6_MODE_6A;
/* fall through */
default:
return RC6_MODE_UNKNOWN;
}
}
/**
* ir_rc6_decode() - Decode one RC6 pulse or space
* @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct rc6_dec *data = &dev->raw->rc6;
u32 scancode;
u8 toggle;
enum rc_type protocol;
if (!(dev->enabled_protocols &
(RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE)))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
goto out;
again:
IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
return 0;
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
/* Note: larger margin on first pulse since each RC6_UNIT
is quite short and some hardware takes some time to
adjust to the signal */
if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
break;
data->state = STATE_PREFIX_SPACE;
data->count = 0;
return 0;
case STATE_PREFIX_SPACE:
if (ev.pulse)
break;
if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
break;
data->state = STATE_HEADER_BIT_START;
data->header = 0;
return 0;
case STATE_HEADER_BIT_START:
if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
break;
data->header <<= 1;
if (ev.pulse)
data->header |= 1;
data->count++;
data->state = STATE_HEADER_BIT_END;
return 0;
case STATE_HEADER_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
if (data->count == RC6_HEADER_NBITS)
data->state = STATE_TOGGLE_START;
else
data->state = STATE_HEADER_BIT_START;
decrease_duration(&ev, RC6_BIT_END);
goto again;
case STATE_TOGGLE_START:
if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
break;
data->toggle = ev.pulse;
data->state = STATE_TOGGLE_END;
return 0;
case STATE_TOGGLE_END:
if (!is_transition(&ev, &dev->raw->prev_ev) ||
!geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
break;
if (!(data->header & RC6_STARTBIT_MASK)) {
IR_dprintk(1, "RC6 invalid start bit\n");
break;
}
data->state = STATE_BODY_BIT_START;
decrease_duration(&ev, RC6_TOGGLE_END);
data->count = 0;
data->body = 0;
switch (rc6_mode(data)) {
case RC6_MODE_0:
data->wanted_bits = RC6_0_NBITS;
break;
case RC6_MODE_6A:
data->wanted_bits = RC6_6A_NBITS;
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
goto out;
}
goto again;
case STATE_BODY_BIT_START:
if (eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2)) {
/* Discard LSB's that won't fit in data->body */
if (data->count++ < CHAR_BIT * sizeof data->body) {
data->body <<= 1;
if (ev.pulse)
data->body |= 1;
}
data->state = STATE_BODY_BIT_END;
return 0;
} else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse &&
geq_margin(ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) {
data->state = STATE_FINISHED;
goto again;
}
break;
case STATE_BODY_BIT_END:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
if (data->count == data->wanted_bits)
data->state = STATE_FINISHED;
else
data->state = STATE_BODY_BIT_START;
decrease_duration(&ev, RC6_BIT_END);
goto again;
case STATE_FINISHED:
if (ev.pulse)
break;
switch (rc6_mode(data)) {
case RC6_MODE_0:
scancode = data->body;
toggle = data->toggle;
protocol = RC_TYPE_RC6_0;
IR_dprintk(1, "RC6(0) scancode 0x%04x (toggle: %u)\n",
scancode, toggle);
break;
case RC6_MODE_6A:
if (data->count > CHAR_BIT * sizeof data->body) {
IR_dprintk(1, "RC6 too many (%u) data bits\n",
data->count);
goto out;
}
scancode = data->body;
switch (data->count) {
case 20:
protocol = RC_TYPE_RC6_6A_20;
toggle = 0;
break;
case 24:
protocol = RC_BIT_RC6_6A_24;
toggle = 0;
break;
case 32:
if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
protocol = RC_TYPE_RC6_MCE;
toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
} else {
protocol = RC_BIT_RC6_6A_32;
toggle = 0;
}
break;
default:
IR_dprintk(1, "RC6(6A) unsupported length\n");
goto out;
}
IR_dprintk(1, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n",
protocol, scancode, toggle);
break;
default:
IR_dprintk(1, "RC6 unknown mode\n");
goto out;
}
rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
return 0;
}
out:
IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler rc6_handler = {
.protocols = RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
RC_BIT_RC6_MCE,
.decode = ir_rc6_decode,
};
static int __init ir_rc6_decode_init(void)
{
ir_raw_handler_register(&rc6_handler);
printk(KERN_INFO "IR RC6 protocol handler initialized\n");
return 0;
}
static void __exit ir_rc6_decode_exit(void)
{
ir_raw_handler_unregister(&rc6_handler);
}
module_init(ir_rc6_decode_init);
module_exit(ir_rc6_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
MODULE_DESCRIPTION("RC6 IR protocol decoder");

485
drivers/media/rc/ir-rx51.c Normal file
View file

@ -0,0 +1,485 @@
/*
* Copyright (C) 2008 Nokia Corporation
*
* Based on lirc_serial.c
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <plat/dmtimer.h>
#include <plat/clock.h>
#include <media/lirc.h>
#include <media/lirc_dev.h>
#include <media/ir-rx51.h>
#define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE | \
LIRC_CAN_SET_SEND_CARRIER | \
LIRC_CAN_SEND_PULSE)
#define DRIVER_NAME "lirc_rx51"
#define WBUF_LEN 256
#define TIMER_MAX_VALUE 0xffffffff
struct lirc_rx51 {
struct omap_dm_timer *pwm_timer;
struct omap_dm_timer *pulse_timer;
struct device *dev;
struct lirc_rx51_platform_data *pdata;
wait_queue_head_t wqueue;
unsigned long fclk_khz;
unsigned int freq; /* carrier frequency */
unsigned int duty_cycle; /* carrier duty cycle */
unsigned int irq_num;
unsigned int match;
int wbuf[WBUF_LEN];
int wbuf_index;
unsigned long device_is_open;
int pwm_timer_num;
};
static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
{
omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
}
static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
{
omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
OMAP_TIMER_TRIGGER_NONE);
}
static int init_timing_params(struct lirc_rx51 *lirc_rx51)
{
u32 load, match;
load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
match = -(lirc_rx51->duty_cycle * -load / 100);
omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
omap_dm_timer_start(lirc_rx51->pwm_timer);
omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
omap_dm_timer_start(lirc_rx51->pulse_timer);
lirc_rx51->match = 0;
return 0;
}
#define tics_after(a, b) ((long)(b) - (long)(a) < 0)
static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
{
int counter;
BUG_ON(usec < 0);
if (lirc_rx51->match == 0)
counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
else
counter = lirc_rx51->match;
counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
OMAP_TIMER_INT_MATCH);
if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
counter)) {
return 1;
}
return 0;
}
static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
{
unsigned int retval;
struct lirc_rx51 *lirc_rx51 = ptr;
retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
if (!retval)
return IRQ_NONE;
if (retval & ~OMAP_TIMER_INT_MATCH)
dev_err_ratelimited(lirc_rx51->dev,
": Unexpected interrupt source: %x\n", retval);
omap_dm_timer_write_status(lirc_rx51->pulse_timer,
OMAP_TIMER_INT_MATCH |
OMAP_TIMER_INT_OVERFLOW |
OMAP_TIMER_INT_CAPTURE);
if (lirc_rx51->wbuf_index < 0) {
dev_err_ratelimited(lirc_rx51->dev,
": BUG wbuf_index has value of %i\n",
lirc_rx51->wbuf_index);
goto end;
}
/*
* If we happen to hit an odd latency spike, loop through the
* pulses until we catch up.
*/
do {
if (lirc_rx51->wbuf_index >= WBUF_LEN)
goto end;
if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
goto end;
if (lirc_rx51->wbuf_index % 2)
lirc_rx51_off(lirc_rx51);
else
lirc_rx51_on(lirc_rx51);
retval = pulse_timer_set_timeout(lirc_rx51,
lirc_rx51->wbuf[lirc_rx51->wbuf_index]);
lirc_rx51->wbuf_index++;
} while (retval);
return IRQ_HANDLED;
end:
/* Stop TX here */
lirc_rx51_off(lirc_rx51);
lirc_rx51->wbuf_index = -1;
omap_dm_timer_stop(lirc_rx51->pwm_timer);
omap_dm_timer_stop(lirc_rx51->pulse_timer);
omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
wake_up_interruptible(&lirc_rx51->wqueue);
return IRQ_HANDLED;
}
static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
{
struct clk *clk_fclk;
int retval, pwm_timer = lirc_rx51->pwm_timer_num;
lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
if (lirc_rx51->pwm_timer == NULL) {
dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
pwm_timer);
return -EBUSY;
}
lirc_rx51->pulse_timer = omap_dm_timer_request();
if (lirc_rx51->pulse_timer == NULL) {
dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
retval = -EBUSY;
goto err1;
}
omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
omap_dm_timer_set_source(lirc_rx51->pulse_timer,
OMAP_TIMER_SRC_SYS_CLK);
omap_dm_timer_enable(lirc_rx51->pwm_timer);
omap_dm_timer_enable(lirc_rx51->pulse_timer);
lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
if (retval) {
dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
goto err2;
}
clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
return 0;
err2:
omap_dm_timer_free(lirc_rx51->pulse_timer);
err1:
omap_dm_timer_free(lirc_rx51->pwm_timer);
return retval;
}
static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
{
omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
free_irq(lirc_rx51->irq_num, lirc_rx51);
lirc_rx51_off(lirc_rx51);
omap_dm_timer_disable(lirc_rx51->pwm_timer);
omap_dm_timer_disable(lirc_rx51->pulse_timer);
omap_dm_timer_free(lirc_rx51->pwm_timer);
omap_dm_timer_free(lirc_rx51->pulse_timer);
lirc_rx51->wbuf_index = -1;
return 0;
}
static ssize_t lirc_rx51_write(struct file *file, const char *buf,
size_t n, loff_t *ppos)
{
int count, i;
struct lirc_rx51 *lirc_rx51 = file->private_data;
if (n % sizeof(int))
return -EINVAL;
count = n / sizeof(int);
if ((count > WBUF_LEN) || (count % 2 == 0))
return -EINVAL;
/* Wait any pending transfers to finish */
wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
if (copy_from_user(lirc_rx51->wbuf, buf, n))
return -EFAULT;
/* Sanity check the input pulses */
for (i = 0; i < count; i++)
if (lirc_rx51->wbuf[i] < 0)
return -EINVAL;
init_timing_params(lirc_rx51);
if (count < WBUF_LEN)
lirc_rx51->wbuf[count] = -1; /* Insert termination mark */
/*
* Adjust latency requirements so the device doesn't go in too
* deep sleep states
*/
lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50);
lirc_rx51_on(lirc_rx51);
lirc_rx51->wbuf_index = 1;
pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]);
/*
* Don't return back to the userspace until the transfer has
* finished
*/
wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
/* We can sleep again */
lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1);
return n;
}
static long lirc_rx51_ioctl(struct file *filep,
unsigned int cmd, unsigned long arg)
{
int result;
unsigned long value;
unsigned int ivalue;
struct lirc_rx51 *lirc_rx51 = filep->private_data;
switch (cmd) {
case LIRC_GET_SEND_MODE:
result = put_user(LIRC_MODE_PULSE, (unsigned long *)arg);
if (result)
return result;
break;
case LIRC_SET_SEND_MODE:
result = get_user(value, (unsigned long *)arg);
if (result)
return result;
/* only LIRC_MODE_PULSE supported */
if (value != LIRC_MODE_PULSE)
return -ENOSYS;
break;
case LIRC_GET_REC_MODE:
result = put_user(0, (unsigned long *) arg);
if (result)
return result;
break;
case LIRC_GET_LENGTH:
return -ENOSYS;
break;
case LIRC_SET_SEND_DUTY_CYCLE:
result = get_user(ivalue, (unsigned int *) arg);
if (result)
return result;
if (ivalue <= 0 || ivalue > 100) {
dev_err(lirc_rx51->dev, ": invalid duty cycle %d\n",
ivalue);
return -EINVAL;
}
lirc_rx51->duty_cycle = ivalue;
break;
case LIRC_SET_SEND_CARRIER:
result = get_user(ivalue, (unsigned int *) arg);
if (result)
return result;
if (ivalue > 500000 || ivalue < 20000) {
dev_err(lirc_rx51->dev, ": invalid carrier freq %d\n",
ivalue);
return -EINVAL;
}
lirc_rx51->freq = ivalue;
break;
case LIRC_GET_FEATURES:
result = put_user(LIRC_RX51_DRIVER_FEATURES,
(unsigned long *) arg);
if (result)
return result;
break;
default:
return -ENOIOCTLCMD;
}
return 0;
}
static int lirc_rx51_open(struct inode *inode, struct file *file)
{
struct lirc_rx51 *lirc_rx51 = lirc_get_pdata(file);
BUG_ON(!lirc_rx51);
file->private_data = lirc_rx51;
if (test_and_set_bit(1, &lirc_rx51->device_is_open))
return -EBUSY;
return lirc_rx51_init_port(lirc_rx51);
}
static int lirc_rx51_release(struct inode *inode, struct file *file)
{
struct lirc_rx51 *lirc_rx51 = file->private_data;
lirc_rx51_free_port(lirc_rx51);
clear_bit(1, &lirc_rx51->device_is_open);
return 0;
}
static struct lirc_rx51 lirc_rx51 = {
.freq = 38000,
.duty_cycle = 50,
.wbuf_index = -1,
};
static const struct file_operations lirc_fops = {
.owner = THIS_MODULE,
.write = lirc_rx51_write,
.unlocked_ioctl = lirc_rx51_ioctl,
.read = lirc_dev_fop_read,
.poll = lirc_dev_fop_poll,
.open = lirc_rx51_open,
.release = lirc_rx51_release,
};
static struct lirc_driver lirc_rx51_driver = {
.name = DRIVER_NAME,
.minor = -1,
.code_length = 1,
.data = &lirc_rx51,
.fops = &lirc_fops,
.owner = THIS_MODULE,
};
#ifdef CONFIG_PM
static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state)
{
/*
* In case the device is still open, do not suspend. Normally
* this should not be a problem as lircd only keeps the device
* open only for short periods of time. We also don't want to
* get involved with race conditions that might happen if we
* were in a middle of a transmit. Thus, we defer any suspend
* actions until transmit has completed.
*/
if (test_and_set_bit(1, &lirc_rx51.device_is_open))
return -EAGAIN;
clear_bit(1, &lirc_rx51.device_is_open);
return 0;
}
static int lirc_rx51_resume(struct platform_device *dev)
{
return 0;
}
#else
#define lirc_rx51_suspend NULL
#define lirc_rx51_resume NULL
#endif /* CONFIG_PM */
static int lirc_rx51_probe(struct platform_device *dev)
{
lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
lirc_rx51.pdata = dev->dev.platform_data;
lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
lirc_rx51.dev = &dev->dev;
lirc_rx51_driver.dev = &dev->dev;
lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
init_waitqueue_head(&lirc_rx51.wqueue);
if (lirc_rx51_driver.minor < 0) {
dev_err(lirc_rx51.dev, ": lirc_register_driver failed: %d\n",
lirc_rx51_driver.minor);
return lirc_rx51_driver.minor;
}
dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
return 0;
}
static int lirc_rx51_remove(struct platform_device *dev)
{
return lirc_unregister_driver(lirc_rx51_driver.minor);
}
struct platform_driver lirc_rx51_platform_driver = {
.probe = lirc_rx51_probe,
.remove = lirc_rx51_remove,
.suspend = lirc_rx51_suspend,
.resume = lirc_rx51_resume,
.driver = {
.name = DRIVER_NAME,
.owner = THIS_MODULE,
},
};
module_platform_driver(lirc_rx51_platform_driver);
MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
MODULE_AUTHOR("Nokia Corporation");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,205 @@
/* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol
*
* Copyright (C) 2011 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This protocol uses the NEC protocol timings. However, data is formatted as:
* 13 bits Custom Code
* 13 bits NOT(Custom Code)
* 8 bits Key data
* 8 bits NOT(Key data)
*
* According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon
* Information for this protocol is available at the Sanyo LC7461 datasheet.
*/
#include <linux/module.h>
#include <linux/bitrev.h>
#include "rc-core-priv.h"
#define SANYO_NBITS (13+13+8+8)
#define SANYO_UNIT 562500 /* ns */
#define SANYO_HEADER_PULSE (16 * SANYO_UNIT)
#define SANYO_HEADER_SPACE (8 * SANYO_UNIT)
#define SANYO_BIT_PULSE (1 * SANYO_UNIT)
#define SANYO_BIT_0_SPACE (1 * SANYO_UNIT)
#define SANYO_BIT_1_SPACE (3 * SANYO_UNIT)
#define SANYO_REPEAT_SPACE (150 * SANYO_UNIT)
#define SANYO_TRAILER_PULSE (1 * SANYO_UNIT)
#define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */
enum sanyo_state {
STATE_INACTIVE,
STATE_HEADER_SPACE,
STATE_BIT_PULSE,
STATE_BIT_SPACE,
STATE_TRAILER_PULSE,
STATE_TRAILER_SPACE,
};
/**
* ir_sanyo_decode() - Decode one SANYO pulse or space
* @dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sanyo_dec *data = &dev->raw->sanyo;
u32 scancode;
u8 address, command, not_command;
if (!(dev->enabled_protocols & RC_BIT_SANYO))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset) {
IR_dprintk(1, "SANYO event reset received. reset to state 0\n");
data->state = STATE_INACTIVE;
}
return 0;
}
IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) {
data->count = 0;
data->state = STATE_HEADER_SPACE;
return 0;
}
break;
case STATE_HEADER_SPACE:
if (ev.pulse)
break;
if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) {
data->state = STATE_BIT_PULSE;
return 0;
}
break;
case STATE_BIT_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2))
break;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_SPACE:
if (ev.pulse)
break;
if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) {
if (!dev->keypressed) {
IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n");
} else {
rc_repeat(dev);
IR_dprintk(1, "SANYO repeat last key\n");
data->state = STATE_INACTIVE;
}
return 0;
}
data->bits <<= 1;
if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2))
data->bits |= 1;
else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2))
break;
data->count++;
if (data->count == SANYO_NBITS)
data->state = STATE_TRAILER_PULSE;
else
data->state = STATE_BIT_PULSE;
return 0;
case STATE_TRAILER_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2))
break;
data->state = STATE_TRAILER_SPACE;
return 0;
case STATE_TRAILER_SPACE:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2))
break;
address = bitrev16((data->bits >> 29) & 0x1fff) >> 3;
/* not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; */
command = bitrev8((data->bits >> 8) & 0xff);
not_command = bitrev8((data->bits >> 0) & 0xff);
if ((command ^ not_command) != 0xff) {
IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n",
data->bits);
data->state = STATE_INACTIVE;
return 0;
}
scancode = address << 8 | command;
IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode);
rc_keydown(dev, RC_TYPE_SANYO, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n",
data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler sanyo_handler = {
.protocols = RC_BIT_SANYO,
.decode = ir_sanyo_decode,
};
static int __init ir_sanyo_decode_init(void)
{
ir_raw_handler_register(&sanyo_handler);
printk(KERN_INFO "IR SANYO protocol handler initialized\n");
return 0;
}
static void __exit ir_sanyo_decode_exit(void)
{
ir_raw_handler_unregister(&sanyo_handler);
}
module_init(ir_sanyo_decode_init);
module_exit(ir_sanyo_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("SANYO IR protocol decoder");

View file

@ -0,0 +1,200 @@
/* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol
*
* Copyright (C) 2013-2014 Imagination Technologies Ltd.
*
* Based on NEC decoder:
* Copyright (C) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"
#define SHARP_NBITS 15
#define SHARP_UNIT 40000 /* ns */
#define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */
#define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */
#define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680ms space) */
#define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */
#define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */
enum sharp_state {
STATE_INACTIVE,
STATE_BIT_PULSE,
STATE_BIT_SPACE,
STATE_TRAILER_PULSE,
STATE_ECHO_SPACE,
STATE_TRAILER_SPACE,
};
/**
* ir_sharp_decode() - Decode one Sharp pulse or space
* @dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sharp_dec *data = &dev->raw->sharp;
u32 msg, echo, address, command, scancode;
if (!(dev->enabled_protocols & RC_BIT_SHARP))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(2, "Sharp decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
SHARP_BIT_PULSE / 2))
break;
data->count = 0;
data->pulse_len = ev.duration;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
SHARP_BIT_PULSE / 2))
break;
data->pulse_len = ev.duration;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_SPACE:
if (ev.pulse)
break;
data->bits <<= 1;
if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD,
SHARP_BIT_PULSE * 2))
data->bits |= 1;
else if (!eq_margin(data->pulse_len + ev.duration,
SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2))
break;
data->count++;
if (data->count == SHARP_NBITS ||
data->count == SHARP_NBITS * 2)
data->state = STATE_TRAILER_PULSE;
else
data->state = STATE_BIT_PULSE;
return 0;
case STATE_TRAILER_PULSE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
SHARP_BIT_PULSE / 2))
break;
if (data->count == SHARP_NBITS) {
/* exp,chk bits should be 1,0 */
if ((data->bits & 0x3) != 0x2)
break;
data->state = STATE_ECHO_SPACE;
} else {
data->state = STATE_TRAILER_SPACE;
}
return 0;
case STATE_ECHO_SPACE:
if (ev.pulse)
break;
if (!eq_margin(ev.duration, SHARP_ECHO_SPACE,
SHARP_ECHO_SPACE / 4))
break;
data->state = STATE_BIT_PULSE;
return 0;
case STATE_TRAILER_SPACE:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE,
SHARP_BIT_PULSE / 2))
break;
/* Validate - command, ext, chk should be inverted in 2nd */
msg = (data->bits >> 15) & 0x7fff;
echo = data->bits & 0x7fff;
if ((msg ^ echo) != 0x3ff) {
IR_dprintk(1,
"Sharp checksum error: received 0x%04x, 0x%04x\n",
msg, echo);
break;
}
address = bitrev8((msg >> 7) & 0xf8);
command = bitrev8((msg >> 2) & 0xff);
scancode = address << 8 | command;
IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode);
rc_keydown(dev, RC_TYPE_SHARP, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(1, "Sharp decode failed at count %d state %d (%uus %s)\n",
data->count, data->state, TO_US(ev.duration),
TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler sharp_handler = {
.protocols = RC_BIT_SHARP,
.decode = ir_sharp_decode,
};
static int __init ir_sharp_decode_init(void)
{
ir_raw_handler_register(&sharp_handler);
pr_info("IR Sharp protocol handler initialized\n");
return 0;
}
static void __exit ir_sharp_decode_exit(void)
{
ir_raw_handler_unregister(&sharp_handler);
}
module_init(ir_sharp_decode_init);
module_exit(ir_sharp_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>");
MODULE_DESCRIPTION("Sharp IR protocol decoder");

View file

@ -0,0 +1,199 @@
/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
*
* Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"
#define SONY_UNIT 600000 /* ns */
#define SONY_HEADER_PULSE (4 * SONY_UNIT)
#define SONY_HEADER_SPACE (1 * SONY_UNIT)
#define SONY_BIT_0_PULSE (1 * SONY_UNIT)
#define SONY_BIT_1_PULSE (2 * SONY_UNIT)
#define SONY_BIT_SPACE (1 * SONY_UNIT)
#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
enum sony_state {
STATE_INACTIVE,
STATE_HEADER_SPACE,
STATE_BIT_PULSE,
STATE_BIT_SPACE,
STATE_FINISHED,
};
/**
* ir_sony_decode() - Decode one Sony pulse or space
* @dev: the struct rc_dev descriptor of the device
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct sony_dec *data = &dev->raw->sony;
enum rc_type protocol;
u32 scancode;
u8 device, subdevice, function;
if (!(dev->enabled_protocols &
(RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20)))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
goto out;
IR_dprintk(2, "Sony decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
break;
data->count = 0;
data->state = STATE_HEADER_SPACE;
return 0;
case STATE_HEADER_SPACE:
if (ev.pulse)
break;
if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
break;
data->state = STATE_BIT_PULSE;
return 0;
case STATE_BIT_PULSE:
if (!ev.pulse)
break;
data->bits <<= 1;
if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
data->bits |= 1;
else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
break;
data->count++;
data->state = STATE_BIT_SPACE;
return 0;
case STATE_BIT_SPACE:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
break;
decrease_duration(&ev, SONY_BIT_SPACE);
if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
data->state = STATE_BIT_PULSE;
return 0;
}
data->state = STATE_FINISHED;
/* Fall through */
case STATE_FINISHED:
if (ev.pulse)
break;
if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
break;
switch (data->count) {
case 12:
if (!(dev->enabled_protocols & RC_BIT_SONY12)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits << 3) & 0xF8);
subdevice = 0;
function = bitrev8((data->bits >> 4) & 0xFE);
protocol = RC_TYPE_SONY12;
break;
case 15:
if (!(dev->enabled_protocols & RC_BIT_SONY15)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits >> 0) & 0xFF);
subdevice = 0;
function = bitrev8((data->bits >> 7) & 0xFE);
protocol = RC_TYPE_SONY15;
break;
case 20:
if (!(dev->enabled_protocols & RC_BIT_SONY20)) {
data->state = STATE_INACTIVE;
return 0;
}
device = bitrev8((data->bits >> 5) & 0xF8);
subdevice = bitrev8((data->bits >> 0) & 0xFF);
function = bitrev8((data->bits >> 12) & 0xFE);
protocol = RC_TYPE_SONY20;
break;
default:
IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
goto out;
}
scancode = device << 16 | subdevice << 8 | function;
IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
rc_keydown(dev, protocol, scancode, 0);
data->state = STATE_INACTIVE;
return 0;
}
out:
IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler sony_handler = {
.protocols = RC_BIT_SONY12 | RC_BIT_SONY15 | RC_BIT_SONY20,
.decode = ir_sony_decode,
};
static int __init ir_sony_decode_init(void)
{
ir_raw_handler_register(&sony_handler);
printk(KERN_INFO "IR Sony protocol handler initialized\n");
return 0;
}
static void __exit ir_sony_decode_exit(void)
{
ir_raw_handler_unregister(&sony_handler);
}
module_init(ir_sony_decode_init);
module_exit(ir_sony_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
MODULE_DESCRIPTION("Sony IR protocol decoder");

View file

@ -0,0 +1,225 @@
/* ir-xmp-decoder.c - handle XMP IR Pulse/Space protocol
*
* Copyright (C) 2014 by Marcel Mol
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* - Based on info from http://www.hifi-remote.com
* - Ignore Toggle=9 frames
* - Ignore XMP-1 XMP-2 difference, always store 16 bit OBC
*/
#include <linux/bitrev.h>
#include <linux/module.h>
#include "rc-core-priv.h"
#define XMP_UNIT 136000 /* ns */
#define XMP_LEADER 210000 /* ns */
#define XMP_NIBBLE_PREFIX 760000 /* ns */
#define XMP_HALFFRAME_SPACE 13800000 /* ns */
#define XMP_TRAILER_SPACE 20000000 /* should be 80ms but not all dureation supliers can go that high */
enum xmp_state {
STATE_INACTIVE,
STATE_LEADER_PULSE,
STATE_NIBBLE_SPACE,
};
/**
* ir_xmp_decode() - Decode one XMP pulse or space
* @dev: the struct rc_dev descriptor of the device
* @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
static int ir_xmp_decode(struct rc_dev *dev, struct ir_raw_event ev)
{
struct xmp_dec *data = &dev->raw->xmp;
if (!(dev->enabled_protocols & RC_BIT_XMP))
return 0;
if (!is_timing_event(ev)) {
if (ev.reset)
data->state = STATE_INACTIVE;
return 0;
}
IR_dprintk(2, "XMP decode started at state %d %d (%uus %s)\n",
data->state, data->count, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2)) {
data->count = 0;
data->state = STATE_NIBBLE_SPACE;
}
return 0;
case STATE_LEADER_PULSE:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, XMP_LEADER, XMP_UNIT / 2))
data->state = STATE_NIBBLE_SPACE;
return 0;
case STATE_NIBBLE_SPACE:
if (ev.pulse)
break;
if (geq_margin(ev.duration, XMP_TRAILER_SPACE, XMP_NIBBLE_PREFIX)) {
int divider, i;
u8 addr, subaddr, subaddr2, toggle, oem, obc1, obc2, sum1, sum2;
u32 *n;
u32 scancode;
if (data->count != 16) {
IR_dprintk(2, "received TRAILER period at index %d: %u\n",
data->count, ev.duration);
data->state = STATE_INACTIVE;
return -EINVAL;
}
n = data->durations;
/*
* the 4th nibble should be 15 so base the divider on this
* to transform durations into nibbles. Substract 2000 from
* the divider to compensate for fluctuations in the signal
*/
divider = (n[3] - XMP_NIBBLE_PREFIX) / 15 - 2000;
if (divider < 50) {
IR_dprintk(2, "divider to small %d.\n", divider);
data->state = STATE_INACTIVE;
return -EINVAL;
}
/* convert to nibbles and do some sanity checks */
for (i = 0; i < 16; i++)
n[i] = (n[i] - XMP_NIBBLE_PREFIX) / divider;
sum1 = (15 + n[0] + n[1] + n[2] + n[3] +
n[4] + n[5] + n[6] + n[7]) % 16;
sum2 = (15 + n[8] + n[9] + n[10] + n[11] +
n[12] + n[13] + n[14] + n[15]) % 16;
if (sum1 != 15 || sum2 != 15) {
IR_dprintk(2, "checksum errors sum1=0x%X sum2=0x%X\n",
sum1, sum2);
data->state = STATE_INACTIVE;
return -EINVAL;
}
subaddr = n[0] << 4 | n[2];
subaddr2 = n[8] << 4 | n[11];
oem = n[4] << 4 | n[5];
addr = n[6] << 4 | n[7];
toggle = n[10];
obc1 = n[12] << 4 | n[13];
obc2 = n[14] << 4 | n[15];
if (subaddr != subaddr2) {
IR_dprintk(2, "subaddress nibbles mismatch 0x%02X != 0x%02X\n",
subaddr, subaddr2);
data->state = STATE_INACTIVE;
return -EINVAL;
}
if (oem != 0x44)
IR_dprintk(1, "Warning: OEM nibbles 0x%02X. Expected 0x44\n",
oem);
scancode = addr << 24 | subaddr << 16 |
obc1 << 8 | obc2;
IR_dprintk(1, "XMP scancode 0x%06x\n", scancode);
if (toggle == 0) {
rc_keydown(dev, RC_TYPE_XMP, scancode, 0);
} else {
rc_repeat(dev);
IR_dprintk(1, "Repeat last key\n");
}
data->state = STATE_INACTIVE;
return 0;
} else if (geq_margin(ev.duration, XMP_HALFFRAME_SPACE, XMP_NIBBLE_PREFIX)) {
/* Expect 8 or 16 nibble pulses. 16 in case of 'final' frame */
if (data->count == 16) {
IR_dprintk(2, "received half frame pulse at index %d. Probably a final frame key-up event: %u\n",
data->count, ev.duration);
/*
* TODO: for now go back to half frame position
* so trailer can be found and key press
* can be handled.
*/
data->count = 8;
}
else if (data->count != 8)
IR_dprintk(2, "received half frame pulse at index %d: %u\n",
data->count, ev.duration);
data->state = STATE_LEADER_PULSE;
return 0;
} else if (geq_margin(ev.duration, XMP_NIBBLE_PREFIX, XMP_UNIT)) {
/* store nibble raw data, decode after trailer */
if (data->count == 16) {
IR_dprintk(2, "to many pulses (%d) ignoring: %u\n",
data->count, ev.duration);
data->state = STATE_INACTIVE;
return -EINVAL;
}
data->durations[data->count] = ev.duration;
data->count++;
data->state = STATE_LEADER_PULSE;
return 0;
}
break;
}
IR_dprintk(1, "XMP decode failed at count %d state %d (%uus %s)\n",
data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler xmp_handler = {
.protocols = RC_BIT_XMP,
.decode = ir_xmp_decode,
};
static int __init ir_xmp_decode_init(void)
{
ir_raw_handler_register(&xmp_handler);
printk(KERN_INFO "IR XMP protocol handler initialized\n");
return 0;
}
static void __exit ir_xmp_decode_exit(void)
{
ir_raw_handler_unregister(&xmp_handler);
}
module_init(ir_xmp_decode_init);
module_exit(ir_xmp_decode_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marcel Mol <marcel@mesa.nl>");
MODULE_AUTHOR("MESA Consulting (http://www.mesa.nl)");
MODULE_DESCRIPTION("XMP IR protocol decoder");

1728
drivers/media/rc/ite-cir.c Normal file

File diff suppressed because it is too large Load diff

484
drivers/media/rc/ite-cir.h Normal file
View file

@ -0,0 +1,484 @@
/*
* Driver for ITE Tech Inc. IT8712F/IT8512F CIR
*
* Copyright (C) 2010 Juan Jesús García de Soria <skandalfo@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA.
*/
/* platform driver name to register */
#define ITE_DRIVER_NAME "ite-cir"
/* logging macros */
#define ite_pr(level, text, ...) \
printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
#define ite_dbg(text, ...) do { \
if (debug) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
} while (0)
#define ite_dbg_verbose(text, ...) do {\
if (debug > 1) \
printk(KERN_DEBUG \
KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
} while (0)
/* FIFO sizes */
#define ITE_TX_FIFO_LEN 32
#define ITE_RX_FIFO_LEN 32
/* interrupt types */
#define ITE_IRQ_TX_FIFO 1
#define ITE_IRQ_RX_FIFO 2
#define ITE_IRQ_RX_FIFO_OVERRUN 4
/* forward declaration */
struct ite_dev;
/* struct for storing the parameters of different recognized devices */
struct ite_dev_params {
/* model of the device */
const char *model;
/* size of the I/O region */
int io_region_size;
/* IR pnp I/O resource number */
int io_rsrc_no;
/* true if the hardware supports transmission */
bool hw_tx_capable;
/* base sampling period, in ns */
u32 sample_period;
/* rx low carrier frequency, in Hz, 0 means no demodulation */
unsigned int rx_low_carrier_freq;
/* tx high carrier frequency, in Hz, 0 means no demodulation */
unsigned int rx_high_carrier_freq;
/* tx carrier frequency, in Hz */
unsigned int tx_carrier_freq;
/* duty cycle, 0-100 */
int tx_duty_cycle;
/* hw-specific operation function pointers; most of these must be
* called while holding the spin lock, except for the TX FIFO length
* one */
/* get pending interrupt causes */
int (*get_irq_causes) (struct ite_dev *dev);
/* enable rx */
void (*enable_rx) (struct ite_dev *dev);
/* make rx enter the idle state; keep listening for a pulse, but stop
* streaming space bytes */
void (*idle_rx) (struct ite_dev *dev);
/* disable rx completely */
void (*disable_rx) (struct ite_dev *dev);
/* read bytes from RX FIFO; return read count */
int (*get_rx_bytes) (struct ite_dev *dev, u8 *buf, int buf_size);
/* enable tx FIFO space available interrupt */
void (*enable_tx_interrupt) (struct ite_dev *dev);
/* disable tx FIFO space available interrupt */
void (*disable_tx_interrupt) (struct ite_dev *dev);
/* get number of full TX FIFO slots */
int (*get_tx_used_slots) (struct ite_dev *dev);
/* put a byte to the TX FIFO */
void (*put_tx_byte) (struct ite_dev *dev, u8 value);
/* disable hardware completely */
void (*disable) (struct ite_dev *dev);
/* initialize the hardware */
void (*init_hardware) (struct ite_dev *dev);
/* set the carrier parameters */
void (*set_carrier_params) (struct ite_dev *dev, bool high_freq,
bool use_demodulator, u8 carrier_freq_bits,
u8 allowance_bits, u8 pulse_width_bits);
};
/* ITE CIR device structure */
struct ite_dev {
struct pnp_dev *pdev;
struct rc_dev *rdev;
struct ir_raw_event rawir;
/* sync data */
spinlock_t lock;
bool in_use, transmitting;
/* transmit support */
int tx_fifo_allowance;
wait_queue_head_t tx_queue, tx_ended;
/* hardware I/O settings */
unsigned long cir_addr;
int cir_irq;
/* overridable copy of model parameters */
struct ite_dev_params params;
};
/* common values for all kinds of hardware */
/* baud rate divisor default */
#define ITE_BAUDRATE_DIVISOR 1
/* low-speed carrier frequency limits (Hz) */
#define ITE_LCF_MIN_CARRIER_FREQ 27000
#define ITE_LCF_MAX_CARRIER_FREQ 58000
/* high-speed carrier frequency limits (Hz) */
#define ITE_HCF_MIN_CARRIER_FREQ 400000
#define ITE_HCF_MAX_CARRIER_FREQ 500000
/* default carrier freq for when demodulator is off (Hz) */
#define ITE_DEFAULT_CARRIER_FREQ 38000
/* default idling timeout in ns (0.2 seconds) */
#define ITE_IDLE_TIMEOUT 200000000UL
/* limit timeout values */
#define ITE_MIN_IDLE_TIMEOUT 100000000UL
#define ITE_MAX_IDLE_TIMEOUT 1000000000UL
/* convert bits to us */
#define ITE_BITS_TO_NS(bits, sample_period) \
((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period))
/*
* n in RDCR produces a tolerance of +/- n * 6.25% around the center
* carrier frequency...
*
* From two limit frequencies, L (low) and H (high), we can get both the
* center frequency F = (L + H) / 2 and the variation from the center
* frequency A = (H - L) / (H + L). We can use this in order to honor the
* s_rx_carrier_range() call in ir-core. We'll suppose that any request
* setting L=0 means we must shut down the demodulator.
*/
#define ITE_RXDCR_PER_10000_STEP 625
/* high speed carrier freq values */
#define ITE_CFQ_400 0x03
#define ITE_CFQ_450 0x08
#define ITE_CFQ_480 0x0b
#define ITE_CFQ_500 0x0d
/* values for pulse widths */
#define ITE_TXMPW_A 0x02
#define ITE_TXMPW_B 0x03
#define ITE_TXMPW_C 0x04
#define ITE_TXMPW_D 0x05
#define ITE_TXMPW_E 0x06
/* values for demodulator carrier range allowance */
#define ITE_RXDCR_DEFAULT 0x01 /* default carrier range */
#define ITE_RXDCR_MAX 0x07 /* default carrier range */
/* DR TX bits */
#define ITE_TX_PULSE 0x00
#define ITE_TX_SPACE 0x80
#define ITE_TX_MAX_RLE 0x80
#define ITE_TX_RLE_MASK 0x7f
/*
* IT8712F
*
* hardware data obtained from:
*
* IT8712F
* Environment Control Low Pin Count Input / Output
* (EC - LPC I/O)
* Preliminary Specification V0. 81
*/
/* register offsets */
#define IT87_DR 0x00 /* data register */
#define IT87_IER 0x01 /* interrupt enable register */
#define IT87_RCR 0x02 /* receiver control register */
#define IT87_TCR1 0x03 /* transmitter control register 1 */
#define IT87_TCR2 0x04 /* transmitter control register 2 */
#define IT87_TSR 0x05 /* transmitter status register */
#define IT87_RSR 0x06 /* receiver status register */
#define IT87_BDLR 0x05 /* baud rate divisor low byte register */
#define IT87_BDHR 0x06 /* baud rate divisor high byte register */
#define IT87_IIR 0x07 /* interrupt identification register */
#define IT87_IOREG_LENGTH 0x08 /* length of register file */
/* IER bits */
#define IT87_TLDLIE 0x01 /* transmitter low data interrupt enable */
#define IT87_RDAIE 0x02 /* receiver data available interrupt enable */
#define IT87_RFOIE 0x04 /* receiver FIFO overrun interrupt enable */
#define IT87_IEC 0x08 /* interrupt enable control */
#define IT87_BR 0x10 /* baud rate register enable */
#define IT87_RESET 0x20 /* reset */
/* RCR bits */
#define IT87_RXDCR 0x07 /* receiver demodulation carrier range mask */
#define IT87_RXACT 0x08 /* receiver active */
#define IT87_RXEND 0x10 /* receiver demodulation enable */
#define IT87_RXEN 0x20 /* receiver enable */
#define IT87_HCFS 0x40 /* high-speed carrier frequency select */
#define IT87_RDWOS 0x80 /* receiver data without sync */
/* TCR1 bits */
#define IT87_TXMPM 0x03 /* transmitter modulation pulse mode mask */
#define IT87_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */
#define IT87_TXENDF 0x04 /* transmitter deferral */
#define IT87_TXRLE 0x08 /* transmitter run length enable */
#define IT87_FIFOTL 0x30 /* FIFO level threshold mask */
#define IT87_FIFOTL_DEFAULT 0x20 /* FIFO level threshold default
* 0x00 -> 1, 0x10 -> 7, 0x20 -> 17,
* 0x30 -> 25 */
#define IT87_ILE 0x40 /* internal loopback enable */
#define IT87_FIFOCLR 0x80 /* FIFO clear bit */
/* TCR2 bits */
#define IT87_TXMPW 0x07 /* transmitter modulation pulse width mask */
#define IT87_TXMPW_DEFAULT 0x04 /* default modulation pulse width */
#define IT87_CFQ 0xf8 /* carrier frequency mask */
#define IT87_CFQ_SHIFT 3 /* carrier frequency bit shift */
/* TSR bits */
#define IT87_TXFBC 0x3f /* transmitter FIFO byte count mask */
/* RSR bits */
#define IT87_RXFBC 0x3f /* receiver FIFO byte count mask */
#define IT87_RXFTO 0x80 /* receiver FIFO time-out */
/* IIR bits */
#define IT87_IP 0x01 /* interrupt pending */
#define IT87_II 0x06 /* interrupt identification mask */
#define IT87_II_NOINT 0x00 /* no interrupt */
#define IT87_II_TXLDL 0x02 /* transmitter low data level */
#define IT87_II_RXDS 0x04 /* receiver data stored */
#define IT87_II_RXFO 0x06 /* receiver FIFO overrun */
/*
* IT8512E/F
*
* Hardware data obtained from:
*
* IT8512E/F
* Embedded Controller
* Preliminary Specification V0.4.1
*
* Note that the CIR registers are not directly available to the host, because
* they only are accessible to the integrated microcontroller. Thus, in order
* use it, some kind of bridging is required. As the bridging may depend on
* the controller firmware in use, we are going to use the PNP ID in order to
* determine the strategy and ports available. See after these generic
* IT8512E/F register definitions for register definitions for those
* strategies.
*/
/* register offsets */
#define IT85_C0DR 0x00 /* data register */
#define IT85_C0MSTCR 0x01 /* master control register */
#define IT85_C0IER 0x02 /* interrupt enable register */
#define IT85_C0IIR 0x03 /* interrupt identification register */
#define IT85_C0CFR 0x04 /* carrier frequency register */
#define IT85_C0RCR 0x05 /* receiver control register */
#define IT85_C0TCR 0x06 /* transmitter control register */
#define IT85_C0SCK 0x07 /* slow clock control register */
#define IT85_C0BDLR 0x08 /* baud rate divisor low byte register */
#define IT85_C0BDHR 0x09 /* baud rate divisor high byte register */
#define IT85_C0TFSR 0x0a /* transmitter FIFO status register */
#define IT85_C0RFSR 0x0b /* receiver FIFO status register */
#define IT85_C0WCL 0x0d /* wakeup code length register */
#define IT85_C0WCR 0x0e /* wakeup code read/write register */
#define IT85_C0WPS 0x0f /* wakeup power control/status register */
#define IT85_IOREG_LENGTH 0x10 /* length of register file */
/* C0MSTCR bits */
#define IT85_RESET 0x01 /* reset */
#define IT85_FIFOCLR 0x02 /* FIFO clear bit */
#define IT85_FIFOTL 0x0c /* FIFO level threshold mask */
#define IT85_FIFOTL_DEFAULT 0x08 /* FIFO level threshold default
* 0x00 -> 1, 0x04 -> 7, 0x08 -> 17,
* 0x0c -> 25 */
#define IT85_ILE 0x10 /* internal loopback enable */
#define IT85_ILSEL 0x20 /* internal loopback select */
/* C0IER bits */
#define IT85_TLDLIE 0x01 /* TX low data level interrupt enable */
#define IT85_RDAIE 0x02 /* RX data available interrupt enable */
#define IT85_RFOIE 0x04 /* RX FIFO overrun interrupt enable */
#define IT85_IEC 0x80 /* interrupt enable function control */
/* C0IIR bits */
#define IT85_TLDLI 0x01 /* transmitter low data level interrupt */
#define IT85_RDAI 0x02 /* receiver data available interrupt */
#define IT85_RFOI 0x04 /* receiver FIFO overrun interrupt */
#define IT85_NIP 0x80 /* no interrupt pending */
/* C0CFR bits */
#define IT85_CFQ 0x1f /* carrier frequency mask */
#define IT85_HCFS 0x20 /* high speed carrier frequency select */
/* C0RCR bits */
#define IT85_RXDCR 0x07 /* receiver demodulation carrier range mask */
#define IT85_RXACT 0x08 /* receiver active */
#define IT85_RXEND 0x10 /* receiver demodulation enable */
#define IT85_RDWOS 0x20 /* receiver data without sync */
#define IT85_RXEN 0x80 /* receiver enable */
/* C0TCR bits */
#define IT85_TXMPW 0x07 /* transmitter modulation pulse width mask */
#define IT85_TXMPW_DEFAULT 0x04 /* default modulation pulse width */
#define IT85_TXMPM 0x18 /* transmitter modulation pulse mode mask */
#define IT85_TXMPM_DEFAULT 0x00 /* modulation pulse mode default */
#define IT85_TXENDF 0x20 /* transmitter deferral */
#define IT85_TXRLE 0x40 /* transmitter run length enable */
/* C0SCK bits */
#define IT85_SCKS 0x01 /* slow clock select */
#define IT85_TXDCKG 0x02 /* TXD clock gating */
#define IT85_DLL1P8E 0x04 /* DLL 1.8432M enable */
#define IT85_DLLTE 0x08 /* DLL test enable */
#define IT85_BRCM 0x70 /* baud rate count mode */
#define IT85_DLLOCK 0x80 /* DLL lock */
/* C0TFSR bits */
#define IT85_TXFBC 0x3f /* transmitter FIFO count mask */
/* C0RFSR bits */
#define IT85_RXFBC 0x3f /* receiver FIFO count mask */
#define IT85_RXFTO 0x80 /* receiver FIFO time-out */
/* C0WCL bits */
#define IT85_WCL 0x3f /* wakeup code length mask */
/* C0WPS bits */
#define IT85_CIRPOSIE 0x01 /* power on/off status interrupt enable */
#define IT85_CIRPOIS 0x02 /* power on/off interrupt status */
#define IT85_CIRPOII 0x04 /* power on/off interrupt identification */
#define IT85_RCRST 0x10 /* wakeup code reading counter reset bit */
#define IT85_WCRST 0x20 /* wakeup code writing counter reset bit */
/*
* ITE8708
*
* Hardware data obtained from hacked driver for IT8512 in this forum post:
*
* http://ubuntuforums.org/showthread.php?t=1028640
*
* Although there's no official documentation for that driver, analysis would
* suggest that it maps the 16 registers of IT8512 onto two 8-register banks,
* selectable by a single bank-select bit that's mapped onto both banks. The
* IT8512 registers are mapped in a different order, so that the first bank
* maps the ones that are used more often, and two registers that share a
* reserved high-order bit are placed at the same offset in both banks in
* order to reuse the reserved bit as the bank select bit.
*/
/* register offsets */
/* mapped onto both banks */
#define IT8708_BANKSEL 0x07 /* bank select register */
#define IT8708_HRAE 0x80 /* high registers access enable */
/* mapped onto the low bank */
#define IT8708_C0DR 0x00 /* data register */
#define IT8708_C0MSTCR 0x01 /* master control register */
#define IT8708_C0IER 0x02 /* interrupt enable register */
#define IT8708_C0IIR 0x03 /* interrupt identification register */
#define IT8708_C0RFSR 0x04 /* receiver FIFO status register */
#define IT8708_C0RCR 0x05 /* receiver control register */
#define IT8708_C0TFSR 0x06 /* transmitter FIFO status register */
#define IT8708_C0TCR 0x07 /* transmitter control register */
/* mapped onto the high bank */
#define IT8708_C0BDLR 0x01 /* baud rate divisor low byte register */
#define IT8708_C0BDHR 0x02 /* baud rate divisor high byte register */
#define IT8708_C0CFR 0x04 /* carrier frequency register */
/* registers whose bank mapping we don't know, since they weren't being used
* in the hacked driver... most probably they belong to the high bank too,
* since they fit in the holes the other registers leave */
#define IT8708_C0SCK 0x03 /* slow clock control register */
#define IT8708_C0WCL 0x05 /* wakeup code length register */
#define IT8708_C0WCR 0x06 /* wakeup code read/write register */
#define IT8708_C0WPS 0x07 /* wakeup power control/status register */
#define IT8708_IOREG_LENGTH 0x08 /* length of register file */
/* two more registers that are defined in the hacked driver, but can't be
* found in the data sheets; no idea what they are or how they are accessed,
* since the hacked driver doesn't seem to use them */
#define IT8708_CSCRR 0x00
#define IT8708_CGPINTR 0x01
/* CSCRR bits */
#define IT8708_CSCRR_SCRB 0x3f
#define IT8708_CSCRR_PM 0x80
/* CGPINTR bits */
#define IT8708_CGPINT 0x01
/*
* ITE8709
*
* Hardware interfacing data obtained from the original lirc_ite8709 driver.
* Verbatim from its sources:
*
* The ITE8709 device seems to be the combination of IT8512 superIO chip and
* a specific firmware running on the IT8512's embedded micro-controller.
* In addition of the embedded micro-controller, the IT8512 chip contains a
* CIR module and several other modules. A few modules are directly accessible
* by the host CPU, but most of them are only accessible by the
* micro-controller. The CIR module is only accessible by the
* micro-controller.
*
* The battery-backed SRAM module is accessible by the host CPU and the
* micro-controller. So one of the MC's firmware role is to act as a bridge
* between the host CPU and the CIR module. The firmware implements a kind of
* communication protocol using the SRAM module as a shared memory. The IT8512
* specification is publicly available on ITE's web site, but the
* communication protocol is not, so it was reverse-engineered.
*/
/* register offsets */
#define IT8709_RAM_IDX 0x00 /* index into the SRAM module bytes */
#define IT8709_RAM_VAL 0x01 /* read/write data to the indexed byte */
#define IT8709_IOREG_LENGTH 0x02 /* length of register file */
/* register offsets inside the SRAM module */
#define IT8709_MODE 0x1a /* request/ack byte */
#define IT8709_REG_IDX 0x1b /* index of the CIR register to access */
#define IT8709_REG_VAL 0x1c /* value read/to be written */
#define IT8709_IIR 0x1e /* interrupt identification register */
#define IT8709_RFSR 0x1f /* receiver FIFO status register */
#define IT8709_FIFO 0x20 /* start of in RAM RX FIFO copy */
/* MODE values */
#define IT8709_IDLE 0x00
#define IT8709_WRITE 0x01
#define IT8709_READ 0x02

View file

@ -0,0 +1,15 @@
config RC_MAP
tristate "Compile Remote Controller keymap modules"
depends on RC_CORE
default y
---help---
This option enables the compilation of lots of Remote
Controller tables. They are short tables, but if you
don't use a remote controller, or prefer to load the
tables on userspace, you should disable it.
The ir-keytable program, available at v4l-utils package
provide the tool and the same RC maps for load from
userspace. Its available at
http://git.linuxtv.org/cgit.cgi/v4l-utils.git/

View file

@ -0,0 +1,103 @@
obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-alink-dtu-m.o \
rc-anysee.o \
rc-apac-viewcomp.o \
rc-asus-pc39.o \
rc-asus-ps3-100.o \
rc-ati-tv-wonder-hd-600.o \
rc-ati-x10.o \
rc-avermedia-a16d.o \
rc-avermedia.o \
rc-avermedia-cardbus.o \
rc-avermedia-dvbt.o \
rc-avermedia-m135a.o \
rc-avermedia-m733a-rm-k6.o \
rc-avermedia-rm-ks.o \
rc-avertv-303.o \
rc-azurewave-ad-tu700.o \
rc-behold.o \
rc-behold-columbus.o \
rc-budget-ci-old.o \
rc-cinergy-1400.o \
rc-cinergy.o \
rc-delock-61959.o \
rc-dib0700-nec.o \
rc-dib0700-rc5.o \
rc-digitalnow-tinytwin.o \
rc-digittrade.o \
rc-dm1105-nec.o \
rc-dntv-live-dvb-t.o \
rc-dntv-live-dvbt-pro.o \
rc-dvbsky.o \
rc-em-terratec.o \
rc-encore-enltv2.o \
rc-encore-enltv.o \
rc-encore-enltv-fm53.o \
rc-evga-indtube.o \
rc-eztv.o \
rc-flydvb.o \
rc-flyvideo.o \
rc-fusionhdtv-mce.o \
rc-gadmei-rm008z.o \
rc-genius-tvgo-a11mce.o \
rc-gotview7135.o \
rc-imon-mce.o \
rc-imon-pad.o \
rc-iodata-bctv7e.o \
rc-it913x-v1.o \
rc-it913x-v2.o \
rc-kaiomy.o \
rc-kworld-315u.o \
rc-kworld-pc150u.o \
rc-kworld-plus-tv-analog.o \
rc-leadtek-y04g0051.o \
rc-lirc.o \
rc-lme2510.o \
rc-manli.o \
rc-medion-x10.o \
rc-medion-x10-digitainer.o \
rc-medion-x10-or2x.o \
rc-msi-digivox-ii.o \
rc-msi-digivox-iii.o \
rc-msi-tvanywhere.o \
rc-msi-tvanywhere-plus.o \
rc-nebula.o \
rc-nec-terratec-cinergy-xs.o \
rc-norwood.o \
rc-npgtech.o \
rc-pctv-sedna.o \
rc-pinnacle-color.o \
rc-pinnacle-grey.o \
rc-pinnacle-pctv-hd.o \
rc-pixelview.o \
rc-pixelview-mk12.o \
rc-pixelview-002t.o \
rc-pixelview-new.o \
rc-powercolor-real-angel.o \
rc-proteus-2309.o \
rc-purpletv.o \
rc-pv951.o \
rc-hauppauge.o \
rc-rc6-mce.o \
rc-real-audio-220-32-keys.o \
rc-reddo.o \
rc-snapstream-firefly.o \
rc-streamzap.o \
rc-tbs-nec.o \
rc-technisat-usb2.o \
rc-terratec-cinergy-xs.o \
rc-terratec-slim.o \
rc-terratec-slim-2.o \
rc-tevii-nec.o \
rc-tivo.o \
rc-total-media-in-hand.o \
rc-total-media-in-hand-02.o \
rc-trekstor.o \
rc-tt-1500.o \
rc-twinhan1027.o \
rc-videomate-m1f.o \
rc-videomate-s350.o \
rc-videomate-tv-pvr.o \
rc-winfast.o \
rc-winfast-usbii-deluxe.o \
rc-su3000.o

View file

@ -0,0 +1,90 @@
/* adstech-dvb-t-pci.h - Keytable for adstech_dvb_t_pci Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* ADS Tech Instant TV DVB-T PCI Remote */
static struct rc_map_table adstech_dvb_t_pci[] = {
/* Keys 0 to 9 */
{ 0x4d, KEY_0 },
{ 0x57, KEY_1 },
{ 0x4f, KEY_2 },
{ 0x53, KEY_3 },
{ 0x56, KEY_4 },
{ 0x4e, KEY_5 },
{ 0x5e, KEY_6 },
{ 0x54, KEY_7 },
{ 0x4c, KEY_8 },
{ 0x5c, KEY_9 },
{ 0x5b, KEY_POWER },
{ 0x5f, KEY_MUTE },
{ 0x55, KEY_GOTO },
{ 0x5d, KEY_SEARCH },
{ 0x17, KEY_EPG }, /* Guide */
{ 0x1f, KEY_MENU },
{ 0x0f, KEY_UP },
{ 0x46, KEY_DOWN },
{ 0x16, KEY_LEFT },
{ 0x1e, KEY_RIGHT },
{ 0x0e, KEY_SELECT }, /* Enter */
{ 0x5a, KEY_INFO },
{ 0x52, KEY_EXIT },
{ 0x59, KEY_PREVIOUS },
{ 0x51, KEY_NEXT },
{ 0x58, KEY_REWIND },
{ 0x50, KEY_FORWARD },
{ 0x44, KEY_PLAYPAUSE },
{ 0x07, KEY_STOP },
{ 0x1b, KEY_RECORD },
{ 0x13, KEY_TUNER }, /* Live */
{ 0x0a, KEY_A },
{ 0x12, KEY_B },
{ 0x03, KEY_RED }, /* 1 */
{ 0x01, KEY_GREEN }, /* 2 */
{ 0x00, KEY_YELLOW }, /* 3 */
{ 0x06, KEY_DVD },
{ 0x48, KEY_AUX }, /* Photo */
{ 0x40, KEY_VIDEO },
{ 0x19, KEY_AUDIO }, /* Music */
{ 0x0b, KEY_CHANNELUP },
{ 0x08, KEY_CHANNELDOWN },
{ 0x15, KEY_VOLUMEUP },
{ 0x1c, KEY_VOLUMEDOWN },
};
static struct rc_map_list adstech_dvb_t_pci_map = {
.map = {
.scan = adstech_dvb_t_pci,
.size = ARRAY_SIZE(adstech_dvb_t_pci),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_ADSTECH_DVB_T_PCI,
}
};
static int __init init_rc_map_adstech_dvb_t_pci(void)
{
return rc_map_register(&adstech_dvb_t_pci_map);
}
static void __exit exit_rc_map_adstech_dvb_t_pci(void)
{
rc_map_unregister(&adstech_dvb_t_pci_map);
}
module_init(init_rc_map_adstech_dvb_t_pci)
module_exit(exit_rc_map_adstech_dvb_t_pci)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,69 @@
/*
* A-Link DTU(m) remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* A-Link DTU(m) slim remote, 6 rows, 3 columns. */
static struct rc_map_table alink_dtu_m[] = {
{ 0x0800, KEY_VOLUMEUP },
{ 0x0801, KEY_1 },
{ 0x0802, KEY_3 },
{ 0x0803, KEY_7 },
{ 0x0804, KEY_9 },
{ 0x0805, KEY_NEW }, /* symbol: PIP */
{ 0x0806, KEY_0 },
{ 0x0807, KEY_CHANNEL }, /* JUMP */
{ 0x080d, KEY_5 },
{ 0x080f, KEY_2 },
{ 0x0812, KEY_POWER2 },
{ 0x0814, KEY_CHANNELUP },
{ 0x0816, KEY_VOLUMEDOWN },
{ 0x0818, KEY_6 },
{ 0x081a, KEY_MUTE },
{ 0x081b, KEY_8 },
{ 0x081c, KEY_4 },
{ 0x081d, KEY_CHANNELDOWN },
};
static struct rc_map_list alink_dtu_m_map = {
.map = {
.scan = alink_dtu_m,
.size = ARRAY_SIZE(alink_dtu_m),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_ALINK_DTU_M,
}
};
static int __init init_rc_map_alink_dtu_m(void)
{
return rc_map_register(&alink_dtu_m_map);
}
static void __exit exit_rc_map_alink_dtu_m(void)
{
rc_map_unregister(&alink_dtu_m_map);
}
module_init(init_rc_map_alink_dtu_m)
module_exit(exit_rc_map_alink_dtu_m)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,94 @@
/*
* Anysee remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table anysee[] = {
{ 0x0800, KEY_0 },
{ 0x0801, KEY_1 },
{ 0x0802, KEY_2 },
{ 0x0803, KEY_3 },
{ 0x0804, KEY_4 },
{ 0x0805, KEY_5 },
{ 0x0806, KEY_6 },
{ 0x0807, KEY_7 },
{ 0x0808, KEY_8 },
{ 0x0809, KEY_9 },
{ 0x080a, KEY_POWER2 }, /* [red power button] */
{ 0x080b, KEY_VIDEO }, /* [*] MODE */
{ 0x080c, KEY_CHANNEL }, /* [symbol counterclockwise arrow] */
{ 0x080d, KEY_NEXT }, /* [>>|] */
{ 0x080e, KEY_MENU }, /* MENU */
{ 0x080f, KEY_EPG }, /* [EPG] */
{ 0x0810, KEY_CLEAR }, /* EXIT */
{ 0x0811, KEY_CHANNELUP },
{ 0x0812, KEY_VOLUMEDOWN },
{ 0x0813, KEY_VOLUMEUP },
{ 0x0814, KEY_CHANNELDOWN },
{ 0x0815, KEY_OK },
{ 0x0816, KEY_RADIO }, /* [symbol TV/radio] */
{ 0x0817, KEY_INFO }, /* [i] */
{ 0x0818, KEY_PREVIOUS }, /* [|<<] */
{ 0x0819, KEY_FAVORITES }, /* FAV. */
{ 0x081a, KEY_SUBTITLE }, /* Subtitle */
{ 0x081b, KEY_CAMERA }, /* [symbol camera] */
{ 0x081c, KEY_YELLOW },
{ 0x081d, KEY_RED },
{ 0x081e, KEY_LANGUAGE }, /* [symbol Second Audio Program] */
{ 0x081f, KEY_GREEN },
{ 0x0820, KEY_SLEEP }, /* Sleep */
{ 0x0821, KEY_SCREEN }, /* 16:9 / 4:3 */
{ 0x0822, KEY_ZOOM }, /* SIZE */
{ 0x0824, KEY_FN }, /* [F1] */
{ 0x0825, KEY_FN }, /* [F2] */
{ 0x0842, KEY_MUTE }, /* symbol mute */
{ 0x0844, KEY_BLUE },
{ 0x0847, KEY_TEXT }, /* TEXT */
{ 0x0848, KEY_STOP },
{ 0x0849, KEY_RECORD },
{ 0x0850, KEY_PLAY },
{ 0x0851, KEY_PAUSE },
};
static struct rc_map_list anysee_map = {
.map = {
.scan = anysee,
.size = ARRAY_SIZE(anysee),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_ANYSEE,
}
};
static int __init init_rc_map_anysee(void)
{
return rc_map_register(&anysee_map);
}
static void __exit exit_rc_map_anysee(void)
{
rc_map_unregister(&anysee_map);
}
module_init(init_rc_map_anysee)
module_exit(exit_rc_map_anysee)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,81 @@
/* apac-viewcomp.h - Keytable for apac_viewcomp Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Attila Kondoros <attila.kondoros@chello.hu> */
static struct rc_map_table apac_viewcomp[] = {
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x00, KEY_0 },
{ 0x17, KEY_LAST }, /* +100 */
{ 0x0a, KEY_LIST }, /* recall */
{ 0x1c, KEY_TUNER }, /* TV/FM */
{ 0x15, KEY_SEARCH }, /* scan */
{ 0x12, KEY_POWER }, /* power */
{ 0x1f, KEY_VOLUMEDOWN }, /* vol up */
{ 0x1b, KEY_VOLUMEUP }, /* vol down */
{ 0x1e, KEY_CHANNELDOWN }, /* chn up */
{ 0x1a, KEY_CHANNELUP }, /* chn down */
{ 0x11, KEY_VIDEO }, /* video */
{ 0x0f, KEY_ZOOM }, /* full screen */
{ 0x13, KEY_MUTE }, /* mute/unmute */
{ 0x10, KEY_TEXT }, /* min */
{ 0x0d, KEY_STOP }, /* freeze */
{ 0x0e, KEY_RECORD }, /* record */
{ 0x1d, KEY_PLAYPAUSE }, /* stop */
{ 0x19, KEY_PLAY }, /* play */
{ 0x16, KEY_GOTO }, /* osd */
{ 0x14, KEY_REFRESH }, /* default */
{ 0x0c, KEY_KPPLUS }, /* fine tune >>>> */
{ 0x18, KEY_KPMINUS }, /* fine tune <<<< */
};
static struct rc_map_list apac_viewcomp_map = {
.map = {
.scan = apac_viewcomp,
.size = ARRAY_SIZE(apac_viewcomp),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_APAC_VIEWCOMP,
}
};
static int __init init_rc_map_apac_viewcomp(void)
{
return rc_map_register(&apac_viewcomp_map);
}
static void __exit exit_rc_map_apac_viewcomp(void)
{
rc_map_unregister(&apac_viewcomp_map);
}
module_init(init_rc_map_apac_viewcomp)
module_exit(exit_rc_map_apac_viewcomp)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,92 @@
/* asus-pc39.h - Keytable for asus_pc39 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Marc Fargas <telenieko@telenieko.com>
* this is the remote control that comes with the asus p7131
* which has a label saying is "Model PC-39"
*/
static struct rc_map_table asus_pc39[] = {
/* Keys 0 to 9 */
{ 0x082a, KEY_0 },
{ 0x0816, KEY_1 },
{ 0x0812, KEY_2 },
{ 0x0814, KEY_3 },
{ 0x0836, KEY_4 },
{ 0x0832, KEY_5 },
{ 0x0834, KEY_6 },
{ 0x080e, KEY_7 },
{ 0x080a, KEY_8 },
{ 0x080c, KEY_9 },
{ 0x0801, KEY_RADIO }, /* radio */
{ 0x083c, KEY_MENU }, /* dvd/menu */
{ 0x0815, KEY_VOLUMEUP },
{ 0x0826, KEY_VOLUMEDOWN },
{ 0x0808, KEY_UP },
{ 0x0804, KEY_DOWN },
{ 0x0818, KEY_LEFT },
{ 0x0810, KEY_RIGHT },
{ 0x081a, KEY_VIDEO }, /* video */
{ 0x0806, KEY_AUDIO }, /* music */
{ 0x081e, KEY_TV }, /* tv */
{ 0x0822, KEY_EXIT }, /* back */
{ 0x0835, KEY_CHANNELUP }, /* channel / program + */
{ 0x0824, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x0825, KEY_ENTER }, /* enter */
{ 0x0839, KEY_PAUSE }, /* play/pause */
{ 0x0821, KEY_PREVIOUS }, /* rew */
{ 0x0819, KEY_NEXT }, /* forward */
{ 0x0831, KEY_REWIND }, /* backward << */
{ 0x0805, KEY_FASTFORWARD }, /* forward >> */
{ 0x0809, KEY_STOP },
{ 0x0811, KEY_RECORD }, /* recording */
{ 0x0829, KEY_POWER }, /* the button that reads "close" */
{ 0x082e, KEY_ZOOM }, /* full screen */
{ 0x082c, KEY_MACRO }, /* recall */
{ 0x081c, KEY_HOME }, /* home */
{ 0x083a, KEY_PVR }, /* picture */
{ 0x0802, KEY_MUTE }, /* mute */
{ 0x083e, KEY_DVD }, /* dvd */
};
static struct rc_map_list asus_pc39_map = {
.map = {
.scan = asus_pc39,
.size = ARRAY_SIZE(asus_pc39),
.rc_type = RC_TYPE_RC5,
.name = RC_MAP_ASUS_PC39,
}
};
static int __init init_rc_map_asus_pc39(void)
{
return rc_map_register(&asus_pc39_map);
}
static void __exit exit_rc_map_asus_pc39(void)
{
rc_map_unregister(&asus_pc39_map);
}
module_init(init_rc_map_asus_pc39)
module_exit(exit_rc_map_asus_pc39)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,91 @@
/* asus-ps3-100.h - Keytable for asus_ps3_100 Remote Controller
*
* Copyright (c) 2012 by Mauro Carvalho Chehab
*
* Based on a previous patch from Remi Schwartz <remi.schwartz@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table asus_ps3_100[] = {
{ 0x081c, KEY_HOME }, /* home */
{ 0x081e, KEY_TV }, /* tv */
{ 0x0803, KEY_TEXT }, /* teletext */
{ 0x0829, KEY_POWER }, /* close */
{ 0x080b, KEY_RED }, /* red */
{ 0x080d, KEY_YELLOW }, /* yellow */
{ 0x0806, KEY_BLUE }, /* blue */
{ 0x0807, KEY_GREEN }, /* green */
/* Keys 0 to 9 */
{ 0x082a, KEY_0 },
{ 0x0816, KEY_1 },
{ 0x0812, KEY_2 },
{ 0x0814, KEY_3 },
{ 0x0836, KEY_4 },
{ 0x0832, KEY_5 },
{ 0x0834, KEY_6 },
{ 0x080e, KEY_7 },
{ 0x080a, KEY_8 },
{ 0x080c, KEY_9 },
{ 0x0815, KEY_VOLUMEUP },
{ 0x0826, KEY_VOLUMEDOWN },
{ 0x0835, KEY_CHANNELUP }, /* channel / program + */
{ 0x0824, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x0808, KEY_UP },
{ 0x0804, KEY_DOWN },
{ 0x0818, KEY_LEFT },
{ 0x0810, KEY_RIGHT },
{ 0x0825, KEY_ENTER }, /* enter */
{ 0x0822, KEY_EXIT }, /* back */
{ 0x082c, KEY_AB }, /* recall */
{ 0x0820, KEY_AUDIO }, /* TV audio */
{ 0x0837, KEY_SCREEN }, /* snapshot */
{ 0x082e, KEY_ZOOM }, /* full screen */
{ 0x0802, KEY_MUTE }, /* mute */
{ 0x0831, KEY_REWIND }, /* backward << */
{ 0x0811, KEY_RECORD }, /* recording */
{ 0x0809, KEY_STOP },
{ 0x0805, KEY_FASTFORWARD }, /* forward >> */
{ 0x0821, KEY_PREVIOUS }, /* rew */
{ 0x081a, KEY_PAUSE }, /* pause */
{ 0x0839, KEY_PLAY }, /* play */
{ 0x0819, KEY_NEXT }, /* forward */
};
static struct rc_map_list asus_ps3_100_map = {
.map = {
.scan = asus_ps3_100,
.size = ARRAY_SIZE(asus_ps3_100),
.rc_type = RC_TYPE_RC5,
.name = RC_MAP_ASUS_PS3_100,
}
};
static int __init init_rc_map_asus_ps3_100(void)
{
return rc_map_register(&asus_ps3_100_map);
}
static void __exit exit_rc_map_asus_ps3_100(void)
{
rc_map_unregister(&asus_ps3_100_map);
}
module_init(init_rc_map_asus_ps3_100)
module_exit(exit_rc_map_asus_ps3_100)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,70 @@
/* ati-tv-wonder-hd-600.h - Keytable for ati_tv_wonder_hd_600 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* ATI TV Wonder HD 600 USB
Devin Heitmueller <devin.heitmueller@gmail.com>
*/
static struct rc_map_table ati_tv_wonder_hd_600[] = {
{ 0x00, KEY_RECORD}, /* Row 1 */
{ 0x01, KEY_PLAYPAUSE},
{ 0x02, KEY_STOP},
{ 0x03, KEY_POWER},
{ 0x04, KEY_PREVIOUS}, /* Row 2 */
{ 0x05, KEY_REWIND},
{ 0x06, KEY_FORWARD},
{ 0x07, KEY_NEXT},
{ 0x08, KEY_EPG}, /* Row 3 */
{ 0x09, KEY_HOME},
{ 0x0a, KEY_MENU},
{ 0x0b, KEY_CHANNELUP},
{ 0x0c, KEY_BACK}, /* Row 4 */
{ 0x0d, KEY_UP},
{ 0x0e, KEY_INFO},
{ 0x0f, KEY_CHANNELDOWN},
{ 0x10, KEY_LEFT}, /* Row 5 */
{ 0x11, KEY_SELECT},
{ 0x12, KEY_RIGHT},
{ 0x13, KEY_VOLUMEUP},
{ 0x14, KEY_LAST}, /* Row 6 */
{ 0x15, KEY_DOWN},
{ 0x16, KEY_MUTE},
{ 0x17, KEY_VOLUMEDOWN},
};
static struct rc_map_list ati_tv_wonder_hd_600_map = {
.map = {
.scan = ati_tv_wonder_hd_600,
.size = ARRAY_SIZE(ati_tv_wonder_hd_600),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_ATI_TV_WONDER_HD_600,
}
};
static int __init init_rc_map_ati_tv_wonder_hd_600(void)
{
return rc_map_register(&ati_tv_wonder_hd_600_map);
}
static void __exit exit_rc_map_ati_tv_wonder_hd_600(void)
{
rc_map_unregister(&ati_tv_wonder_hd_600_map);
}
module_init(init_rc_map_ati_tv_wonder_hd_600)
module_exit(exit_rc_map_ati_tv_wonder_hd_600)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,138 @@
/*
* ATI X10 RF remote keytable
*
* Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
*
* This file is based on the static generic keytable previously found in
* ati_remote.c, which is
* Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
* Copyright (c) 2002 Vladimir Dergachev
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/module.h>
#include <media/rc-map.h>
/*
* Intended usage comments below are from vendor-supplied
* Source: ATI REMOTE WONDER Installation Guide
* http://www2.ati.com/manuals/remctrl.pdf
*
* Scancodes were in strict left-right, top-bottom order on the
* original ATI Remote Wonder, but were moved on later models.
*
* Keys A-F are intended to be user-programmable.
*/
static struct rc_map_table ati_x10[] = {
/* keyboard - Above the cursor pad */
{ 0x00, KEY_A },
{ 0x01, KEY_B },
{ 0x02, KEY_POWER }, /* Power */
{ 0x03, KEY_TV }, /* TV */
{ 0x04, KEY_DVD }, /* DVD */
{ 0x05, KEY_WWW }, /* WEB */
{ 0x06, KEY_BOOKMARKS }, /* "book": Open Media Library */
{ 0x07, KEY_EDIT }, /* "hand": Toggle left mouse button (grab) */
/* Mouse emulation pad goes here, handled by driver separately */
{ 0x09, KEY_VOLUMEDOWN }, /* VOL + */
{ 0x08, KEY_VOLUMEUP }, /* VOL - */
{ 0x0a, KEY_MUTE }, /* MUTE */
{ 0x0b, KEY_CHANNELUP }, /* CH + */
{ 0x0c, KEY_CHANNELDOWN },/* CH - */
/*
* We could use KEY_NUMERIC_x for these, but the X11 protocol
* has problems with keycodes greater than 255, so avoid those high
* keycodes in default maps.
*/
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
{ 0x10, KEY_4 },
{ 0x11, KEY_5 },
{ 0x12, KEY_6 },
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
{ 0x16, KEY_MENU }, /* "menu": DVD root menu */
/* KEY_NUMERIC_STAR? */
{ 0x17, KEY_0 },
{ 0x18, KEY_SETUP }, /* "check": DVD setup menu */
/* KEY_NUMERIC_POUND? */
/* DVD navigation buttons */
{ 0x19, KEY_C },
{ 0x1a, KEY_UP }, /* up */
{ 0x1b, KEY_D },
{ 0x1c, KEY_PROPS }, /* "timer" Should be Data On Screen */
/* Symbol is "circle nailed to box" */
{ 0x1d, KEY_LEFT }, /* left */
{ 0x1e, KEY_OK }, /* "OK" */
{ 0x1f, KEY_RIGHT }, /* right */
{ 0x20, KEY_SCREEN }, /* "max" (X11 warning: 0x177) */
/* Should be AC View Toggle, but
that's not in <input/input.h>.
KEY_ZOOM (0x174)? */
{ 0x21, KEY_E },
{ 0x22, KEY_DOWN }, /* down */
{ 0x23, KEY_F },
/* Play/stop/pause buttons */
{ 0x24, KEY_REWIND }, /* (<<) Rewind */
{ 0x25, KEY_PLAY }, /* ( >) Play (KEY_PLAYCD?) */
{ 0x26, KEY_FASTFORWARD }, /* (>>) Fast forward */
{ 0x27, KEY_RECORD }, /* ( o) red */
{ 0x28, KEY_STOPCD }, /* ([]) Stop (KEY_STOP is something else!) */
{ 0x29, KEY_PAUSE }, /* ('') Pause (KEY_PAUSECD?) */
/* Extra keys, not on the original ATI remote */
{ 0x2a, KEY_NEXT }, /* (>+) */
{ 0x2b, KEY_PREVIOUS }, /* (<-) */
{ 0x2d, KEY_INFO }, /* PLAYING (X11 warning: 0x166) */
{ 0x2e, KEY_HOME }, /* TOP */
{ 0x2f, KEY_END }, /* END */
{ 0x30, KEY_SELECT }, /* SELECT (X11 warning: 0x161) */
};
static struct rc_map_list ati_x10_map = {
.map = {
.scan = ati_x10,
.size = ARRAY_SIZE(ati_x10),
.rc_type = RC_TYPE_OTHER,
.name = RC_MAP_ATI_X10,
}
};
static int __init init_rc_map_ati_x10(void)
{
return rc_map_register(&ati_x10_map);
}
static void __exit exit_rc_map_ati_x10(void)
{
rc_map_unregister(&ati_x10_map);
}
module_init(init_rc_map_ati_x10)
module_exit(exit_rc_map_ati_x10)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");

View file

@ -0,0 +1,76 @@
/* avermedia-a16d.h - Keytable for avermedia_a16d Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table avermedia_a16d[] = {
{ 0x20, KEY_LIST},
{ 0x00, KEY_POWER},
{ 0x28, KEY_1},
{ 0x18, KEY_2},
{ 0x38, KEY_3},
{ 0x24, KEY_4},
{ 0x14, KEY_5},
{ 0x34, KEY_6},
{ 0x2c, KEY_7},
{ 0x1c, KEY_8},
{ 0x3c, KEY_9},
{ 0x12, KEY_SUBTITLE},
{ 0x22, KEY_0},
{ 0x32, KEY_REWIND},
{ 0x3a, KEY_SHUFFLE},
{ 0x02, KEY_PRINT},
{ 0x11, KEY_CHANNELDOWN},
{ 0x31, KEY_CHANNELUP},
{ 0x0c, KEY_ZOOM},
{ 0x1e, KEY_VOLUMEDOWN},
{ 0x3e, KEY_VOLUMEUP},
{ 0x0a, KEY_MUTE},
{ 0x04, KEY_AUDIO},
{ 0x26, KEY_RECORD},
{ 0x06, KEY_PLAY},
{ 0x36, KEY_STOP},
{ 0x16, KEY_PAUSE},
{ 0x2e, KEY_REWIND},
{ 0x0e, KEY_FASTFORWARD},
{ 0x30, KEY_TEXT},
{ 0x21, KEY_GREEN},
{ 0x01, KEY_BLUE},
{ 0x08, KEY_EPG},
{ 0x2a, KEY_MENU},
};
static struct rc_map_list avermedia_a16d_map = {
.map = {
.scan = avermedia_a16d,
.size = ARRAY_SIZE(avermedia_a16d),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_AVERMEDIA_A16D,
}
};
static int __init init_rc_map_avermedia_a16d(void)
{
return rc_map_register(&avermedia_a16d_map);
}
static void __exit exit_rc_map_avermedia_a16d(void)
{
rc_map_unregister(&avermedia_a16d_map);
}
module_init(init_rc_map_avermedia_a16d)
module_exit(exit_rc_map_avermedia_a16d)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,98 @@
/* avermedia-cardbus.h - Keytable for avermedia_cardbus Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Oldrich Jedlicka <oldium.pro@seznam.cz> */
static struct rc_map_table avermedia_cardbus[] = {
{ 0x00, KEY_POWER },
{ 0x01, KEY_TUNER }, /* TV/FM */
{ 0x03, KEY_TEXT }, /* Teletext */
{ 0x04, KEY_EPG },
{ 0x05, KEY_1 },
{ 0x06, KEY_2 },
{ 0x07, KEY_3 },
{ 0x08, KEY_AUDIO },
{ 0x09, KEY_4 },
{ 0x0a, KEY_5 },
{ 0x0b, KEY_6 },
{ 0x0c, KEY_ZOOM }, /* Full screen */
{ 0x0d, KEY_7 },
{ 0x0e, KEY_8 },
{ 0x0f, KEY_9 },
{ 0x10, KEY_PAGEUP }, /* 16-CH PREV */
{ 0x11, KEY_0 },
{ 0x12, KEY_INFO },
{ 0x13, KEY_AGAIN }, /* CH RTN - channel return */
{ 0x14, KEY_MUTE },
{ 0x15, KEY_EDIT }, /* Autoscan */
{ 0x17, KEY_SAVE }, /* Screenshot */
{ 0x18, KEY_PLAYPAUSE },
{ 0x19, KEY_RECORD },
{ 0x1a, KEY_PLAY },
{ 0x1b, KEY_STOP },
{ 0x1c, KEY_FASTFORWARD },
{ 0x1d, KEY_REWIND },
{ 0x1e, KEY_VOLUMEDOWN },
{ 0x1f, KEY_VOLUMEUP },
{ 0x22, KEY_SLEEP }, /* Sleep */
{ 0x23, KEY_ZOOM }, /* Aspect */
{ 0x26, KEY_SCREEN }, /* Pos */
{ 0x27, KEY_ANGLE }, /* Size */
{ 0x28, KEY_SELECT }, /* Select */
{ 0x29, KEY_BLUE }, /* Blue/Picture */
{ 0x2a, KEY_BACKSPACE }, /* Back */
{ 0x2b, KEY_VIDEO }, /* PIP (Picture-in-picture) */
{ 0x2c, KEY_DOWN },
{ 0x2e, KEY_DOT },
{ 0x2f, KEY_TV }, /* Live TV */
{ 0x32, KEY_LEFT },
{ 0x33, KEY_CLEAR }, /* Clear */
{ 0x35, KEY_RED }, /* Red/TV */
{ 0x36, KEY_UP },
{ 0x37, KEY_HOME }, /* Home */
{ 0x39, KEY_GREEN }, /* Green/Video */
{ 0x3d, KEY_YELLOW }, /* Yellow/Music */
{ 0x3e, KEY_OK }, /* Ok */
{ 0x3f, KEY_RIGHT },
{ 0x40, KEY_NEXT }, /* Next */
{ 0x41, KEY_PREVIOUS }, /* Previous */
{ 0x42, KEY_CHANNELDOWN }, /* Channel down */
{ 0x43, KEY_CHANNELUP }, /* Channel up */
};
static struct rc_map_list avermedia_cardbus_map = {
.map = {
.scan = avermedia_cardbus,
.size = ARRAY_SIZE(avermedia_cardbus),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_AVERMEDIA_CARDBUS,
}
};
static int __init init_rc_map_avermedia_cardbus(void)
{
return rc_map_register(&avermedia_cardbus_map);
}
static void __exit exit_rc_map_avermedia_cardbus(void)
{
rc_map_unregister(&avermedia_cardbus_map);
}
module_init(init_rc_map_avermedia_cardbus)
module_exit(exit_rc_map_avermedia_cardbus)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,79 @@
/* avermedia-dvbt.h - Keytable for avermedia_dvbt Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Matt Jesson <dvb@jesson.eclipse.co.uk */
static struct rc_map_table avermedia_dvbt[] = {
{ 0x28, KEY_0 }, /* '0' / 'enter' */
{ 0x22, KEY_1 }, /* '1' */
{ 0x12, KEY_2 }, /* '2' / 'up arrow' */
{ 0x32, KEY_3 }, /* '3' */
{ 0x24, KEY_4 }, /* '4' / 'left arrow' */
{ 0x14, KEY_5 }, /* '5' */
{ 0x34, KEY_6 }, /* '6' / 'right arrow' */
{ 0x26, KEY_7 }, /* '7' */
{ 0x16, KEY_8 }, /* '8' / 'down arrow' */
{ 0x36, KEY_9 }, /* '9' */
{ 0x20, KEY_VIDEO }, /* 'source' */
{ 0x10, KEY_TEXT }, /* 'teletext' */
{ 0x00, KEY_POWER }, /* 'power' */
{ 0x04, KEY_AUDIO }, /* 'audio' */
{ 0x06, KEY_ZOOM }, /* 'full screen' */
{ 0x18, KEY_SWITCHVIDEOMODE }, /* 'display' */
{ 0x38, KEY_SEARCH }, /* 'loop' */
{ 0x08, KEY_INFO }, /* 'preview' */
{ 0x2a, KEY_REWIND }, /* 'backward <<' */
{ 0x1a, KEY_FASTFORWARD }, /* 'forward >>' */
{ 0x3a, KEY_RECORD }, /* 'capture' */
{ 0x0a, KEY_MUTE }, /* 'mute' */
{ 0x2c, KEY_RECORD }, /* 'record' */
{ 0x1c, KEY_PAUSE }, /* 'pause' */
{ 0x3c, KEY_STOP }, /* 'stop' */
{ 0x0c, KEY_PLAY }, /* 'play' */
{ 0x2e, KEY_RED }, /* 'red' */
{ 0x01, KEY_BLUE }, /* 'blue' / 'cancel' */
{ 0x0e, KEY_YELLOW }, /* 'yellow' / 'ok' */
{ 0x21, KEY_GREEN }, /* 'green' */
{ 0x11, KEY_CHANNELDOWN }, /* 'channel -' */
{ 0x31, KEY_CHANNELUP }, /* 'channel +' */
{ 0x1e, KEY_VOLUMEDOWN }, /* 'volume -' */
{ 0x3e, KEY_VOLUMEUP }, /* 'volume +' */
};
static struct rc_map_list avermedia_dvbt_map = {
.map = {
.scan = avermedia_dvbt,
.size = ARRAY_SIZE(avermedia_dvbt),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_AVERMEDIA_DVBT,
}
};
static int __init init_rc_map_avermedia_dvbt(void)
{
return rc_map_register(&avermedia_dvbt_map);
}
static void __exit exit_rc_map_avermedia_dvbt(void)
{
rc_map_unregister(&avermedia_dvbt_map);
}
module_init(init_rc_map_avermedia_dvbt)
module_exit(exit_rc_map_avermedia_dvbt)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,148 @@
/* avermedia-m135a.c - Keytable for Avermedia M135A Remote Controllers
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
* Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Avermedia M135A with RM-JX and RM-K6 remote controls
*
* On Avermedia M135A with IR model RM-JX, the same codes exist on both
* Positivo (BR) and original IR, initial version and remote control codes
* added by Mauro Carvalho Chehab <mchehab@infradead.org>
*
* Positivo also ships Avermedia M135A with model RM-K6, extra control
* codes added by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*/
static struct rc_map_table avermedia_m135a[] = {
/* RM-JX */
{ 0x0200, KEY_POWER2 },
{ 0x022e, KEY_DOT }, /* '.' */
{ 0x0201, KEY_MODE }, /* TV/FM or SOURCE */
{ 0x0205, KEY_1 },
{ 0x0206, KEY_2 },
{ 0x0207, KEY_3 },
{ 0x0209, KEY_4 },
{ 0x020a, KEY_5 },
{ 0x020b, KEY_6 },
{ 0x020d, KEY_7 },
{ 0x020e, KEY_8 },
{ 0x020f, KEY_9 },
{ 0x0211, KEY_0 },
{ 0x0213, KEY_RIGHT }, /* -> or L */
{ 0x0212, KEY_LEFT }, /* <- or R */
{ 0x0217, KEY_SLEEP }, /* Capturar Imagem or Snapshot */
{ 0x0210, KEY_SHUFFLE }, /* Amostra or 16 chan prev */
{ 0x0303, KEY_CHANNELUP },
{ 0x0302, KEY_CHANNELDOWN },
{ 0x021f, KEY_VOLUMEUP },
{ 0x021e, KEY_VOLUMEDOWN },
{ 0x020c, KEY_ENTER }, /* Full Screen */
{ 0x0214, KEY_MUTE },
{ 0x0208, KEY_AUDIO },
{ 0x0203, KEY_TEXT }, /* Teletext */
{ 0x0204, KEY_EPG },
{ 0x022b, KEY_TV2 }, /* TV2 or PIP */
{ 0x021d, KEY_RED },
{ 0x021c, KEY_YELLOW },
{ 0x0301, KEY_GREEN },
{ 0x0300, KEY_BLUE },
{ 0x021a, KEY_PLAYPAUSE },
{ 0x0219, KEY_RECORD },
{ 0x0218, KEY_PLAY },
{ 0x021b, KEY_STOP },
/* RM-K6 */
{ 0x0401, KEY_POWER2 },
{ 0x0406, KEY_MUTE },
{ 0x0408, KEY_MODE }, /* TV/FM */
{ 0x0409, KEY_1 },
{ 0x040a, KEY_2 },
{ 0x040b, KEY_3 },
{ 0x040c, KEY_4 },
{ 0x040d, KEY_5 },
{ 0x040e, KEY_6 },
{ 0x040f, KEY_7 },
{ 0x0410, KEY_8 },
{ 0x0411, KEY_9 },
{ 0x044c, KEY_DOT }, /* '.' */
{ 0x0412, KEY_0 },
{ 0x0407, KEY_REFRESH }, /* Refresh/Reload */
{ 0x0413, KEY_AUDIO },
{ 0x0440, KEY_SCREEN }, /* Full Screen toggle */
{ 0x0441, KEY_HOME },
{ 0x0442, KEY_BACK },
{ 0x0447, KEY_UP },
{ 0x0448, KEY_DOWN },
{ 0x0449, KEY_LEFT },
{ 0x044a, KEY_RIGHT },
{ 0x044b, KEY_OK },
{ 0x0404, KEY_VOLUMEUP },
{ 0x0405, KEY_VOLUMEDOWN },
{ 0x0402, KEY_CHANNELUP },
{ 0x0403, KEY_CHANNELDOWN },
{ 0x0443, KEY_RED },
{ 0x0444, KEY_GREEN },
{ 0x0445, KEY_YELLOW },
{ 0x0446, KEY_BLUE },
{ 0x0414, KEY_TEXT },
{ 0x0415, KEY_EPG },
{ 0x041a, KEY_TV2 }, /* PIP */
{ 0x041b, KEY_CAMERA }, /* Snapshot */
{ 0x0417, KEY_RECORD },
{ 0x0416, KEY_PLAYPAUSE },
{ 0x0418, KEY_STOP },
{ 0x0419, KEY_PAUSE },
{ 0x041f, KEY_PREVIOUS },
{ 0x041c, KEY_REWIND },
{ 0x041d, KEY_FORWARD },
{ 0x041e, KEY_NEXT },
};
static struct rc_map_list avermedia_m135a_map = {
.map = {
.scan = avermedia_m135a,
.size = ARRAY_SIZE(avermedia_m135a),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_M135A,
}
};
static int __init init_rc_map_avermedia_m135a(void)
{
return rc_map_register(&avermedia_m135a_map);
}
static void __exit exit_rc_map_avermedia_m135a(void)
{
rc_map_unregister(&avermedia_m135a_map);
}
module_init(init_rc_map_avermedia_m135a)
module_exit(exit_rc_map_avermedia_m135a)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,96 @@
/* avermedia-m733a-rm-k6.h - Keytable for avermedia_m733a_rm_k6 Remote Controller
*
* Copyright (c) 2010 by Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Avermedia M733A with IR model RM-K6
* This is the stock remote controller used with Positivo machines with M733A
* Herton Ronaldo Krzesinski <herton@mandriva.com.br>
*/
static struct rc_map_table avermedia_m733a_rm_k6[] = {
{ 0x0401, KEY_POWER2 },
{ 0x0406, KEY_MUTE },
{ 0x0408, KEY_MODE }, /* TV/FM */
{ 0x0409, KEY_1 },
{ 0x040a, KEY_2 },
{ 0x040b, KEY_3 },
{ 0x040c, KEY_4 },
{ 0x040d, KEY_5 },
{ 0x040e, KEY_6 },
{ 0x040f, KEY_7 },
{ 0x0410, KEY_8 },
{ 0x0411, KEY_9 },
{ 0x044c, KEY_DOT }, /* '.' */
{ 0x0412, KEY_0 },
{ 0x0407, KEY_REFRESH }, /* Refresh/Reload */
{ 0x0413, KEY_AUDIO },
{ 0x0440, KEY_SCREEN }, /* Full Screen toggle */
{ 0x0441, KEY_HOME },
{ 0x0442, KEY_BACK },
{ 0x0447, KEY_UP },
{ 0x0448, KEY_DOWN },
{ 0x0449, KEY_LEFT },
{ 0x044a, KEY_RIGHT },
{ 0x044b, KEY_OK },
{ 0x0404, KEY_VOLUMEUP },
{ 0x0405, KEY_VOLUMEDOWN },
{ 0x0402, KEY_CHANNELUP },
{ 0x0403, KEY_CHANNELDOWN },
{ 0x0443, KEY_RED },
{ 0x0444, KEY_GREEN },
{ 0x0445, KEY_YELLOW },
{ 0x0446, KEY_BLUE },
{ 0x0414, KEY_TEXT },
{ 0x0415, KEY_EPG },
{ 0x041a, KEY_TV2 }, /* PIP */
{ 0x041b, KEY_CAMERA }, /* Snapshot */
{ 0x0417, KEY_RECORD },
{ 0x0416, KEY_PLAYPAUSE },
{ 0x0418, KEY_STOP },
{ 0x0419, KEY_PAUSE },
{ 0x041f, KEY_PREVIOUS },
{ 0x041c, KEY_REWIND },
{ 0x041d, KEY_FORWARD },
{ 0x041e, KEY_NEXT },
};
static struct rc_map_list avermedia_m733a_rm_k6_map = {
.map = {
.scan = avermedia_m733a_rm_k6,
.size = ARRAY_SIZE(avermedia_m733a_rm_k6),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_M733A_RM_K6,
}
};
static int __init init_rc_map_avermedia_m733a_rm_k6(void)
{
return rc_map_register(&avermedia_m733a_rm_k6_map);
}
static void __exit exit_rc_map_avermedia_m733a_rm_k6(void)
{
rc_map_unregister(&avermedia_m733a_rm_k6_map);
}
module_init(init_rc_map_avermedia_m733a_rm_k6)
module_exit(exit_rc_map_avermedia_m733a_rm_k6)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,80 @@
/*
* AverMedia RM-KS remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Initial keytable is from Jose Alberto Reguero <jareguero@telefonica.net>
and Felipe Morales Moreno <felipe.morales.moreno@gmail.com> */
/* FIXME: mappings are not 100% correct? */
static struct rc_map_table avermedia_rm_ks[] = {
{ 0x0501, KEY_POWER2 },
{ 0x0502, KEY_CHANNELUP },
{ 0x0503, KEY_CHANNELDOWN },
{ 0x0504, KEY_VOLUMEUP },
{ 0x0505, KEY_VOLUMEDOWN },
{ 0x0506, KEY_MUTE },
{ 0x0507, KEY_RIGHT },
{ 0x0508, KEY_RED },
{ 0x0509, KEY_1 },
{ 0x050a, KEY_2 },
{ 0x050b, KEY_3 },
{ 0x050c, KEY_4 },
{ 0x050d, KEY_5 },
{ 0x050e, KEY_6 },
{ 0x050f, KEY_7 },
{ 0x0510, KEY_8 },
{ 0x0511, KEY_9 },
{ 0x0512, KEY_0 },
{ 0x0513, KEY_AUDIO },
{ 0x0515, KEY_EPG },
{ 0x0516, KEY_PLAY },
{ 0x0517, KEY_RECORD },
{ 0x0518, KEY_STOP },
{ 0x051c, KEY_BACK },
{ 0x051d, KEY_FORWARD },
{ 0x054d, KEY_LEFT },
{ 0x0556, KEY_ZOOM },
};
static struct rc_map_list avermedia_rm_ks_map = {
.map = {
.scan = avermedia_rm_ks,
.size = ARRAY_SIZE(avermedia_rm_ks),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_AVERMEDIA_RM_KS,
}
};
static int __init init_rc_map_avermedia_rm_ks(void)
{
return rc_map_register(&avermedia_rm_ks_map);
}
static void __exit exit_rc_map_avermedia_rm_ks(void)
{
rc_map_unregister(&avermedia_rm_ks_map);
}
module_init(init_rc_map_avermedia_rm_ks)
module_exit(exit_rc_map_avermedia_rm_ks)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,87 @@
/* avermedia.h - Keytable for avermedia Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Alex Hermann <gaaf@gmx.net> */
static struct rc_map_table avermedia[] = {
{ 0x28, KEY_1 },
{ 0x18, KEY_2 },
{ 0x38, KEY_3 },
{ 0x24, KEY_4 },
{ 0x14, KEY_5 },
{ 0x34, KEY_6 },
{ 0x2c, KEY_7 },
{ 0x1c, KEY_8 },
{ 0x3c, KEY_9 },
{ 0x22, KEY_0 },
{ 0x20, KEY_TV }, /* TV/FM */
{ 0x10, KEY_CD }, /* CD */
{ 0x30, KEY_TEXT }, /* TELETEXT */
{ 0x00, KEY_POWER }, /* POWER */
{ 0x08, KEY_VIDEO }, /* VIDEO */
{ 0x04, KEY_AUDIO }, /* AUDIO */
{ 0x0c, KEY_ZOOM }, /* FULL SCREEN */
{ 0x12, KEY_SUBTITLE }, /* DISPLAY */
{ 0x32, KEY_REWIND }, /* LOOP */
{ 0x02, KEY_PRINT }, /* PREVIEW */
{ 0x2a, KEY_SEARCH }, /* AUTOSCAN */
{ 0x1a, KEY_SLEEP }, /* FREEZE */
{ 0x3a, KEY_CAMERA }, /* SNAPSHOT */
{ 0x0a, KEY_MUTE }, /* MUTE */
{ 0x26, KEY_RECORD }, /* RECORD */
{ 0x16, KEY_PAUSE }, /* PAUSE */
{ 0x36, KEY_STOP }, /* STOP */
{ 0x06, KEY_PLAY }, /* PLAY */
{ 0x2e, KEY_RED }, /* RED */
{ 0x21, KEY_GREEN }, /* GREEN */
{ 0x0e, KEY_YELLOW }, /* YELLOW */
{ 0x01, KEY_BLUE }, /* BLUE */
{ 0x1e, KEY_VOLUMEDOWN }, /* VOLUME- */
{ 0x3e, KEY_VOLUMEUP }, /* VOLUME+ */
{ 0x11, KEY_CHANNELDOWN }, /* CHANNEL/PAGE- */
{ 0x31, KEY_CHANNELUP } /* CHANNEL/PAGE+ */
};
static struct rc_map_list avermedia_map = {
.map = {
.scan = avermedia,
.size = ARRAY_SIZE(avermedia),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_AVERMEDIA,
}
};
static int __init init_rc_map_avermedia(void)
{
return rc_map_register(&avermedia_map);
}
static void __exit exit_rc_map_avermedia(void)
{
rc_map_unregister(&avermedia_map);
}
module_init(init_rc_map_avermedia)
module_exit(exit_rc_map_avermedia)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,86 @@
/* avertv-303.h - Keytable for avertv_303 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* AVERTV STUDIO 303 Remote */
static struct rc_map_table avertv_303[] = {
{ 0x2a, KEY_1 },
{ 0x32, KEY_2 },
{ 0x3a, KEY_3 },
{ 0x4a, KEY_4 },
{ 0x52, KEY_5 },
{ 0x5a, KEY_6 },
{ 0x6a, KEY_7 },
{ 0x72, KEY_8 },
{ 0x7a, KEY_9 },
{ 0x0e, KEY_0 },
{ 0x02, KEY_POWER },
{ 0x22, KEY_VIDEO },
{ 0x42, KEY_AUDIO },
{ 0x62, KEY_ZOOM },
{ 0x0a, KEY_TV },
{ 0x12, KEY_CD },
{ 0x1a, KEY_TEXT },
{ 0x16, KEY_SUBTITLE },
{ 0x1e, KEY_REWIND },
{ 0x06, KEY_PRINT },
{ 0x2e, KEY_SEARCH },
{ 0x36, KEY_SLEEP },
{ 0x3e, KEY_SHUFFLE },
{ 0x26, KEY_MUTE },
{ 0x4e, KEY_RECORD },
{ 0x56, KEY_PAUSE },
{ 0x5e, KEY_STOP },
{ 0x46, KEY_PLAY },
{ 0x6e, KEY_RED },
{ 0x0b, KEY_GREEN },
{ 0x66, KEY_YELLOW },
{ 0x03, KEY_BLUE },
{ 0x76, KEY_LEFT },
{ 0x7e, KEY_RIGHT },
{ 0x13, KEY_DOWN },
{ 0x1b, KEY_UP },
};
static struct rc_map_list avertv_303_map = {
.map = {
.scan = avertv_303,
.size = ARRAY_SIZE(avertv_303),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_AVERTV_303,
}
};
static int __init init_rc_map_avertv_303(void)
{
return rc_map_register(&avertv_303_map);
}
static void __exit exit_rc_map_avertv_303(void)
{
rc_map_unregister(&avertv_303_map);
}
module_init(init_rc_map_avertv_303)
module_exit(exit_rc_map_avertv_303)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,103 @@
/*
* TwinHan AzureWave AD-TU700(704J) remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table azurewave_ad_tu700[] = {
{ 0x0000, KEY_TAB }, /* Tab */
{ 0x0001, KEY_2 },
{ 0x0002, KEY_CHANNELDOWN },
{ 0x0003, KEY_1 },
{ 0x0004, KEY_MENU }, /* Record List */
{ 0x0005, KEY_CHANNELUP },
{ 0x0006, KEY_3 },
{ 0x0007, KEY_SLEEP }, /* Hibernate */
{ 0x0008, KEY_VIDEO }, /* A/V */
{ 0x0009, KEY_4 },
{ 0x000a, KEY_VOLUMEDOWN },
{ 0x000c, KEY_CANCEL }, /* Cancel */
{ 0x000d, KEY_7 },
{ 0x000e, KEY_AGAIN }, /* Recall */
{ 0x000f, KEY_TEXT }, /* Teletext */
{ 0x0010, KEY_MUTE },
{ 0x0011, KEY_RECORD },
{ 0x0012, KEY_FASTFORWARD }, /* FF >> */
{ 0x0013, KEY_BACK }, /* Back */
{ 0x0014, KEY_PLAY },
{ 0x0015, KEY_0 },
{ 0x0016, KEY_POWER2 }, /* [red power button] */
{ 0x0017, KEY_FAVORITES }, /* Favorite List */
{ 0x0018, KEY_RED },
{ 0x0019, KEY_8 },
{ 0x001a, KEY_STOP },
{ 0x001b, KEY_9 },
{ 0x001c, KEY_EPG }, /* Info/EPG */
{ 0x001d, KEY_5 },
{ 0x001e, KEY_VOLUMEUP },
{ 0x001f, KEY_6 },
{ 0x0040, KEY_REWIND }, /* FR << */
{ 0x0041, KEY_PREVIOUS }, /* Replay */
{ 0x0042, KEY_NEXT }, /* Skip */
{ 0x0043, KEY_SUBTITLE }, /* Subtitle / CC */
{ 0x0045, KEY_KPPLUS }, /* Zoom+ */
{ 0x0046, KEY_KPMINUS }, /* Zoom- */
{ 0x0047, KEY_NEW }, /* PIP */
{ 0x0048, KEY_INFO }, /* Preview */
{ 0x0049, KEY_MODE }, /* L/R */
{ 0x004a, KEY_CLEAR }, /* Clear */
{ 0x004b, KEY_UP }, /* up arrow */
{ 0x004c, KEY_PAUSE },
{ 0x004d, KEY_ZOOM }, /* Full Screen */
{ 0x004e, KEY_LEFT }, /* left arrow */
{ 0x004f, KEY_OK }, /* Enter / ok */
{ 0x0050, KEY_LANGUAGE }, /* SAP */
{ 0x0051, KEY_DOWN }, /* down arrow */
{ 0x0052, KEY_RIGHT }, /* right arrow */
{ 0x0053, KEY_GREEN },
{ 0x0054, KEY_CAMERA }, /* Capture */
{ 0x005e, KEY_YELLOW },
{ 0x005f, KEY_BLUE },
};
static struct rc_map_list azurewave_ad_tu700_map = {
.map = {
.scan = azurewave_ad_tu700,
.size = ARRAY_SIZE(azurewave_ad_tu700),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_AZUREWAVE_AD_TU700,
}
};
static int __init init_rc_map_azurewave_ad_tu700(void)
{
return rc_map_register(&azurewave_ad_tu700_map);
}
static void __exit exit_rc_map_azurewave_ad_tu700(void)
{
rc_map_unregister(&azurewave_ad_tu700_map);
}
module_init(init_rc_map_azurewave_ad_tu700)
module_exit(exit_rc_map_azurewave_ad_tu700)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,109 @@
/* behold-columbus.h - Keytable for behold_columbus Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Beholder Intl. Ltd. 2008
* Dmitry Belimov d.belimov@google.com
* Keytable is used by BeholdTV Columbus
* The "ascii-art picture" below (in comments, first row
* is the keycode in hex, and subsequent row(s) shows
* the button labels (several variants when appropriate)
* helps to descide which keycodes to assign to the buttons.
*/
static struct rc_map_table behold_columbus[] = {
/* 0x13 0x11 0x1C 0x12 *
* Mute Source TV/FM Power *
* */
{ 0x13, KEY_MUTE },
{ 0x11, KEY_VIDEO },
{ 0x1C, KEY_TUNER }, /* KEY_TV/KEY_RADIO */
{ 0x12, KEY_POWER },
/* 0x01 0x02 0x03 0x0D *
* 1 2 3 Stereo *
* *
* 0x04 0x05 0x06 0x19 *
* 4 5 6 Snapshot *
* *
* 0x07 0x08 0x09 0x10 *
* 7 8 9 Zoom *
* */
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x0D, KEY_SETUP }, /* Setup key */
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x19, KEY_CAMERA }, /* Snapshot key */
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x10, KEY_ZOOM },
/* 0x0A 0x00 0x0B 0x0C *
* RECALL 0 ChannelUp VolumeUp *
* */
{ 0x0A, KEY_AGAIN },
{ 0x00, KEY_0 },
{ 0x0B, KEY_CHANNELUP },
{ 0x0C, KEY_VOLUMEUP },
/* 0x1B 0x1D 0x15 0x18 *
* Timeshift Record ChannelDown VolumeDown *
* */
{ 0x1B, KEY_TIME },
{ 0x1D, KEY_RECORD },
{ 0x15, KEY_CHANNELDOWN },
{ 0x18, KEY_VOLUMEDOWN },
/* 0x0E 0x1E 0x0F 0x1A *
* Stop Pause Previouse Next *
* */
{ 0x0E, KEY_STOP },
{ 0x1E, KEY_PAUSE },
{ 0x0F, KEY_PREVIOUS },
{ 0x1A, KEY_NEXT },
};
static struct rc_map_list behold_columbus_map = {
.map = {
.scan = behold_columbus,
.size = ARRAY_SIZE(behold_columbus),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_BEHOLD_COLUMBUS,
}
};
static int __init init_rc_map_behold_columbus(void)
{
return rc_map_register(&behold_columbus_map);
}
static void __exit exit_rc_map_behold_columbus(void)
{
rc_map_unregister(&behold_columbus_map);
}
module_init(init_rc_map_behold_columbus)
module_exit(exit_rc_map_behold_columbus)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,142 @@
/* behold.h - Keytable for behold Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Igor Kuznetsov <igk72@ya.ru>
* Andrey J. Melnikov <temnota@kmv.ru>
*
* Keytable is used by BeholdTV 60x series, M6 series at
* least, and probably other cards too.
* The "ascii-art picture" below (in comments, first row
* is the keycode in hex, and subsequent row(s) shows
* the button labels (several variants when appropriate)
* helps to descide which keycodes to assign to the buttons.
*/
static struct rc_map_table behold[] = {
/* 0x1c 0x12 *
* TV/FM POWER *
* */
{ 0x866b1c, KEY_TUNER }, /* XXX KEY_TV / KEY_RADIO */
{ 0x866b12, KEY_POWER },
/* 0x01 0x02 0x03 *
* 1 2 3 *
* *
* 0x04 0x05 0x06 *
* 4 5 6 *
* *
* 0x07 0x08 0x09 *
* 7 8 9 *
* */
{ 0x866b01, KEY_1 },
{ 0x866b02, KEY_2 },
{ 0x866b03, KEY_3 },
{ 0x866b04, KEY_4 },
{ 0x866b05, KEY_5 },
{ 0x866b06, KEY_6 },
{ 0x866b07, KEY_7 },
{ 0x866b08, KEY_8 },
{ 0x866b09, KEY_9 },
/* 0x0a 0x00 0x17 *
* RECALL 0 MODE *
* */
{ 0x866b0a, KEY_AGAIN },
{ 0x866b00, KEY_0 },
{ 0x866b17, KEY_MODE },
/* 0x14 0x10 *
* ASPECT FULLSCREEN *
* */
{ 0x866b14, KEY_SCREEN },
{ 0x866b10, KEY_ZOOM },
/* 0x0b *
* Up *
* *
* 0x18 0x16 0x0c *
* Left Ok Right *
* *
* 0x015 *
* Down *
* */
{ 0x866b0b, KEY_CHANNELUP },
{ 0x866b18, KEY_VOLUMEDOWN },
{ 0x866b16, KEY_OK }, /* XXX KEY_ENTER */
{ 0x866b0c, KEY_VOLUMEUP },
{ 0x866b15, KEY_CHANNELDOWN },
/* 0x11 0x0d *
* MUTE INFO *
* */
{ 0x866b11, KEY_MUTE },
{ 0x866b0d, KEY_INFO },
/* 0x0f 0x1b 0x1a *
* RECORD PLAY/PAUSE STOP *
* *
* 0x0e 0x1f 0x1e *
*TELETEXT AUDIO SOURCE *
* RED YELLOW *
* */
{ 0x866b0f, KEY_RECORD },
{ 0x866b1b, KEY_PLAYPAUSE },
{ 0x866b1a, KEY_STOP },
{ 0x866b0e, KEY_TEXT },
{ 0x866b1f, KEY_RED }, /*XXX KEY_AUDIO */
{ 0x866b1e, KEY_VIDEO },
/* 0x1d 0x13 0x19 *
* SLEEP PREVIEW DVB *
* GREEN BLUE *
* */
{ 0x866b1d, KEY_SLEEP },
{ 0x866b13, KEY_GREEN },
{ 0x866b19, KEY_BLUE }, /* XXX KEY_SAT */
/* 0x58 0x5c *
* FREEZE SNAPSHOT *
* */
{ 0x866b58, KEY_SLOW },
{ 0x866b5c, KEY_CAMERA },
};
static struct rc_map_list behold_map = {
.map = {
.scan = behold,
.size = ARRAY_SIZE(behold),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_BEHOLD,
}
};
static int __init init_rc_map_behold(void)
{
return rc_map_register(&behold_map);
}
static void __exit exit_rc_map_behold(void)
{
rc_map_unregister(&behold_map);
}
module_init(init_rc_map_behold)
module_exit(exit_rc_map_behold)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,94 @@
/* budget-ci-old.h - Keytable for budget_ci_old Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* From reading the following remotes:
* Zenith Universal 7 / TV Mode 807 / VCR Mode 837
* Hauppauge (from NOVA-CI-s box product)
* This is a "middle of the road" approach, differences are noted
*/
static struct rc_map_table budget_ci_old[] = {
{ 0x00, KEY_0 },
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x0a, KEY_ENTER },
{ 0x0b, KEY_RED },
{ 0x0c, KEY_POWER }, /* RADIO on Hauppauge */
{ 0x0d, KEY_MUTE },
{ 0x0f, KEY_A }, /* TV on Hauppauge */
{ 0x10, KEY_VOLUMEUP },
{ 0x11, KEY_VOLUMEDOWN },
{ 0x14, KEY_B },
{ 0x1c, KEY_UP },
{ 0x1d, KEY_DOWN },
{ 0x1e, KEY_OPTION }, /* RESERVED on Hauppauge */
{ 0x1f, KEY_BREAK },
{ 0x20, KEY_CHANNELUP },
{ 0x21, KEY_CHANNELDOWN },
{ 0x22, KEY_PREVIOUS }, /* Prev Ch on Zenith, SOURCE on Hauppauge */
{ 0x24, KEY_RESTART },
{ 0x25, KEY_OK },
{ 0x26, KEY_CYCLEWINDOWS }, /* MINIMIZE on Hauppauge */
{ 0x28, KEY_ENTER }, /* VCR mode on Zenith */
{ 0x29, KEY_PAUSE },
{ 0x2b, KEY_RIGHT },
{ 0x2c, KEY_LEFT },
{ 0x2e, KEY_MENU }, /* FULL SCREEN on Hauppauge */
{ 0x30, KEY_SLOW },
{ 0x31, KEY_PREVIOUS }, /* VCR mode on Zenith */
{ 0x32, KEY_REWIND },
{ 0x34, KEY_FASTFORWARD },
{ 0x35, KEY_PLAY },
{ 0x36, KEY_STOP },
{ 0x37, KEY_RECORD },
{ 0x38, KEY_TUNER }, /* TV/VCR on Zenith */
{ 0x3a, KEY_C },
{ 0x3c, KEY_EXIT },
{ 0x3d, KEY_POWER2 },
{ 0x3e, KEY_TUNER },
};
static struct rc_map_list budget_ci_old_map = {
.map = {
.scan = budget_ci_old,
.size = ARRAY_SIZE(budget_ci_old),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_BUDGET_CI_OLD,
}
};
static int __init init_rc_map_budget_ci_old(void)
{
return rc_map_register(&budget_ci_old_map);
}
static void __exit exit_rc_map_budget_ci_old(void)
{
rc_map_unregister(&budget_ci_old_map);
}
module_init(init_rc_map_budget_ci_old)
module_exit(exit_rc_map_budget_ci_old)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,85 @@
/* cinergy-1400.h - Keytable for cinergy_1400 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Cinergy 1400 DVB-T */
static struct rc_map_table cinergy_1400[] = {
{ 0x01, KEY_POWER },
{ 0x02, KEY_1 },
{ 0x03, KEY_2 },
{ 0x04, KEY_3 },
{ 0x05, KEY_4 },
{ 0x06, KEY_5 },
{ 0x07, KEY_6 },
{ 0x08, KEY_7 },
{ 0x09, KEY_8 },
{ 0x0a, KEY_9 },
{ 0x0c, KEY_0 },
{ 0x0b, KEY_VIDEO },
{ 0x0d, KEY_REFRESH },
{ 0x0e, KEY_SELECT },
{ 0x0f, KEY_EPG },
{ 0x10, KEY_UP },
{ 0x11, KEY_LEFT },
{ 0x12, KEY_OK },
{ 0x13, KEY_RIGHT },
{ 0x14, KEY_DOWN },
{ 0x15, KEY_TEXT },
{ 0x16, KEY_INFO },
{ 0x17, KEY_RED },
{ 0x18, KEY_GREEN },
{ 0x19, KEY_YELLOW },
{ 0x1a, KEY_BLUE },
{ 0x1b, KEY_CHANNELUP },
{ 0x1c, KEY_VOLUMEUP },
{ 0x1d, KEY_MUTE },
{ 0x1e, KEY_VOLUMEDOWN },
{ 0x1f, KEY_CHANNELDOWN },
{ 0x40, KEY_PAUSE },
{ 0x4c, KEY_PLAY },
{ 0x58, KEY_RECORD },
{ 0x54, KEY_PREVIOUS },
{ 0x48, KEY_STOP },
{ 0x5c, KEY_NEXT },
};
static struct rc_map_list cinergy_1400_map = {
.map = {
.scan = cinergy_1400,
.size = ARRAY_SIZE(cinergy_1400),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_CINERGY_1400,
}
};
static int __init init_rc_map_cinergy_1400(void)
{
return rc_map_register(&cinergy_1400_map);
}
static void __exit exit_rc_map_cinergy_1400(void)
{
rc_map_unregister(&cinergy_1400_map);
}
module_init(init_rc_map_cinergy_1400)
module_exit(exit_rc_map_cinergy_1400)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,79 @@
/* cinergy.h - Keytable for cinergy Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table cinergy[] = {
{ 0x00, KEY_0 },
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x0a, KEY_POWER },
{ 0x0b, KEY_MEDIA }, /* app */
{ 0x0c, KEY_ZOOM }, /* zoom/fullscreen */
{ 0x0d, KEY_CHANNELUP }, /* channel */
{ 0x0e, KEY_CHANNELDOWN }, /* channel- */
{ 0x0f, KEY_VOLUMEUP },
{ 0x10, KEY_VOLUMEDOWN },
{ 0x11, KEY_TUNER }, /* AV */
{ 0x12, KEY_NUMLOCK }, /* -/-- */
{ 0x13, KEY_AUDIO }, /* audio */
{ 0x14, KEY_MUTE },
{ 0x15, KEY_UP },
{ 0x16, KEY_DOWN },
{ 0x17, KEY_LEFT },
{ 0x18, KEY_RIGHT },
{ 0x19, BTN_LEFT, },
{ 0x1a, BTN_RIGHT, },
{ 0x1b, KEY_WWW }, /* text */
{ 0x1c, KEY_REWIND },
{ 0x1d, KEY_FORWARD },
{ 0x1e, KEY_RECORD },
{ 0x1f, KEY_PLAY },
{ 0x20, KEY_PREVIOUSSONG },
{ 0x21, KEY_NEXTSONG },
{ 0x22, KEY_PAUSE },
{ 0x23, KEY_STOP },
};
static struct rc_map_list cinergy_map = {
.map = {
.scan = cinergy,
.size = ARRAY_SIZE(cinergy),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_CINERGY,
}
};
static int __init init_rc_map_cinergy(void)
{
return rc_map_register(&cinergy_map);
}
static void __exit exit_rc_map_cinergy(void)
{
rc_map_unregister(&cinergy_map);
}
module_init(init_rc_map_cinergy)
module_exit(exit_rc_map_cinergy)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,83 @@
/* rc-delock-61959.c - Keytable for Delock
*
* Copyright (c) 2013 by Jakob Haufe <sur5r@sur5r.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Keytable for remote provided with Delock 61959
*/
static struct rc_map_table delock_61959[] = {
{ 0x866b16, KEY_POWER2 }, /* Power */
{ 0x866b0c, KEY_POWER }, /* Shut Down */
{ 0x866b00, KEY_1},
{ 0x866b01, KEY_2},
{ 0x866b02, KEY_3},
{ 0x866b03, KEY_4},
{ 0x866b04, KEY_5},
{ 0x866b05, KEY_6},
{ 0x866b06, KEY_7},
{ 0x866b07, KEY_8},
{ 0x866b08, KEY_9},
{ 0x866b14, KEY_0},
{ 0x866b0a, KEY_ZOOM}, /* Full Screen */
{ 0x866b10, KEY_CAMERA}, /* Photo */
{ 0x866b0e, KEY_CHANNEL}, /* circular arrow / Recall */
{ 0x866b13, KEY_ESC}, /* Back */
{ 0x866b20, KEY_UP},
{ 0x866b21, KEY_DOWN},
{ 0x866b42, KEY_LEFT},
{ 0x866b43, KEY_RIGHT},
{ 0x866b0b, KEY_OK},
{ 0x866b11, KEY_CHANNELUP},
{ 0x866b1b, KEY_CHANNELDOWN},
{ 0x866b12, KEY_VOLUMEUP},
{ 0x866b48, KEY_VOLUMEDOWN},
{ 0x866b44, KEY_MUTE},
{ 0x866b1a, KEY_RECORD},
{ 0x866b41, KEY_PLAY},
{ 0x866b40, KEY_STOP},
{ 0x866b19, KEY_PAUSE},
{ 0x866b1c, KEY_FASTFORWARD}, /* >> / FWD */
{ 0x866b1e, KEY_REWIND}, /* << / REW */
};
static struct rc_map_list delock_61959_map = {
.map = {
.scan = delock_61959,
.size = ARRAY_SIZE(delock_61959),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_DELOCK_61959,
}
};
static int __init init_rc_map_delock_61959(void)
{
return rc_map_register(&delock_61959_map);
}
static void __exit exit_rc_map_delock_61959(void)
{
rc_map_unregister(&delock_61959_map);
}
module_init(init_rc_map_delock_61959)
module_exit(exit_rc_map_delock_61959)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jakob Haufe <sur5r@sur5r.net>");
MODULE_DESCRIPTION("Delock 61959 remote keytable");

View file

@ -0,0 +1,125 @@
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* TODO: This table is a real mess, as it merges RC codes from several
* devices into a big table. It also has both RC-5 and NEC codes inside.
* It should be broken into small tables, and the protocols should properly
* be identificated.
*
* The table were imported from dib0700_devices.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table dib0700_nec_table[] = {
/* Key codes for the Pixelview SBTVD remote */
{ 0x866b13, KEY_MUTE },
{ 0x866b12, KEY_POWER },
{ 0x866b01, KEY_1 },
{ 0x866b02, KEY_2 },
{ 0x866b03, KEY_3 },
{ 0x866b04, KEY_4 },
{ 0x866b05, KEY_5 },
{ 0x866b06, KEY_6 },
{ 0x866b07, KEY_7 },
{ 0x866b08, KEY_8 },
{ 0x866b09, KEY_9 },
{ 0x866b00, KEY_0 },
{ 0x866b0d, KEY_CHANNELUP },
{ 0x866b19, KEY_CHANNELDOWN },
{ 0x866b10, KEY_VOLUMEUP },
{ 0x866b0c, KEY_VOLUMEDOWN },
{ 0x866b0a, KEY_CAMERA },
{ 0x866b0b, KEY_ZOOM },
{ 0x866b1b, KEY_BACKSPACE },
{ 0x866b15, KEY_ENTER },
{ 0x866b1d, KEY_UP },
{ 0x866b1e, KEY_DOWN },
{ 0x866b0e, KEY_LEFT },
{ 0x866b0f, KEY_RIGHT },
{ 0x866b18, KEY_RECORD },
{ 0x866b1a, KEY_STOP },
/* Key codes for the EvolutePC TVWay+ remote */
{ 0x7a00, KEY_MENU },
{ 0x7a01, KEY_RECORD },
{ 0x7a02, KEY_PLAY },
{ 0x7a03, KEY_STOP },
{ 0x7a10, KEY_CHANNELUP },
{ 0x7a11, KEY_CHANNELDOWN },
{ 0x7a12, KEY_VOLUMEUP },
{ 0x7a13, KEY_VOLUMEDOWN },
{ 0x7a40, KEY_POWER },
{ 0x7a41, KEY_MUTE },
/* Key codes for the Elgato EyeTV Diversity silver remote */
{ 0x4501, KEY_POWER },
{ 0x4502, KEY_MUTE },
{ 0x4503, KEY_1 },
{ 0x4504, KEY_2 },
{ 0x4505, KEY_3 },
{ 0x4506, KEY_4 },
{ 0x4507, KEY_5 },
{ 0x4508, KEY_6 },
{ 0x4509, KEY_7 },
{ 0x450a, KEY_8 },
{ 0x450b, KEY_9 },
{ 0x450c, KEY_LAST },
{ 0x450d, KEY_0 },
{ 0x450e, KEY_ENTER },
{ 0x450f, KEY_RED },
{ 0x4510, KEY_CHANNELUP },
{ 0x4511, KEY_GREEN },
{ 0x4512, KEY_VOLUMEDOWN },
{ 0x4513, KEY_OK },
{ 0x4514, KEY_VOLUMEUP },
{ 0x4515, KEY_YELLOW },
{ 0x4516, KEY_CHANNELDOWN },
{ 0x4517, KEY_BLUE },
{ 0x4518, KEY_LEFT }, /* Skip backwards */
{ 0x4519, KEY_PLAYPAUSE },
{ 0x451a, KEY_RIGHT }, /* Skip forward */
{ 0x451b, KEY_REWIND },
{ 0x451c, KEY_L }, /* Live */
{ 0x451d, KEY_FASTFORWARD },
{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
{ 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
};
static struct rc_map_list dib0700_nec_map = {
.map = {
.scan = dib0700_nec_table,
.size = ARRAY_SIZE(dib0700_nec_table),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_DIB0700_NEC_TABLE,
}
};
static int __init init_rc_map(void)
{
return rc_map_register(&dib0700_nec_map);
}
static void __exit exit_rc_map(void)
{
rc_map_unregister(&dib0700_nec_map);
}
module_init(init_rc_map)
module_exit(exit_rc_map)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,236 @@
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* TODO: This table is a real mess, as it merges RC codes from several
* devices into a big table. It also has both RC-5 and NEC codes inside.
* It should be broken into small tables, and the protocols should properly
* be identificated.
*
* The table were imported from dib0700_devices.c.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table dib0700_rc5_table[] = {
/* Key codes for the tiny Pinnacle remote*/
{ 0x0700, KEY_MUTE },
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
{ 0x0739, KEY_POWER },
{ 0x0703, KEY_VOLUMEUP },
{ 0x0709, KEY_VOLUMEDOWN },
{ 0x0706, KEY_CHANNELUP },
{ 0x070c, KEY_CHANNELDOWN },
{ 0x070f, KEY_1 },
{ 0x0715, KEY_2 },
{ 0x0710, KEY_3 },
{ 0x0718, KEY_4 },
{ 0x071b, KEY_5 },
{ 0x071e, KEY_6 },
{ 0x0711, KEY_7 },
{ 0x0721, KEY_8 },
{ 0x0712, KEY_9 },
{ 0x0727, KEY_0 },
{ 0x0724, KEY_SCREEN }, /* 'Square' key */
{ 0x072a, KEY_TEXT }, /* 'T' key */
{ 0x072d, KEY_REWIND },
{ 0x0730, KEY_PLAY },
{ 0x0733, KEY_FASTFORWARD },
{ 0x0736, KEY_RECORD },
{ 0x073c, KEY_STOP },
{ 0x073f, KEY_CANCEL }, /* '?' key */
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
{ 0xeb01, KEY_POWER },
{ 0xeb02, KEY_1 },
{ 0xeb03, KEY_2 },
{ 0xeb04, KEY_3 },
{ 0xeb05, KEY_4 },
{ 0xeb06, KEY_5 },
{ 0xeb07, KEY_6 },
{ 0xeb08, KEY_7 },
{ 0xeb09, KEY_8 },
{ 0xeb0a, KEY_9 },
{ 0xeb0b, KEY_VIDEO },
{ 0xeb0c, KEY_0 },
{ 0xeb0d, KEY_REFRESH },
{ 0xeb0f, KEY_EPG },
{ 0xeb10, KEY_UP },
{ 0xeb11, KEY_LEFT },
{ 0xeb12, KEY_OK },
{ 0xeb13, KEY_RIGHT },
{ 0xeb14, KEY_DOWN },
{ 0xeb16, KEY_INFO },
{ 0xeb17, KEY_RED },
{ 0xeb18, KEY_GREEN },
{ 0xeb19, KEY_YELLOW },
{ 0xeb1a, KEY_BLUE },
{ 0xeb1b, KEY_CHANNELUP },
{ 0xeb1c, KEY_VOLUMEUP },
{ 0xeb1d, KEY_MUTE },
{ 0xeb1e, KEY_VOLUMEDOWN },
{ 0xeb1f, KEY_CHANNELDOWN },
{ 0xeb40, KEY_PAUSE },
{ 0xeb41, KEY_HOME },
{ 0xeb42, KEY_MENU }, /* DVD Menu */
{ 0xeb43, KEY_SUBTITLE },
{ 0xeb44, KEY_TEXT }, /* Teletext */
{ 0xeb45, KEY_DELETE },
{ 0xeb46, KEY_TV },
{ 0xeb47, KEY_DVD },
{ 0xeb48, KEY_STOP },
{ 0xeb49, KEY_VIDEO },
{ 0xeb4a, KEY_AUDIO }, /* Music */
{ 0xeb4b, KEY_SCREEN }, /* Pic */
{ 0xeb4c, KEY_PLAY },
{ 0xeb4d, KEY_BACK },
{ 0xeb4e, KEY_REWIND },
{ 0xeb4f, KEY_FASTFORWARD },
{ 0xeb54, KEY_PREVIOUS },
{ 0xeb58, KEY_RECORD },
{ 0xeb5c, KEY_NEXT },
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
{ 0x1e00, KEY_0 },
{ 0x1e01, KEY_1 },
{ 0x1e02, KEY_2 },
{ 0x1e03, KEY_3 },
{ 0x1e04, KEY_4 },
{ 0x1e05, KEY_5 },
{ 0x1e06, KEY_6 },
{ 0x1e07, KEY_7 },
{ 0x1e08, KEY_8 },
{ 0x1e09, KEY_9 },
{ 0x1e0a, KEY_KPASTERISK },
{ 0x1e0b, KEY_RED },
{ 0x1e0c, KEY_RADIO },
{ 0x1e0d, KEY_MENU },
{ 0x1e0e, KEY_GRAVE }, /* # */
{ 0x1e0f, KEY_MUTE },
{ 0x1e10, KEY_VOLUMEUP },
{ 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e12, KEY_CHANNEL },
{ 0x1e14, KEY_UP },
{ 0x1e15, KEY_DOWN },
{ 0x1e16, KEY_LEFT },
{ 0x1e17, KEY_RIGHT },
{ 0x1e18, KEY_VIDEO },
{ 0x1e19, KEY_AUDIO },
{ 0x1e1a, KEY_MEDIA },
{ 0x1e1b, KEY_EPG },
{ 0x1e1c, KEY_TV },
{ 0x1e1e, KEY_NEXT },
{ 0x1e1f, KEY_BACK },
{ 0x1e20, KEY_CHANNELUP },
{ 0x1e21, KEY_CHANNELDOWN },
{ 0x1e24, KEY_LAST }, /* Skip backwards */
{ 0x1e25, KEY_OK },
{ 0x1e29, KEY_BLUE},
{ 0x1e2e, KEY_GREEN },
{ 0x1e30, KEY_PAUSE },
{ 0x1e32, KEY_REWIND },
{ 0x1e34, KEY_FASTFORWARD },
{ 0x1e35, KEY_PLAY },
{ 0x1e36, KEY_STOP },
{ 0x1e37, KEY_RECORD },
{ 0x1e38, KEY_YELLOW },
{ 0x1e3b, KEY_GOTO },
{ 0x1e3d, KEY_POWER },
/* Key codes for the Leadtek Winfast DTV Dongle */
{ 0x0042, KEY_POWER },
{ 0x077c, KEY_TUNER },
{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
{ 0x0f71, KEY_DOT }, /* frequency */
{ 0x0743, KEY_0 },
{ 0x0c41, KEY_1 },
{ 0x0443, KEY_2 },
{ 0x0b7f, KEY_3 },
{ 0x0e41, KEY_4 },
{ 0x0643, KEY_5 },
{ 0x097f, KEY_6 },
{ 0x0d7e, KEY_7 },
{ 0x057c, KEY_8 },
{ 0x0a40, KEY_9 },
{ 0x0e4e, KEY_CLEAR },
{ 0x047c, KEY_CHANNEL }, /* show channel number */
{ 0x0f41, KEY_LAST }, /* recall */
{ 0x0342, KEY_MUTE },
{ 0x064c, KEY_RESERVED }, /* PIP button*/
{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
{ 0x0b70, KEY_RECORD },
{ 0x037d, KEY_VOLUMEUP },
{ 0x017d, KEY_VOLUMEDOWN },
{ 0x0242, KEY_CHANNELUP },
{ 0x007d, KEY_CHANNELDOWN },
/* Key codes for Nova-TD "credit card" remote control. */
{ 0x1d00, KEY_0 },
{ 0x1d01, KEY_1 },
{ 0x1d02, KEY_2 },
{ 0x1d03, KEY_3 },
{ 0x1d04, KEY_4 },
{ 0x1d05, KEY_5 },
{ 0x1d06, KEY_6 },
{ 0x1d07, KEY_7 },
{ 0x1d08, KEY_8 },
{ 0x1d09, KEY_9 },
{ 0x1d0a, KEY_TEXT },
{ 0x1d0d, KEY_MENU },
{ 0x1d0f, KEY_MUTE },
{ 0x1d10, KEY_VOLUMEUP },
{ 0x1d11, KEY_VOLUMEDOWN },
{ 0x1d12, KEY_CHANNEL },
{ 0x1d14, KEY_UP },
{ 0x1d15, KEY_DOWN },
{ 0x1d16, KEY_LEFT },
{ 0x1d17, KEY_RIGHT },
{ 0x1d1c, KEY_TV },
{ 0x1d1e, KEY_NEXT },
{ 0x1d1f, KEY_BACK },
{ 0x1d20, KEY_CHANNELUP },
{ 0x1d21, KEY_CHANNELDOWN },
{ 0x1d24, KEY_LAST },
{ 0x1d25, KEY_OK },
{ 0x1d30, KEY_PAUSE },
{ 0x1d32, KEY_REWIND },
{ 0x1d34, KEY_FASTFORWARD },
{ 0x1d35, KEY_PLAY },
{ 0x1d36, KEY_STOP },
{ 0x1d37, KEY_RECORD },
{ 0x1d3b, KEY_GOTO },
{ 0x1d3d, KEY_POWER },
};
static struct rc_map_list dib0700_rc5_map = {
.map = {
.scan = dib0700_rc5_table,
.size = ARRAY_SIZE(dib0700_rc5_table),
.rc_type = RC_TYPE_RC5,
.name = RC_MAP_DIB0700_RC5_TABLE,
}
};
static int __init init_rc_map(void)
{
return rc_map_register(&dib0700_rc5_map);
}
static void __exit exit_rc_map(void)
{
rc_map_unregister(&dib0700_rc5_map);
}
module_init(init_rc_map)
module_exit(exit_rc_map)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,99 @@
/*
* DigitalNow TinyTwin remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table digitalnow_tinytwin[] = {
{ 0x0000, KEY_MUTE }, /* [symbol speaker] */
{ 0x0001, KEY_VOLUMEUP },
{ 0x0002, KEY_POWER2 }, /* TV [power button] */
{ 0x0003, KEY_2 },
{ 0x0004, KEY_3 },
{ 0x0005, KEY_4 },
{ 0x0006, KEY_6 },
{ 0x0007, KEY_7 },
{ 0x0008, KEY_8 },
{ 0x0009, KEY_NUMERIC_STAR }, /* [*] */
{ 0x000a, KEY_0 },
{ 0x000b, KEY_NUMERIC_POUND }, /* [#] */
{ 0x000c, KEY_RIGHT }, /* [right arrow] */
{ 0x000d, KEY_HOMEPAGE }, /* [symbol home] Start */
{ 0x000e, KEY_RED }, /* [red] Videos */
{ 0x0010, KEY_POWER }, /* PC [power button] */
{ 0x0011, KEY_YELLOW }, /* [yellow] Pictures */
{ 0x0012, KEY_DOWN }, /* [down arrow] */
{ 0x0013, KEY_GREEN }, /* [green] Music */
{ 0x0014, KEY_CYCLEWINDOWS }, /* BACK */
{ 0x0015, KEY_FAVORITES }, /* MORE */
{ 0x0016, KEY_UP }, /* [up arrow] */
{ 0x0017, KEY_LEFT }, /* [left arrow] */
{ 0x0018, KEY_OK }, /* OK */
{ 0x0019, KEY_BLUE }, /* [blue] MyTV */
{ 0x001a, KEY_REWIND }, /* REW [<<] */
{ 0x001b, KEY_PLAY }, /* PLAY */
{ 0x001c, KEY_5 },
{ 0x001d, KEY_9 },
{ 0x001e, KEY_VOLUMEDOWN },
{ 0x001f, KEY_1 },
{ 0x0040, KEY_STOP }, /* STOP */
{ 0x0042, KEY_PAUSE }, /* PAUSE */
{ 0x0043, KEY_SCREEN }, /* Aspect */
{ 0x0044, KEY_FORWARD }, /* FWD [>>] */
{ 0x0045, KEY_NEXT }, /* SKIP */
{ 0x0048, KEY_RECORD }, /* RECORD */
{ 0x0049, KEY_VIDEO }, /* RTV */
{ 0x004a, KEY_EPG }, /* Guide */
{ 0x004b, KEY_CHANNELUP },
{ 0x004c, KEY_HELP }, /* Help */
{ 0x004d, KEY_RADIO }, /* Radio */
{ 0x004f, KEY_CHANNELDOWN },
{ 0x0050, KEY_DVD }, /* DVD */
{ 0x0051, KEY_AUDIO }, /* Audio */
{ 0x0052, KEY_TITLE }, /* Title */
{ 0x0053, KEY_NEW }, /* [symbol PIP?] */
{ 0x0057, KEY_MENU }, /* Mouse */
{ 0x005a, KEY_PREVIOUS }, /* REPLAY */
};
static struct rc_map_list digitalnow_tinytwin_map = {
.map = {
.scan = digitalnow_tinytwin,
.size = ARRAY_SIZE(digitalnow_tinytwin),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_DIGITALNOW_TINYTWIN,
}
};
static int __init init_rc_map_digitalnow_tinytwin(void)
{
return rc_map_register(&digitalnow_tinytwin_map);
}
static void __exit exit_rc_map_digitalnow_tinytwin(void)
{
rc_map_unregister(&digitalnow_tinytwin_map);
}
module_init(init_rc_map_digitalnow_tinytwin)
module_exit(exit_rc_map_digitalnow_tinytwin)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,83 @@
/*
* Digittrade DVB-T USB Stick remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Digittrade DVB-T USB Stick remote controller. */
/* Imported from af9015.h.
Initial keytable was from Alain Kalker <miki@dds.nl> */
/* Digittrade DVB-T USB Stick */
static struct rc_map_table digittrade[] = {
{ 0x0000, KEY_9 },
{ 0x0001, KEY_EPG }, /* EPG */
{ 0x0002, KEY_VOLUMEDOWN }, /* Vol Dn */
{ 0x0003, KEY_TEXT }, /* TELETEXT */
{ 0x0004, KEY_8 },
{ 0x0005, KEY_MUTE }, /* MUTE */
{ 0x0006, KEY_POWER2 }, /* POWER */
{ 0x0009, KEY_ZOOM }, /* FULLSCREEN */
{ 0x000a, KEY_RECORD }, /* RECORD */
{ 0x000d, KEY_SUBTITLE }, /* SUBTITLE */
{ 0x000e, KEY_STOP }, /* STOP */
{ 0x0010, KEY_OK }, /* RETURN */
{ 0x0011, KEY_2 },
{ 0x0012, KEY_4 },
{ 0x0015, KEY_3 },
{ 0x0016, KEY_5 },
{ 0x0017, KEY_CHANNELDOWN }, /* Ch Dn */
{ 0x0019, KEY_CHANNELUP }, /* CH Up */
{ 0x001a, KEY_PAUSE }, /* PAUSE */
{ 0x001b, KEY_1 },
{ 0x001d, KEY_AUDIO }, /* DUAL SOUND */
{ 0x001e, KEY_PLAY }, /* PLAY */
{ 0x001f, KEY_CAMERA }, /* SNAPSHOT */
{ 0x0040, KEY_VOLUMEUP }, /* Vol Up */
{ 0x0048, KEY_7 },
{ 0x004c, KEY_6 },
{ 0x004d, KEY_PLAYPAUSE }, /* TIMESHIFT */
{ 0x0054, KEY_0 },
};
static struct rc_map_list digittrade_map = {
.map = {
.scan = digittrade,
.size = ARRAY_SIZE(digittrade),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_DIGITTRADE,
}
};
static int __init init_rc_map_digittrade(void)
{
return rc_map_register(&digittrade_map);
}
static void __exit exit_rc_map_digittrade(void)
{
rc_map_unregister(&digittrade_map);
}
module_init(init_rc_map_digittrade)
module_exit(exit_rc_map_digittrade)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,77 @@
/* dm1105-nec.h - Keytable for dm1105_nec Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* DVBWorld remotes
Igor M. Liplianin <liplianin@me.by>
*/
static struct rc_map_table dm1105_nec[] = {
{ 0x0a, KEY_POWER2}, /* power */
{ 0x0c, KEY_MUTE}, /* mute */
{ 0x11, KEY_1},
{ 0x12, KEY_2},
{ 0x13, KEY_3},
{ 0x14, KEY_4},
{ 0x15, KEY_5},
{ 0x16, KEY_6},
{ 0x17, KEY_7},
{ 0x18, KEY_8},
{ 0x19, KEY_9},
{ 0x10, KEY_0},
{ 0x1c, KEY_CHANNELUP}, /* ch+ */
{ 0x0f, KEY_CHANNELDOWN}, /* ch- */
{ 0x1a, KEY_VOLUMEUP}, /* vol+ */
{ 0x0e, KEY_VOLUMEDOWN}, /* vol- */
{ 0x04, KEY_RECORD}, /* rec */
{ 0x09, KEY_CHANNEL}, /* fav */
{ 0x08, KEY_BACKSPACE}, /* rewind */
{ 0x07, KEY_FASTFORWARD}, /* fast */
{ 0x0b, KEY_PAUSE}, /* pause */
{ 0x02, KEY_ESC}, /* cancel */
{ 0x03, KEY_TAB}, /* tab */
{ 0x00, KEY_UP}, /* up */
{ 0x1f, KEY_ENTER}, /* ok */
{ 0x01, KEY_DOWN}, /* down */
{ 0x05, KEY_RECORD}, /* cap */
{ 0x06, KEY_STOP}, /* stop */
{ 0x40, KEY_ZOOM}, /* full */
{ 0x1e, KEY_TV}, /* tvmode */
{ 0x1b, KEY_B}, /* recall */
};
static struct rc_map_list dm1105_nec_map = {
.map = {
.scan = dm1105_nec,
.size = ARRAY_SIZE(dm1105_nec),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_DM1105_NEC,
}
};
static int __init init_rc_map_dm1105_nec(void)
{
return rc_map_register(&dm1105_nec_map);
}
static void __exit exit_rc_map_dm1105_nec(void)
{
rc_map_unregister(&dm1105_nec_map);
}
module_init(init_rc_map_dm1105_nec)
module_exit(exit_rc_map_dm1105_nec)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,79 @@
/* dntv-live-dvb-t.h - Keytable for dntv_live_dvb_t Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* DigitalNow DNTV Live DVB-T Remote */
static struct rc_map_table dntv_live_dvb_t[] = {
{ 0x00, KEY_ESC }, /* 'go up a level?' */
/* Keys 0 to 9 */
{ 0x0a, KEY_0 },
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
{ 0x0b, KEY_TUNER }, /* tv/fm */
{ 0x0c, KEY_SEARCH }, /* scan */
{ 0x0d, KEY_STOP },
{ 0x0e, KEY_PAUSE },
{ 0x0f, KEY_VIDEO }, /* source */
{ 0x10, KEY_MUTE },
{ 0x11, KEY_REWIND }, /* backward << */
{ 0x12, KEY_POWER },
{ 0x13, KEY_CAMERA }, /* snap */
{ 0x14, KEY_AUDIO }, /* stereo */
{ 0x15, KEY_CLEAR }, /* reset */
{ 0x16, KEY_PLAY },
{ 0x17, KEY_ENTER },
{ 0x18, KEY_ZOOM }, /* full screen */
{ 0x19, KEY_FASTFORWARD }, /* forward >> */
{ 0x1a, KEY_CHANNELUP },
{ 0x1b, KEY_VOLUMEUP },
{ 0x1c, KEY_INFO }, /* preview */
{ 0x1d, KEY_RECORD }, /* record */
{ 0x1e, KEY_CHANNELDOWN },
{ 0x1f, KEY_VOLUMEDOWN },
};
static struct rc_map_list dntv_live_dvb_t_map = {
.map = {
.scan = dntv_live_dvb_t,
.size = ARRAY_SIZE(dntv_live_dvb_t),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_DNTV_LIVE_DVB_T,
}
};
static int __init init_rc_map_dntv_live_dvb_t(void)
{
return rc_map_register(&dntv_live_dvb_t_map);
}
static void __exit exit_rc_map_dntv_live_dvb_t(void)
{
rc_map_unregister(&dntv_live_dvb_t_map);
}
module_init(init_rc_map_dntv_live_dvb_t)
module_exit(exit_rc_map_dntv_live_dvb_t)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,98 @@
/* dntv-live-dvbt-pro.h - Keytable for dntv_live_dvbt_pro Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* DigitalNow DNTV Live! DVB-T Pro Remote */
static struct rc_map_table dntv_live_dvbt_pro[] = {
{ 0x16, KEY_POWER },
{ 0x5b, KEY_HOME },
{ 0x55, KEY_TV }, /* live tv */
{ 0x58, KEY_TUNER }, /* digital Radio */
{ 0x5a, KEY_RADIO }, /* FM radio */
{ 0x59, KEY_DVD }, /* dvd menu */
{ 0x03, KEY_1 },
{ 0x01, KEY_2 },
{ 0x06, KEY_3 },
{ 0x09, KEY_4 },
{ 0x1d, KEY_5 },
{ 0x1f, KEY_6 },
{ 0x0d, KEY_7 },
{ 0x19, KEY_8 },
{ 0x1b, KEY_9 },
{ 0x0c, KEY_CANCEL },
{ 0x15, KEY_0 },
{ 0x4a, KEY_CLEAR },
{ 0x13, KEY_BACK },
{ 0x00, KEY_TAB },
{ 0x4b, KEY_UP },
{ 0x4e, KEY_LEFT },
{ 0x4f, KEY_OK },
{ 0x52, KEY_RIGHT },
{ 0x51, KEY_DOWN },
{ 0x1e, KEY_VOLUMEUP },
{ 0x0a, KEY_VOLUMEDOWN },
{ 0x02, KEY_CHANNELDOWN },
{ 0x05, KEY_CHANNELUP },
{ 0x11, KEY_RECORD },
{ 0x14, KEY_PLAY },
{ 0x4c, KEY_PAUSE },
{ 0x1a, KEY_STOP },
{ 0x40, KEY_REWIND },
{ 0x12, KEY_FASTFORWARD },
{ 0x41, KEY_PREVIOUSSONG }, /* replay |< */
{ 0x42, KEY_NEXTSONG }, /* skip >| */
{ 0x54, KEY_CAMERA }, /* capture */
{ 0x50, KEY_LANGUAGE }, /* sap */
{ 0x47, KEY_TV2 }, /* pip */
{ 0x4d, KEY_SCREEN },
{ 0x43, KEY_SUBTITLE },
{ 0x10, KEY_MUTE },
{ 0x49, KEY_AUDIO }, /* l/r */
{ 0x07, KEY_SLEEP },
{ 0x08, KEY_VIDEO }, /* a/v */
{ 0x0e, KEY_PREVIOUS }, /* recall */
{ 0x45, KEY_ZOOM }, /* zoom + */
{ 0x46, KEY_ANGLE }, /* zoom - */
{ 0x56, KEY_RED },
{ 0x57, KEY_GREEN },
{ 0x5c, KEY_YELLOW },
{ 0x5d, KEY_BLUE },
};
static struct rc_map_list dntv_live_dvbt_pro_map = {
.map = {
.scan = dntv_live_dvbt_pro,
.size = ARRAY_SIZE(dntv_live_dvbt_pro),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_DNTV_LIVE_DVBT_PRO,
}
};
static int __init init_rc_map_dntv_live_dvbt_pro(void)
{
return rc_map_register(&dntv_live_dvbt_pro_map);
}
static void __exit exit_rc_map_dntv_live_dvbt_pro(void)
{
rc_map_unregister(&dntv_live_dvbt_pro_map);
}
module_init(init_rc_map_dntv_live_dvbt_pro)
module_exit(exit_rc_map_dntv_live_dvbt_pro)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,78 @@
/* rc-dvbsky.c - Keytable for DVBSky Remote Controllers
*
* keymap imported from ir-keymaps.c
*
*
* Copyright (c) 2010-2012 by Nibble Max <nibble.max@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* This table contains the complete RC5 code, instead of just the data part
*/
static struct rc_map_table rc5_dvbsky[] = {
{ 0x0000, KEY_0 },
{ 0x0001, KEY_1 },
{ 0x0002, KEY_2 },
{ 0x0003, KEY_3 },
{ 0x0004, KEY_4 },
{ 0x0005, KEY_5 },
{ 0x0006, KEY_6 },
{ 0x0007, KEY_7 },
{ 0x0008, KEY_8 },
{ 0x0009, KEY_9 },
{ 0x000a, KEY_MUTE },
{ 0x000d, KEY_OK },
{ 0x000b, KEY_STOP },
{ 0x000c, KEY_EXIT },
{ 0x000e, KEY_CAMERA }, /*Snap shot*/
{ 0x000f, KEY_SUBTITLE }, /*PIP*/
{ 0x0010, KEY_VOLUMEUP },
{ 0x0011, KEY_VOLUMEDOWN },
{ 0x0012, KEY_FAVORITES },
{ 0x0013, KEY_LIST }, /*Info*/
{ 0x0016, KEY_PAUSE },
{ 0x0017, KEY_PLAY },
{ 0x001f, KEY_RECORD },
{ 0x0020, KEY_CHANNELDOWN },
{ 0x0021, KEY_CHANNELUP },
{ 0x0025, KEY_POWER2 },
{ 0x0026, KEY_REWIND },
{ 0x0027, KEY_FASTFORWARD },
{ 0x0029, KEY_LAST },
{ 0x002b, KEY_MENU },
{ 0x002c, KEY_EPG },
{ 0x002d, KEY_ZOOM },
};
static struct rc_map_list rc5_dvbsky_map = {
.map = {
.scan = rc5_dvbsky,
.size = ARRAY_SIZE(rc5_dvbsky),
.rc_type = RC_TYPE_RC5,
.name = RC_MAP_DVBSKY,
}
};
static int __init init_rc_map_rc5_dvbsky(void)
{
return rc_map_register(&rc5_dvbsky_map);
}
static void __exit exit_rc_map_rc5_dvbsky(void)
{
rc_map_unregister(&rc5_dvbsky_map);
}
module_init(init_rc_map_rc5_dvbsky)
module_exit(exit_rc_map_rc5_dvbsky)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nibble Max <nibble.max@gmail.com>");

View file

@ -0,0 +1,70 @@
/* em-terratec.h - Keytable for em_terratec Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table em_terratec[] = {
{ 0x01, KEY_CHANNEL },
{ 0x02, KEY_SELECT },
{ 0x03, KEY_MUTE },
{ 0x04, KEY_POWER },
{ 0x05, KEY_1 },
{ 0x06, KEY_2 },
{ 0x07, KEY_3 },
{ 0x08, KEY_CHANNELUP },
{ 0x09, KEY_4 },
{ 0x0a, KEY_5 },
{ 0x0b, KEY_6 },
{ 0x0c, KEY_CHANNELDOWN },
{ 0x0d, KEY_7 },
{ 0x0e, KEY_8 },
{ 0x0f, KEY_9 },
{ 0x10, KEY_VOLUMEUP },
{ 0x11, KEY_0 },
{ 0x12, KEY_MENU },
{ 0x13, KEY_PRINT },
{ 0x14, KEY_VOLUMEDOWN },
{ 0x16, KEY_PAUSE },
{ 0x18, KEY_RECORD },
{ 0x19, KEY_REWIND },
{ 0x1a, KEY_PLAY },
{ 0x1b, KEY_FORWARD },
{ 0x1c, KEY_BACKSPACE },
{ 0x1e, KEY_STOP },
{ 0x40, KEY_ZOOM },
};
static struct rc_map_list em_terratec_map = {
.map = {
.scan = em_terratec,
.size = ARRAY_SIZE(em_terratec),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_EM_TERRATEC,
}
};
static int __init init_rc_map_em_terratec(void)
{
return rc_map_register(&em_terratec_map);
}
static void __exit exit_rc_map_em_terratec(void)
{
rc_map_unregister(&em_terratec_map);
}
module_init(init_rc_map_em_terratec)
module_exit(exit_rc_map_em_terratec)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,82 @@
/* encore-enltv-fm53.h - Keytable for encore_enltv_fm53 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Encore ENLTV-FM v5.3
Mauro Carvalho Chehab <mchehab@infradead.org>
*/
static struct rc_map_table encore_enltv_fm53[] = {
{ 0x10, KEY_POWER2},
{ 0x06, KEY_MUTE},
{ 0x09, KEY_1},
{ 0x1d, KEY_2},
{ 0x1f, KEY_3},
{ 0x19, KEY_4},
{ 0x1b, KEY_5},
{ 0x11, KEY_6},
{ 0x17, KEY_7},
{ 0x12, KEY_8},
{ 0x16, KEY_9},
{ 0x48, KEY_0},
{ 0x04, KEY_LIST}, /* -/-- */
{ 0x40, KEY_LAST}, /* recall */
{ 0x02, KEY_MODE}, /* TV/AV */
{ 0x05, KEY_CAMERA}, /* SNAPSHOT */
{ 0x4c, KEY_CHANNELUP}, /* UP */
{ 0x00, KEY_CHANNELDOWN}, /* DOWN */
{ 0x0d, KEY_VOLUMEUP}, /* RIGHT */
{ 0x15, KEY_VOLUMEDOWN}, /* LEFT */
{ 0x49, KEY_ENTER}, /* OK */
{ 0x54, KEY_RECORD},
{ 0x4d, KEY_PLAY}, /* pause */
{ 0x1e, KEY_MENU}, /* video setting */
{ 0x0e, KEY_RIGHT}, /* <- */
{ 0x1a, KEY_LEFT}, /* -> */
{ 0x0a, KEY_CLEAR}, /* video default */
{ 0x0c, KEY_ZOOM}, /* hide pannel */
{ 0x47, KEY_SLEEP}, /* shutdown */
};
static struct rc_map_list encore_enltv_fm53_map = {
.map = {
.scan = encore_enltv_fm53,
.size = ARRAY_SIZE(encore_enltv_fm53),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_ENCORE_ENLTV_FM53,
}
};
static int __init init_rc_map_encore_enltv_fm53(void)
{
return rc_map_register(&encore_enltv_fm53_map);
}
static void __exit exit_rc_map_encore_enltv_fm53(void)
{
rc_map_unregister(&encore_enltv_fm53_map);
}
module_init(init_rc_map_encore_enltv_fm53)
module_exit(exit_rc_map_encore_enltv_fm53)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,113 @@
/* encore-enltv.h - Keytable for encore_enltv Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Encore ENLTV-FM - black plastic, white front cover with white glowing buttons
Juan Pablo Sormani <sorman@gmail.com> */
static struct rc_map_table encore_enltv[] = {
/* Power button does nothing, neither in Windows app,
although it sends data (used for BIOS wakeup?) */
{ 0x0d, KEY_MUTE },
{ 0x1e, KEY_TV },
{ 0x00, KEY_VIDEO },
{ 0x01, KEY_AUDIO }, /* music */
{ 0x02, KEY_CAMERA }, /* picture */
{ 0x1f, KEY_1 },
{ 0x03, KEY_2 },
{ 0x04, KEY_3 },
{ 0x05, KEY_4 },
{ 0x1c, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x1d, KEY_9 },
{ 0x0a, KEY_0 },
{ 0x09, KEY_LIST }, /* -/-- */
{ 0x0b, KEY_LAST }, /* recall */
{ 0x14, KEY_HOME }, /* win start menu */
{ 0x15, KEY_EXIT }, /* exit */
{ 0x16, KEY_CHANNELUP }, /* UP */
{ 0x12, KEY_CHANNELDOWN }, /* DOWN */
{ 0x0c, KEY_VOLUMEUP }, /* RIGHT */
{ 0x17, KEY_VOLUMEDOWN }, /* LEFT */
{ 0x18, KEY_ENTER }, /* OK */
{ 0x0e, KEY_ESC },
{ 0x13, KEY_CYCLEWINDOWS }, /* desktop */
{ 0x11, KEY_TAB },
{ 0x19, KEY_SWITCHVIDEOMODE }, /* switch */
{ 0x1a, KEY_MENU },
{ 0x1b, KEY_ZOOM }, /* fullscreen */
{ 0x44, KEY_TIME }, /* time shift */
{ 0x40, KEY_MODE }, /* source */
{ 0x5a, KEY_RECORD },
{ 0x42, KEY_PLAY }, /* play/pause */
{ 0x45, KEY_STOP },
{ 0x43, KEY_CAMERA }, /* camera icon */
{ 0x48, KEY_REWIND },
{ 0x4a, KEY_FASTFORWARD },
{ 0x49, KEY_PREVIOUS },
{ 0x4b, KEY_NEXT },
{ 0x4c, KEY_FAVORITES }, /* tv wall */
{ 0x4d, KEY_SOUND }, /* DVD sound */
{ 0x4e, KEY_LANGUAGE }, /* DVD lang */
{ 0x4f, KEY_TEXT }, /* DVD text */
{ 0x50, KEY_SLEEP }, /* shutdown */
{ 0x51, KEY_MODE }, /* stereo > main */
{ 0x52, KEY_SELECT }, /* stereo > sap */
{ 0x53, KEY_TEXT }, /* teletext */
{ 0x59, KEY_RED }, /* AP1 */
{ 0x41, KEY_GREEN }, /* AP2 */
{ 0x47, KEY_YELLOW }, /* AP3 */
{ 0x57, KEY_BLUE }, /* AP4 */
};
static struct rc_map_list encore_enltv_map = {
.map = {
.scan = encore_enltv,
.size = ARRAY_SIZE(encore_enltv),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_ENCORE_ENLTV,
}
};
static int __init init_rc_map_encore_enltv(void)
{
return rc_map_register(&encore_enltv_map);
}
static void __exit exit_rc_map_encore_enltv(void)
{
rc_map_unregister(&encore_enltv_map);
}
module_init(init_rc_map_encore_enltv)
module_exit(exit_rc_map_encore_enltv)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,91 @@
/* encore-enltv2.h - Keytable for encore_enltv2 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Encore ENLTV2-FM - silver plastic - "Wand Media" written at the botton
Mauro Carvalho Chehab <mchehab@infradead.org> */
static struct rc_map_table encore_enltv2[] = {
{ 0x4c, KEY_POWER2 },
{ 0x4a, KEY_TUNER },
{ 0x40, KEY_1 },
{ 0x60, KEY_2 },
{ 0x50, KEY_3 },
{ 0x70, KEY_4 },
{ 0x48, KEY_5 },
{ 0x68, KEY_6 },
{ 0x58, KEY_7 },
{ 0x78, KEY_8 },
{ 0x44, KEY_9 },
{ 0x54, KEY_0 },
{ 0x64, KEY_LAST }, /* +100 */
{ 0x4e, KEY_AGAIN }, /* Recall */
{ 0x6c, KEY_VIDEO }, /* Video Source */
{ 0x5e, KEY_MENU },
{ 0x56, KEY_SCREEN },
{ 0x7a, KEY_SETUP },
{ 0x46, KEY_MUTE },
{ 0x5c, KEY_MODE }, /* Stereo */
{ 0x74, KEY_INFO },
{ 0x7c, KEY_CLEAR },
{ 0x55, KEY_UP },
{ 0x49, KEY_DOWN },
{ 0x7e, KEY_LEFT },
{ 0x59, KEY_RIGHT },
{ 0x6a, KEY_ENTER },
{ 0x42, KEY_VOLUMEUP },
{ 0x62, KEY_VOLUMEDOWN },
{ 0x52, KEY_CHANNELUP },
{ 0x72, KEY_CHANNELDOWN },
{ 0x41, KEY_RECORD },
{ 0x51, KEY_CAMERA }, /* Snapshot */
{ 0x75, KEY_TIME }, /* Timeshift */
{ 0x71, KEY_TV2 }, /* PIP */
{ 0x45, KEY_REWIND },
{ 0x6f, KEY_PAUSE },
{ 0x7d, KEY_FORWARD },
{ 0x79, KEY_STOP },
};
static struct rc_map_list encore_enltv2_map = {
.map = {
.scan = encore_enltv2,
.size = ARRAY_SIZE(encore_enltv2),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_ENCORE_ENLTV2,
}
};
static int __init init_rc_map_encore_enltv2(void)
{
return rc_map_register(&encore_enltv2_map);
}
static void __exit exit_rc_map_encore_enltv2(void)
{
rc_map_unregister(&encore_enltv2_map);
}
module_init(init_rc_map_encore_enltv2)
module_exit(exit_rc_map_encore_enltv2)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,62 @@
/* evga-indtube.h - Keytable for evga_indtube Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* EVGA inDtube
Devin Heitmueller <devin.heitmueller@gmail.com>
*/
static struct rc_map_table evga_indtube[] = {
{ 0x12, KEY_POWER},
{ 0x02, KEY_MODE}, /* TV */
{ 0x14, KEY_MUTE},
{ 0x1a, KEY_CHANNELUP},
{ 0x16, KEY_TV2}, /* PIP */
{ 0x1d, KEY_VOLUMEUP},
{ 0x05, KEY_CHANNELDOWN},
{ 0x0f, KEY_PLAYPAUSE},
{ 0x19, KEY_VOLUMEDOWN},
{ 0x1c, KEY_REWIND},
{ 0x0d, KEY_RECORD},
{ 0x18, KEY_FORWARD},
{ 0x1e, KEY_PREVIOUS},
{ 0x1b, KEY_STOP},
{ 0x1f, KEY_NEXT},
{ 0x13, KEY_CAMERA},
};
static struct rc_map_list evga_indtube_map = {
.map = {
.scan = evga_indtube,
.size = ARRAY_SIZE(evga_indtube),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_EVGA_INDTUBE,
}
};
static int __init init_rc_map_evga_indtube(void)
{
return rc_map_register(&evga_indtube_map);
}
static void __exit exit_rc_map_evga_indtube(void)
{
rc_map_unregister(&evga_indtube_map);
}
module_init(init_rc_map_evga_indtube)
module_exit(exit_rc_map_evga_indtube)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,97 @@
/* eztv.h - Keytable for eztv Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Alfons Geser <a.geser@cox.net>
* updates from Job D. R. Borges <jobdrb@ig.com.br> */
static struct rc_map_table eztv[] = {
{ 0x12, KEY_POWER },
{ 0x01, KEY_TV }, /* DVR */
{ 0x15, KEY_DVD }, /* DVD */
{ 0x17, KEY_AUDIO }, /* music */
/* DVR mode / DVD mode / music mode */
{ 0x1b, KEY_MUTE }, /* mute */
{ 0x02, KEY_LANGUAGE }, /* MTS/SAP / audio / autoseek */
{ 0x1e, KEY_SUBTITLE }, /* closed captioning / subtitle / seek */
{ 0x16, KEY_ZOOM }, /* full screen */
{ 0x1c, KEY_VIDEO }, /* video source / eject / delall */
{ 0x1d, KEY_RESTART }, /* playback / angle / del */
{ 0x2f, KEY_SEARCH }, /* scan / menu / playlist */
{ 0x30, KEY_CHANNEL }, /* CH surfing / bookmark / memo */
{ 0x31, KEY_HELP }, /* help */
{ 0x32, KEY_MODE }, /* num/memo */
{ 0x33, KEY_ESC }, /* cancel */
{ 0x0c, KEY_UP }, /* up */
{ 0x10, KEY_DOWN }, /* down */
{ 0x08, KEY_LEFT }, /* left */
{ 0x04, KEY_RIGHT }, /* right */
{ 0x03, KEY_SELECT }, /* select */
{ 0x1f, KEY_REWIND }, /* rewind */
{ 0x20, KEY_PLAYPAUSE },/* play/pause */
{ 0x29, KEY_FORWARD }, /* forward */
{ 0x14, KEY_AGAIN }, /* repeat */
{ 0x2b, KEY_RECORD }, /* recording */
{ 0x2c, KEY_STOP }, /* stop */
{ 0x2d, KEY_PLAY }, /* play */
{ 0x2e, KEY_CAMERA }, /* snapshot / shuffle */
{ 0x00, KEY_0 },
{ 0x05, KEY_1 },
{ 0x06, KEY_2 },
{ 0x07, KEY_3 },
{ 0x09, KEY_4 },
{ 0x0a, KEY_5 },
{ 0x0b, KEY_6 },
{ 0x0d, KEY_7 },
{ 0x0e, KEY_8 },
{ 0x0f, KEY_9 },
{ 0x2a, KEY_VOLUMEUP },
{ 0x11, KEY_VOLUMEDOWN },
{ 0x18, KEY_CHANNELUP },/* CH.tracking up */
{ 0x19, KEY_CHANNELDOWN },/* CH.tracking down */
{ 0x13, KEY_ENTER }, /* enter */
{ 0x21, KEY_DOT }, /* . (decimal dot) */
};
static struct rc_map_list eztv_map = {
.map = {
.scan = eztv,
.size = ARRAY_SIZE(eztv),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_EZTV,
}
};
static int __init init_rc_map_eztv(void)
{
return rc_map_register(&eztv_map);
}
static void __exit exit_rc_map_eztv(void)
{
rc_map_unregister(&eztv_map);
}
module_init(init_rc_map_eztv)
module_exit(exit_rc_map_eztv)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,78 @@
/* flydvb.h - Keytable for flydvb Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table flydvb[] = {
{ 0x01, KEY_ZOOM }, /* Full Screen */
{ 0x00, KEY_POWER }, /* Power */
{ 0x03, KEY_1 },
{ 0x04, KEY_2 },
{ 0x05, KEY_3 },
{ 0x07, KEY_4 },
{ 0x08, KEY_5 },
{ 0x09, KEY_6 },
{ 0x0b, KEY_7 },
{ 0x0c, KEY_8 },
{ 0x0d, KEY_9 },
{ 0x06, KEY_AGAIN }, /* Recall */
{ 0x0f, KEY_0 },
{ 0x10, KEY_MUTE }, /* Mute */
{ 0x02, KEY_RADIO }, /* TV/Radio */
{ 0x1b, KEY_LANGUAGE }, /* SAP (Second Audio Program) */
{ 0x14, KEY_VOLUMEUP }, /* VOL+ */
{ 0x17, KEY_VOLUMEDOWN }, /* VOL- */
{ 0x12, KEY_CHANNELUP }, /* CH+ */
{ 0x13, KEY_CHANNELDOWN }, /* CH- */
{ 0x1d, KEY_ENTER }, /* Enter */
{ 0x1a, KEY_TV2 }, /* PIP */
{ 0x18, KEY_VIDEO }, /* Source */
{ 0x1e, KEY_RECORD }, /* Record/Pause */
{ 0x15, KEY_ANGLE }, /* Swap (no label on key) */
{ 0x1c, KEY_PAUSE }, /* Timeshift/Pause */
{ 0x19, KEY_BACK }, /* Rewind << */
{ 0x0a, KEY_PLAYPAUSE }, /* Play/Pause */
{ 0x1f, KEY_FORWARD }, /* Forward >> */
{ 0x16, KEY_PREVIOUS }, /* Back |<< */
{ 0x11, KEY_STOP }, /* Stop */
{ 0x0e, KEY_NEXT }, /* End >>| */
};
static struct rc_map_list flydvb_map = {
.map = {
.scan = flydvb,
.size = ARRAY_SIZE(flydvb),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_FLYDVB,
}
};
static int __init init_rc_map_flydvb(void)
{
return rc_map_register(&flydvb_map);
}
static void __exit exit_rc_map_flydvb(void)
{
rc_map_unregister(&flydvb_map);
}
module_init(init_rc_map_flydvb)
module_exit(exit_rc_map_flydvb)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,71 @@
/* flyvideo.h - Keytable for flyvideo Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table flyvideo[] = {
{ 0x0f, KEY_0 },
{ 0x03, KEY_1 },
{ 0x04, KEY_2 },
{ 0x05, KEY_3 },
{ 0x07, KEY_4 },
{ 0x08, KEY_5 },
{ 0x09, KEY_6 },
{ 0x0b, KEY_7 },
{ 0x0c, KEY_8 },
{ 0x0d, KEY_9 },
{ 0x0e, KEY_MODE }, /* Air/Cable */
{ 0x11, KEY_VIDEO }, /* Video */
{ 0x15, KEY_AUDIO }, /* Audio */
{ 0x00, KEY_POWER }, /* Power */
{ 0x18, KEY_TUNER }, /* AV Source */
{ 0x02, KEY_ZOOM }, /* Fullscreen */
{ 0x1a, KEY_LANGUAGE }, /* Stereo */
{ 0x1b, KEY_MUTE }, /* Mute */
{ 0x14, KEY_VOLUMEUP }, /* Volume + */
{ 0x17, KEY_VOLUMEDOWN },/* Volume - */
{ 0x12, KEY_CHANNELUP },/* Channel + */
{ 0x13, KEY_CHANNELDOWN },/* Channel - */
{ 0x06, KEY_AGAIN }, /* Recall */
{ 0x10, KEY_ENTER }, /* Enter */
{ 0x19, KEY_BACK }, /* Rewind ( <<< ) */
{ 0x1f, KEY_FORWARD }, /* Forward ( >>> ) */
{ 0x0a, KEY_ANGLE }, /* no label, may be used as the PAUSE button */
};
static struct rc_map_list flyvideo_map = {
.map = {
.scan = flyvideo,
.size = ARRAY_SIZE(flyvideo),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_FLYVIDEO,
}
};
static int __init init_rc_map_flyvideo(void)
{
return rc_map_register(&flyvideo_map);
}
static void __exit exit_rc_map_flyvideo(void)
{
rc_map_unregister(&flyvideo_map);
}
module_init(init_rc_map_flyvideo)
module_exit(exit_rc_map_flyvideo)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,99 @@
/* fusionhdtv-mce.h - Keytable for fusionhdtv_mce Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* DViCO FUSION HDTV MCE remote */
static struct rc_map_table fusionhdtv_mce[] = {
{ 0x0b, KEY_1 },
{ 0x17, KEY_2 },
{ 0x1b, KEY_3 },
{ 0x07, KEY_4 },
{ 0x50, KEY_5 },
{ 0x54, KEY_6 },
{ 0x48, KEY_7 },
{ 0x4c, KEY_8 },
{ 0x58, KEY_9 },
{ 0x03, KEY_0 },
{ 0x5e, KEY_OK },
{ 0x51, KEY_UP },
{ 0x53, KEY_DOWN },
{ 0x5b, KEY_LEFT },
{ 0x5f, KEY_RIGHT },
{ 0x02, KEY_TV }, /* Labeled DTV on remote */
{ 0x0e, KEY_MP3 },
{ 0x1a, KEY_DVD },
{ 0x1e, KEY_FAVORITES }, /* Labeled CPF on remote */
{ 0x16, KEY_SETUP },
{ 0x46, KEY_POWER2 }, /* TV On/Off button on remote */
{ 0x0a, KEY_EPG }, /* Labeled Guide on remote */
{ 0x49, KEY_BACK },
{ 0x59, KEY_INFO }, /* Labeled MORE on remote */
{ 0x4d, KEY_MENU }, /* Labeled DVDMENU on remote */
{ 0x55, KEY_CYCLEWINDOWS }, /* Labeled ALT-TAB on remote */
{ 0x0f, KEY_PREVIOUSSONG }, /* Labeled |<< REPLAY on remote */
{ 0x12, KEY_NEXTSONG }, /* Labeled >>| SKIP on remote */
{ 0x42, KEY_ENTER }, /* Labeled START with a green
MS windows logo on remote */
{ 0x15, KEY_VOLUMEUP },
{ 0x05, KEY_VOLUMEDOWN },
{ 0x11, KEY_CHANNELUP },
{ 0x09, KEY_CHANNELDOWN },
{ 0x52, KEY_CAMERA },
{ 0x5a, KEY_TUNER },
{ 0x19, KEY_OPEN },
{ 0x13, KEY_MODE }, /* 4:3 16:9 select */
{ 0x1f, KEY_ZOOM },
{ 0x43, KEY_REWIND },
{ 0x47, KEY_PLAYPAUSE },
{ 0x4f, KEY_FASTFORWARD },
{ 0x57, KEY_MUTE },
{ 0x0d, KEY_STOP },
{ 0x01, KEY_RECORD },
{ 0x4e, KEY_POWER },
};
static struct rc_map_list fusionhdtv_mce_map = {
.map = {
.scan = fusionhdtv_mce,
.size = ARRAY_SIZE(fusionhdtv_mce),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_FUSIONHDTV_MCE,
}
};
static int __init init_rc_map_fusionhdtv_mce(void)
{
return rc_map_register(&fusionhdtv_mce_map);
}
static void __exit exit_rc_map_fusionhdtv_mce(void)
{
rc_map_unregister(&fusionhdtv_mce_map);
}
module_init(init_rc_map_fusionhdtv_mce)
module_exit(exit_rc_map_fusionhdtv_mce)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,82 @@
/* gadmei-rm008z.h - Keytable for gadmei_rm008z Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* GADMEI UTV330+ RM008Z remote
Shine Liu <shinel@foxmail.com>
*/
static struct rc_map_table gadmei_rm008z[] = {
{ 0x14, KEY_POWER2}, /* POWER OFF */
{ 0x0c, KEY_MUTE}, /* MUTE */
{ 0x18, KEY_TV}, /* TV */
{ 0x0e, KEY_VIDEO}, /* AV */
{ 0x0b, KEY_AUDIO}, /* SV */
{ 0x0f, KEY_RADIO}, /* FM */
{ 0x00, KEY_1},
{ 0x01, KEY_2},
{ 0x02, KEY_3},
{ 0x03, KEY_4},
{ 0x04, KEY_5},
{ 0x05, KEY_6},
{ 0x06, KEY_7},
{ 0x07, KEY_8},
{ 0x08, KEY_9},
{ 0x09, KEY_0},
{ 0x0a, KEY_INFO}, /* OSD */
{ 0x1c, KEY_BACKSPACE}, /* LAST */
{ 0x0d, KEY_PLAY}, /* PLAY */
{ 0x1e, KEY_CAMERA}, /* SNAPSHOT */
{ 0x1a, KEY_RECORD}, /* RECORD */
{ 0x17, KEY_STOP}, /* STOP */
{ 0x1f, KEY_UP}, /* UP */
{ 0x44, KEY_DOWN}, /* DOWN */
{ 0x46, KEY_TAB}, /* BACK */
{ 0x4a, KEY_ZOOM}, /* FULLSECREEN */
{ 0x10, KEY_VOLUMEUP}, /* VOLUMEUP */
{ 0x11, KEY_VOLUMEDOWN}, /* VOLUMEDOWN */
{ 0x12, KEY_CHANNELUP}, /* CHANNELUP */
{ 0x13, KEY_CHANNELDOWN}, /* CHANNELDOWN */
{ 0x15, KEY_ENTER}, /* OK */
};
static struct rc_map_list gadmei_rm008z_map = {
.map = {
.scan = gadmei_rm008z,
.size = ARRAY_SIZE(gadmei_rm008z),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_GADMEI_RM008Z,
}
};
static int __init init_rc_map_gadmei_rm008z(void)
{
return rc_map_register(&gadmei_rm008z_map);
}
static void __exit exit_rc_map_gadmei_rm008z(void)
{
rc_map_unregister(&gadmei_rm008z_map);
}
module_init(init_rc_map_gadmei_rm008z)
module_exit(exit_rc_map_gadmei_rm008z)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,85 @@
/* genius-tvgo-a11mce.h - Keytable for genius_tvgo_a11mce Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Remote control for the Genius TVGO A11MCE
* Adrian Pardini <pardo.bsso@gmail.com>
*/
static struct rc_map_table genius_tvgo_a11mce[] = {
/* Keys 0 to 9 */
{ 0x48, KEY_0 },
{ 0x09, KEY_1 },
{ 0x1d, KEY_2 },
{ 0x1f, KEY_3 },
{ 0x19, KEY_4 },
{ 0x1b, KEY_5 },
{ 0x11, KEY_6 },
{ 0x17, KEY_7 },
{ 0x12, KEY_8 },
{ 0x16, KEY_9 },
{ 0x54, KEY_RECORD }, /* recording */
{ 0x06, KEY_MUTE }, /* mute */
{ 0x10, KEY_POWER },
{ 0x40, KEY_LAST }, /* recall */
{ 0x4c, KEY_CHANNELUP }, /* channel / program + */
{ 0x00, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x0d, KEY_VOLUMEUP },
{ 0x15, KEY_VOLUMEDOWN },
{ 0x4d, KEY_OK }, /* also labeled as Pause */
{ 0x1c, KEY_ZOOM }, /* full screen and Stop*/
{ 0x02, KEY_MODE }, /* AV Source or Rewind*/
{ 0x04, KEY_LIST }, /* -/-- */
/* small arrows above numbers */
{ 0x1a, KEY_NEXT }, /* also Fast Forward */
{ 0x0e, KEY_PREVIOUS }, /* also Rewind */
/* these are in a rather non standard layout and have
an alternate name written */
{ 0x1e, KEY_UP }, /* Video Setting */
{ 0x0a, KEY_DOWN }, /* Video Default */
{ 0x05, KEY_CAMERA }, /* Snapshot */
{ 0x0c, KEY_RIGHT }, /* Hide Panel */
/* Four buttons without label */
{ 0x49, KEY_RED },
{ 0x0b, KEY_GREEN },
{ 0x13, KEY_YELLOW },
{ 0x50, KEY_BLUE },
};
static struct rc_map_list genius_tvgo_a11mce_map = {
.map = {
.scan = genius_tvgo_a11mce,
.size = ARRAY_SIZE(genius_tvgo_a11mce),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_GENIUS_TVGO_A11MCE,
}
};
static int __init init_rc_map_genius_tvgo_a11mce(void)
{
return rc_map_register(&genius_tvgo_a11mce_map);
}
static void __exit exit_rc_map_genius_tvgo_a11mce(void)
{
rc_map_unregister(&genius_tvgo_a11mce_map);
}
module_init(init_rc_map_genius_tvgo_a11mce)
module_exit(exit_rc_map_genius_tvgo_a11mce)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,80 @@
/* gotview7135.h - Keytable for gotview7135 Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Mike Baikov <mike@baikov.com> */
static struct rc_map_table gotview7135[] = {
{ 0x11, KEY_POWER },
{ 0x35, KEY_TV },
{ 0x1b, KEY_0 },
{ 0x29, KEY_1 },
{ 0x19, KEY_2 },
{ 0x39, KEY_3 },
{ 0x1f, KEY_4 },
{ 0x2c, KEY_5 },
{ 0x21, KEY_6 },
{ 0x24, KEY_7 },
{ 0x18, KEY_8 },
{ 0x2b, KEY_9 },
{ 0x3b, KEY_AGAIN }, /* LOOP */
{ 0x06, KEY_AUDIO },
{ 0x31, KEY_PRINT }, /* PREVIEW */
{ 0x3e, KEY_VIDEO },
{ 0x10, KEY_CHANNELUP },
{ 0x20, KEY_CHANNELDOWN },
{ 0x0c, KEY_VOLUMEDOWN },
{ 0x28, KEY_VOLUMEUP },
{ 0x08, KEY_MUTE },
{ 0x26, KEY_SEARCH }, /* SCAN */
{ 0x3f, KEY_CAMERA }, /* SNAPSHOT */
{ 0x12, KEY_RECORD },
{ 0x32, KEY_STOP },
{ 0x3c, KEY_PLAY },
{ 0x1d, KEY_REWIND },
{ 0x2d, KEY_PAUSE },
{ 0x0d, KEY_FORWARD },
{ 0x05, KEY_ZOOM }, /*FULL*/
{ 0x2a, KEY_F21 }, /* LIVE TIMESHIFT */
{ 0x0e, KEY_F22 }, /* MIN TIMESHIFT */
{ 0x1e, KEY_TIME }, /* TIMESHIFT */
{ 0x38, KEY_F24 }, /* NORMAL TIMESHIFT */
};
static struct rc_map_list gotview7135_map = {
.map = {
.scan = gotview7135,
.size = ARRAY_SIZE(gotview7135),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_GOTVIEW7135,
}
};
static int __init init_rc_map_gotview7135(void)
{
return rc_map_register(&gotview7135_map);
}
static void __exit exit_rc_map_gotview7135(void)
{
rc_map_unregister(&gotview7135_map);
}
module_init(init_rc_map_gotview7135)
module_exit(exit_rc_map_gotview7135)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,293 @@
/* rc-hauppauge.c - Keytable for Hauppauge Remote Controllers
*
* keymap imported from ir-keymaps.c
*
* This map currently contains the code for four different RCs:
* - New Hauppauge Gray;
* - Old Hauppauge Gray (with a golden screen for media keys);
* - Hauppauge Black;
* - DSR-0112 remote bundled with Haupauge MiniStick.
*
* Copyright (c) 2010-2011 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* Hauppauge:the newer, gray remotes (seems there are multiple
* slightly different versions), shipped with cx88+ivtv cards.
*
* This table contains the complete RC5 code, instead of just the data part
*/
static struct rc_map_table rc5_hauppauge_new[] = {
/*
* Remote Controller Hauppauge Gray found on modern devices
* Keycodes start with address = 0x1e
*/
{ 0x1e3b, KEY_SELECT }, /* GO / house symbol */
{ 0x1e3d, KEY_POWER2 }, /* system power (green button) */
{ 0x1e1c, KEY_TV },
{ 0x1e18, KEY_VIDEO }, /* Videos */
{ 0x1e19, KEY_AUDIO }, /* Music */
{ 0x1e1a, KEY_CAMERA }, /* Pictures */
{ 0x1e1b, KEY_EPG }, /* Guide */
{ 0x1e0c, KEY_RADIO },
{ 0x1e14, KEY_UP },
{ 0x1e15, KEY_DOWN },
{ 0x1e16, KEY_LEFT },
{ 0x1e17, KEY_RIGHT },
{ 0x1e25, KEY_OK }, /* OK */
{ 0x1e1f, KEY_EXIT }, /* back/exit */
{ 0x1e0d, KEY_MENU },
{ 0x1e10, KEY_VOLUMEUP },
{ 0x1e11, KEY_VOLUMEDOWN },
{ 0x1e12, KEY_PREVIOUS }, /* previous channel */
{ 0x1e0f, KEY_MUTE },
{ 0x1e20, KEY_CHANNELUP }, /* channel / program + */
{ 0x1e21, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x1e37, KEY_RECORD }, /* recording */
{ 0x1e36, KEY_STOP },
{ 0x1e32, KEY_REWIND }, /* backward << */
{ 0x1e35, KEY_PLAY },
{ 0x1e34, KEY_FASTFORWARD }, /* forward >> */
{ 0x1e24, KEY_PREVIOUSSONG }, /* replay |< */
{ 0x1e30, KEY_PAUSE }, /* pause */
{ 0x1e1e, KEY_NEXTSONG }, /* skip >| */
{ 0x1e01, KEY_1 },
{ 0x1e02, KEY_2 },
{ 0x1e03, KEY_3 },
{ 0x1e04, KEY_4 },
{ 0x1e05, KEY_5 },
{ 0x1e06, KEY_6 },
{ 0x1e07, KEY_7 },
{ 0x1e08, KEY_8 },
{ 0x1e09, KEY_9 },
{ 0x1e0a, KEY_TEXT }, /* keypad asterisk as well */
{ 0x1e00, KEY_0 },
{ 0x1e0e, KEY_SUBTITLE }, /* also the Pound key (#) */
{ 0x1e0b, KEY_RED }, /* red button */
{ 0x1e2e, KEY_GREEN }, /* green button */
{ 0x1e38, KEY_YELLOW }, /* yellow key */
{ 0x1e29, KEY_BLUE }, /* blue key */
/*
* Old Remote Controller Hauppauge Gray with a golden screen
* Keycodes start with address = 0x1f
*/
{ 0x1f3d, KEY_POWER2 }, /* system power (green button) */
{ 0x1f3b, KEY_SELECT }, /* GO */
/* Keys 0 to 9 */
{ 0x1f00, KEY_0 },
{ 0x1f01, KEY_1 },
{ 0x1f02, KEY_2 },
{ 0x1f03, KEY_3 },
{ 0x1f04, KEY_4 },
{ 0x1f05, KEY_5 },
{ 0x1f06, KEY_6 },
{ 0x1f07, KEY_7 },
{ 0x1f08, KEY_8 },
{ 0x1f09, KEY_9 },
{ 0x1f1f, KEY_EXIT }, /* back/exit */
{ 0x1f0d, KEY_MENU },
{ 0x1f10, KEY_VOLUMEUP },
{ 0x1f11, KEY_VOLUMEDOWN },
{ 0x1f20, KEY_CHANNELUP }, /* channel / program + */
{ 0x1f21, KEY_CHANNELDOWN }, /* channel / program - */
{ 0x1f25, KEY_ENTER }, /* OK */
{ 0x1f0b, KEY_RED }, /* red button */
{ 0x1f2e, KEY_GREEN }, /* green button */
{ 0x1f38, KEY_YELLOW }, /* yellow key */
{ 0x1f29, KEY_BLUE }, /* blue key */
{ 0x1f0f, KEY_MUTE },
{ 0x1f0c, KEY_RADIO }, /* There's no indicator on this key */
{ 0x1f3c, KEY_ZOOM }, /* full */
{ 0x1f32, KEY_REWIND }, /* backward << */
{ 0x1f35, KEY_PLAY },
{ 0x1f34, KEY_FASTFORWARD }, /* forward >> */
{ 0x1f37, KEY_RECORD }, /* recording */
{ 0x1f36, KEY_STOP },
{ 0x1f30, KEY_PAUSE }, /* pause */
{ 0x1f24, KEY_PREVIOUSSONG }, /* replay |< */
{ 0x1f1e, KEY_NEXTSONG }, /* skip >| */
/*
* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick
* Keycodes start with address = 0x1d
*/
{ 0x1d00, KEY_0 },
{ 0x1d01, KEY_1 },
{ 0x1d02, KEY_2 },
{ 0x1d03, KEY_3 },
{ 0x1d04, KEY_4 },
{ 0x1d05, KEY_5 },
{ 0x1d06, KEY_6 },
{ 0x1d07, KEY_7 },
{ 0x1d08, KEY_8 },
{ 0x1d09, KEY_9 },
{ 0x1d0a, KEY_TEXT },
{ 0x1d0d, KEY_MENU },
{ 0x1d0f, KEY_MUTE },
{ 0x1d10, KEY_VOLUMEUP },
{ 0x1d11, KEY_VOLUMEDOWN },
{ 0x1d12, KEY_PREVIOUS }, /* Prev.Ch .. ??? */
{ 0x1d14, KEY_UP },
{ 0x1d15, KEY_DOWN },
{ 0x1d16, KEY_LEFT },
{ 0x1d17, KEY_RIGHT },
{ 0x1d1c, KEY_TV },
{ 0x1d1e, KEY_NEXT }, /* >| */
{ 0x1d1f, KEY_EXIT },
{ 0x1d20, KEY_CHANNELUP },
{ 0x1d21, KEY_CHANNELDOWN },
{ 0x1d24, KEY_LAST }, /* <| */
{ 0x1d25, KEY_OK },
{ 0x1d30, KEY_PAUSE },
{ 0x1d32, KEY_REWIND },
{ 0x1d34, KEY_FASTFORWARD },
{ 0x1d35, KEY_PLAY },
{ 0x1d36, KEY_STOP },
{ 0x1d37, KEY_RECORD },
{ 0x1d3b, KEY_GOTO },
{ 0x1d3d, KEY_POWER },
{ 0x1d3f, KEY_HOME },
/*
* Keycodes for PT# R-005 remote bundled with Haupauge HVR-930C
* Keycodes start with address = 0x1c
*/
{ 0x1c3b, KEY_GOTO },
{ 0x1c3d, KEY_POWER },
{ 0x1c14, KEY_UP },
{ 0x1c15, KEY_DOWN },
{ 0x1c16, KEY_LEFT },
{ 0x1c17, KEY_RIGHT },
{ 0x1c25, KEY_OK },
{ 0x1c00, KEY_0 },
{ 0x1c01, KEY_1 },
{ 0x1c02, KEY_2 },
{ 0x1c03, KEY_3 },
{ 0x1c04, KEY_4 },
{ 0x1c05, KEY_5 },
{ 0x1c06, KEY_6 },
{ 0x1c07, KEY_7 },
{ 0x1c08, KEY_8 },
{ 0x1c09, KEY_9 },
{ 0x1c1f, KEY_EXIT }, /* BACK */
{ 0x1c0d, KEY_MENU },
{ 0x1c1c, KEY_TV },
{ 0x1c10, KEY_VOLUMEUP },
{ 0x1c11, KEY_VOLUMEDOWN },
{ 0x1c20, KEY_CHANNELUP },
{ 0x1c21, KEY_CHANNELDOWN },
{ 0x1c0f, KEY_MUTE },
{ 0x1c12, KEY_PREVIOUS }, /* Prev */
{ 0x1c36, KEY_STOP },
{ 0x1c37, KEY_RECORD },
{ 0x1c24, KEY_LAST }, /* <| */
{ 0x1c1e, KEY_NEXT }, /* >| */
{ 0x1c0a, KEY_TEXT },
{ 0x1c0e, KEY_SUBTITLE }, /* CC */
{ 0x1c32, KEY_REWIND },
{ 0x1c30, KEY_PAUSE },
{ 0x1c35, KEY_PLAY },
{ 0x1c34, KEY_FASTFORWARD },
/*
* Keycodes for the old Black Remote Controller
* This one also uses RC-5 protocol
* Keycodes start with address = 0x00
*/
{ 0x001f, KEY_TV },
{ 0x0020, KEY_CHANNELUP },
{ 0x000c, KEY_RADIO },
{ 0x0011, KEY_VOLUMEDOWN },
{ 0x002e, KEY_ZOOM }, /* full screen */
{ 0x0010, KEY_VOLUMEUP },
{ 0x000d, KEY_MUTE },
{ 0x0021, KEY_CHANNELDOWN },
{ 0x0022, KEY_VIDEO }, /* source */
{ 0x0001, KEY_1 },
{ 0x0002, KEY_2 },
{ 0x0003, KEY_3 },
{ 0x0004, KEY_4 },
{ 0x0005, KEY_5 },
{ 0x0006, KEY_6 },
{ 0x0007, KEY_7 },
{ 0x0008, KEY_8 },
{ 0x0009, KEY_9 },
{ 0x001e, KEY_RED }, /* Reserved */
{ 0x0000, KEY_0 },
{ 0x0026, KEY_SLEEP }, /* Minimize */
};
static struct rc_map_list rc5_hauppauge_new_map = {
.map = {
.scan = rc5_hauppauge_new,
.size = ARRAY_SIZE(rc5_hauppauge_new),
.rc_type = RC_TYPE_RC5,
.name = RC_MAP_HAUPPAUGE,
}
};
static int __init init_rc_map_rc5_hauppauge_new(void)
{
return rc_map_register(&rc5_hauppauge_new_map);
}
static void __exit exit_rc_map_rc5_hauppauge_new(void)
{
rc_map_unregister(&rc5_hauppauge_new_map);
}
module_init(init_rc_map_rc5_hauppauge_new)
module_exit(exit_rc_map_rc5_hauppauge_new)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,143 @@
/* rc5-imon-mce.c - Keytable for Windows Media Center RC-6 remotes for use
* with the SoundGraph iMON/Antec Veris hardware IR decoder
*
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* mce-mode imon mce remote key table */
static struct rc_map_table imon_mce[] = {
/* keys sorted mostly by frequency of use to optimize lookups */
{ 0x800ff415, KEY_REWIND },
{ 0x800ff414, KEY_FASTFORWARD },
{ 0x800ff41b, KEY_PREVIOUS },
{ 0x800ff41a, KEY_NEXT },
{ 0x800ff416, KEY_PLAY },
{ 0x800ff418, KEY_PAUSE },
{ 0x800ff419, KEY_STOP },
{ 0x800ff417, KEY_RECORD },
{ 0x02000052, KEY_UP },
{ 0x02000051, KEY_DOWN },
{ 0x02000050, KEY_LEFT },
{ 0x0200004f, KEY_RIGHT },
{ 0x800ff41e, KEY_UP },
{ 0x800ff41f, KEY_DOWN },
{ 0x800ff420, KEY_LEFT },
{ 0x800ff421, KEY_RIGHT },
/* 0x800ff40b also KEY_NUMERIC_POUND on some receivers */
{ 0x800ff40b, KEY_ENTER },
{ 0x02000028, KEY_ENTER },
/* the OK and Enter buttons decode to the same value on some remotes
{ 0x02000028, KEY_OK }, */
{ 0x800ff422, KEY_OK },
{ 0x0200002a, KEY_EXIT },
{ 0x800ff423, KEY_EXIT },
{ 0x02000029, KEY_DELETE },
/* 0x800ff40a also KEY_NUMERIC_STAR on some receivers */
{ 0x800ff40a, KEY_DELETE },
{ 0x800ff40e, KEY_MUTE },
{ 0x800ff410, KEY_VOLUMEUP },
{ 0x800ff411, KEY_VOLUMEDOWN },
{ 0x800ff412, KEY_CHANNELUP },
{ 0x800ff413, KEY_CHANNELDOWN },
{ 0x0200001e, KEY_NUMERIC_1 },
{ 0x0200001f, KEY_NUMERIC_2 },
{ 0x02000020, KEY_NUMERIC_3 },
{ 0x02000021, KEY_NUMERIC_4 },
{ 0x02000022, KEY_NUMERIC_5 },
{ 0x02000023, KEY_NUMERIC_6 },
{ 0x02000024, KEY_NUMERIC_7 },
{ 0x02000025, KEY_NUMERIC_8 },
{ 0x02000026, KEY_NUMERIC_9 },
{ 0x02000027, KEY_NUMERIC_0 },
{ 0x800ff401, KEY_NUMERIC_1 },
{ 0x800ff402, KEY_NUMERIC_2 },
{ 0x800ff403, KEY_NUMERIC_3 },
{ 0x800ff404, KEY_NUMERIC_4 },
{ 0x800ff405, KEY_NUMERIC_5 },
{ 0x800ff406, KEY_NUMERIC_6 },
{ 0x800ff407, KEY_NUMERIC_7 },
{ 0x800ff408, KEY_NUMERIC_8 },
{ 0x800ff409, KEY_NUMERIC_9 },
{ 0x800ff400, KEY_NUMERIC_0 },
{ 0x02200025, KEY_NUMERIC_STAR },
{ 0x02200020, KEY_NUMERIC_POUND },
/* 0x800ff41d also KEY_BLUE on some receivers */
{ 0x800ff41d, KEY_NUMERIC_STAR },
/* 0x800ff41c also KEY_PREVIOUS on some receivers */
{ 0x800ff41c, KEY_NUMERIC_POUND },
{ 0x800ff446, KEY_TV },
{ 0x800ff447, KEY_AUDIO }, /* My Music */
{ 0x800ff448, KEY_PVR }, /* RecordedTV */
{ 0x800ff449, KEY_CAMERA },
{ 0x800ff44a, KEY_VIDEO },
/* 0x800ff424 also KEY_MENU on some receivers */
{ 0x800ff424, KEY_DVD },
/* 0x800ff425 also KEY_GREEN on some receivers */
{ 0x800ff425, KEY_TUNER }, /* LiveTV */
{ 0x800ff450, KEY_RADIO },
{ 0x800ff44c, KEY_LANGUAGE },
{ 0x800ff427, KEY_ZOOM }, /* Aspect */
{ 0x800ff45b, KEY_RED },
{ 0x800ff45c, KEY_GREEN },
{ 0x800ff45d, KEY_YELLOW },
{ 0x800ff45e, KEY_BLUE },
{ 0x800ff466, KEY_RED },
/* { 0x800ff425, KEY_GREEN }, */
{ 0x800ff468, KEY_YELLOW },
/* { 0x800ff41d, KEY_BLUE }, */
{ 0x800ff40f, KEY_INFO },
{ 0x800ff426, KEY_EPG }, /* Guide */
{ 0x800ff45a, KEY_SUBTITLE }, /* Caption/Teletext */
{ 0x800ff44d, KEY_TITLE },
{ 0x800ff40c, KEY_POWER },
{ 0x800ff40d, KEY_MEDIA }, /* Windows MCE button */
};
static struct rc_map_list imon_mce_map = {
.map = {
.scan = imon_mce,
.size = ARRAY_SIZE(imon_mce),
/* its RC6, but w/a hardware decoder */
.rc_type = RC_TYPE_RC6_MCE,
.name = RC_MAP_IMON_MCE,
}
};
static int __init init_rc_map_imon_mce(void)
{
return rc_map_register(&imon_mce_map);
}
static void __exit exit_rc_map_imon_mce(void)
{
rc_map_unregister(&imon_mce_map);
}
module_init(init_rc_map_imon_mce)
module_exit(exit_rc_map_imon_mce)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

View file

@ -0,0 +1,157 @@
/* rc5-imon-pad.c - Keytable for SoundGraph iMON PAD and Antec Veris
* RM-200 Remote Control
*
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/*
* standard imon remote key table, which isn't really entirely
* "standard", as different receivers decode the same key on the
* same remote to different hex codes, and the silkscreened names
* vary a bit between the SoundGraph and Antec remotes... ugh.
*/
static struct rc_map_table imon_pad[] = {
/* keys sorted mostly by frequency of use to optimize lookups */
{ 0x2a8195b7, KEY_REWIND },
{ 0x298315b7, KEY_REWIND },
{ 0x2b8115b7, KEY_FASTFORWARD },
{ 0x2b8315b7, KEY_FASTFORWARD },
{ 0x2b9115b7, KEY_PREVIOUS },
{ 0x298195b7, KEY_NEXT },
{ 0x2a8115b7, KEY_PLAY },
{ 0x2a8315b7, KEY_PLAY },
{ 0x2a9115b7, KEY_PAUSE },
{ 0x2b9715b7, KEY_STOP },
{ 0x298115b7, KEY_RECORD },
{ 0x01008000, KEY_UP },
{ 0x01007f00, KEY_DOWN },
{ 0x01000080, KEY_LEFT },
{ 0x0100007f, KEY_RIGHT },
{ 0x2aa515b7, KEY_UP },
{ 0x289515b7, KEY_DOWN },
{ 0x29a515b7, KEY_LEFT },
{ 0x2ba515b7, KEY_RIGHT },
{ 0x0200002c, KEY_SPACE }, /* Select/Space */
{ 0x2a9315b7, KEY_SPACE }, /* Select/Space */
{ 0x02000028, KEY_ENTER },
{ 0x28a195b7, KEY_ENTER },
{ 0x288195b7, KEY_EXIT },
{ 0x02000029, KEY_ESC },
{ 0x2bb715b7, KEY_ESC },
{ 0x0200002a, KEY_BACKSPACE },
{ 0x28a115b7, KEY_BACKSPACE },
{ 0x2b9595b7, KEY_MUTE },
{ 0x28a395b7, KEY_VOLUMEUP },
{ 0x28a595b7, KEY_VOLUMEDOWN },
{ 0x289395b7, KEY_CHANNELUP },
{ 0x288795b7, KEY_CHANNELDOWN },
{ 0x0200001e, KEY_NUMERIC_1 },
{ 0x0200001f, KEY_NUMERIC_2 },
{ 0x02000020, KEY_NUMERIC_3 },
{ 0x02000021, KEY_NUMERIC_4 },
{ 0x02000022, KEY_NUMERIC_5 },
{ 0x02000023, KEY_NUMERIC_6 },
{ 0x02000024, KEY_NUMERIC_7 },
{ 0x02000025, KEY_NUMERIC_8 },
{ 0x02000026, KEY_NUMERIC_9 },
{ 0x02000027, KEY_NUMERIC_0 },
{ 0x28b595b7, KEY_NUMERIC_1 },
{ 0x2bb195b7, KEY_NUMERIC_2 },
{ 0x28b195b7, KEY_NUMERIC_3 },
{ 0x2a8595b7, KEY_NUMERIC_4 },
{ 0x299595b7, KEY_NUMERIC_5 },
{ 0x2aa595b7, KEY_NUMERIC_6 },
{ 0x2b9395b7, KEY_NUMERIC_7 },
{ 0x2a8515b7, KEY_NUMERIC_8 },
{ 0x2aa115b7, KEY_NUMERIC_9 },
{ 0x2ba595b7, KEY_NUMERIC_0 },
{ 0x02200025, KEY_NUMERIC_STAR },
{ 0x28b515b7, KEY_NUMERIC_STAR },
{ 0x02200020, KEY_NUMERIC_POUND },
{ 0x29a115b7, KEY_NUMERIC_POUND },
{ 0x2b8515b7, KEY_VIDEO },
{ 0x299195b7, KEY_AUDIO },
{ 0x2ba115b7, KEY_IMAGES },
{ 0x28a515b7, KEY_TV },
{ 0x29a395b7, KEY_DVD },
{ 0x29a295b7, KEY_DVD },
/* the Menu key between DVD and Subtitle on the RM-200... */
{ 0x2ba385b7, KEY_MENU },
{ 0x2ba395b7, KEY_MENU },
{ 0x288515b7, KEY_BOOKMARKS },
{ 0x2ab715b7, KEY_CAMERA }, /* Thumbnail */
{ 0x298595b7, KEY_SUBTITLE },
{ 0x2b8595b7, KEY_LANGUAGE },
{ 0x29a595b7, KEY_ZOOM },
{ 0x2aa395b7, KEY_SCREEN }, /* FullScreen */
{ 0x299115b7, KEY_KEYBOARD },
{ 0x299135b7, KEY_KEYBOARD },
{ 0x01010000, BTN_LEFT },
{ 0x01020000, BTN_RIGHT },
{ 0x01010080, BTN_LEFT },
{ 0x01020080, BTN_RIGHT },
{ 0x688301b7, BTN_LEFT },
{ 0x688481b7, BTN_RIGHT },
{ 0x2a9395b7, KEY_CYCLEWINDOWS }, /* TaskSwitcher */
{ 0x2b8395b7, KEY_TIME }, /* Timer */
{ 0x289115b7, KEY_POWER },
{ 0x29b195b7, KEY_EJECTCD }, /* the one next to play */
{ 0x299395b7, KEY_EJECTCLOSECD }, /* eject (by TaskSw) */
{ 0x02800000, KEY_CONTEXT_MENU }, /* Left Menu */
{ 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
{ 0x02000065, KEY_COMPOSE }, /* RightMenu */
{ 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
{ 0x2ab195b7, KEY_MEDIA }, /* Go or MultiMon */
{ 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
};
static struct rc_map_list imon_pad_map = {
.map = {
.scan = imon_pad,
.size = ARRAY_SIZE(imon_pad),
/* actual protocol details unknown, hardware decoder */
.rc_type = RC_TYPE_OTHER,
.name = RC_MAP_IMON_PAD,
}
};
static int __init init_rc_map_imon_pad(void)
{
return rc_map_register(&imon_pad_map);
}
static void __exit exit_rc_map_imon_pad(void)
{
rc_map_unregister(&imon_pad_map);
}
module_init(init_rc_map_imon_pad)
module_exit(exit_rc_map_imon_pad)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

View file

@ -0,0 +1,89 @@
/* iodata-bctv7e.h - Keytable for iodata_bctv7e Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* IO-DATA BCTV7E Remote */
static struct rc_map_table iodata_bctv7e[] = {
{ 0x40, KEY_TV },
{ 0x20, KEY_RADIO }, /* FM */
{ 0x60, KEY_EPG },
{ 0x00, KEY_POWER },
/* Keys 0 to 9 */
{ 0x44, KEY_0 }, /* 10 */
{ 0x50, KEY_1 },
{ 0x30, KEY_2 },
{ 0x70, KEY_3 },
{ 0x48, KEY_4 },
{ 0x28, KEY_5 },
{ 0x68, KEY_6 },
{ 0x58, KEY_7 },
{ 0x38, KEY_8 },
{ 0x78, KEY_9 },
{ 0x10, KEY_L }, /* Live */
{ 0x08, KEY_TIME }, /* Time Shift */
{ 0x18, KEY_PLAYPAUSE }, /* Play */
{ 0x24, KEY_ENTER }, /* 11 */
{ 0x64, KEY_ESC }, /* 12 */
{ 0x04, KEY_M }, /* Multi */
{ 0x54, KEY_VIDEO },
{ 0x34, KEY_CHANNELUP },
{ 0x74, KEY_VOLUMEUP },
{ 0x14, KEY_MUTE },
{ 0x4c, KEY_VCR }, /* SVIDEO */
{ 0x2c, KEY_CHANNELDOWN },
{ 0x6c, KEY_VOLUMEDOWN },
{ 0x0c, KEY_ZOOM },
{ 0x5c, KEY_PAUSE },
{ 0x3c, KEY_RED }, /* || (red) */
{ 0x7c, KEY_RECORD }, /* recording */
{ 0x1c, KEY_STOP },
{ 0x41, KEY_REWIND }, /* backward << */
{ 0x21, KEY_PLAY },
{ 0x61, KEY_FASTFORWARD }, /* forward >> */
{ 0x01, KEY_NEXT }, /* skip >| */
};
static struct rc_map_list iodata_bctv7e_map = {
.map = {
.scan = iodata_bctv7e,
.size = ARRAY_SIZE(iodata_bctv7e),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_IODATA_BCTV7E,
}
};
static int __init init_rc_map_iodata_bctv7e(void)
{
return rc_map_register(&iodata_bctv7e_map);
}
static void __exit exit_rc_map_iodata_bctv7e(void)
{
rc_map_unregister(&iodata_bctv7e_map);
}
module_init(init_rc_map_iodata_bctv7e)
module_exit(exit_rc_map_iodata_bctv7e)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,95 @@
/* ITE Generic remotes Version 1
*
* Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table it913x_v1_rc[] = {
/* Type 1 */
{ 0x61d601, KEY_VIDEO }, /* Source */
{ 0x61d602, KEY_3 },
{ 0x61d603, KEY_POWER }, /* ShutDown */
{ 0x61d604, KEY_1 },
{ 0x61d605, KEY_5 },
{ 0x61d606, KEY_6 },
{ 0x61d607, KEY_CHANNELDOWN }, /* CH- */
{ 0x61d608, KEY_2 },
{ 0x61d609, KEY_CHANNELUP }, /* CH+ */
{ 0x61d60a, KEY_9 },
{ 0x61d60b, KEY_ZOOM }, /* Zoom */
{ 0x61d60c, KEY_7 },
{ 0x61d60d, KEY_8 },
{ 0x61d60e, KEY_VOLUMEUP }, /* Vol+ */
{ 0x61d60f, KEY_4 },
{ 0x61d610, KEY_ESC }, /* [back up arrow] */
{ 0x61d611, KEY_0 },
{ 0x61d612, KEY_OK }, /* [enter arrow] */
{ 0x61d613, KEY_VOLUMEDOWN }, /* Vol- */
{ 0x61d614, KEY_RECORD }, /* Rec */
{ 0x61d615, KEY_STOP }, /* Stop */
{ 0x61d616, KEY_PLAY }, /* Play */
{ 0x61d617, KEY_MUTE }, /* Mute */
{ 0x61d618, KEY_UP },
{ 0x61d619, KEY_DOWN },
{ 0x61d61a, KEY_LEFT },
{ 0x61d61b, KEY_RIGHT },
{ 0x61d61c, KEY_RED },
{ 0x61d61d, KEY_GREEN },
{ 0x61d61e, KEY_YELLOW },
{ 0x61d61f, KEY_BLUE },
{ 0x61d643, KEY_POWER2 }, /* [red power button] */
/* Type 2 - 20 buttons */
{ 0x807f0d, KEY_0 },
{ 0x807f04, KEY_1 },
{ 0x807f05, KEY_2 },
{ 0x807f06, KEY_3 },
{ 0x807f07, KEY_4 },
{ 0x807f08, KEY_5 },
{ 0x807f09, KEY_6 },
{ 0x807f0a, KEY_7 },
{ 0x807f1b, KEY_8 },
{ 0x807f1f, KEY_9 },
{ 0x807f12, KEY_POWER },
{ 0x807f01, KEY_MEDIA_REPEAT}, /* Recall */
{ 0x807f19, KEY_PAUSE }, /* Timeshift */
{ 0x807f1e, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
{ 0x807f03, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
{ 0x807f1a, KEY_CHANNELUP },
{ 0x807f02, KEY_CHANNELDOWN },
{ 0x807f0c, KEY_ZOOM },
{ 0x807f00, KEY_RECORD },
{ 0x807f0e, KEY_STOP },
};
static struct rc_map_list it913x_v1_map = {
.map = {
.scan = it913x_v1_rc,
.size = ARRAY_SIZE(it913x_v1_rc),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_IT913X_V1,
}
};
static int __init init_rc_it913x_v1_map(void)
{
return rc_map_register(&it913x_v1_map);
}
static void __exit exit_rc_it913x_v1_map(void)
{
rc_map_unregister(&it913x_v1_map);
}
module_init(init_rc_it913x_v1_map)
module_exit(exit_rc_it913x_v1_map)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");

View file

@ -0,0 +1,94 @@
/* ITE Generic remotes Version 2
*
* Copyright (C) 2012 Malcolm Priestley (tvboxspy@gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table it913x_v2_rc[] = {
/* Type 1 */
/* 9005 remote */
{ 0x807f12, KEY_POWER2 }, /* Power (RED POWER BUTTON)*/
{ 0x807f1a, KEY_VIDEO }, /* Source */
{ 0x807f1e, KEY_MUTE }, /* Mute */
{ 0x807f01, KEY_RECORD }, /* Record */
{ 0x807f02, KEY_CHANNELUP }, /* Channel+ */
{ 0x807f03, KEY_TIME }, /* TimeShift */
{ 0x807f04, KEY_VOLUMEUP }, /* Volume- */
{ 0x807f05, KEY_SCREEN }, /* FullScreen */
{ 0x807f06, KEY_VOLUMEDOWN }, /* Volume- */
{ 0x807f07, KEY_0 }, /* 0 */
{ 0x807f08, KEY_CHANNELDOWN }, /* Channel- */
{ 0x807f09, KEY_PREVIOUS }, /* Recall */
{ 0x807f0a, KEY_1 }, /* 1 */
{ 0x807f1b, KEY_2 }, /* 2 */
{ 0x807f1f, KEY_3 }, /* 3 */
{ 0x807f0c, KEY_4 }, /* 4 */
{ 0x807f0d, KEY_5 }, /* 5 */
{ 0x807f0e, KEY_6 }, /* 6 */
{ 0x807f00, KEY_7 }, /* 7 */
{ 0x807f0f, KEY_8 }, /* 8 */
{ 0x807f19, KEY_9 }, /* 9 */
/* Type 2 */
/* keys stereo, snapshot unassigned */
{ 0x866b00, KEY_0 },
{ 0x866b01, KEY_1 },
{ 0x866b02, KEY_2 },
{ 0x866b03, KEY_3 },
{ 0x866b04, KEY_4 },
{ 0x866b05, KEY_5 },
{ 0x866b06, KEY_6 },
{ 0x866b07, KEY_7 },
{ 0x866b08, KEY_8 },
{ 0x866b09, KEY_9 },
{ 0x866b12, KEY_POWER },
{ 0x866b13, KEY_MUTE },
{ 0x866b0a, KEY_PREVIOUS }, /* Recall */
{ 0x866b1e, KEY_PAUSE },
{ 0x866b0c, KEY_VOLUMEUP },
{ 0x866b18, KEY_VOLUMEDOWN },
{ 0x866b0b, KEY_CHANNELUP },
{ 0x866b18, KEY_CHANNELDOWN },
{ 0x866b10, KEY_ZOOM },
{ 0x866b1d, KEY_RECORD },
{ 0x866b0e, KEY_STOP },
{ 0x866b11, KEY_EPG},
{ 0x866b1a, KEY_FASTFORWARD },
{ 0x866b0f, KEY_REWIND },
{ 0x866b1c, KEY_TV },
{ 0x866b1b, KEY_TEXT },
};
static struct rc_map_list it913x_v2_map = {
.map = {
.scan = it913x_v2_rc,
.size = ARRAY_SIZE(it913x_v2_rc),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_IT913X_V2,
}
};
static int __init init_rc_it913x_v2_map(void)
{
return rc_map_register(&it913x_v2_map);
}
static void __exit exit_rc_it913x_v2_map(void)
{
rc_map_unregister(&it913x_v2_map);
}
module_init(init_rc_it913x_v2_map)
module_exit(exit_rc_it913x_v2_map)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");

View file

@ -0,0 +1,88 @@
/* kaiomy.h - Keytable for kaiomy Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Kaiomy TVnPC U2
Mauro Carvalho Chehab <mchehab@infradead.org>
*/
static struct rc_map_table kaiomy[] = {
{ 0x43, KEY_POWER2},
{ 0x01, KEY_LIST},
{ 0x0b, KEY_ZOOM},
{ 0x03, KEY_POWER},
{ 0x04, KEY_1},
{ 0x08, KEY_2},
{ 0x02, KEY_3},
{ 0x0f, KEY_4},
{ 0x05, KEY_5},
{ 0x06, KEY_6},
{ 0x0c, KEY_7},
{ 0x0d, KEY_8},
{ 0x0a, KEY_9},
{ 0x11, KEY_0},
{ 0x09, KEY_CHANNELUP},
{ 0x07, KEY_CHANNELDOWN},
{ 0x0e, KEY_VOLUMEUP},
{ 0x13, KEY_VOLUMEDOWN},
{ 0x10, KEY_HOME},
{ 0x12, KEY_ENTER},
{ 0x14, KEY_RECORD},
{ 0x15, KEY_STOP},
{ 0x16, KEY_PLAY},
{ 0x17, KEY_MUTE},
{ 0x18, KEY_UP},
{ 0x19, KEY_DOWN},
{ 0x1a, KEY_LEFT},
{ 0x1b, KEY_RIGHT},
{ 0x1c, KEY_RED},
{ 0x1d, KEY_GREEN},
{ 0x1e, KEY_YELLOW},
{ 0x1f, KEY_BLUE},
};
static struct rc_map_list kaiomy_map = {
.map = {
.scan = kaiomy,
.size = ARRAY_SIZE(kaiomy),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_KAIOMY,
}
};
static int __init init_rc_map_kaiomy(void)
{
return rc_map_register(&kaiomy_map);
}
static void __exit exit_rc_map_kaiomy(void)
{
rc_map_unregister(&kaiomy_map);
}
module_init(init_rc_map_kaiomy)
module_exit(exit_rc_map_kaiomy)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,84 @@
/* kworld-315u.h - Keytable for kworld_315u Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Kworld 315U
*/
static struct rc_map_table kworld_315u[] = {
{ 0x6143, KEY_POWER },
{ 0x6101, KEY_VIDEO }, /* source */
{ 0x610b, KEY_ZOOM },
{ 0x6103, KEY_POWER2 }, /* shutdown */
{ 0x6104, KEY_1 },
{ 0x6108, KEY_2 },
{ 0x6102, KEY_3 },
{ 0x6109, KEY_CHANNELUP },
{ 0x610f, KEY_4 },
{ 0x6105, KEY_5 },
{ 0x6106, KEY_6 },
{ 0x6107, KEY_CHANNELDOWN },
{ 0x610c, KEY_7 },
{ 0x610d, KEY_8 },
{ 0x610a, KEY_9 },
{ 0x610e, KEY_VOLUMEUP },
{ 0x6110, KEY_LAST },
{ 0x6111, KEY_0 },
{ 0x6112, KEY_ENTER },
{ 0x6113, KEY_VOLUMEDOWN },
{ 0x6114, KEY_RECORD },
{ 0x6115, KEY_STOP },
{ 0x6116, KEY_PLAY },
{ 0x6117, KEY_MUTE },
{ 0x6118, KEY_UP },
{ 0x6119, KEY_DOWN },
{ 0x611a, KEY_LEFT },
{ 0x611b, KEY_RIGHT },
{ 0x611c, KEY_RED },
{ 0x611d, KEY_GREEN },
{ 0x611e, KEY_YELLOW },
{ 0x611f, KEY_BLUE },
};
static struct rc_map_list kworld_315u_map = {
.map = {
.scan = kworld_315u,
.size = ARRAY_SIZE(kworld_315u),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_KWORLD_315U,
}
};
static int __init init_rc_map_kworld_315u(void)
{
return rc_map_register(&kworld_315u_map);
}
static void __exit exit_rc_map_kworld_315u(void)
{
rc_map_unregister(&kworld_315u_map);
}
module_init(init_rc_map_kworld_315u)
module_exit(exit_rc_map_kworld_315u)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,102 @@
/* kworld-pc150u.c - Keytable for kworld_pc150u Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Kyle Strickland
* (based on kworld-plus-tv-analog.c by
* Mauro Carvalho Chehab)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Kworld PC150-U
Kyle Strickland <kyle@kyle.strickland.name>
*/
static struct rc_map_table kworld_pc150u[] = {
{ 0x0c, KEY_MEDIA }, /* Kworld key */
{ 0x16, KEY_EJECTCLOSECD }, /* -> ) */
{ 0x1d, KEY_POWER2 },
{ 0x00, KEY_1 },
{ 0x01, KEY_2 },
{ 0x02, KEY_3 },
{ 0x03, KEY_4 },
{ 0x04, KEY_5 },
{ 0x05, KEY_6 },
{ 0x06, KEY_7 },
{ 0x07, KEY_8 },
{ 0x08, KEY_9 },
{ 0x0a, KEY_0 },
{ 0x09, KEY_AGAIN },
{ 0x14, KEY_MUTE },
{ 0x1e, KEY_LAST },
{ 0x17, KEY_ZOOM },
{ 0x1f, KEY_HOMEPAGE },
{ 0x0e, KEY_ESC },
{ 0x20, KEY_UP },
{ 0x21, KEY_DOWN },
{ 0x42, KEY_LEFT },
{ 0x43, KEY_RIGHT },
{ 0x0b, KEY_ENTER },
{ 0x10, KEY_CHANNELUP },
{ 0x11, KEY_CHANNELDOWN },
{ 0x13, KEY_VOLUMEUP },
{ 0x12, KEY_VOLUMEDOWN },
{ 0x19, KEY_TIME}, /* Timeshift */
{ 0x1a, KEY_STOP},
{ 0x1b, KEY_RECORD},
{ 0x4b, KEY_EMAIL},
{ 0x40, KEY_REWIND},
{ 0x44, KEY_PLAYPAUSE},
{ 0x41, KEY_FORWARD},
{ 0x22, KEY_TEXT},
{ 0x15, KEY_AUDIO}, /* ((*)) */
{ 0x0f, KEY_MODE}, /* display ratio */
{ 0x1c, KEY_SYSRQ}, /* snapshot */
{ 0x4a, KEY_SLEEP}, /* sleep timer */
{ 0x48, KEY_SOUND}, /* switch theater mode */
{ 0x49, KEY_BLUE}, /* A */
{ 0x18, KEY_RED}, /* B */
{ 0x23, KEY_GREEN}, /* C */
};
static struct rc_map_list kworld_pc150u_map = {
.map = {
.scan = kworld_pc150u,
.size = ARRAY_SIZE(kworld_pc150u),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_KWORLD_PC150U,
}
};
static int __init init_rc_map_kworld_pc150u(void)
{
return rc_map_register(&kworld_pc150u_map);
}
static void __exit exit_rc_map_kworld_pc150u(void)
{
rc_map_unregister(&kworld_pc150u_map);
}
module_init(init_rc_map_kworld_pc150u)
module_exit(exit_rc_map_kworld_pc150u)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kyle Strickland <kyle@kyle.strickland.name>");

View file

@ -0,0 +1,100 @@
/* kworld-plus-tv-analog.h - Keytable for kworld_plus_tv_analog Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Kworld Plus TV Analog Lite PCI IR
Mauro Carvalho Chehab <mchehab@infradead.org>
*/
static struct rc_map_table kworld_plus_tv_analog[] = {
{ 0x0c, KEY_MEDIA }, /* Kworld key */
{ 0x16, KEY_CLOSECD }, /* -> ) */
{ 0x1d, KEY_POWER2 },
{ 0x00, KEY_1 },
{ 0x01, KEY_2 },
{ 0x02, KEY_3 }, /* Two keys have the same code: 3 and left */
{ 0x03, KEY_4 }, /* Two keys have the same code: 3 and right */
{ 0x04, KEY_5 },
{ 0x05, KEY_6 },
{ 0x06, KEY_7 },
{ 0x07, KEY_8 },
{ 0x08, KEY_9 },
{ 0x0a, KEY_0 },
{ 0x09, KEY_AGAIN },
{ 0x14, KEY_MUTE },
{ 0x20, KEY_UP },
{ 0x21, KEY_DOWN },
{ 0x0b, KEY_ENTER },
{ 0x10, KEY_CHANNELUP },
{ 0x11, KEY_CHANNELDOWN },
/* Couldn't map key left/key right since those
conflict with '3' and '4' scancodes
I dunno what the original driver does
*/
{ 0x13, KEY_VOLUMEUP },
{ 0x12, KEY_VOLUMEDOWN },
/* The lower part of the IR
There are several duplicated keycodes there.
Most of them conflict with digits.
Add mappings just to the unused scancodes.
Somehow, the original driver has a way to know,
but this doesn't seem to be on some GPIO.
Also, it is not related to the time between keyup
and keydown.
*/
{ 0x19, KEY_TIME}, /* Timeshift */
{ 0x1a, KEY_STOP},
{ 0x1b, KEY_RECORD},
{ 0x22, KEY_TEXT},
{ 0x15, KEY_AUDIO}, /* ((*)) */
{ 0x0f, KEY_ZOOM},
{ 0x1c, KEY_CAMERA}, /* snapshot */
{ 0x18, KEY_RED}, /* B */
{ 0x23, KEY_GREEN}, /* C */
};
static struct rc_map_list kworld_plus_tv_analog_map = {
.map = {
.scan = kworld_plus_tv_analog,
.size = ARRAY_SIZE(kworld_plus_tv_analog),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_KWORLD_PLUS_TV_ANALOG,
}
};
static int __init init_rc_map_kworld_plus_tv_analog(void)
{
return rc_map_register(&kworld_plus_tv_analog_map);
}
static void __exit exit_rc_map_kworld_plus_tv_analog(void)
{
rc_map_unregister(&kworld_plus_tv_analog_map);
}
module_init(init_rc_map_kworld_plus_tv_analog)
module_exit(exit_rc_map_kworld_plus_tv_analog)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,100 @@
/*
* LeadTek Y04G0051 remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table leadtek_y04g0051[] = {
{ 0x0300, KEY_POWER2 },
{ 0x0303, KEY_SCREEN },
{ 0x0304, KEY_RIGHT },
{ 0x0305, KEY_1 },
{ 0x0306, KEY_2 },
{ 0x0307, KEY_3 },
{ 0x0308, KEY_LEFT },
{ 0x0309, KEY_4 },
{ 0x030a, KEY_5 },
{ 0x030b, KEY_6 },
{ 0x030c, KEY_UP },
{ 0x030d, KEY_7 },
{ 0x030e, KEY_8 },
{ 0x030f, KEY_9 },
{ 0x0310, KEY_DOWN },
{ 0x0311, KEY_AGAIN },
{ 0x0312, KEY_0 },
{ 0x0313, KEY_OK }, /* 1st ok */
{ 0x0314, KEY_MUTE },
{ 0x0316, KEY_OK }, /* 2nd ok */
{ 0x031e, KEY_VIDEO }, /* 2nd video */
{ 0x031b, KEY_AUDIO },
{ 0x031f, KEY_TEXT },
{ 0x0340, KEY_SLEEP },
{ 0x0341, KEY_DOT },
{ 0x0342, KEY_REWIND },
{ 0x0343, KEY_PLAY },
{ 0x0344, KEY_FASTFORWARD },
{ 0x0345, KEY_TIME },
{ 0x0346, KEY_STOP }, /* 2nd stop */
{ 0x0347, KEY_RECORD },
{ 0x0348, KEY_CAMERA },
{ 0x0349, KEY_ESC },
{ 0x034a, KEY_NEW },
{ 0x034b, KEY_RED },
{ 0x034c, KEY_GREEN },
{ 0x034d, KEY_YELLOW },
{ 0x034e, KEY_BLUE },
{ 0x034f, KEY_MENU },
{ 0x0350, KEY_STOP }, /* 1st stop */
{ 0x0351, KEY_CHANNEL },
{ 0x0352, KEY_VIDEO }, /* 1st video */
{ 0x0353, KEY_EPG },
{ 0x0354, KEY_PREVIOUS },
{ 0x0355, KEY_NEXT },
{ 0x0356, KEY_TV },
{ 0x035a, KEY_VOLUMEDOWN },
{ 0x035b, KEY_CHANNELUP },
{ 0x035e, KEY_VOLUMEUP },
{ 0x035f, KEY_CHANNELDOWN },
};
static struct rc_map_list leadtek_y04g0051_map = {
.map = {
.scan = leadtek_y04g0051,
.size = ARRAY_SIZE(leadtek_y04g0051),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_LEADTEK_Y04G0051,
}
};
static int __init init_rc_map_leadtek_y04g0051(void)
{
return rc_map_register(&leadtek_y04g0051_map);
}
static void __exit exit_rc_map_leadtek_y04g0051(void)
{
rc_map_unregister(&leadtek_y04g0051_map);
}
module_init(init_rc_map_leadtek_y04g0051)
module_exit(exit_rc_map_leadtek_y04g0051)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

View file

@ -0,0 +1,42 @@
/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
* all raw IR data to the lirc userspace decoder.
*
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-core.h>
#include <linux/module.h>
static struct rc_map_table lirc[] = {
{ },
};
static struct rc_map_list lirc_map = {
.map = {
.scan = lirc,
.size = ARRAY_SIZE(lirc),
.rc_type = RC_TYPE_LIRC,
.name = RC_MAP_LIRC,
}
};
static int __init init_rc_map_lirc(void)
{
return rc_map_register(&lirc_map);
}
static void __exit exit_rc_map_lirc(void)
{
rc_map_unregister(&lirc_map);
}
module_init(init_rc_map_lirc)
module_exit(exit_rc_map_lirc)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");

View file

@ -0,0 +1,111 @@
/* LME2510 remote control
*
*
* Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table lme2510_rc[] = {
/* Type 1 - 26 buttons */
{ 0x10ed45, KEY_0 },
{ 0x10ed5f, KEY_1 },
{ 0x10ed50, KEY_2 },
{ 0x10ed5d, KEY_3 },
{ 0x10ed41, KEY_4 },
{ 0x10ed0a, KEY_5 },
{ 0x10ed42, KEY_6 },
{ 0x10ed47, KEY_7 },
{ 0x10ed49, KEY_8 },
{ 0x10ed05, KEY_9 },
{ 0x10ed43, KEY_POWER },
{ 0x10ed46, KEY_SUBTITLE },
{ 0x10ed06, KEY_PAUSE },
{ 0x10ed03, KEY_MEDIA_REPEAT},
{ 0x10ed02, KEY_PAUSE },
{ 0x10ed5e, KEY_VOLUMEUP },
{ 0x10ed5c, KEY_VOLUMEDOWN },
{ 0x10ed09, KEY_CHANNELUP },
{ 0x10ed1a, KEY_CHANNELDOWN },
{ 0x10ed1e, KEY_PLAY },
{ 0x10ed1b, KEY_ZOOM },
{ 0x10ed59, KEY_MUTE },
{ 0x10ed5a, KEY_TV },
{ 0x10ed18, KEY_RECORD },
{ 0x10ed07, KEY_EPG },
{ 0x10ed01, KEY_STOP },
/* Type 2 - 20 buttons */
{ 0xbf15, KEY_0 },
{ 0xbf08, KEY_1 },
{ 0xbf09, KEY_2 },
{ 0xbf0a, KEY_3 },
{ 0xbf0c, KEY_4 },
{ 0xbf0d, KEY_5 },
{ 0xbf0e, KEY_6 },
{ 0xbf10, KEY_7 },
{ 0xbf11, KEY_8 },
{ 0xbf12, KEY_9 },
{ 0xbf00, KEY_POWER },
{ 0xbf04, KEY_MEDIA_REPEAT}, /* Recall */
{ 0xbf1a, KEY_PAUSE }, /* Timeshift */
{ 0xbf02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
{ 0xbf06, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
{ 0xbf01, KEY_CHANNELUP },
{ 0xbf05, KEY_CHANNELDOWN },
{ 0xbf14, KEY_ZOOM },
{ 0xbf18, KEY_RECORD },
{ 0xbf16, KEY_STOP },
/* Type 3 - 20 buttons */
{ 0x1c, KEY_0 },
{ 0x07, KEY_1 },
{ 0x15, KEY_2 },
{ 0x09, KEY_3 },
{ 0x16, KEY_4 },
{ 0x19, KEY_5 },
{ 0x0d, KEY_6 },
{ 0x0c, KEY_7 },
{ 0x18, KEY_8 },
{ 0x5e, KEY_9 },
{ 0x45, KEY_POWER },
{ 0x44, KEY_MEDIA_REPEAT}, /* Recall */
{ 0x4a, KEY_PAUSE }, /* Timeshift */
{ 0x47, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
{ 0x43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
{ 0x46, KEY_CHANNELUP },
{ 0x40, KEY_CHANNELDOWN },
{ 0x08, KEY_ZOOM },
{ 0x42, KEY_RECORD },
{ 0x5a, KEY_STOP },
};
static struct rc_map_list lme2510_map = {
.map = {
.scan = lme2510_rc,
.size = ARRAY_SIZE(lme2510_rc),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_LME2510,
}
};
static int __init init_rc_lme2510_map(void)
{
return rc_map_register(&lme2510_map);
}
static void __exit exit_rc_lme2510_map(void)
{
rc_map_unregister(&lme2510_map);
}
module_init(init_rc_lme2510_map)
module_exit(exit_rc_lme2510_map)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Malcolm Priestley tvboxspy@gmail.com");

View file

@ -0,0 +1,135 @@
/* manli.h - Keytable for manli Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
#include <linux/module.h>
/* Michael Tokarev <mjt@tls.msk.ru>
keytable is used by MANLI MTV00[0x0c] and BeholdTV 40[13] at
least, and probably other cards too.
The "ascii-art picture" below (in comments, first row
is the keycode in hex, and subsequent row(s) shows
the button labels (several variants when appropriate)
helps to descide which keycodes to assign to the buttons.
*/
static struct rc_map_table manli[] = {
/* 0x1c 0x12 *
* FUNCTION POWER *
* FM (|) *
* */
{ 0x1c, KEY_RADIO }, /*XXX*/
{ 0x12, KEY_POWER },
/* 0x01 0x02 0x03 *
* 1 2 3 *
* *
* 0x04 0x05 0x06 *
* 4 5 6 *
* *
* 0x07 0x08 0x09 *
* 7 8 9 *
* */
{ 0x01, KEY_1 },
{ 0x02, KEY_2 },
{ 0x03, KEY_3 },
{ 0x04, KEY_4 },
{ 0x05, KEY_5 },
{ 0x06, KEY_6 },
{ 0x07, KEY_7 },
{ 0x08, KEY_8 },
{ 0x09, KEY_9 },
/* 0x0a 0x00 0x17 *
* RECALL 0 +100 *
* PLUS *
* */
{ 0x0a, KEY_AGAIN }, /*XXX KEY_REWIND? */
{ 0x00, KEY_0 },
{ 0x17, KEY_DIGITS }, /*XXX*/
/* 0x14 0x10 *
* MENU INFO *
* OSD */
{ 0x14, KEY_MENU },
{ 0x10, KEY_INFO },
/* 0x0b *
* Up *
* *
* 0x18 0x16 0x0c *
* Left Ok Right *
* *
* 0x015 *
* Down *
* */
{ 0x0b, KEY_UP },
{ 0x18, KEY_LEFT },
{ 0x16, KEY_OK }, /*XXX KEY_SELECT? KEY_ENTER? */
{ 0x0c, KEY_RIGHT },
{ 0x15, KEY_DOWN },
/* 0x11 0x0d *
* TV/AV MODE *
* SOURCE STEREO *
* */
{ 0x11, KEY_TV }, /*XXX*/
{ 0x0d, KEY_MODE }, /*XXX there's no KEY_STEREO */
/* 0x0f 0x1b 0x1a *
* AUDIO Vol+ Chan+ *
* TIMESHIFT??? *
* *
* 0x0e 0x1f 0x1e *
* SLEEP Vol- Chan- *
* */
{ 0x0f, KEY_AUDIO },
{ 0x1b, KEY_VOLUMEUP },
{ 0x1a, KEY_CHANNELUP },
{ 0x0e, KEY_TIME },
{ 0x1f, KEY_VOLUMEDOWN },
{ 0x1e, KEY_CHANNELDOWN },
/* 0x13 0x19 *
* MUTE SNAPSHOT*
* */
{ 0x13, KEY_MUTE },
{ 0x19, KEY_CAMERA },
/* 0x1d unused ? */
};
static struct rc_map_list manli_map = {
.map = {
.scan = manli,
.size = ARRAY_SIZE(manli),
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_MANLI,
}
};
static int __init init_rc_map_manli(void)
{
return rc_map_register(&manli_map);
}
static void __exit exit_rc_map_manli(void)
{
rc_map_unregister(&manli_map);
}
module_init(init_rc_map_manli)
module_exit(exit_rc_map_manli)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab");

View file

@ -0,0 +1,123 @@
/*
* Medion X10 RF remote keytable (Digitainer variant)
*
* Copyright (C) 2012 Anssi Hannula <anssi.hannula@iki.fi>
*
* This keymap is for a variant that has a distinctive scrollwheel instead of
* up/down buttons (tested with P/N 40009936 / 20018268), reportedly
* originally shipped with Medion Digitainer but now sold separately simply as
* an "X10" remote.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/module.h>
#include <media/rc-map.h>
static struct rc_map_table medion_x10_digitainer[] = {
{ 0x02, KEY_POWER },
{ 0x2c, KEY_TV },
{ 0x2d, KEY_VIDEO },
{ 0x04, KEY_DVD }, /* CD/DVD */
{ 0x16, KEY_TEXT }, /* "teletext" icon, i.e. a screen with lines */
{ 0x06, KEY_AUDIO },
{ 0x2e, KEY_RADIO },
{ 0x31, KEY_EPG }, /* a screen with an open book */
{ 0x05, KEY_IMAGES }, /* Photo */
{ 0x2f, KEY_INFO },
{ 0x78, KEY_UP }, /* scrollwheel up 1 notch */
/* 0x79..0x7f: 2-8 notches, driver repeats 0x78 entry */
{ 0x70, KEY_DOWN }, /* scrollwheel down 1 notch */
/* 0x71..0x77: 2-8 notches, driver repeats 0x70 entry */
{ 0x19, KEY_MENU },
{ 0x1d, KEY_LEFT },
{ 0x1e, KEY_OK }, /* scrollwheel press */
{ 0x1f, KEY_RIGHT },
{ 0x20, KEY_BACK },
{ 0x09, KEY_VOLUMEUP },
{ 0x08, KEY_VOLUMEDOWN },
{ 0x00, KEY_MUTE },
{ 0x1b, KEY_SELECT }, /* also has "U" rotated 90 degrees CCW */
{ 0x0b, KEY_CHANNELUP },
{ 0x0c, KEY_CHANNELDOWN },
{ 0x1c, KEY_LAST },
{ 0x32, KEY_RED }, /* also Audio */
{ 0x33, KEY_GREEN }, /* also Subtitle */
{ 0x34, KEY_YELLOW }, /* also Angle */
{ 0x35, KEY_BLUE }, /* also Title */
{ 0x28, KEY_STOP },
{ 0x29, KEY_PAUSE },
{ 0x25, KEY_PLAY },
{ 0x21, KEY_PREVIOUS },
{ 0x18, KEY_CAMERA },
{ 0x23, KEY_NEXT },
{ 0x24, KEY_REWIND },
{ 0x27, KEY_RECORD },
{ 0x26, KEY_FORWARD },
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
{ 0x10, KEY_4 },
{ 0x11, KEY_5 },
{ 0x12, KEY_6 },
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
{ 0x17, KEY_0 },
/* these do not actually exist on this remote, but these scancodes
* exist on all other Medion X10 remotes and adding them here allows
* such remotes to be adequately usable with this keymap in case
* this keymap is wrongly used with them (which is quite possible as
* there are lots of different Medion X10 remotes): */
{ 0x1a, KEY_UP },
{ 0x22, KEY_DOWN },
};
static struct rc_map_list medion_x10_digitainer_map = {
.map = {
.scan = medion_x10_digitainer,
.size = ARRAY_SIZE(medion_x10_digitainer),
.rc_type = RC_TYPE_OTHER,
.name = RC_MAP_MEDION_X10_DIGITAINER,
}
};
static int __init init_rc_map_medion_x10_digitainer(void)
{
return rc_map_register(&medion_x10_digitainer_map);
}
static void __exit exit_rc_map_medion_x10_digitainer(void)
{
rc_map_unregister(&medion_x10_digitainer_map);
}
module_init(init_rc_map_medion_x10_digitainer)
module_exit(exit_rc_map_medion_x10_digitainer)
MODULE_DESCRIPTION("Medion X10 RF remote keytable (Digitainer variant)");
MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,108 @@
/*
* Medion X10 OR22/OR24 RF remote keytable
*
* Copyright (C) 2012 Anssi Hannula <anssi.hannula@iki.fi>
*
* This keymap is for several Medion X10 remotes that have the Windows MCE
* button. This has been tested with a "RF VISTA Remote Control", OR24V,
* P/N 20035335, but should work with other variants that have the same
* buttons, such as OR22V and OR24E.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/module.h>
#include <media/rc-map.h>
static struct rc_map_table medion_x10_or2x[] = {
{ 0x02, KEY_POWER },
{ 0x16, KEY_TEXT }, /* "T" in a box, for teletext */
{ 0x09, KEY_VOLUMEUP },
{ 0x08, KEY_VOLUMEDOWN },
{ 0x00, KEY_MUTE },
{ 0x0b, KEY_CHANNELUP },
{ 0x0c, KEY_CHANNELDOWN },
{ 0x32, KEY_RED },
{ 0x33, KEY_GREEN },
{ 0x34, KEY_YELLOW },
{ 0x35, KEY_BLUE },
{ 0x18, KEY_PVR }, /* record symbol inside a tv symbol */
{ 0x04, KEY_DVD }, /* disc symbol */
{ 0x31, KEY_EPG }, /* a tv schedule symbol */
{ 0x1c, KEY_TV }, /* play symbol inside a tv symbol */
{ 0x20, KEY_BACK },
{ 0x2f, KEY_INFO },
{ 0x1a, KEY_UP },
{ 0x22, KEY_DOWN },
{ 0x1d, KEY_LEFT },
{ 0x1f, KEY_RIGHT },
{ 0x1e, KEY_OK },
{ 0x1b, KEY_MEDIA }, /* Windows MCE button */
{ 0x21, KEY_PREVIOUS },
{ 0x23, KEY_NEXT },
{ 0x24, KEY_REWIND },
{ 0x26, KEY_FORWARD },
{ 0x25, KEY_PLAY },
{ 0x28, KEY_STOP },
{ 0x29, KEY_PAUSE },
{ 0x27, KEY_RECORD },
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
{ 0x10, KEY_4 },
{ 0x11, KEY_5 },
{ 0x12, KEY_6 },
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
{ 0x17, KEY_0 },
{ 0x30, KEY_CLEAR },
{ 0x36, KEY_ENTER },
{ 0x37, KEY_NUMERIC_STAR },
{ 0x38, KEY_NUMERIC_POUND },
};
static struct rc_map_list medion_x10_or2x_map = {
.map = {
.scan = medion_x10_or2x,
.size = ARRAY_SIZE(medion_x10_or2x),
.rc_type = RC_TYPE_OTHER,
.name = RC_MAP_MEDION_X10_OR2X,
}
};
static int __init init_rc_map_medion_x10_or2x(void)
{
return rc_map_register(&medion_x10_or2x_map);
}
static void __exit exit_rc_map_medion_x10_or2x(void)
{
rc_map_unregister(&medion_x10_or2x_map);
}
module_init(init_rc_map_medion_x10_or2x)
module_exit(exit_rc_map_medion_x10_or2x)
MODULE_DESCRIPTION("Medion X10 OR22/OR24 RF remote keytable");
MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");
MODULE_LICENSE("GPL");

View file

@ -0,0 +1,117 @@
/*
* Medion X10 RF remote keytable
*
* Copyright (C) 2011 Anssi Hannula <anssi.hannula@?ki.fi>
*
* This file is based on a keytable provided by
* Jan Losinski <losinski@wh2.tu-dresden.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/module.h>
#include <media/rc-map.h>
static struct rc_map_table medion_x10[] = {
{ 0x2c, KEY_TV }, /* TV */
{ 0x2d, KEY_VCR }, /* VCR */
{ 0x04, KEY_DVD }, /* DVD */
{ 0x06, KEY_AUDIO }, /* MUSIC */
{ 0x2e, KEY_RADIO }, /* RADIO */
{ 0x05, KEY_DIRECTORY }, /* PHOTO */
{ 0x2f, KEY_INFO }, /* TV-PREVIEW */
{ 0x30, KEY_LIST }, /* CHANNEL-LST */
{ 0x1b, KEY_SETUP }, /* SETUP */
{ 0x31, KEY_VIDEO }, /* VIDEO DESKTOP */
{ 0x08, KEY_VOLUMEDOWN }, /* VOL - */
{ 0x09, KEY_VOLUMEUP }, /* VOL + */
{ 0x0b, KEY_CHANNELUP }, /* CHAN + */
{ 0x0c, KEY_CHANNELDOWN }, /* CHAN - */
{ 0x00, KEY_MUTE }, /* MUTE */
{ 0x32, KEY_RED }, /* red */
{ 0x33, KEY_GREEN }, /* green */
{ 0x34, KEY_YELLOW }, /* yellow */
{ 0x35, KEY_BLUE }, /* blue */
{ 0x16, KEY_TEXT }, /* TXT */
{ 0x0d, KEY_1 },
{ 0x0e, KEY_2 },
{ 0x0f, KEY_3 },
{ 0x10, KEY_4 },
{ 0x11, KEY_5 },
{ 0x12, KEY_6 },
{ 0x13, KEY_7 },
{ 0x14, KEY_8 },
{ 0x15, KEY_9 },
{ 0x17, KEY_0 },
{ 0x1c, KEY_SEARCH }, /* TV/RAD, CH SRC */
{ 0x20, KEY_DELETE }, /* DELETE */
{ 0x36, KEY_KEYBOARD }, /* RENAME */
{ 0x18, KEY_SCREEN }, /* SNAPSHOT */
{ 0x1a, KEY_UP }, /* up */
{ 0x22, KEY_DOWN }, /* down */
{ 0x1d, KEY_LEFT }, /* left */
{ 0x1f, KEY_RIGHT }, /* right */
{ 0x1e, KEY_OK }, /* OK */
{ 0x37, KEY_SELECT }, /* ACQUIRE IMAGE */
{ 0x38, KEY_EDIT }, /* EDIT IMAGE */
{ 0x24, KEY_REWIND }, /* rewind (<<) */
{ 0x25, KEY_PLAY }, /* play ( >) */
{ 0x26, KEY_FORWARD }, /* forward (>>) */
{ 0x27, KEY_RECORD }, /* record ( o) */
{ 0x28, KEY_STOP }, /* stop ([]) */
{ 0x29, KEY_PAUSE }, /* pause ('') */
{ 0x21, KEY_PREVIOUS }, /* prev */
{ 0x39, KEY_SWITCHVIDEOMODE }, /* F SCR */
{ 0x23, KEY_NEXT }, /* next */
{ 0x19, KEY_MENU }, /* MENU */
{ 0x3a, KEY_LANGUAGE }, /* AUDIO */
{ 0x02, KEY_POWER }, /* POWER */
};
static struct rc_map_list medion_x10_map = {
.map = {
.scan = medion_x10,
.size = ARRAY_SIZE(medion_x10),
.rc_type = RC_TYPE_OTHER,
.name = RC_MAP_MEDION_X10,
}
};
static int __init init_rc_map_medion_x10(void)
{
return rc_map_register(&medion_x10_map);
}
static void __exit exit_rc_map_medion_x10(void)
{
rc_map_unregister(&medion_x10_map);
}
module_init(init_rc_map_medion_x10)
module_exit(exit_rc_map_medion_x10)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anssi Hannula <anssi.hannula@iki.fi>");

View file

@ -0,0 +1,68 @@
/*
* MSI DIGIVOX mini II remote controller keytable
*
* Copyright (C) 2010 Antti Palosaari <crope@iki.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <media/rc-map.h>
#include <linux/module.h>
static struct rc_map_table msi_digivox_ii[] = {
{ 0x0302, KEY_2 },
{ 0x0303, KEY_UP }, /* up */
{ 0x0304, KEY_3 },
{ 0x0305, KEY_CHANNELDOWN },
{ 0x0308, KEY_5 },
{ 0x0309, KEY_0 },
{ 0x030b, KEY_8 },
{ 0x030d, KEY_DOWN }, /* down */
{ 0x0310, KEY_9 },
{ 0x0311, KEY_7 },
{ 0x0314, KEY_VOLUMEUP },
{ 0x0315, KEY_CHANNELUP },
{ 0x0316, KEY_OK },
{ 0x0317, KEY_POWER2 },
{ 0x031a, KEY_1 },
{ 0x031c, KEY_4 },
{ 0x031d, KEY_6 },
{ 0x031f, KEY_VOLUMEDOWN },
};
static struct rc_map_list msi_digivox_ii_map = {
.map = {
.scan = msi_digivox_ii,
.size = ARRAY_SIZE(msi_digivox_ii),
.rc_type = RC_TYPE_NEC,
.name = RC_MAP_MSI_DIGIVOX_II,
}
};
static int __init init_rc_map_msi_digivox_ii(void)
{
return rc_map_register(&msi_digivox_ii_map);
}
static void __exit exit_rc_map_msi_digivox_ii(void)
{
rc_map_unregister(&msi_digivox_ii_map);
}
module_init(init_rc_map_msi_digivox_ii)
module_exit(exit_rc_map_msi_digivox_ii)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");

Some files were not shown because too many files have changed in this diff Show more