mirror of
https://github.com/suyu-emu/horinux.git
synced 2026-09-21 14:15:21 -07:00
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (94 commits) V4L/DVB: tvp7002: fix write to H-PLL Feedback Divider LSB register V4L/DVB: dvb: siano: free spinlock before schedule() V4L/DVB: media: video: pvrusb2: remove custom hex_to_bin() V4L/DVB: drivers: usbvideo: remove custom implementation of hex_to_bin() V4L/DVB: Report supported QAM modes on bt8xx V4L/DVB: media: ir-keytable: null dereference in debug code V4L/DVB: ivtv: convert to the new control framework V4L/DVB: ivtv: convert gpio subdev to new control framework V4L/DVB: wm8739: convert to the new control framework V4L/DVB: cs53l32a: convert to new control framework V4L/DVB: wm8775: convert to the new control framework V4L/DVB: cx2341x: convert to the control framework V4L/DVB: cx25840: convert to the new control framework V4L/DVB: cx25840/ivtv: replace ugly priv control with s_config V4L/DVB: saa717x: convert to the new control framework V4L/DVB: msp3400: convert to the new control framework V4L/DVB: saa7115: convert to the new control framework V4L/DVB: v4l2: hook up the new control framework into the core framework V4L/DVB: Documentation: add v4l2-controls.txt documenting the new controls API V4L/DVB: v4l2-ctrls: Whitespace cleanups ...
This commit is contained in:
@@ -229,6 +229,22 @@ on working with the default settings initially.</para>
|
||||
and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>LIRC_SET_WIDEBAND_RECEIVER</term>
|
||||
<listitem>
|
||||
<para>Some receivers are equipped with special wide band receiver which is intended
|
||||
to be used to learn output of existing remote.
|
||||
Calling that ioctl with (1) will enable it, and with (0) disable it.
|
||||
This might be useful of receivers that have otherwise narrow band receiver
|
||||
that prevents them to be used with some remotes.
|
||||
Wide band receiver might also be more precise
|
||||
On the other hand its disadvantage it usually reduced range of reception.
|
||||
Note: wide band receiver might be implictly enabled if you enable
|
||||
carrier reports. In that case it will be disabled as soon as you disable
|
||||
carrier reports. Trying to disable wide band receiver while carrier
|
||||
reports are active will do nothing.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
@@ -240,6 +240,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-BGR666">
|
||||
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
|
||||
<entry>'BGRH'</entry>
|
||||
<entry></entry>
|
||||
<entry>b<subscript>5</subscript></entry>
|
||||
<entry>b<subscript>4</subscript></entry>
|
||||
<entry>b<subscript>3</subscript></entry>
|
||||
<entry>b<subscript>2</subscript></entry>
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
<entry>g<subscript>5</subscript></entry>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
<entry>g<subscript>2</subscript></entry>
|
||||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
<entry>r<subscript>5</subscript></entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
<entry>r<subscript>3</subscript></entry>
|
||||
<entry>r<subscript>2</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-BGR24">
|
||||
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
||||
<entry>'BGR3'</entry>
|
||||
@@ -700,6 +739,45 @@ defined in error. Drivers may interpret them as in <xref
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
</row>
|
||||
<row id="V4L2-PIX-FMT-BGR666">
|
||||
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
|
||||
<entry>'BGRH'</entry>
|
||||
<entry></entry>
|
||||
<entry>b<subscript>5</subscript></entry>
|
||||
<entry>b<subscript>4</subscript></entry>
|
||||
<entry>b<subscript>3</subscript></entry>
|
||||
<entry>b<subscript>2</subscript></entry>
|
||||
<entry>b<subscript>1</subscript></entry>
|
||||
<entry>b<subscript>0</subscript></entry>
|
||||
<entry>g<subscript>5</subscript></entry>
|
||||
<entry>g<subscript>4</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>g<subscript>3</subscript></entry>
|
||||
<entry>g<subscript>2</subscript></entry>
|
||||
<entry>g<subscript>1</subscript></entry>
|
||||
<entry>g<subscript>0</subscript></entry>
|
||||
<entry>r<subscript>5</subscript></entry>
|
||||
<entry>r<subscript>4</subscript></entry>
|
||||
<entry>r<subscript>3</subscript></entry>
|
||||
<entry>r<subscript>2</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry>r<subscript>1</subscript></entry>
|
||||
<entry>r<subscript>0</subscript></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
<entry></entry>
|
||||
</row>
|
||||
<row><!-- id="V4L2-PIX-FMT-BGR24" -->
|
||||
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
|
||||
<entry>'BGR3'</entry>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2203,6 +2203,12 @@ F: drivers/misc/cb710/
|
||||
F: drivers/mmc/host/cb710-mmc.*
|
||||
F: include/linux/cb710.h
|
||||
|
||||
ENE KB2426 (ENE0100/ENE020XX) INFRARED RECEIVER
|
||||
M: Maxim Levitsky <maximlevitsky@gmail.com>
|
||||
S: Maintained
|
||||
F: drivers/media/IR/ene_ir.c
|
||||
F: drivers/media/IR/ene_ir.h
|
||||
|
||||
EPSON 1355 FRAMEBUFFER DRIVER
|
||||
M: Christopher Hoover <ch@murgatroid.com>
|
||||
M: Christopher Hoover <ch@hpl.hp.com>
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
config IR_CORE
|
||||
tristate
|
||||
menuconfig IR_CORE
|
||||
tristate "Infrared remote controller adapters"
|
||||
depends on INPUT
|
||||
default INPUT
|
||||
|
||||
if IR_CORE
|
||||
|
||||
config VIDEO_IR
|
||||
tristate
|
||||
depends on IR_CORE
|
||||
@@ -16,7 +18,7 @@ config LIRC
|
||||
Enable this option to build the Linux Infrared Remote
|
||||
Control (LIRC) core device interface driver. The LIRC
|
||||
interface passes raw IR to and from userspace, where the
|
||||
LIRC daemon handles protocol decoding for IR reception ann
|
||||
LIRC daemon handles protocol decoding for IR reception and
|
||||
encoding for IR transmitting (aka "blasting").
|
||||
|
||||
source "drivers/media/IR/keymaps/Kconfig"
|
||||
@@ -103,3 +105,31 @@ config IR_MCEUSB
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mceusb.
|
||||
|
||||
config IR_ENE
|
||||
tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
|
||||
depends on PNP
|
||||
depends on IR_CORE
|
||||
---help---
|
||||
Say Y here to enable support for integrated infrared receiver
|
||||
/transciever made by ENE.
|
||||
|
||||
You can see if you have it by looking at lspnp output.
|
||||
Output should include ENE0100 ENE0200 or something similiar.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ene_ir.
|
||||
|
||||
config IR_STREAMZAP
|
||||
tristate "Streamzap PC Remote IR Receiver"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
depends on IR_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.
|
||||
|
||||
endif #IR_CORE
|
||||
|
||||
@@ -16,3 +16,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
|
||||
# stand-alone IR receivers/transmitters
|
||||
obj-$(CONFIG_IR_IMON) += imon.o
|
||||
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
|
||||
obj-$(CONFIG_IR_ENE) += ene_ir.o
|
||||
obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* driver for ENE KB3926 B/C/D 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_MAX_IO 4
|
||||
|
||||
/* 8 bytes of samples, divided in 2 halfs*/
|
||||
#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
|
||||
#define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */
|
||||
#define ENE_SAMPLE_VALUE_MASK 0x7F
|
||||
#define ENE_SAMPLE_OVERFLOW 0x7F
|
||||
#define ENE_SAMPLES_SIZE 4
|
||||
|
||||
/* fan input sample buffer */
|
||||
#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
|
||||
/* each sample of normal buffer */
|
||||
#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
|
||||
/* if set, says that sample is pulse */
|
||||
#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
|
||||
|
||||
/* first firmware register */
|
||||
#define ENE_FW1 0xF8F8
|
||||
#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
|
||||
#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
|
||||
#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
|
||||
#define ENE_FW1_IRQ 0x80 /* enable interrupt */
|
||||
|
||||
/* second firmware register */
|
||||
#define ENE_FW2 0xF8F9
|
||||
#define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */
|
||||
#define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */
|
||||
#define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */
|
||||
/* learning input */
|
||||
#define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */
|
||||
#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
|
||||
|
||||
/* transmitter ports */
|
||||
#define ENE_TX_PORT2 0xFC01 /* this enables one or both */
|
||||
#define ENE_TX_PORT2_EN 0x20 /* TX ports */
|
||||
#define ENE_TX_PORT1 0xFC08
|
||||
#define ENE_TX_PORT1_EN 0x02
|
||||
|
||||
/* 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 - only if learning capable */
|
||||
#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
|
||||
#define ENE_FAN_AS_IN1_EN 0xCD
|
||||
#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
|
||||
#define ENE_FAN_AS_IN2_EN 0x03
|
||||
#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
|
||||
|
||||
/* IRQ registers block (for revision C,D) */
|
||||
#define ENEC_IRQ 0xFE9B /* new irq settings register */
|
||||
#define ENEC_IRQ_MASK 0x0F /* irq number mask */
|
||||
#define ENEC_IRQ_UNK_EN 0x10 /* always enabled */
|
||||
#define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */
|
||||
|
||||
/* CIR block settings */
|
||||
#define ENE_CIR_CONF1 0xFEC0
|
||||
#define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */
|
||||
/* while transmitting */
|
||||
#define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */
|
||||
#define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */
|
||||
#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
|
||||
#define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */
|
||||
|
||||
#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
|
||||
#define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */
|
||||
#define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */
|
||||
|
||||
#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
|
||||
#define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */
|
||||
|
||||
|
||||
/* Two byte tx buffer */
|
||||
#define ENE_TX_INPUT1 0xFEC9
|
||||
#define ENE_TX_INPUT2 0xFECA
|
||||
#define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */
|
||||
#define ENE_TX_SMLP_MASK 0x7F
|
||||
#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */
|
||||
|
||||
|
||||
/* Unknown TX setting - TX sample period ??? */
|
||||
#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
|
||||
|
||||
/* Current received carrier period */
|
||||
#define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */
|
||||
#define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */
|
||||
|
||||
|
||||
/* TX period (1/carrier) */
|
||||
#define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */
|
||||
#define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/
|
||||
#define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/
|
||||
|
||||
/* Hardware versions */
|
||||
#define ENE_HW_VERSION 0xFF00 /* hardware revision */
|
||||
#define ENE_PLLFRH 0xFF16
|
||||
#define ENE_PLLFRL 0xFF17
|
||||
|
||||
#define ENE_HW_UNK 0xFF1D
|
||||
#define ENE_HW_UNK_CLR 0x04
|
||||
#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
|
||||
#define ENE_HW_VER_MINOR 0xFF1F
|
||||
#define ENE_HW_VER_OLD 0xFD00
|
||||
|
||||
/* Normal/Learning carrier ranges - only valid if we have learning input*/
|
||||
/* TODO: test */
|
||||
#define ENE_NORMAL_RX_LOW 34
|
||||
#define ENE_NORMAL_RX_HI 38
|
||||
|
||||
/* Tx carrier range */
|
||||
/* Hardware might be able to do more, but this range is enough for
|
||||
all purposes */
|
||||
#define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */
|
||||
#define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */
|
||||
|
||||
|
||||
|
||||
/* Minimal and maximal gaps */
|
||||
|
||||
/* Normal case:
|
||||
Minimal gap is 0x7F * sample period
|
||||
Maximum gap depends on hardware.
|
||||
For KB3926B, it is unlimited, for newer models its around
|
||||
250000, after which HW stops sending samples, and that is
|
||||
not possible to change */
|
||||
|
||||
/* Fan case:
|
||||
Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
|
||||
And there is nothing to change this setting
|
||||
*/
|
||||
|
||||
#define ENE_MAXGAP 250000
|
||||
#define ENE_MINGAP (127 * sample_period)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
#define ENE_DRIVER_NAME "ene_ir"
|
||||
|
||||
#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 */
|
||||
|
||||
#define ene_printk(level, text, ...) \
|
||||
printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
|
||||
|
||||
#define ene_dbg(text, ...) \
|
||||
if (debug) \
|
||||
printk(KERN_DEBUG \
|
||||
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
#define ene_dbg_verbose(text, ...) \
|
||||
if (debug > 1) \
|
||||
printk(KERN_DEBUG \
|
||||
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
|
||||
|
||||
|
||||
struct ene_device {
|
||||
struct pnp_dev *pnp_dev;
|
||||
struct input_dev *idev;
|
||||
struct ir_dev_props *props;
|
||||
int in_use;
|
||||
|
||||
/* hw IO settings */
|
||||
unsigned long hw_io;
|
||||
int irq;
|
||||
spinlock_t hw_lock;
|
||||
|
||||
/* HW features */
|
||||
int hw_revision; /* hardware revision */
|
||||
bool hw_learning_and_tx_capable; /* learning capable */
|
||||
bool hw_gpio40_learning; /* gpio40 is learning */
|
||||
bool hw_fan_as_normal_input; /* fan input is used as */
|
||||
/* regular input */
|
||||
/* HW state*/
|
||||
int rx_pointer; /* hw pointer to rx buffer */
|
||||
bool rx_fan_input_inuse; /* is fan input in use for rx*/
|
||||
int tx_reg; /* current reg used for TX */
|
||||
u8 saved_conf1; /* saved FEC0 reg */
|
||||
|
||||
/* TX sample handling */
|
||||
unsigned int tx_sample; /* current sample for TX */
|
||||
bool tx_sample_pulse; /* current sample is pulse */
|
||||
|
||||
/* TX buffer */
|
||||
int *tx_buffer; /* input samples buffer*/
|
||||
int tx_pos; /* position in that bufer */
|
||||
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_enabled; /* learning input enabled */
|
||||
bool carrier_detect_enabled; /* carrier detect enabled */
|
||||
int rx_period_adjust;
|
||||
};
|
||||
+1
-19
@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf,
|
||||
struct imon_context {
|
||||
struct device *dev;
|
||||
struct ir_dev_props *props;
|
||||
struct ir_input_dev *ir;
|
||||
/* Newer devices have two interfaces */
|
||||
struct usb_device *usbdev_intf0;
|
||||
struct usb_device *usbdev_intf1;
|
||||
@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
|
||||
{
|
||||
struct input_dev *idev;
|
||||
struct ir_dev_props *props;
|
||||
struct ir_input_dev *ir;
|
||||
int ret, i;
|
||||
|
||||
idev = input_allocate_device();
|
||||
@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
|
||||
goto props_alloc_failed;
|
||||
}
|
||||
|
||||
ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
|
||||
if (!ir) {
|
||||
dev_err(ictx->dev, "remote ir input dev allocation failed\n");
|
||||
goto ir_dev_alloc_failed;
|
||||
}
|
||||
|
||||
snprintf(ictx->name_idev, sizeof(ictx->name_idev),
|
||||
"iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
|
||||
idev->name = ictx->name_idev;
|
||||
@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
|
||||
props->change_protocol = imon_ir_change_protocol;
|
||||
ictx->props = props;
|
||||
|
||||
ictx->ir = ir;
|
||||
memcpy(&ir->dev, ictx->dev, sizeof(struct device));
|
||||
|
||||
usb_to_input_id(ictx->usbdev_intf0, &idev->id);
|
||||
idev->dev.parent = ictx->dev;
|
||||
|
||||
input_set_drvdata(idev, ir);
|
||||
|
||||
ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
|
||||
if (ret < 0) {
|
||||
dev_err(ictx->dev, "remote input dev register failed\n");
|
||||
@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
|
||||
return idev;
|
||||
|
||||
idev_register_failed:
|
||||
kfree(ir);
|
||||
ir_dev_alloc_failed:
|
||||
kfree(props);
|
||||
props_alloc_failed:
|
||||
input_free_device(idev);
|
||||
@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
|
||||
|
||||
urb_submit_failed:
|
||||
ir_input_unregister(ictx->idev);
|
||||
input_free_device(ictx->idev);
|
||||
idev_setup_failed:
|
||||
find_endpoint_failed:
|
||||
mutex_unlock(&ictx->lock);
|
||||
@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
|
||||
return ictx;
|
||||
|
||||
urb_submit_failed:
|
||||
if (ictx->touch) {
|
||||
if (ictx->touch)
|
||||
input_unregister_device(ictx->touch);
|
||||
input_free_device(ictx->touch);
|
||||
}
|
||||
touch_setup_failed:
|
||||
find_endpoint_failed:
|
||||
mutex_unlock(&ictx->lock);
|
||||
|
||||
@@ -32,7 +32,7 @@ struct ir_raw_handler {
|
||||
|
||||
struct ir_raw_event_ctrl {
|
||||
struct list_head list; /* to keep track of raw clients */
|
||||
struct work_struct rx_work; /* for the rx decoding workqueue */
|
||||
struct task_struct *thread;
|
||||
struct kfifo kfifo; /* fifo for the pulse/space durations */
|
||||
ktime_t last_event; /* when last event occurred */
|
||||
enum raw_event_type last_type; /* last event type */
|
||||
@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl {
|
||||
|
||||
/* raw decoder state follows */
|
||||
struct ir_raw_event prev_ev;
|
||||
struct ir_raw_event this_ev;
|
||||
struct nec_dec {
|
||||
int state;
|
||||
unsigned count;
|
||||
u32 bits;
|
||||
bool is_nec_x;
|
||||
bool necx_repeat;
|
||||
} nec;
|
||||
struct rc5_dec {
|
||||
int state;
|
||||
@@ -76,7 +79,7 @@ struct ir_raw_event_ctrl {
|
||||
struct lirc_codec {
|
||||
struct ir_input_dev *ir_dev;
|
||||
struct lirc_driver *drv;
|
||||
int lircdata;
|
||||
int carrier_low;
|
||||
} lirc;
|
||||
};
|
||||
|
||||
@@ -104,10 +107,9 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
|
||||
ev->duration -= duration;
|
||||
}
|
||||
|
||||
#define TO_US(duration) (((duration) + 500) / 1000)
|
||||
#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
|
||||
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
|
||||
#define IS_RESET(ev) (ev.duration == 0)
|
||||
|
||||
/*
|
||||
* Routines from ir-sysfs.c - Meant to be called only internally inside
|
||||
* ir-core
|
||||
@@ -126,7 +128,8 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
|
||||
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
|
||||
void ir_raw_init(void);
|
||||
|
||||
|
||||
int ir_rcmap_init(void);
|
||||
void ir_rcmap_cleanup(void);
|
||||
/*
|
||||
* Decoder initialization code
|
||||
*
|
||||
|
||||
@@ -32,6 +32,7 @@ enum jvc_state {
|
||||
STATE_BIT_SPACE,
|
||||
STATE_TRAILER_PULSE,
|
||||
STATE_TRAILER_SPACE,
|
||||
STATE_CHECK_REPEAT,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
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:
|
||||
@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
}
|
||||
|
||||
data->count = 0;
|
||||
data->state = STATE_BIT_PULSE;
|
||||
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:
|
||||
|
||||
@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev)
|
||||
|
||||
spin_lock_irqsave(&ir->keylock, flags);
|
||||
|
||||
input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
|
||||
|
||||
if (!ir->keypressed)
|
||||
goto out;
|
||||
|
||||
@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
|
||||
|
||||
spin_lock_irqsave(&ir->keylock, flags);
|
||||
|
||||
input_event(dev, EV_MSC, MSC_SCAN, scancode);
|
||||
|
||||
/* Repeat event? */
|
||||
if (ir->keypressed &&
|
||||
ir->last_scancode == scancode &&
|
||||
@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
|
||||
ir->last_toggle = toggle;
|
||||
ir->last_keycode = keycode;
|
||||
|
||||
|
||||
if (keycode == KEY_RESERVED)
|
||||
goto out;
|
||||
|
||||
|
||||
/* Register a keypress */
|
||||
ir->keypressed = true;
|
||||
IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
|
||||
@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *input_dev)
|
||||
*/
|
||||
int __ir_input_register(struct input_dev *input_dev,
|
||||
const struct ir_scancode_table *rc_tab,
|
||||
const struct ir_dev_props *props,
|
||||
struct ir_dev_props *props,
|
||||
const char *driver_name)
|
||||
{
|
||||
struct ir_input_dev *ir_dev;
|
||||
@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev *input_dev,
|
||||
|
||||
set_bit(EV_KEY, input_dev->evbit);
|
||||
set_bit(EV_REP, input_dev->evbit);
|
||||
set_bit(EV_MSC, input_dev->evbit);
|
||||
set_bit(MSC_SCAN, input_dev->mscbit);
|
||||
|
||||
if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
|
||||
rc = -ENOMEM;
|
||||
@@ -499,7 +507,8 @@ int __ir_input_register(struct input_dev *input_dev,
|
||||
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
|
||||
driver_name, rc_tab->name,
|
||||
ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : "");
|
||||
(ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
|
||||
" in raw mode" : "");
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
int sample;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
|
||||
return 0;
|
||||
@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
|
||||
return -EINVAL;
|
||||
|
||||
if (IS_RESET(ev))
|
||||
return 0;
|
||||
|
||||
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
|
||||
TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
|
||||
ir_dev->raw->lirc.lircdata += ev.duration / 1000;
|
||||
sample = ev.duration / 1000;
|
||||
if (ev.pulse)
|
||||
ir_dev->raw->lirc.lircdata |= PULSE_BIT;
|
||||
sample |= PULSE_BIT;
|
||||
|
||||
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
|
||||
(unsigned char *) &ir_dev->raw->lirc.lircdata);
|
||||
(unsigned char *) &sample);
|
||||
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
|
||||
|
||||
ir_dev->raw->lirc.lircdata = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -92,13 +95,14 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
|
||||
unsigned long __user arg)
|
||||
{
|
||||
struct lirc_codec *lirc;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int ret = 0;
|
||||
void *drv_data;
|
||||
unsigned long val;
|
||||
unsigned long val = 0;
|
||||
|
||||
lirc = lirc_get_pdata(filep);
|
||||
if (!lirc)
|
||||
@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar
|
||||
|
||||
drv_data = ir_dev->props->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case LIRC_SET_TRANSMITTER_MASK:
|
||||
if (_IOC_DIR(cmd) & _IOC_WRITE) {
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_mask)
|
||||
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;
|
||||
break;
|
||||
|
||||
/* TX settings */
|
||||
case LIRC_SET_TRANSMITTER_MASK:
|
||||
if (ir_dev->props->s_tx_mask)
|
||||
ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_CARRIER:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_carrier)
|
||||
if (ir_dev->props->s_tx_carrier)
|
||||
ir_dev->props->s_tx_carrier(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_GET_SEND_MODE:
|
||||
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
|
||||
ret = put_user(val, (unsigned long *)arg);
|
||||
case LIRC_SET_SEND_DUTY_CYCLE:
|
||||
if (!ir_dev->props->s_tx_duty_cycle)
|
||||
return -ENOSYS;
|
||||
|
||||
if (val <= 0 || val >= 100)
|
||||
return -EINVAL;
|
||||
|
||||
ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_MODE:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
/* RX settings */
|
||||
case LIRC_SET_REC_CARRIER:
|
||||
if (ir_dev->props->s_rx_carrier_range)
|
||||
ret = ir_dev->props->s_rx_carrier_range(
|
||||
ir_dev->props->priv,
|
||||
ir_dev->raw->lirc.carrier_low, val);
|
||||
else
|
||||
return -ENOSYS;
|
||||
|
||||
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
|
||||
if (!ret)
|
||||
ir_dev->raw->lirc.carrier_low = 0;
|
||||
break;
|
||||
|
||||
case LIRC_SET_REC_CARRIER_RANGE:
|
||||
if (val >= 0)
|
||||
ir_dev->raw->lirc.carrier_low = val;
|
||||
break;
|
||||
|
||||
|
||||
case LIRC_GET_REC_RESOLUTION:
|
||||
val = ir_dev->props->rx_resolution;
|
||||
break;
|
||||
|
||||
case LIRC_SET_WIDEBAND_RECEIVER:
|
||||
if (ir_dev->props->s_learning_mode)
|
||||
return ir_dev->props->s_learning_mode(
|
||||
ir_dev->props->priv, !!val);
|
||||
else
|
||||
return -ENOSYS;
|
||||
|
||||
/* Generic timeout support */
|
||||
case LIRC_GET_MIN_TIMEOUT:
|
||||
if (!ir_dev->props->max_timeout)
|
||||
return -ENOSYS;
|
||||
val = ir_dev->props->min_timeout / 1000;
|
||||
break;
|
||||
|
||||
case LIRC_GET_MAX_TIMEOUT:
|
||||
if (!ir_dev->props->max_timeout)
|
||||
return -ENOSYS;
|
||||
val = ir_dev->props->max_timeout / 1000;
|
||||
break;
|
||||
|
||||
case LIRC_SET_REC_TIMEOUT:
|
||||
if (val < ir_dev->props->min_timeout ||
|
||||
val > ir_dev->props->max_timeout)
|
||||
return -EINVAL;
|
||||
ir_dev->props->timeout = val * 1000;
|
||||
break;
|
||||
|
||||
default:
|
||||
return lirc_dev_fop_ioctl(filep, cmd, arg);
|
||||
}
|
||||
|
||||
if (_IOC_DIR(cmd) & _IOC_READ)
|
||||
ret = put_user(val, (unsigned long *)arg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev)
|
||||
|
||||
features = LIRC_CAN_REC_MODE2;
|
||||
if (ir_dev->props->tx_ir) {
|
||||
|
||||
features |= LIRC_CAN_SEND_PULSE;
|
||||
if (ir_dev->props->s_tx_mask)
|
||||
features |= LIRC_CAN_SET_TRANSMITTER_MASK;
|
||||
if (ir_dev->props->s_tx_carrier)
|
||||
features |= LIRC_CAN_SET_SEND_CARRIER;
|
||||
|
||||
if (ir_dev->props->s_tx_duty_cycle)
|
||||
features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
|
||||
}
|
||||
|
||||
if (ir_dev->props->s_rx_carrier_range)
|
||||
features |= LIRC_CAN_SET_REC_CARRIER |
|
||||
LIRC_CAN_SET_REC_CARRIER_RANGE;
|
||||
|
||||
if (ir_dev->props->s_learning_mode)
|
||||
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
|
||||
|
||||
if (ir_dev->props->max_timeout)
|
||||
features |= LIRC_CAN_SET_REC_TIMEOUT;
|
||||
|
||||
|
||||
snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
|
||||
ir_dev->driver_name);
|
||||
drv->minor = -1;
|
||||
@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev)
|
||||
|
||||
ir_dev->raw->lirc.drv = drv;
|
||||
ir_dev->raw->lirc.ir_dev = ir_dev;
|
||||
ir_dev->raw->lirc.lircdata = PULSE_MASK;
|
||||
|
||||
return 0;
|
||||
|
||||
lirc_register_failed:
|
||||
|
||||
@@ -20,12 +20,13 @@
|
||||
#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 (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,
|
||||
@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
if (!ev.pulse)
|
||||
break;
|
||||
|
||||
if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) &&
|
||||
!eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
|
||||
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;
|
||||
@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
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");
|
||||
ir_repeat(input_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;
|
||||
@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
|
||||
}
|
||||
|
||||
if (data->is_nec_x)
|
||||
data->necx_repeat = true;
|
||||
|
||||
ir_keydown(input_dev, scancode, 0);
|
||||
data->state = STATE_INACTIVE;
|
||||
return 0;
|
||||
|
||||
+132
-25
@@ -12,9 +12,10 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/freezer.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
/* Define the max number of pulse/space transitions to buffer */
|
||||
@@ -24,7 +25,7 @@
|
||||
static LIST_HEAD(ir_raw_client_list);
|
||||
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
static DEFINE_MUTEX(ir_raw_handler_lock);
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static u64 available_protocols;
|
||||
|
||||
@@ -33,20 +34,30 @@ static u64 available_protocols;
|
||||
static struct work_struct wq_load;
|
||||
#endif
|
||||
|
||||
static void ir_raw_event_work(struct work_struct *work)
|
||||
static int ir_raw_event_thread(void *data)
|
||||
{
|
||||
struct ir_raw_event ev;
|
||||
struct ir_raw_handler *handler;
|
||||
struct ir_raw_event_ctrl *raw =
|
||||
container_of(work, struct ir_raw_event_ctrl, rx_work);
|
||||
struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
raw->prev_ev = ev;
|
||||
while (!kthread_should_stop()) {
|
||||
try_to_freeze();
|
||||
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
raw->prev_ev = ev;
|
||||
}
|
||||
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
|
||||
if (!ir->raw)
|
||||
return -EINVAL;
|
||||
|
||||
IR_dprintk(2, "sample: (05%dus %s)\n",
|
||||
TO_US(ev->duration), TO_STR(ev->pulse));
|
||||
|
||||
if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -125,6 +139,90 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
|
||||
|
||||
/**
|
||||
* ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
|
||||
* @input_dev: the struct input_dev device descriptor
|
||||
* @type: the type of the event that has occurred
|
||||
*
|
||||
* This routine (which may be called from an interrupt context) works
|
||||
* in similiar manner to ir_raw_event_store_edge.
|
||||
* This routine is intended for devices with limited internal buffer
|
||||
* It automerges samples of same type, and handles timeouts
|
||||
*/
|
||||
int ir_raw_event_store_with_filter(struct input_dev *input_dev,
|
||||
struct ir_raw_event *ev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_event_ctrl *raw = ir->raw;
|
||||
|
||||
if (!raw || !ir->props)
|
||||
return -EINVAL;
|
||||
|
||||
/* Ignore spaces in idle mode */
|
||||
if (ir->idle && !ev->pulse)
|
||||
return 0;
|
||||
else if (ir->idle)
|
||||
ir_raw_event_set_idle(input_dev, 0);
|
||||
|
||||
if (!raw->this_ev.duration) {
|
||||
raw->this_ev = *ev;
|
||||
} else if (ev->pulse == raw->this_ev.pulse) {
|
||||
raw->this_ev.duration += ev->duration;
|
||||
} else {
|
||||
ir_raw_event_store(input_dev, &raw->this_ev);
|
||||
raw->this_ev = *ev;
|
||||
}
|
||||
|
||||
/* Enter idle mode if nessesary */
|
||||
if (!ev->pulse && ir->props->timeout &&
|
||||
raw->this_ev.duration >= ir->props->timeout)
|
||||
ir_raw_event_set_idle(input_dev, 1);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
|
||||
|
||||
void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_event_ctrl *raw = ir->raw;
|
||||
ktime_t now;
|
||||
u64 delta;
|
||||
|
||||
if (!ir->props)
|
||||
return;
|
||||
|
||||
if (!ir->raw)
|
||||
goto out;
|
||||
|
||||
if (idle) {
|
||||
IR_dprintk(2, "enter idle mode\n");
|
||||
raw->last_event = ktime_get();
|
||||
} else {
|
||||
IR_dprintk(2, "exit idle mode\n");
|
||||
|
||||
now = ktime_get();
|
||||
delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
|
||||
|
||||
WARN_ON(raw->this_ev.pulse);
|
||||
|
||||
raw->this_ev.duration =
|
||||
min(raw->this_ev.duration + delta,
|
||||
(u64)IR_MAX_DURATION);
|
||||
|
||||
ir_raw_event_store(input_dev, &raw->this_ev);
|
||||
|
||||
if (raw->this_ev.duration == IR_MAX_DURATION)
|
||||
ir_raw_event_reset(input_dev);
|
||||
|
||||
raw->this_ev.duration = 0;
|
||||
}
|
||||
out:
|
||||
if (ir->props->s_idle)
|
||||
ir->props->s_idle(ir->props->priv, idle);
|
||||
ir->idle = idle;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
|
||||
|
||||
/**
|
||||
* ir_raw_event_handle() - schedules the decoding of stored ir data
|
||||
* @input_dev: the struct input_dev device descriptor
|
||||
@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_dev *input_dev)
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
schedule_work(&ir->raw->rx_work);
|
||||
wake_up_process(ir->raw->thread);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_handle);
|
||||
|
||||
@@ -147,9 +245,9 @@ u64
|
||||
ir_raw_get_allowed_protocols()
|
||||
{
|
||||
u64 protocols;
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
protocols = available_protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
return protocols;
|
||||
}
|
||||
|
||||
@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->raw->input_dev = input_dev;
|
||||
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
|
||||
|
||||
ir->raw->enabled_protocols = ~0;
|
||||
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
|
||||
GFP_KERNEL);
|
||||
@@ -177,12 +275,21 @@ int ir_raw_event_register(struct input_dev *input_dev)
|
||||
return rc;
|
||||
}
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
|
||||
"rc%u", (unsigned int)ir->devno);
|
||||
|
||||
if (IS_ERR(ir->raw->thread)) {
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return PTR_ERR(ir->raw->thread);
|
||||
}
|
||||
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir->raw->list, &ir_raw_client_list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_register)
|
||||
handler->raw_register(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -195,14 +302,14 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
kthread_stop(ir->raw->thread);
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir->raw->list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_unregister)
|
||||
handler->raw_unregister(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
@@ -217,13 +324,13 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
|
||||
if (ir_raw_handler->raw_register)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_register(raw->input_dev);
|
||||
available_protocols |= ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -233,13 +340,13 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
mutex_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir_raw_handler->list);
|
||||
if (ir_raw_handler->raw_unregister)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_unregister(raw->input_dev);
|
||||
available_protocols &= ~ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
mutex_unlock(&ir_raw_handler_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ir_raw_handler_unregister);
|
||||
|
||||
|
||||
@@ -325,6 +325,7 @@ static int __init ir_core_init(void)
|
||||
|
||||
/* Initialize/load the decoders/keymap code that will be used */
|
||||
ir_raw_init();
|
||||
ir_rcmap_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -332,6 +333,7 @@ static int __init ir_core_init(void)
|
||||
static void __exit ir_core_exit(void)
|
||||
{
|
||||
class_unregister(&ir_input_class);
|
||||
ir_rcmap_cleanup();
|
||||
}
|
||||
|
||||
module_init(ir_core_init);
|
||||
|
||||
@@ -19,7 +19,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
||||
rc-dm1105-nec.o \
|
||||
rc-dntv-live-dvb-t.o \
|
||||
rc-dntv-live-dvbt-pro.o \
|
||||
rc-empty.o \
|
||||
rc-em-terratec.o \
|
||||
rc-encore-enltv2.o \
|
||||
rc-encore-enltv.o \
|
||||
@@ -59,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
||||
rc-purpletv.o \
|
||||
rc-pv951.o \
|
||||
rc-rc5-hauppauge-new.o \
|
||||
rc-rc5-streamzap.o \
|
||||
rc-rc5-tv.o \
|
||||
rc-rc6-mce.o \
|
||||
rc-real-audio-220-32-keys.o \
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/* empty.h - Keytable for empty Remote Controller
|
||||
*
|
||||
* keymap imported from ir-keymaps.c
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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>
|
||||
|
||||
/* empty keytable, can be used as placeholder for not-yet created keytables */
|
||||
|
||||
static struct ir_scancode empty[] = {
|
||||
{ 0x2a, KEY_COFFEE },
|
||||
};
|
||||
|
||||
static struct rc_keymap empty_map = {
|
||||
.map = {
|
||||
.scan = empty,
|
||||
.size = ARRAY_SIZE(empty),
|
||||
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.name = RC_MAP_EMPTY,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_empty(void)
|
||||
{
|
||||
return ir_register_map(&empty_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_empty(void)
|
||||
{
|
||||
ir_unregister_map(&empty_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_empty)
|
||||
module_exit(exit_rc_map_empty)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
|
||||
@@ -0,0 +1,81 @@
|
||||
/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
|
||||
* with the Streamzap PC Remote IR Receiver.
|
||||
*
|
||||
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode rc5_streamzap[] = {
|
||||
/*
|
||||
* FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
|
||||
* bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
|
||||
* We either have to enhance the decoder to support it, add a new decoder,
|
||||
* or just rely on lirc userspace decoding.
|
||||
*/
|
||||
{ 0x00, KEY_NUMERIC_0 },
|
||||
{ 0x01, KEY_NUMERIC_1 },
|
||||
{ 0x02, KEY_NUMERIC_2 },
|
||||
{ 0x03, KEY_NUMERIC_3 },
|
||||
{ 0x04, KEY_NUMERIC_4 },
|
||||
{ 0x05, KEY_NUMERIC_5 },
|
||||
{ 0x06, KEY_NUMERIC_6 },
|
||||
{ 0x07, KEY_NUMERIC_7 },
|
||||
{ 0x08, KEY_NUMERIC_8 },
|
||||
{ 0x0a, KEY_POWER },
|
||||
{ 0x0b, KEY_MUTE },
|
||||
{ 0x0c, KEY_CHANNELUP },
|
||||
{ 0x0d, KEY_VOLUMEUP },
|
||||
{ 0x0e, KEY_CHANNELDOWN },
|
||||
{ 0x0f, KEY_VOLUMEDOWN },
|
||||
{ 0x10, KEY_UP },
|
||||
{ 0x11, KEY_LEFT },
|
||||
{ 0x12, KEY_OK },
|
||||
{ 0x13, KEY_RIGHT },
|
||||
{ 0x14, KEY_DOWN },
|
||||
{ 0x15, KEY_MENU },
|
||||
{ 0x16, KEY_EXIT },
|
||||
{ 0x17, KEY_PLAY },
|
||||
{ 0x18, KEY_PAUSE },
|
||||
{ 0x19, KEY_STOP },
|
||||
{ 0x1a, KEY_BACK },
|
||||
{ 0x1b, KEY_FORWARD },
|
||||
{ 0x1c, KEY_RECORD },
|
||||
{ 0x1d, KEY_REWIND },
|
||||
{ 0x1e, KEY_FASTFORWARD },
|
||||
{ 0x20, KEY_RED },
|
||||
{ 0x21, KEY_GREEN },
|
||||
{ 0x22, KEY_YELLOW },
|
||||
{ 0x23, KEY_BLUE },
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap rc5_streamzap_map = {
|
||||
.map = {
|
||||
.scan = rc5_streamzap,
|
||||
.size = ARRAY_SIZE(rc5_streamzap),
|
||||
.ir_type = IR_TYPE_RC5,
|
||||
.name = RC_MAP_RC5_STREAMZAP,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_rc5_streamzap(void)
|
||||
{
|
||||
return ir_register_map(&rc5_streamzap_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_rc5_streamzap(void)
|
||||
{
|
||||
ir_unregister_map(&rc5_streamzap_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_rc5_streamzap)
|
||||
module_exit(exit_rc_map_rc5_streamzap)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
|
||||
@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = {
|
||||
{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
|
||||
{ 0x800f044d, KEY_TITLE },
|
||||
|
||||
{ 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
|
||||
|
||||
{ 0x800f040c, KEY_POWER },
|
||||
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user