mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-30 11:41:38 -04:00
Merge branch 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_2.6.35' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (243 commits) V4L/DVB: sms: Convert IR support to use the Remote Controller core V4L/DVB: sms: properly initialize IR phys and IR name V4L/DVB: standardize names at rc-dib0700 tables V4L/DVB: smsusb: enable IR port for Hauppauge WinTV MiniStick V4L/DVB: dib0700: Fix RC protocol logic to properly handle NEC/NECx and RC-5 V4L/DVB: dib0700: properly implement IR change_protocol V4L/DVB: dib0700: break keytable into NEC and RC-5 variants V4L/DVB: dib0700: avoid bad repeat V4L/DVB: Port dib0700 to rc-core V4L/DVB: Add a keymap file with dib0700 table V4L/DVB: dvb-usb: add support for rc-core mode V4L/DVB: dvb-usb: prepare drivers for using rc-core V4L/DVB: dvb-usb: get rid of struct dvb_usb_rc_key V4L/DVB: rj54n1cb0c: fix a comment in the driver V4L/DVB: V4L2: sh_vou: VOU does support the full PAL resolution too V4L/DVB: V4L2: sh_mobile_camera_ceu: add support for CSI2 V4L/DVB: V4L2: soc-camera: add a MIPI CSI-2 driver for SH-Mobile platforms V4L/DVB: V4L2: soc-camera: export soc-camera bus type for notifications V4L/DVB: V4L2: mediabus: add 12-bit Bayer and YUV420 pixel formats V4L/DVB: mediabus: fix ambiguous pixel code names ...
This commit is contained in:
commit
f63b759c44
320 changed files with 27790 additions and 31664 deletions
|
|
@ -8,6 +8,17 @@ config VIDEO_IR
|
|||
depends on IR_CORE
|
||||
default IR_CORE
|
||||
|
||||
config LIRC
|
||||
tristate
|
||||
default y
|
||||
|
||||
---help---
|
||||
Enable this option to build the Linux Infrared Remote
|
||||
Control (LIRC) core device interface driver. The LIRC
|
||||
interface passes raw IR to and from userspace, where the
|
||||
LIRC daemon handles protocol decoding for IR reception ann
|
||||
encoding for IR transmitting (aka "blasting").
|
||||
|
||||
source "drivers/media/IR/keymaps/Kconfig"
|
||||
|
||||
config IR_NEC_DECODER
|
||||
|
|
@ -33,6 +44,7 @@ config IR_RC5_DECODER
|
|||
config IR_RC6_DECODER
|
||||
tristate "Enable IR raw decoder for the RC6 protocol"
|
||||
depends on IR_CORE
|
||||
select BITREVERSE
|
||||
default y
|
||||
|
||||
---help---
|
||||
|
|
@ -42,6 +54,7 @@ config IR_RC6_DECODER
|
|||
config IR_JVC_DECODER
|
||||
tristate "Enable IR raw decoder for the JVC protocol"
|
||||
depends on IR_CORE
|
||||
select BITREVERSE
|
||||
default y
|
||||
|
||||
---help---
|
||||
|
|
@ -57,6 +70,16 @@ config IR_SONY_DECODER
|
|||
Enable this option if you have an infrared remote control which
|
||||
uses the Sony protocol, and you need software decoding support.
|
||||
|
||||
config IR_LIRC_CODEC
|
||||
tristate "Enable IR to LIRC bridge"
|
||||
depends on IR_CORE
|
||||
depends on LIRC
|
||||
default y
|
||||
|
||||
---help---
|
||||
Enable this option to pass raw IR to and from userspace via
|
||||
the LIRC interface.
|
||||
|
||||
config IR_IMON
|
||||
tristate "SoundGraph iMON Receiver and Display"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
|
|
@ -68,3 +91,15 @@ config IR_IMON
|
|||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imon.
|
||||
|
||||
config IR_MCEUSB
|
||||
tristate "Windows Media Center Ed. eHome Infrared Transceiver"
|
||||
depends on USB_ARCH_HAS_HCD
|
||||
depends on IR_CORE
|
||||
select USB
|
||||
---help---
|
||||
Say Y here if you want to use a Windows Media Center Edition
|
||||
eHome Infrared Transceiver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called mceusb.
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@ obj-y += keymaps/
|
|||
|
||||
obj-$(CONFIG_IR_CORE) += ir-core.o
|
||||
obj-$(CONFIG_VIDEO_IR) += ir-common.o
|
||||
obj-$(CONFIG_LIRC) += lirc_dev.o
|
||||
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
|
||||
obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
|
||||
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
|
||||
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
|
||||
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
|
||||
obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
|
||||
|
||||
# stand-alone IR receivers/transmitters
|
||||
obj-$(CONFIG_IR_IMON) += imon.o
|
||||
obj-$(CONFIG_IR_MCEUSB) += mceusb.o
|
||||
|
|
|
|||
|
|
@ -407,7 +407,7 @@ static int display_close(struct inode *inode, struct file *file)
|
|||
struct imon_context *ictx = NULL;
|
||||
int retval = 0;
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
|
|
@ -812,7 +812,7 @@ static ssize_t vfd_write(struct file *file, const char *buf,
|
|||
const unsigned char vfd_packet6[] = {
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF };
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
return -ENODEV;
|
||||
|
|
@ -896,7 +896,7 @@ static ssize_t lcd_write(struct file *file, const char *buf,
|
|||
int retval = 0;
|
||||
struct imon_context *ictx;
|
||||
|
||||
ictx = (struct imon_context *)file->private_data;
|
||||
ictx = file->private_data;
|
||||
if (!ictx) {
|
||||
err("%s: no context for device", __func__);
|
||||
return -ENODEV;
|
||||
|
|
@ -1943,7 +1943,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
|
|||
return ictx;
|
||||
|
||||
urb_submit_failed:
|
||||
input_unregister_device(ictx->idev);
|
||||
ir_input_unregister(ictx->idev);
|
||||
input_free_device(ictx->idev);
|
||||
idev_setup_failed:
|
||||
find_endpoint_failed:
|
||||
|
|
@ -2067,6 +2067,7 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
|
|||
detected_display_type = IMON_DISPLAY_TYPE_VFD;
|
||||
break;
|
||||
/* iMON LCD, MCE IR */
|
||||
case 0x9e:
|
||||
case 0x9f:
|
||||
dev_info(ictx->dev, "0xffdc iMON LCD, MCE IR");
|
||||
detected_display_type = IMON_DISPLAY_TYPE_LCD;
|
||||
|
|
@ -2306,7 +2307,7 @@ static void __devexit imon_disconnect(struct usb_interface *interface)
|
|||
if (ifnum == 0) {
|
||||
ictx->dev_present_intf0 = false;
|
||||
usb_kill_urb(ictx->rx_urb_intf0);
|
||||
input_unregister_device(ictx->idev);
|
||||
ir_input_unregister(ictx->idev);
|
||||
if (ictx->display_supported) {
|
||||
if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
|
||||
usb_deregister_dev(interface, &imon_lcd_class);
|
||||
|
|
|
|||
|
|
@ -22,17 +22,62 @@
|
|||
struct ir_raw_handler {
|
||||
struct list_head list;
|
||||
|
||||
u64 protocols; /* which are handled by this handler */
|
||||
int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
|
||||
|
||||
/* These two should only be used by the lirc decoder */
|
||||
int (*raw_register)(struct input_dev *input_dev);
|
||||
int (*raw_unregister)(struct input_dev *input_dev);
|
||||
};
|
||||
|
||||
struct ir_raw_event_ctrl {
|
||||
struct list_head list; /* to keep track of raw clients */
|
||||
struct work_struct rx_work; /* for the rx decoding workqueue */
|
||||
struct kfifo kfifo; /* fifo for the pulse/space durations */
|
||||
ktime_t last_event; /* when last event occurred */
|
||||
enum raw_event_type last_type; /* last event type */
|
||||
struct input_dev *input_dev; /* pointer to the parent input_dev */
|
||||
u64 enabled_protocols; /* enabled raw protocol decoders */
|
||||
|
||||
/* raw decoder state follows */
|
||||
struct ir_raw_event prev_ev;
|
||||
struct nec_dec {
|
||||
int state;
|
||||
unsigned count;
|
||||
u32 bits;
|
||||
} nec;
|
||||
struct rc5_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc5;
|
||||
struct rc6_dec {
|
||||
int state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc6;
|
||||
struct sony_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
} sony;
|
||||
struct jvc_dec {
|
||||
int state;
|
||||
u16 bits;
|
||||
u16 old_bits;
|
||||
unsigned count;
|
||||
bool first;
|
||||
bool toggle;
|
||||
} jvc;
|
||||
struct lirc_codec {
|
||||
struct ir_input_dev *ir_dev;
|
||||
struct lirc_driver *drv;
|
||||
int lircdata;
|
||||
} lirc;
|
||||
};
|
||||
|
||||
/* macros for IR decoders */
|
||||
|
|
@ -74,6 +119,7 @@ void ir_unregister_class(struct input_dev *input_dev);
|
|||
/*
|
||||
* Routines from ir-raw-event.c to be used internally and by decoders
|
||||
*/
|
||||
u64 ir_raw_get_allowed_protocols(void);
|
||||
int ir_raw_event_register(struct input_dev *input_dev);
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev);
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
|
||||
|
|
@ -123,4 +169,12 @@ void ir_raw_init(void);
|
|||
#define load_sony_decode() 0
|
||||
#endif
|
||||
|
||||
/* from ir-lirc-codec.c */
|
||||
#ifdef CONFIG_IR_LIRC_CODEC_MODULE
|
||||
#define load_lirc_codec() request_module("ir-lirc-codec")
|
||||
#else
|
||||
#define load_lirc_codec() 0
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _IR_RAW_EVENT */
|
||||
|
|
|
|||
|
|
@ -25,10 +25,6 @@
|
|||
#define JVC_TRAILER_PULSE (1 * JVC_UNIT)
|
||||
#define JVC_TRAILER_SPACE (35 * JVC_UNIT)
|
||||
|
||||
/* Used to register jvc_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum jvc_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
|
@ -38,87 +34,6 @@ enum jvc_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum jvc_state state;
|
||||
u16 jvc_bits;
|
||||
u16 jvc_old_bits;
|
||||
unsigned count;
|
||||
bool first;
|
||||
bool toggle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "jvc_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_jvc_decode() - Decode one JVC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
|
@ -128,14 +43,10 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct jvc_dec *data = &ir_dev->raw->jvc;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
|
@ -188,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->jvc_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
|
||||
data->jvc_bits |= 1;
|
||||
data->bits |= 1;
|
||||
decrease_duration(&ev, JVC_BIT_1_SPACE);
|
||||
} else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
|
||||
decrease_duration(&ev, JVC_BIT_0_SPACE);
|
||||
|
|
@ -223,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
if (data->first) {
|
||||
u32 scancode;
|
||||
scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
|
||||
scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->bits >> 0) & 0xff) << 0);
|
||||
IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
|
||||
ir_keydown(input_dev, scancode, data->toggle);
|
||||
data->first = false;
|
||||
data->jvc_old_bits = data->jvc_bits;
|
||||
} else if (data->jvc_bits == data->jvc_old_bits) {
|
||||
data->old_bits = data->bits;
|
||||
} else if (data->bits == data->old_bits) {
|
||||
IR_dprintk(1, "JVC repeat\n");
|
||||
ir_repeat(input_dev);
|
||||
} else {
|
||||
|
|
@ -249,54 +160,9 @@ out:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_jvc_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_jvc_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler jvc_handler = {
|
||||
.protocols = IR_TYPE_JVC,
|
||||
.decode = ir_jvc_decode,
|
||||
.raw_register = ir_jvc_register,
|
||||
.raw_unregister = ir_jvc_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_jvc_decode_init(void)
|
||||
|
|
|
|||
|
|
@ -497,8 +497,9 @@ int __ir_input_register(struct input_dev *input_dev,
|
|||
goto out_event;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote.\n",
|
||||
driver_name, rc_tab->name);
|
||||
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
|
||||
driver_name, rc_tab->name,
|
||||
ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : "");
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
|||
278
drivers/media/IR/ir-lirc-codec.c
Normal file
278
drivers/media/IR/ir-lirc-codec.c
Normal file
|
|
@ -0,0 +1,278 @@
|
|||
/* ir-lirc-codec.c - ir-core to classic lirc interface bridge
|
||||
*
|
||||
* Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/wait.h>
|
||||
#include <media/lirc.h>
|
||||
#include <media/lirc_dev.h>
|
||||
#include <media/ir-core.h>
|
||||
#include "ir-core-priv.h"
|
||||
|
||||
#define LIRCBUF_SIZE 256
|
||||
|
||||
/**
|
||||
* ir_lirc_decode() - Send raw IR data to lirc_dev to be relayed to the
|
||||
* lircd userspace daemon for decoding.
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
* @duration: the struct ir_raw_event descriptor of the pulse/space
|
||||
*
|
||||
* This function returns -EINVAL if the lirc interfaces aren't wired up.
|
||||
*/
|
||||
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
|
||||
return 0;
|
||||
|
||||
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
|
||||
return -EINVAL;
|
||||
|
||||
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
|
||||
TO_US(ev.duration), TO_STR(ev.pulse));
|
||||
|
||||
ir_dev->raw->lirc.lircdata += ev.duration / 1000;
|
||||
if (ev.pulse)
|
||||
ir_dev->raw->lirc.lircdata |= PULSE_BIT;
|
||||
|
||||
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
|
||||
(unsigned char *) &ir_dev->raw->lirc.lircdata);
|
||||
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
|
||||
|
||||
ir_dev->raw->lirc.lircdata = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
|
||||
size_t n, loff_t *ppos)
|
||||
{
|
||||
struct lirc_codec *lirc;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int *txbuf; /* buffer with values to transmit */
|
||||
int ret = 0, count;
|
||||
|
||||
lirc = lirc_get_pdata(file);
|
||||
if (!lirc)
|
||||
return -EFAULT;
|
||||
|
||||
if (n % sizeof(int))
|
||||
return -EINVAL;
|
||||
|
||||
count = n / sizeof(int);
|
||||
if (count > LIRCBUF_SIZE || count % 2 == 0)
|
||||
return -EINVAL;
|
||||
|
||||
txbuf = memdup_user(buf, n);
|
||||
if (IS_ERR(txbuf))
|
||||
return PTR_ERR(txbuf);
|
||||
|
||||
ir_dev = lirc->ir_dev;
|
||||
if (!ir_dev) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->tx_ir)
|
||||
ret = ir_dev->props->tx_ir(ir_dev->props->priv, txbuf, (u32)n);
|
||||
|
||||
out:
|
||||
kfree(txbuf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct lirc_codec *lirc;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int ret = 0;
|
||||
void *drv_data;
|
||||
unsigned long val;
|
||||
|
||||
lirc = lirc_get_pdata(filep);
|
||||
if (!lirc)
|
||||
return -EFAULT;
|
||||
|
||||
ir_dev = lirc->ir_dev;
|
||||
if (!ir_dev || !ir_dev->props || !ir_dev->props->priv)
|
||||
return -EFAULT;
|
||||
|
||||
drv_data = ir_dev->props->priv;
|
||||
|
||||
switch (cmd) {
|
||||
case LIRC_SET_TRANSMITTER_MASK:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_mask)
|
||||
ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_CARRIER:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (ir_dev->props && ir_dev->props->s_tx_carrier)
|
||||
ir_dev->props->s_tx_carrier(drv_data, (u32)val);
|
||||
else
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case LIRC_GET_SEND_MODE:
|
||||
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
|
||||
ret = put_user(val, (unsigned long *)arg);
|
||||
break;
|
||||
|
||||
case LIRC_SET_SEND_MODE:
|
||||
ret = get_user(val, (unsigned long *)arg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return lirc_dev_fop_ioctl(filep, cmd, arg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ir_lirc_open(void *data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ir_lirc_close(void *data)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static struct file_operations lirc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.write = ir_lirc_transmit_ir,
|
||||
.unlocked_ioctl = ir_lirc_ioctl,
|
||||
.read = lirc_dev_fop_read,
|
||||
.poll = lirc_dev_fop_poll,
|
||||
.open = lirc_dev_fop_open,
|
||||
.release = lirc_dev_fop_close,
|
||||
};
|
||||
|
||||
static int ir_lirc_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct lirc_driver *drv;
|
||||
struct lirc_buffer *rbuf;
|
||||
int rc = -ENOMEM;
|
||||
unsigned long features;
|
||||
|
||||
drv = kzalloc(sizeof(struct lirc_driver), GFP_KERNEL);
|
||||
if (!drv)
|
||||
return rc;
|
||||
|
||||
rbuf = kzalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
|
||||
if (!rbuf)
|
||||
goto rbuf_alloc_failed;
|
||||
|
||||
rc = lirc_buffer_init(rbuf, sizeof(int), LIRCBUF_SIZE);
|
||||
if (rc)
|
||||
goto rbuf_init_failed;
|
||||
|
||||
features = LIRC_CAN_REC_MODE2;
|
||||
if (ir_dev->props->tx_ir) {
|
||||
features |= LIRC_CAN_SEND_PULSE;
|
||||
if (ir_dev->props->s_tx_mask)
|
||||
features |= LIRC_CAN_SET_TRANSMITTER_MASK;
|
||||
if (ir_dev->props->s_tx_carrier)
|
||||
features |= LIRC_CAN_SET_SEND_CARRIER;
|
||||
}
|
||||
|
||||
snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
|
||||
ir_dev->driver_name);
|
||||
drv->minor = -1;
|
||||
drv->features = features;
|
||||
drv->data = &ir_dev->raw->lirc;
|
||||
drv->rbuf = rbuf;
|
||||
drv->set_use_inc = &ir_lirc_open;
|
||||
drv->set_use_dec = &ir_lirc_close;
|
||||
drv->code_length = sizeof(struct ir_raw_event) * 8;
|
||||
drv->fops = &lirc_fops;
|
||||
drv->dev = &ir_dev->dev;
|
||||
drv->owner = THIS_MODULE;
|
||||
|
||||
drv->minor = lirc_register_driver(drv);
|
||||
if (drv->minor < 0) {
|
||||
rc = -ENODEV;
|
||||
goto lirc_register_failed;
|
||||
}
|
||||
|
||||
ir_dev->raw->lirc.drv = drv;
|
||||
ir_dev->raw->lirc.ir_dev = ir_dev;
|
||||
ir_dev->raw->lirc.lircdata = PULSE_MASK;
|
||||
|
||||
return 0;
|
||||
|
||||
lirc_register_failed:
|
||||
rbuf_init_failed:
|
||||
kfree(rbuf);
|
||||
rbuf_alloc_failed:
|
||||
kfree(drv);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int ir_lirc_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct lirc_codec *lirc = &ir_dev->raw->lirc;
|
||||
|
||||
lirc_unregister_driver(lirc->drv->minor);
|
||||
lirc_buffer_free(lirc->drv->rbuf);
|
||||
kfree(lirc->drv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler lirc_handler = {
|
||||
.protocols = IR_TYPE_LIRC,
|
||||
.decode = ir_lirc_decode,
|
||||
.raw_register = ir_lirc_register,
|
||||
.raw_unregister = ir_lirc_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_lirc_codec_init(void)
|
||||
{
|
||||
ir_raw_handler_register(&lirc_handler);
|
||||
|
||||
printk(KERN_INFO "IR LIRC bridge handler initialized\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ir_lirc_codec_exit(void)
|
||||
{
|
||||
ir_raw_handler_unregister(&lirc_handler);
|
||||
}
|
||||
|
||||
module_init(ir_lirc_codec_init);
|
||||
module_exit(ir_lirc_codec_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <[email protected]>");
|
||||
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
|
||||
MODULE_DESCRIPTION("LIRC IR handler bridge");
|
||||
|
|
@ -27,10 +27,6 @@
|
|||
#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
|
||||
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
|
||||
|
||||
/* Used to register nec_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum nec_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
|
@ -40,84 +36,6 @@ enum nec_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum nec_state state;
|
||||
u32 nec_bits;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "nec_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_nec_decode() - Decode one NEC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
|
@ -127,16 +45,12 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct nec_dec *data = &ir_dev->raw->nec;
|
||||
u32 scancode;
|
||||
u8 address, not_address, command, not_command;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
|
@ -191,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->nec_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
|
||||
data->nec_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
|
||||
break;
|
||||
data->count++;
|
||||
|
|
@ -222,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
|
||||
break;
|
||||
|
||||
address = bitrev8((data->nec_bits >> 24) & 0xff);
|
||||
not_address = bitrev8((data->nec_bits >> 16) & 0xff);
|
||||
command = bitrev8((data->nec_bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->nec_bits >> 0) & 0xff);
|
||||
address = bitrev8((data->bits >> 24) & 0xff);
|
||||
not_address = bitrev8((data->bits >> 16) & 0xff);
|
||||
command = bitrev8((data->bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->bits >> 0) & 0xff);
|
||||
|
||||
if ((command ^ not_command) != 0xff) {
|
||||
IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
|
||||
data->nec_bits);
|
||||
data->bits);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -256,54 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_nec_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_nec_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler nec_handler = {
|
||||
.protocols = IR_TYPE_NEC,
|
||||
.decode = ir_nec_decode,
|
||||
.raw_register = ir_nec_register,
|
||||
.raw_unregister = ir_nec_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_nec_decode_init(void)
|
||||
|
|
|
|||
|
|
@ -20,35 +20,13 @@
|
|||
/* Define the max number of pulse/space transitions to buffer */
|
||||
#define MAX_IR_EVENT_SIZE 512
|
||||
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
|
||||
static LIST_HEAD(ir_raw_client_list);
|
||||
|
||||
/**
|
||||
* RUN_DECODER() - runs an operation on all IR decoders
|
||||
* @ops: IR raw handler operation to be called
|
||||
* @arg: arguments to be passed to the callback
|
||||
*
|
||||
* Calls ir_raw_handler::ops for all registered IR handlers. It prevents
|
||||
* new decode addition/removal while running, by locking ir_raw_handler_lock
|
||||
* mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum
|
||||
* of the return codes.
|
||||
*/
|
||||
#define RUN_DECODER(ops, ...) ({ \
|
||||
struct ir_raw_handler *_ir_raw_handler; \
|
||||
int _sumrc = 0, _rc; \
|
||||
spin_lock(&ir_raw_handler_lock); \
|
||||
list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \
|
||||
if (_ir_raw_handler->ops) { \
|
||||
_rc = _ir_raw_handler->ops(__VA_ARGS__); \
|
||||
if (_rc < 0) \
|
||||
break; \
|
||||
_sumrc += _rc; \
|
||||
} \
|
||||
} \
|
||||
spin_unlock(&ir_raw_handler_lock); \
|
||||
_sumrc; \
|
||||
})
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static u64 available_protocols;
|
||||
|
||||
#ifdef MODULE
|
||||
/* Used to load the decoders */
|
||||
|
|
@ -58,57 +36,17 @@ static struct work_struct wq_load;
|
|||
static void ir_raw_event_work(struct work_struct *work)
|
||||
{
|
||||
struct ir_raw_event ev;
|
||||
struct ir_raw_handler *handler;
|
||||
struct ir_raw_event_ctrl *raw =
|
||||
container_of(work, struct ir_raw_event_ctrl, rx_work);
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
|
||||
RUN_DECODER(decode, raw->input_dev, ev);
|
||||
}
|
||||
|
||||
int ir_raw_event_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
|
||||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
|
||||
if (!ir->raw)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->raw->input_dev = input_dev;
|
||||
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
|
||||
|
||||
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (rc < 0) {
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
raw->prev_ev = ev;
|
||||
}
|
||||
|
||||
rc = RUN_DECODER(raw_register, input_dev);
|
||||
if (rc < 0) {
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
RUN_DECODER(raw_unregister, input_dev);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(ir_raw_event_handle);
|
||||
|
||||
/* used internally by the sysfs interface */
|
||||
u64
|
||||
ir_raw_get_allowed_protocols()
|
||||
{
|
||||
u64 protocols;
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
protocols = available_protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
return protocols;
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to (un)register raw event clients
|
||||
*/
|
||||
int ir_raw_event_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
|
||||
if (!ir->raw)
|
||||
return -ENOMEM;
|
||||
|
||||
ir->raw->input_dev = input_dev;
|
||||
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
|
||||
ir->raw->enabled_protocols = ~0;
|
||||
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
|
||||
GFP_KERNEL);
|
||||
if (rc < 0) {
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir->raw->list, &ir_raw_client_list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_register)
|
||||
handler->raw_register(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir->raw->list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_unregister)
|
||||
handler->raw_unregister(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extension interface - used to register the IR decoders
|
||||
*/
|
||||
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
|
||||
if (ir_raw_handler->raw_register)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_register(raw->input_dev);
|
||||
available_protocols |= ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ir_raw_handler_register);
|
||||
|
||||
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir_raw_handler->list);
|
||||
if (ir_raw_handler->raw_unregister)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_unregister(raw->input_dev);
|
||||
available_protocols &= ~ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ir_raw_handler_unregister);
|
||||
|
|
@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work)
|
|||
load_rc6_decode();
|
||||
load_jvc_decode();
|
||||
load_sony_decode();
|
||||
load_lirc_codec();
|
||||
|
||||
/* If needed, we may later add some init code. In this case,
|
||||
it is needed to change the CONFIG_MODULE test at ir-core.h
|
||||
|
|
|
|||
|
|
@ -30,10 +30,6 @@
|
|||
#define RC5_BIT_END (1 * RC5_UNIT)
|
||||
#define RC5X_SPACE (4 * RC5_UNIT)
|
||||
|
||||
/* Used to register rc5_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc5_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_BIT_START,
|
||||
|
|
@ -42,87 +38,6 @@ enum rc5_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum rc5_state state;
|
||||
u32 rc5_bits;
|
||||
struct ir_raw_event prev_ev;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "rc5_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_rc5_decode() - Decode one RC-5 pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
|
@ -132,17 +47,13 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct rc5_dec *data = &ir_dev->raw->rc5;
|
||||
u8 toggle;
|
||||
u32 scancode;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
return 0;
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
data->state = STATE_INACTIVE;
|
||||
|
|
@ -176,16 +87,15 @@ again:
|
|||
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
|
||||
break;
|
||||
|
||||
data->rc5_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (!ev.pulse)
|
||||
data->rc5_bits |= 1;
|
||||
data->bits |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
|
@ -217,11 +127,11 @@ again:
|
|||
if (data->wanted_bits == RC5X_NBITS) {
|
||||
/* RC5X */
|
||||
u8 xdata, command, system;
|
||||
xdata = (data->rc5_bits & 0x0003F) >> 0;
|
||||
command = (data->rc5_bits & 0x00FC0) >> 6;
|
||||
system = (data->rc5_bits & 0x1F000) >> 12;
|
||||
toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
|
||||
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
|
||||
xdata = (data->bits & 0x0003F) >> 0;
|
||||
command = (data->bits & 0x00FC0) >> 6;
|
||||
system = (data->bits & 0x1F000) >> 12;
|
||||
toggle = (data->bits & 0x20000) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 16 | command << 8 | xdata;
|
||||
|
||||
IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
|
||||
|
|
@ -230,10 +140,10 @@ again:
|
|||
} else {
|
||||
/* RC5 */
|
||||
u8 command, system;
|
||||
command = (data->rc5_bits & 0x0003F) >> 0;
|
||||
system = (data->rc5_bits & 0x007C0) >> 6;
|
||||
toggle = (data->rc5_bits & 0x00800) ? 1 : 0;
|
||||
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
|
||||
command = (data->bits & 0x0003F) >> 0;
|
||||
system = (data->bits & 0x007C0) >> 6;
|
||||
toggle = (data->bits & 0x00800) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 8 | command;
|
||||
|
||||
IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
|
||||
|
|
@ -252,54 +162,9 @@ out:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc5_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc5_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc5_handler = {
|
||||
.protocols = IR_TYPE_RC5,
|
||||
.decode = ir_rc5_decode,
|
||||
.raw_register = ir_rc5_register,
|
||||
.raw_unregister = ir_rc5_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc5_decode_init(void)
|
||||
|
|
|
|||
|
|
@ -36,10 +36,6 @@
|
|||
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
|
||||
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
|
||||
|
||||
/* Used to register rc6_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc6_mode {
|
||||
RC6_MODE_0,
|
||||
RC6_MODE_6A,
|
||||
|
|
@ -58,89 +54,8 @@ enum rc6_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum rc6_state state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
struct ir_raw_event prev_ev;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
static enum rc6_mode rc6_mode(struct rc6_dec *data)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "rc6_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
static enum rc6_mode rc6_mode(struct decoder_data *data) {
|
||||
switch (data->header & RC6_MODE_MASK) {
|
||||
case 0:
|
||||
return RC6_MODE_0;
|
||||
|
|
@ -162,16 +77,12 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
|
|||
*/
|
||||
static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct rc6_dec *data = &ir_dev->raw->rc6;
|
||||
u32 scancode;
|
||||
u8 toggle;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
|
@ -223,12 +134,11 @@ again:
|
|||
if (ev.pulse)
|
||||
data->header |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_HEADER_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_HEADER_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == RC6_HEADER_NBITS)
|
||||
|
|
@ -244,12 +154,11 @@ again:
|
|||
break;
|
||||
|
||||
data->toggle = ev.pulse;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_TOGGLE_END;
|
||||
return 0;
|
||||
|
||||
case STATE_TOGGLE_END:
|
||||
if (!is_transition(&ev, &data->prev_ev) ||
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
|
||||
!geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
|
@ -259,7 +168,6 @@ again:
|
|||
}
|
||||
|
||||
data->state = STATE_BODY_BIT_START;
|
||||
data->prev_ev = ev;
|
||||
decrease_duration(&ev, RC6_TOGGLE_END);
|
||||
data->count = 0;
|
||||
|
||||
|
|
@ -291,13 +199,11 @@ again:
|
|||
if (ev.pulse)
|
||||
data->body |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
|
||||
data->state = STATE_BODY_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BODY_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
|
@ -348,54 +254,9 @@ out:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc6_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc6_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc6_handler = {
|
||||
.protocols = IR_TYPE_RC6,
|
||||
.decode = ir_rc6_decode,
|
||||
.raw_register = ir_rc6_register,
|
||||
.raw_unregister = ir_rc6_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc6_decode_init(void)
|
||||
|
|
|
|||
|
|
@ -23,10 +23,6 @@
|
|||
#define SONY_BIT_SPACE (1 * SONY_UNIT)
|
||||
#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
|
||||
|
||||
/* Used to register sony_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum sony_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
|
@ -35,84 +31,6 @@ enum sony_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
int enabled:1;
|
||||
|
||||
/* State machine control */
|
||||
enum sony_state state;
|
||||
u32 sony_bits;
|
||||
unsigned count;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* get_decoder_data() - gets decoder data
|
||||
* @input_dev: input device
|
||||
*
|
||||
* Returns the struct decoder_data that corresponds to a device
|
||||
*/
|
||||
static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
||||
{
|
||||
struct decoder_data *data = NULL;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_for_each_entry(data, &decoder_list, list) {
|
||||
if (data->ir_dev == ir_dev)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&decoder_lock);
|
||||
return data;
|
||||
}
|
||||
|
||||
static ssize_t store_enabled(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *buf,
|
||||
size_t len)
|
||||
{
|
||||
unsigned long value;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (strict_strtoul(buf, 10, &value) || value > 1)
|
||||
return -EINVAL;
|
||||
|
||||
data->enabled = value;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_enabled(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
struct decoder_data *data = get_decoder_data(ir_dev);
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (data->enabled)
|
||||
return sprintf(buf, "1\n");
|
||||
else
|
||||
return sprintf(buf, "0\n");
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
|
||||
|
||||
static struct attribute *decoder_attributes[] = {
|
||||
&dev_attr_enabled.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group decoder_attribute_group = {
|
||||
.name = "sony_decoder",
|
||||
.attrs = decoder_attributes,
|
||||
};
|
||||
|
||||
/**
|
||||
* ir_sony_decode() - Decode one Sony pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
|
@ -122,16 +40,12 @@ static struct attribute_group decoder_attribute_group = {
|
|||
*/
|
||||
static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
||||
{
|
||||
struct decoder_data *data;
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct sony_dec *data = &ir_dev->raw->sony;
|
||||
u32 scancode;
|
||||
u8 device, subdevice, function;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!data->enabled)
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
|
||||
return 0;
|
||||
|
||||
if (IS_RESET(ev)) {
|
||||
|
|
@ -172,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!ev.pulse)
|
||||
break;
|
||||
|
||||
data->sony_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
|
||||
data->sony_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
|
@ -208,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
switch (data->count) {
|
||||
case 12:
|
||||
device = bitrev8((data->sony_bits << 3) & 0xF8);
|
||||
device = bitrev8((data->bits << 3) & 0xF8);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 4) & 0xFE);
|
||||
function = bitrev8((data->bits >> 4) & 0xFE);
|
||||
break;
|
||||
case 15:
|
||||
device = bitrev8((data->sony_bits >> 0) & 0xFF);
|
||||
device = bitrev8((data->bits >> 0) & 0xFF);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 7) & 0xFD);
|
||||
function = bitrev8((data->bits >> 7) & 0xFD);
|
||||
break;
|
||||
case 20:
|
||||
device = bitrev8((data->sony_bits >> 5) & 0xF8);
|
||||
subdevice = bitrev8((data->sony_bits >> 0) & 0xFF);
|
||||
function = bitrev8((data->sony_bits >> 12) & 0xFE);
|
||||
device = bitrev8((data->bits >> 5) & 0xF8);
|
||||
subdevice = bitrev8((data->bits >> 0) & 0xFF);
|
||||
function = bitrev8((data->bits >> 12) & 0xFE);
|
||||
break;
|
||||
default:
|
||||
IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
|
||||
|
|
@ -241,54 +155,9 @@ out:
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_sony_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
int rc;
|
||||
|
||||
rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
data->enabled = 1;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_sony_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
static struct decoder_data *data;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return 0;
|
||||
|
||||
sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler sony_handler = {
|
||||
.protocols = IR_TYPE_SONY,
|
||||
.decode = ir_sony_decode,
|
||||
.raw_register = ir_sony_register,
|
||||
.raw_unregister = ir_sony_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_sony_decode_init(void)
|
||||
|
|
|
|||
|
|
@ -33,125 +33,172 @@ static struct class ir_input_class = {
|
|||
.devnode = ir_devnode,
|
||||
};
|
||||
|
||||
static struct {
|
||||
u64 type;
|
||||
char *name;
|
||||
} proto_names[] = {
|
||||
{ IR_TYPE_UNKNOWN, "unknown" },
|
||||
{ IR_TYPE_RC5, "rc-5" },
|
||||
{ IR_TYPE_NEC, "nec" },
|
||||
{ IR_TYPE_RC6, "rc-6" },
|
||||
{ IR_TYPE_JVC, "jvc" },
|
||||
{ IR_TYPE_SONY, "sony" },
|
||||
{ IR_TYPE_LIRC, "lirc" },
|
||||
};
|
||||
|
||||
#define PROTO_NONE "none"
|
||||
|
||||
/**
|
||||
* show_protocol() - shows the current IR protocol
|
||||
* show_protocols() - shows the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the output buffer
|
||||
*
|
||||
* This routine is a callback routine for input read the IR protocol type.
|
||||
* it is trigged by reading /sys/class/rc/rc?/current_protocol.
|
||||
* It returns the protocol name, as understood by the driver.
|
||||
* This routine is a callback routine for input read the IR protocol type(s).
|
||||
* it is trigged by reading /sys/class/rc/rc?/protocols.
|
||||
* It returns the protocol names of supported protocols.
|
||||
* Enabled protocols are printed in brackets.
|
||||
*/
|
||||
static ssize_t show_protocol(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
static ssize_t show_protocols(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
char *s;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = ir_dev->rc_tab.ir_type;
|
||||
u64 allowed, enabled;
|
||||
char *tmp = buf;
|
||||
int i;
|
||||
|
||||
IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type);
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
enabled = ir_dev->rc_tab.ir_type;
|
||||
allowed = ir_dev->props->allowed_protos;
|
||||
} else {
|
||||
enabled = ir_dev->raw->enabled_protocols;
|
||||
allowed = ir_raw_get_allowed_protocols();
|
||||
}
|
||||
|
||||
/* FIXME: doesn't support multiple protocols at the same time */
|
||||
if (ir_type == IR_TYPE_UNKNOWN)
|
||||
s = "Unknown";
|
||||
else if (ir_type == IR_TYPE_RC5)
|
||||
s = "rc-5";
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
s = "nec";
|
||||
else if (ir_type == IR_TYPE_RC6)
|
||||
s = "rc6";
|
||||
else if (ir_type == IR_TYPE_JVC)
|
||||
s = "jvc";
|
||||
else if (ir_type == IR_TYPE_SONY)
|
||||
s = "sony";
|
||||
else
|
||||
s = "other";
|
||||
IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
|
||||
(long long)allowed,
|
||||
(long long)enabled);
|
||||
|
||||
return sprintf(buf, "%s\n", s);
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (allowed & enabled & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
|
||||
else if (allowed & proto_names[i].type)
|
||||
tmp += sprintf(tmp, "%s ", proto_names[i].name);
|
||||
}
|
||||
|
||||
if (tmp != buf)
|
||||
tmp--;
|
||||
*tmp = '\n';
|
||||
return tmp + 1 - buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* store_protocol() - shows the current IR protocol
|
||||
* store_protocols() - changes the current IR protocol(s)
|
||||
* @d: the device descriptor
|
||||
* @mattr: the device attribute struct (unused)
|
||||
* @buf: a pointer to the input buffer
|
||||
* @len: length of the input buffer
|
||||
*
|
||||
* This routine is a callback routine for changing the IR protocol type.
|
||||
* it is trigged by reading /sys/class/rc/rc?/current_protocol.
|
||||
* It changes the IR the protocol name, if the IR type is recognized
|
||||
* by the driver.
|
||||
* If an unknown protocol name is used, returns -EINVAL.
|
||||
* It is trigged by writing to /sys/class/rc/rc?/protocols.
|
||||
* Writing "+proto" will add a protocol to the list of enabled protocols.
|
||||
* Writing "-proto" will remove a protocol from the list of enabled protocols.
|
||||
* Writing "proto" will enable only "proto".
|
||||
* Writing "none" will disable all protocols.
|
||||
* Returns -EINVAL if an invalid protocol combination or unknown protocol name
|
||||
* is used, otherwise @len.
|
||||
*/
|
||||
static ssize_t store_protocol(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
static ssize_t store_protocols(struct device *d,
|
||||
struct device_attribute *mattr,
|
||||
const char *data,
|
||||
size_t len)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
u64 ir_type = 0;
|
||||
int rc = -EINVAL;
|
||||
bool enable, disable;
|
||||
const char *tmp;
|
||||
u64 type;
|
||||
u64 mask;
|
||||
int rc, i, count = 0;
|
||||
unsigned long flags;
|
||||
char *buf;
|
||||
|
||||
while ((buf = strsep((char **) &data, " \n")) != NULL) {
|
||||
if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
|
||||
ir_type |= IR_TYPE_RC5;
|
||||
if (!strcasecmp(buf, "nec"))
|
||||
ir_type |= IR_TYPE_NEC;
|
||||
if (!strcasecmp(buf, "jvc"))
|
||||
ir_type |= IR_TYPE_JVC;
|
||||
if (!strcasecmp(buf, "sony"))
|
||||
ir_type |= IR_TYPE_SONY;
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
type = ir_dev->rc_tab.ir_type;
|
||||
else
|
||||
type = ir_dev->raw->enabled_protocols;
|
||||
|
||||
while ((tmp = strsep((char **) &data, " \n")) != NULL) {
|
||||
if (!*tmp)
|
||||
break;
|
||||
|
||||
if (*tmp == '+') {
|
||||
enable = true;
|
||||
disable = false;
|
||||
tmp++;
|
||||
} else if (*tmp == '-') {
|
||||
enable = false;
|
||||
disable = true;
|
||||
tmp++;
|
||||
} else {
|
||||
enable = false;
|
||||
disable = false;
|
||||
}
|
||||
|
||||
if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
|
||||
tmp += sizeof(PROTO_NONE);
|
||||
mask = 0;
|
||||
count++;
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
|
||||
if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
|
||||
tmp += strlen(proto_names[i].name);
|
||||
mask = proto_names[i].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == ARRAY_SIZE(proto_names)) {
|
||||
IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
|
||||
return -EINVAL;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
type |= mask;
|
||||
else if (disable)
|
||||
type &= ~mask;
|
||||
else
|
||||
type = mask;
|
||||
}
|
||||
|
||||
if (!ir_type) {
|
||||
IR_dprintk(1, "Unknown protocol\n");
|
||||
if (!count) {
|
||||
IR_dprintk(1, "Protocol not specified\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ir_dev->props && ir_dev->props->change_protocol)
|
||||
if (ir_dev->props && ir_dev->props->change_protocol) {
|
||||
rc = ir_dev->props->change_protocol(ir_dev->props->priv,
|
||||
ir_type);
|
||||
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocol to %lld\n",
|
||||
(long long)ir_type);
|
||||
return -EINVAL;
|
||||
type);
|
||||
if (rc < 0) {
|
||||
IR_dprintk(1, "Error setting protocols to 0x%llx\n",
|
||||
(long long)type);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = ir_type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
|
||||
spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
|
||||
ir_dev->rc_tab.ir_type = type;
|
||||
spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
|
||||
} else {
|
||||
ir_dev->raw->enabled_protocols = type;
|
||||
}
|
||||
|
||||
IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
|
||||
(long long)ir_type);
|
||||
IR_dprintk(1, "Current protocol(s): 0x%llx\n",
|
||||
(long long)type);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t show_supported_protocols(struct device *d,
|
||||
struct device_attribute *mattr, char *buf)
|
||||
{
|
||||
char *orgbuf = buf;
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(d);
|
||||
|
||||
/* FIXME: doesn't support multiple protocols at the same time */
|
||||
if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
|
||||
buf += sprintf(buf, "unknown ");
|
||||
if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
|
||||
buf += sprintf(buf, "rc-5 ");
|
||||
if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
|
||||
buf += sprintf(buf, "nec ");
|
||||
if (buf == orgbuf)
|
||||
buf += sprintf(buf, "other ");
|
||||
|
||||
buf += sprintf(buf - 1, "\n");
|
||||
|
||||
return buf - orgbuf;
|
||||
}
|
||||
|
||||
#define ADD_HOTPLUG_VAR(fmt, val...) \
|
||||
do { \
|
||||
int err = add_uevent_var(env, fmt, val); \
|
||||
|
|
@ -159,7 +206,7 @@ static ssize_t show_supported_protocols(struct device *d,
|
|||
return err; \
|
||||
} while (0)
|
||||
|
||||
static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = dev_get_drvdata(device);
|
||||
|
||||
|
|
@ -174,34 +221,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
|
|||
/*
|
||||
* Static device attribute struct with the sysfs attributes for IR's
|
||||
*/
|
||||
static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
|
||||
show_protocol, store_protocol);
|
||||
static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
|
||||
show_protocols, store_protocols);
|
||||
|
||||
static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
|
||||
show_supported_protocols, NULL);
|
||||
|
||||
static struct attribute *ir_hw_dev_attrs[] = {
|
||||
&dev_attr_protocol.attr,
|
||||
&dev_attr_supported_protocols.attr,
|
||||
static struct attribute *rc_dev_attrs[] = {
|
||||
&dev_attr_protocols.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group ir_hw_dev_attr_grp = {
|
||||
.attrs = ir_hw_dev_attrs,
|
||||
static struct attribute_group rc_dev_attr_grp = {
|
||||
.attrs = rc_dev_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *ir_hw_dev_attr_groups[] = {
|
||||
&ir_hw_dev_attr_grp,
|
||||
static const struct attribute_group *rc_dev_attr_groups[] = {
|
||||
&rc_dev_attr_grp,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct device_type rc_dev_type = {
|
||||
.groups = ir_hw_dev_attr_groups,
|
||||
.uevent = ir_dev_uevent,
|
||||
};
|
||||
|
||||
static struct device_type ir_raw_dev_type = {
|
||||
.uevent = ir_dev_uevent,
|
||||
.groups = rc_dev_attr_groups,
|
||||
.uevent = rc_dev_uevent,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -221,11 +260,7 @@ int ir_register_class(struct input_dev *input_dev)
|
|||
if (unlikely(devno < 0))
|
||||
return devno;
|
||||
|
||||
if (ir_dev->props) {
|
||||
if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
} else
|
||||
ir_dev->dev.type = &ir_raw_dev_type;
|
||||
ir_dev->dev.type = &rc_dev_type;
|
||||
|
||||
ir_dev->dev.class = &ir_input_class;
|
||||
ir_dev->dev.parent = input_dev->dev.parent;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-budget-ci-old.o \
|
||||
rc-cinergy-1400.o \
|
||||
rc-cinergy.o \
|
||||
rc-dib0700-nec.o \
|
||||
rc-dib0700-rc5.o \
|
||||
rc-dm1105-nec.o \
|
||||
rc-dntv-live-dvb-t.o \
|
||||
rc-dntv-live-dvbt-pro.o \
|
||||
|
|
@ -37,6 +39,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-kaiomy.o \
|
||||
rc-kworld-315u.o \
|
||||
rc-kworld-plus-tv-analog.o \
|
||||
rc-lirc.o \
|
||||
rc-manli.o \
|
||||
rc-msi-tvanywhere.o \
|
||||
rc-msi-tvanywhere-plus.o \
|
||||
|
|
@ -57,6 +60,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
|
|||
rc-pv951.o \
|
||||
rc-rc5-hauppauge-new.o \
|
||||
rc-rc5-tv.o \
|
||||
rc-rc6-mce.o \
|
||||
rc-real-audio-220-32-keys.o \
|
||||
rc-tbs-nec.o \
|
||||
rc-terratec-cinergy-xs.o \
|
||||
|
|
|
|||
124
drivers/media/IR/keymaps/rc-dib0700-nec.c
Normal file
124
drivers/media/IR/keymaps/rc-dib0700-nec.c
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* TODO: This table is a real mess, as it merges RC codes from several
|
||||
* devices into a big table. It also has both RC-5 and NEC codes inside.
|
||||
* It should be broken into small tables, and the protocols should properly
|
||||
* be indentificated.
|
||||
*
|
||||
* The table were imported from dib0700_devices.c.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode dib0700_nec_table[] = {
|
||||
/* Key codes for the Pixelview SBTVD remote */
|
||||
{ 0x8613, KEY_MUTE },
|
||||
{ 0x8612, KEY_POWER },
|
||||
{ 0x8601, KEY_1 },
|
||||
{ 0x8602, KEY_2 },
|
||||
{ 0x8603, KEY_3 },
|
||||
{ 0x8604, KEY_4 },
|
||||
{ 0x8605, KEY_5 },
|
||||
{ 0x8606, KEY_6 },
|
||||
{ 0x8607, KEY_7 },
|
||||
{ 0x8608, KEY_8 },
|
||||
{ 0x8609, KEY_9 },
|
||||
{ 0x8600, KEY_0 },
|
||||
{ 0x860d, KEY_CHANNELUP },
|
||||
{ 0x8619, KEY_CHANNELDOWN },
|
||||
{ 0x8610, KEY_VOLUMEUP },
|
||||
{ 0x860c, KEY_VOLUMEDOWN },
|
||||
|
||||
{ 0x860a, KEY_CAMERA },
|
||||
{ 0x860b, KEY_ZOOM },
|
||||
{ 0x861b, KEY_BACKSPACE },
|
||||
{ 0x8615, KEY_ENTER },
|
||||
|
||||
{ 0x861d, KEY_UP },
|
||||
{ 0x861e, KEY_DOWN },
|
||||
{ 0x860e, KEY_LEFT },
|
||||
{ 0x860f, KEY_RIGHT },
|
||||
|
||||
{ 0x8618, KEY_RECORD },
|
||||
{ 0x861a, KEY_STOP },
|
||||
|
||||
/* Key codes for the EvolutePC TVWay+ remote */
|
||||
{ 0x7a00, KEY_MENU },
|
||||
{ 0x7a01, KEY_RECORD },
|
||||
{ 0x7a02, KEY_PLAY },
|
||||
{ 0x7a03, KEY_STOP },
|
||||
{ 0x7a10, KEY_CHANNELUP },
|
||||
{ 0x7a11, KEY_CHANNELDOWN },
|
||||
{ 0x7a12, KEY_VOLUMEUP },
|
||||
{ 0x7a13, KEY_VOLUMEDOWN },
|
||||
{ 0x7a40, KEY_POWER },
|
||||
{ 0x7a41, KEY_MUTE },
|
||||
|
||||
/* Key codes for the Elgato EyeTV Diversity silver remote */
|
||||
{ 0x4501, KEY_POWER },
|
||||
{ 0x4502, KEY_MUTE },
|
||||
{ 0x4503, KEY_1 },
|
||||
{ 0x4504, KEY_2 },
|
||||
{ 0x4505, KEY_3 },
|
||||
{ 0x4506, KEY_4 },
|
||||
{ 0x4507, KEY_5 },
|
||||
{ 0x4508, KEY_6 },
|
||||
{ 0x4509, KEY_7 },
|
||||
{ 0x450a, KEY_8 },
|
||||
{ 0x450b, KEY_9 },
|
||||
{ 0x450c, KEY_LAST },
|
||||
{ 0x450d, KEY_0 },
|
||||
{ 0x450e, KEY_ENTER },
|
||||
{ 0x450f, KEY_RED },
|
||||
{ 0x4510, KEY_CHANNELUP },
|
||||
{ 0x4511, KEY_GREEN },
|
||||
{ 0x4512, KEY_VOLUMEDOWN },
|
||||
{ 0x4513, KEY_OK },
|
||||
{ 0x4514, KEY_VOLUMEUP },
|
||||
{ 0x4515, KEY_YELLOW },
|
||||
{ 0x4516, KEY_CHANNELDOWN },
|
||||
{ 0x4517, KEY_BLUE },
|
||||
{ 0x4518, KEY_LEFT }, /* Skip backwards */
|
||||
{ 0x4519, KEY_PLAYPAUSE },
|
||||
{ 0x451a, KEY_RIGHT }, /* Skip forward */
|
||||
{ 0x451b, KEY_REWIND },
|
||||
{ 0x451c, KEY_L }, /* Live */
|
||||
{ 0x451d, KEY_FASTFORWARD },
|
||||
{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
|
||||
{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
|
||||
{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
|
||||
{ 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
|
||||
{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
|
||||
};
|
||||
|
||||
static struct rc_keymap dib0700_nec_map = {
|
||||
.map = {
|
||||
.scan = dib0700_nec_table,
|
||||
.size = ARRAY_SIZE(dib0700_nec_table),
|
||||
.ir_type = IR_TYPE_NEC,
|
||||
.name = RC_MAP_DIB0700_NEC_TABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map(void)
|
||||
{
|
||||
return ir_register_map(&dib0700_nec_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map(void)
|
||||
{
|
||||
ir_unregister_map(&dib0700_nec_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map)
|
||||
module_exit(exit_rc_map)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <[email protected]>");
|
||||
235
drivers/media/IR/keymaps/rc-dib0700-rc5.c
Normal file
235
drivers/media/IR/keymaps/rc-dib0700-rc5.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/* rc-dvb0700-big.c - Keytable for devices in dvb0700
|
||||
*
|
||||
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
|
||||
*
|
||||
* TODO: This table is a real mess, as it merges RC codes from several
|
||||
* devices into a big table. It also has both RC-5 and NEC codes inside.
|
||||
* It should be broken into small tables, and the protocols should properly
|
||||
* be indentificated.
|
||||
*
|
||||
* The table were imported from dib0700_devices.c.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode dib0700_rc5_table[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
|
||||
{ 0x0739, KEY_POWER },
|
||||
{ 0x0703, KEY_VOLUMEUP },
|
||||
{ 0x0709, KEY_VOLUMEDOWN },
|
||||
{ 0x0706, KEY_CHANNELUP },
|
||||
{ 0x070c, KEY_CHANNELDOWN },
|
||||
{ 0x070f, KEY_1 },
|
||||
{ 0x0715, KEY_2 },
|
||||
{ 0x0710, KEY_3 },
|
||||
{ 0x0718, KEY_4 },
|
||||
{ 0x071b, KEY_5 },
|
||||
{ 0x071e, KEY_6 },
|
||||
{ 0x0711, KEY_7 },
|
||||
{ 0x0721, KEY_8 },
|
||||
{ 0x0712, KEY_9 },
|
||||
{ 0x0727, KEY_0 },
|
||||
{ 0x0724, KEY_SCREEN }, /* 'Square' key */
|
||||
{ 0x072a, KEY_TEXT }, /* 'T' key */
|
||||
{ 0x072d, KEY_REWIND },
|
||||
{ 0x0730, KEY_PLAY },
|
||||
{ 0x0733, KEY_FASTFORWARD },
|
||||
{ 0x0736, KEY_RECORD },
|
||||
{ 0x073c, KEY_STOP },
|
||||
{ 0x073f, KEY_CANCEL }, /* '?' key */
|
||||
|
||||
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
|
||||
{ 0xeb01, KEY_POWER },
|
||||
{ 0xeb02, KEY_1 },
|
||||
{ 0xeb03, KEY_2 },
|
||||
{ 0xeb04, KEY_3 },
|
||||
{ 0xeb05, KEY_4 },
|
||||
{ 0xeb06, KEY_5 },
|
||||
{ 0xeb07, KEY_6 },
|
||||
{ 0xeb08, KEY_7 },
|
||||
{ 0xeb09, KEY_8 },
|
||||
{ 0xeb0a, KEY_9 },
|
||||
{ 0xeb0b, KEY_VIDEO },
|
||||
{ 0xeb0c, KEY_0 },
|
||||
{ 0xeb0d, KEY_REFRESH },
|
||||
{ 0xeb0f, KEY_EPG },
|
||||
{ 0xeb10, KEY_UP },
|
||||
{ 0xeb11, KEY_LEFT },
|
||||
{ 0xeb12, KEY_OK },
|
||||
{ 0xeb13, KEY_RIGHT },
|
||||
{ 0xeb14, KEY_DOWN },
|
||||
{ 0xeb16, KEY_INFO },
|
||||
{ 0xeb17, KEY_RED },
|
||||
{ 0xeb18, KEY_GREEN },
|
||||
{ 0xeb19, KEY_YELLOW },
|
||||
{ 0xeb1a, KEY_BLUE },
|
||||
{ 0xeb1b, KEY_CHANNELUP },
|
||||
{ 0xeb1c, KEY_VOLUMEUP },
|
||||
{ 0xeb1d, KEY_MUTE },
|
||||
{ 0xeb1e, KEY_VOLUMEDOWN },
|
||||
{ 0xeb1f, KEY_CHANNELDOWN },
|
||||
{ 0xeb40, KEY_PAUSE },
|
||||
{ 0xeb41, KEY_HOME },
|
||||
{ 0xeb42, KEY_MENU }, /* DVD Menu */
|
||||
{ 0xeb43, KEY_SUBTITLE },
|
||||
{ 0xeb44, KEY_TEXT }, /* Teletext */
|
||||
{ 0xeb45, KEY_DELETE },
|
||||
{ 0xeb46, KEY_TV },
|
||||
{ 0xeb47, KEY_DVD },
|
||||
{ 0xeb48, KEY_STOP },
|
||||
{ 0xeb49, KEY_VIDEO },
|
||||
{ 0xeb4a, KEY_AUDIO }, /* Music */
|
||||
{ 0xeb4b, KEY_SCREEN }, /* Pic */
|
||||
{ 0xeb4c, KEY_PLAY },
|
||||
{ 0xeb4d, KEY_BACK },
|
||||
{ 0xeb4e, KEY_REWIND },
|
||||
{ 0xeb4f, KEY_FASTFORWARD },
|
||||
{ 0xeb54, KEY_PREVIOUS },
|
||||
{ 0xeb58, KEY_RECORD },
|
||||
{ 0xeb5c, KEY_NEXT },
|
||||
|
||||
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
{ 0x1e03, KEY_3 },
|
||||
{ 0x1e04, KEY_4 },
|
||||
{ 0x1e05, KEY_5 },
|
||||
{ 0x1e06, KEY_6 },
|
||||
{ 0x1e07, KEY_7 },
|
||||
{ 0x1e08, KEY_8 },
|
||||
{ 0x1e09, KEY_9 },
|
||||
{ 0x1e0a, KEY_KPASTERISK },
|
||||
{ 0x1e0b, KEY_RED },
|
||||
{ 0x1e0c, KEY_RADIO },
|
||||
{ 0x1e0d, KEY_MENU },
|
||||
{ 0x1e0e, KEY_GRAVE }, /* # */
|
||||
{ 0x1e0f, KEY_MUTE },
|
||||
{ 0x1e10, KEY_VOLUMEUP },
|
||||
{ 0x1e11, KEY_VOLUMEDOWN },
|
||||
{ 0x1e12, KEY_CHANNEL },
|
||||
{ 0x1e14, KEY_UP },
|
||||
{ 0x1e15, KEY_DOWN },
|
||||
{ 0x1e16, KEY_LEFT },
|
||||
{ 0x1e17, KEY_RIGHT },
|
||||
{ 0x1e18, KEY_VIDEO },
|
||||
{ 0x1e19, KEY_AUDIO },
|
||||
{ 0x1e1a, KEY_MEDIA },
|
||||
{ 0x1e1b, KEY_EPG },
|
||||
{ 0x1e1c, KEY_TV },
|
||||
{ 0x1e1e, KEY_NEXT },
|
||||
{ 0x1e1f, KEY_BACK },
|
||||
{ 0x1e20, KEY_CHANNELUP },
|
||||
{ 0x1e21, KEY_CHANNELDOWN },
|
||||
{ 0x1e24, KEY_LAST }, /* Skip backwards */
|
||||
{ 0x1e25, KEY_OK },
|
||||
{ 0x1e29, KEY_BLUE},
|
||||
{ 0x1e2e, KEY_GREEN },
|
||||
{ 0x1e30, KEY_PAUSE },
|
||||
{ 0x1e32, KEY_REWIND },
|
||||
{ 0x1e34, KEY_FASTFORWARD },
|
||||
{ 0x1e35, KEY_PLAY },
|
||||
{ 0x1e36, KEY_STOP },
|
||||
{ 0x1e37, KEY_RECORD },
|
||||
{ 0x1e38, KEY_YELLOW },
|
||||
{ 0x1e3b, KEY_GOTO },
|
||||
{ 0x1e3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Leadtek Winfast DTV Dongle */
|
||||
{ 0x0042, KEY_POWER },
|
||||
{ 0x077c, KEY_TUNER },
|
||||
{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
|
||||
{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
|
||||
{ 0x0f71, KEY_DOT }, /* frequency */
|
||||
{ 0x0743, KEY_0 },
|
||||
{ 0x0c41, KEY_1 },
|
||||
{ 0x0443, KEY_2 },
|
||||
{ 0x0b7f, KEY_3 },
|
||||
{ 0x0e41, KEY_4 },
|
||||
{ 0x0643, KEY_5 },
|
||||
{ 0x097f, KEY_6 },
|
||||
{ 0x0d7e, KEY_7 },
|
||||
{ 0x057c, KEY_8 },
|
||||
{ 0x0a40, KEY_9 },
|
||||
{ 0x0e4e, KEY_CLEAR },
|
||||
{ 0x047c, KEY_CHANNEL }, /* show channel number */
|
||||
{ 0x0f41, KEY_LAST }, /* recall */
|
||||
{ 0x0342, KEY_MUTE },
|
||||
{ 0x064c, KEY_RESERVED }, /* PIP button*/
|
||||
{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
|
||||
{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
|
||||
{ 0x0b70, KEY_RECORD },
|
||||
{ 0x037d, KEY_VOLUMEUP },
|
||||
{ 0x017d, KEY_VOLUMEDOWN },
|
||||
{ 0x0242, KEY_CHANNELUP },
|
||||
{ 0x007d, KEY_CHANNELDOWN },
|
||||
|
||||
/* Key codes for Nova-TD "credit card" remote control. */
|
||||
{ 0x1d00, KEY_0 },
|
||||
{ 0x1d01, KEY_1 },
|
||||
{ 0x1d02, KEY_2 },
|
||||
{ 0x1d03, KEY_3 },
|
||||
{ 0x1d04, KEY_4 },
|
||||
{ 0x1d05, KEY_5 },
|
||||
{ 0x1d06, KEY_6 },
|
||||
{ 0x1d07, KEY_7 },
|
||||
{ 0x1d08, KEY_8 },
|
||||
{ 0x1d09, KEY_9 },
|
||||
{ 0x1d0a, KEY_TEXT },
|
||||
{ 0x1d0d, KEY_MENU },
|
||||
{ 0x1d0f, KEY_MUTE },
|
||||
{ 0x1d10, KEY_VOLUMEUP },
|
||||
{ 0x1d11, KEY_VOLUMEDOWN },
|
||||
{ 0x1d12, KEY_CHANNEL },
|
||||
{ 0x1d14, KEY_UP },
|
||||
{ 0x1d15, KEY_DOWN },
|
||||
{ 0x1d16, KEY_LEFT },
|
||||
{ 0x1d17, KEY_RIGHT },
|
||||
{ 0x1d1c, KEY_TV },
|
||||
{ 0x1d1e, KEY_NEXT },
|
||||
{ 0x1d1f, KEY_BACK },
|
||||
{ 0x1d20, KEY_CHANNELUP },
|
||||
{ 0x1d21, KEY_CHANNELDOWN },
|
||||
{ 0x1d24, KEY_LAST },
|
||||
{ 0x1d25, KEY_OK },
|
||||
{ 0x1d30, KEY_PAUSE },
|
||||
{ 0x1d32, KEY_REWIND },
|
||||
{ 0x1d34, KEY_FASTFORWARD },
|
||||
{ 0x1d35, KEY_PLAY },
|
||||
{ 0x1d36, KEY_STOP },
|
||||
{ 0x1d37, KEY_RECORD },
|
||||
{ 0x1d3b, KEY_GOTO },
|
||||
{ 0x1d3d, KEY_POWER },
|
||||
};
|
||||
|
||||
static struct rc_keymap dib0700_rc5_map = {
|
||||
.map = {
|
||||
.scan = dib0700_rc5_table,
|
||||
.size = ARRAY_SIZE(dib0700_rc5_table),
|
||||
.ir_type = IR_TYPE_RC5,
|
||||
.name = RC_MAP_DIB0700_RC5_TABLE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map(void)
|
||||
{
|
||||
return ir_register_map(&dib0700_rc5_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map(void)
|
||||
{
|
||||
ir_unregister_map(&dib0700_rc5_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map)
|
||||
module_exit(exit_rc_map)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Mauro Carvalho Chehab <[email protected]>");
|
||||
41
drivers/media/IR/keymaps/rc-lirc.c
Normal file
41
drivers/media/IR/keymaps/rc-lirc.c
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/* rc-lirc.c - Empty dummy keytable, for use when its preferred to pass
|
||||
* all raw IR data to the lirc userspace decoder.
|
||||
*
|
||||
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/ir-core.h>
|
||||
|
||||
static struct ir_scancode lirc[] = {
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct rc_keymap lirc_map = {
|
||||
.map = {
|
||||
.scan = lirc,
|
||||
.size = ARRAY_SIZE(lirc),
|
||||
.ir_type = IR_TYPE_LIRC,
|
||||
.name = RC_MAP_LIRC,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_lirc(void)
|
||||
{
|
||||
return ir_register_map(&lirc_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_lirc(void)
|
||||
{
|
||||
ir_unregister_map(&lirc_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_lirc)
|
||||
module_exit(exit_rc_map_lirc)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <[email protected]>");
|
||||
105
drivers/media/IR/keymaps/rc-rc6-mce.c
Normal file
105
drivers/media/IR/keymaps/rc-rc6-mce.c
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
/* rc-rc6-mce.c - Keytable for Windows Media Center RC-6 remotes for use
|
||||
* with the Media Center Edition eHome Infrared Transceiver.
|
||||
*
|
||||
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <media/rc-map.h>
|
||||
|
||||
static struct ir_scancode rc6_mce[] = {
|
||||
{ 0x800f0415, KEY_REWIND },
|
||||
{ 0x800f0414, KEY_FASTFORWARD },
|
||||
{ 0x800f041b, KEY_PREVIOUS },
|
||||
{ 0x800f041a, KEY_NEXT },
|
||||
|
||||
{ 0x800f0416, KEY_PLAY },
|
||||
{ 0x800f0418, KEY_PAUSE },
|
||||
{ 0x800f0419, KEY_STOP },
|
||||
{ 0x800f0417, KEY_RECORD },
|
||||
|
||||
{ 0x800f041e, KEY_UP },
|
||||
{ 0x800f041f, KEY_DOWN },
|
||||
{ 0x800f0420, KEY_LEFT },
|
||||
{ 0x800f0421, KEY_RIGHT },
|
||||
|
||||
{ 0x800f040b, KEY_ENTER },
|
||||
{ 0x800f0422, KEY_OK },
|
||||
{ 0x800f0423, KEY_EXIT },
|
||||
{ 0x800f040a, KEY_DELETE },
|
||||
|
||||
{ 0x800f040e, KEY_MUTE },
|
||||
{ 0x800f0410, KEY_VOLUMEUP },
|
||||
{ 0x800f0411, KEY_VOLUMEDOWN },
|
||||
{ 0x800f0412, KEY_CHANNELUP },
|
||||
{ 0x800f0413, KEY_CHANNELDOWN },
|
||||
|
||||
{ 0x800f0401, KEY_NUMERIC_1 },
|
||||
{ 0x800f0402, KEY_NUMERIC_2 },
|
||||
{ 0x800f0403, KEY_NUMERIC_3 },
|
||||
{ 0x800f0404, KEY_NUMERIC_4 },
|
||||
{ 0x800f0405, KEY_NUMERIC_5 },
|
||||
{ 0x800f0406, KEY_NUMERIC_6 },
|
||||
{ 0x800f0407, KEY_NUMERIC_7 },
|
||||
{ 0x800f0408, KEY_NUMERIC_8 },
|
||||
{ 0x800f0409, KEY_NUMERIC_9 },
|
||||
{ 0x800f0400, KEY_NUMERIC_0 },
|
||||
|
||||
{ 0x800f041d, KEY_NUMERIC_STAR },
|
||||
{ 0x800f041c, KEY_NUMERIC_POUND },
|
||||
|
||||
{ 0x800f0446, KEY_TV },
|
||||
{ 0x800f0447, KEY_AUDIO }, /* My Music */
|
||||
{ 0x800f0448, KEY_PVR }, /* RecordedTV */
|
||||
{ 0x800f0449, KEY_CAMERA },
|
||||
{ 0x800f044a, KEY_VIDEO },
|
||||
{ 0x800f0424, KEY_DVD },
|
||||
{ 0x800f0425, KEY_TUNER }, /* LiveTV */
|
||||
{ 0x800f0450, KEY_RADIO },
|
||||
|
||||
{ 0x800f044c, KEY_LANGUAGE },
|
||||
{ 0x800f0427, KEY_ZOOM }, /* Aspect */
|
||||
|
||||
{ 0x800f045b, KEY_RED },
|
||||
{ 0x800f045c, KEY_GREEN },
|
||||
{ 0x800f045d, KEY_YELLOW },
|
||||
{ 0x800f045e, KEY_BLUE },
|
||||
|
||||
{ 0x800f040f, KEY_INFO },
|
||||
{ 0x800f0426, KEY_EPG }, /* Guide */
|
||||
{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
|
||||
{ 0x800f044d, KEY_TITLE },
|
||||
|
||||
{ 0x800f040c, KEY_POWER },
|
||||
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
|
||||
|
||||
};
|
||||
|
||||
static struct rc_keymap rc6_mce_map = {
|
||||
.map = {
|
||||
.scan = rc6_mce,
|
||||
.size = ARRAY_SIZE(rc6_mce),
|
||||
.ir_type = IR_TYPE_RC6,
|
||||
.name = RC_MAP_RC6_MCE,
|
||||
}
|
||||
};
|
||||
|
||||
static int __init init_rc_map_rc6_mce(void)
|
||||
{
|
||||
return ir_register_map(&rc6_mce_map);
|
||||
}
|
||||
|
||||
static void __exit exit_rc_map_rc6_mce(void)
|
||||
{
|
||||
ir_unregister_map(&rc6_mce_map);
|
||||
}
|
||||
|
||||
module_init(init_rc_map_rc6_mce)
|
||||
module_exit(exit_rc_map_rc6_mce)
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Jarod Wilson <[email protected]>");
|
||||
764
drivers/media/IR/lirc_dev.c
Normal file
764
drivers/media/IR/lirc_dev.c
Normal file
|
|
@ -0,0 +1,764 @@
|
|||
/*
|
||||
* LIRC base driver
|
||||
*
|
||||
* by Artur Lipowski <alipowski@interia.pl>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/cdev.h>
|
||||
|
||||
#include <media/lirc.h>
|
||||
#include <media/lirc_dev.h>
|
||||
|
||||
static int debug;
|
||||
|
||||
#define IRCTL_DEV_NAME "BaseRemoteCtl"
|
||||
#define NOPLUG -1
|
||||
#define LOGHEAD "lirc_dev (%s[%d]): "
|
||||
|
||||
static dev_t lirc_base_dev;
|
||||
|
||||
struct irctl {
|
||||
struct lirc_driver d;
|
||||
int attached;
|
||||
int open;
|
||||
|
||||
struct mutex irctl_lock;
|
||||
struct lirc_buffer *buf;
|
||||
unsigned int chunk_size;
|
||||
|
||||
struct task_struct *task;
|
||||
long jiffies_to_wait;
|
||||
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(lirc_dev_lock);
|
||||
|
||||
static struct irctl *irctls[MAX_IRCTL_DEVICES];
|
||||
|
||||
/* Only used for sysfs but defined to void otherwise */
|
||||
static struct class *lirc_class;
|
||||
|
||||
/* helper function
|
||||
* initializes the irctl structure
|
||||
*/
|
||||
static void init_irctl(struct irctl *ir)
|
||||
{
|
||||
dev_dbg(ir->d.dev, LOGHEAD "initializing irctl\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
mutex_init(&ir->irctl_lock);
|
||||
ir->d.minor = NOPLUG;
|
||||
}
|
||||
|
||||
static void cleanup(struct irctl *ir)
|
||||
{
|
||||
dev_dbg(ir->d.dev, LOGHEAD "cleaning up\n", ir->d.name, ir->d.minor);
|
||||
|
||||
device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
|
||||
|
||||
if (ir->buf != ir->d.rbuf) {
|
||||
lirc_buffer_free(ir->buf);
|
||||
kfree(ir->buf);
|
||||
}
|
||||
ir->buf = NULL;
|
||||
}
|
||||
|
||||
/* helper function
|
||||
* reads key codes from driver and puts them into buffer
|
||||
* returns 0 on success
|
||||
*/
|
||||
static int add_to_buf(struct irctl *ir)
|
||||
{
|
||||
if (ir->d.add_to_buf) {
|
||||
int res = -ENODATA;
|
||||
int got_data = 0;
|
||||
|
||||
/*
|
||||
* service the device as long as it is returning
|
||||
* data and we have space
|
||||
*/
|
||||
get_data:
|
||||
res = ir->d.add_to_buf(ir->d.data, ir->buf);
|
||||
if (res == 0) {
|
||||
got_data++;
|
||||
goto get_data;
|
||||
}
|
||||
|
||||
if (res == -ENODEV)
|
||||
kthread_stop(ir->task);
|
||||
|
||||
return got_data ? 0 : res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* main function of the polling thread
|
||||
*/
|
||||
static int lirc_thread(void *irctl)
|
||||
{
|
||||
struct irctl *ir = irctl;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll thread started\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
do {
|
||||
if (ir->open) {
|
||||
if (ir->jiffies_to_wait) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule_timeout(ir->jiffies_to_wait);
|
||||
}
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
if (!add_to_buf(ir))
|
||||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
} else {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
}
|
||||
} while (!kthread_should_stop());
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll thread ended\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static struct file_operations fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = lirc_dev_fop_read,
|
||||
.write = lirc_dev_fop_write,
|
||||
.poll = lirc_dev_fop_poll,
|
||||
.unlocked_ioctl = lirc_dev_fop_ioctl,
|
||||
.open = lirc_dev_fop_open,
|
||||
.release = lirc_dev_fop_close,
|
||||
};
|
||||
|
||||
static int lirc_cdev_add(struct irctl *ir)
|
||||
{
|
||||
int retval;
|
||||
struct lirc_driver *d = &ir->d;
|
||||
|
||||
if (d->fops) {
|
||||
cdev_init(&ir->cdev, d->fops);
|
||||
ir->cdev.owner = d->owner;
|
||||
} else {
|
||||
cdev_init(&ir->cdev, &fops);
|
||||
ir->cdev.owner = THIS_MODULE;
|
||||
}
|
||||
kobject_set_name(&ir->cdev.kobj, "lirc%d", d->minor);
|
||||
|
||||
retval = cdev_add(&ir->cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
if (retval)
|
||||
kobject_put(&ir->cdev.kobj);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int lirc_register_driver(struct lirc_driver *d)
|
||||
{
|
||||
struct irctl *ir;
|
||||
int minor;
|
||||
int bytes_in_key;
|
||||
unsigned int chunk_size;
|
||||
unsigned int buffer_size;
|
||||
int err;
|
||||
|
||||
if (!d) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_register_driver: "
|
||||
"driver pointer must be not NULL!\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (MAX_IRCTL_DEVICES <= d->minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"\"minor\" must be between 0 and %d (%d)!\n",
|
||||
MAX_IRCTL_DEVICES-1, d->minor);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (1 > d->code_length || (BUFLEN * 8) < d->code_length) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"code length in bits for minor (%d) "
|
||||
"must be less than %d!\n",
|
||||
d->minor, BUFLEN * 8);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_dbg(d->dev, "lirc_dev: lirc_register_driver: sample_rate: %d\n",
|
||||
d->sample_rate);
|
||||
if (d->sample_rate) {
|
||||
if (2 > d->sample_rate || HZ < d->sample_rate) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"sample_rate must be between 2 and %d!\n", HZ);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
if (!d->add_to_buf) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"add_to_buf cannot be NULL when "
|
||||
"sample_rate is set\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
} else if (!(d->fops && d->fops->read) && !d->rbuf) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"fops->read and rbuf cannot all be NULL!\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
} else if (!d->rbuf) {
|
||||
if (!(d->fops && d->fops->read && d->fops->poll &&
|
||||
d->fops->unlocked_ioctl)) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"neither read, poll nor unlocked_ioctl can be NULL!\n");
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
minor = d->minor;
|
||||
|
||||
if (minor < 0) {
|
||||
/* find first free slot for driver */
|
||||
for (minor = 0; minor < MAX_IRCTL_DEVICES; minor++)
|
||||
if (!irctls[minor])
|
||||
break;
|
||||
if (MAX_IRCTL_DEVICES == minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"no free slots for drivers!\n");
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
} else if (irctls[minor]) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"minor (%d) just registered!\n", minor);
|
||||
err = -EBUSY;
|
||||
goto out_lock;
|
||||
}
|
||||
|
||||
ir = kzalloc(sizeof(struct irctl), GFP_KERNEL);
|
||||
if (!ir) {
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
init_irctl(ir);
|
||||
irctls[minor] = ir;
|
||||
d->minor = minor;
|
||||
|
||||
if (d->sample_rate) {
|
||||
ir->jiffies_to_wait = HZ / d->sample_rate;
|
||||
} else {
|
||||
/* it means - wait for external event in task queue */
|
||||
ir->jiffies_to_wait = 0;
|
||||
}
|
||||
|
||||
/* some safety check 8-) */
|
||||
d->name[sizeof(d->name)-1] = '\0';
|
||||
|
||||
bytes_in_key = BITS_TO_LONGS(d->code_length) +
|
||||
(d->code_length % 8 ? 1 : 0);
|
||||
buffer_size = d->buffer_size ? d->buffer_size : BUFLEN / bytes_in_key;
|
||||
chunk_size = d->chunk_size ? d->chunk_size : bytes_in_key;
|
||||
|
||||
if (d->rbuf) {
|
||||
ir->buf = d->rbuf;
|
||||
} else {
|
||||
ir->buf = kmalloc(sizeof(struct lirc_buffer), GFP_KERNEL);
|
||||
if (!ir->buf) {
|
||||
err = -ENOMEM;
|
||||
goto out_lock;
|
||||
}
|
||||
err = lirc_buffer_init(ir->buf, chunk_size, buffer_size);
|
||||
if (err) {
|
||||
kfree(ir->buf);
|
||||
goto out_lock;
|
||||
}
|
||||
}
|
||||
ir->chunk_size = ir->buf->chunk_size;
|
||||
|
||||
if (d->features == 0)
|
||||
d->features = LIRC_CAN_REC_LIRCCODE;
|
||||
|
||||
ir->d = *d;
|
||||
ir->d.minor = minor;
|
||||
|
||||
device_create(lirc_class, ir->d.dev,
|
||||
MKDEV(MAJOR(lirc_base_dev), ir->d.minor), NULL,
|
||||
"lirc%u", ir->d.minor);
|
||||
|
||||
if (d->sample_rate) {
|
||||
/* try to fire up polling thread */
|
||||
ir->task = kthread_run(lirc_thread, (void *)ir, "lirc_dev");
|
||||
if (IS_ERR(ir->task)) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"cannot run poll thread for minor = %d\n",
|
||||
d->minor);
|
||||
err = -ECHILD;
|
||||
goto out_sysfs;
|
||||
}
|
||||
}
|
||||
|
||||
err = lirc_cdev_add(ir);
|
||||
if (err)
|
||||
goto out_sysfs;
|
||||
|
||||
ir->attached = 1;
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
dev_info(ir->d.dev, "lirc_dev: driver %s registered at minor = %d\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
return minor;
|
||||
|
||||
out_sysfs:
|
||||
device_destroy(lirc_class, MKDEV(MAJOR(lirc_base_dev), ir->d.minor));
|
||||
out_lock:
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_register_driver);
|
||||
|
||||
int lirc_unregister_driver(int minor)
|
||||
{
|
||||
struct irctl *ir;
|
||||
|
||||
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
|
||||
"\"minor (%d)\" must be between 0 and %d!\n",
|
||||
minor, MAX_IRCTL_DEVICES-1);
|
||||
return -EBADRQC;
|
||||
}
|
||||
|
||||
ir = irctls[minor];
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
if (ir->d.minor != minor) {
|
||||
printk(KERN_ERR "lirc_dev: lirc_unregister_driver: "
|
||||
"minor (%d) device not registered!", minor);
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* end up polling thread */
|
||||
if (ir->task)
|
||||
kthread_stop(ir->task);
|
||||
|
||||
dev_dbg(ir->d.dev, "lirc_dev: driver %s unregistered from minor = %d\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
|
||||
ir->attached = 0;
|
||||
if (ir->open) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "releasing opened driver\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
wake_up_interruptible(&ir->buf->wait_poll);
|
||||
mutex_lock(&ir->irctl_lock);
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
cdev_del(&ir->cdev);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
cdev_del(&ir->cdev);
|
||||
kfree(ir);
|
||||
irctls[minor] = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_unregister_driver);
|
||||
|
||||
int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir;
|
||||
int retval = 0;
|
||||
|
||||
if (iminor(inode) >= MAX_IRCTL_DEVICES) {
|
||||
printk(KERN_WARNING "lirc_dev [%d]: open result = -ENODEV\n",
|
||||
iminor(inode));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (mutex_lock_interruptible(&lirc_dev_lock))
|
||||
return -ERESTARTSYS;
|
||||
|
||||
ir = irctls[iminor(inode)];
|
||||
if (!ir) {
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
file->private_data = ir;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "open called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (ir->d.minor == NOPLUG) {
|
||||
retval = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ir->open) {
|
||||
retval = -EBUSY;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (try_module_get(ir->d.owner)) {
|
||||
++ir->open;
|
||||
retval = ir->d.set_use_inc(ir->d.data);
|
||||
|
||||
if (retval) {
|
||||
module_put(ir->d.owner);
|
||||
--ir->open;
|
||||
} else {
|
||||
lirc_buffer_clear(ir->buf);
|
||||
}
|
||||
if (ir->task)
|
||||
wake_up_process(ir->task);
|
||||
}
|
||||
|
||||
error:
|
||||
if (ir)
|
||||
dev_dbg(ir->d.dev, LOGHEAD "open result = %d\n",
|
||||
ir->d.name, ir->d.minor, retval);
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_open);
|
||||
|
||||
int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(inode)];
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
|
||||
|
||||
--ir->open;
|
||||
if (ir->attached) {
|
||||
ir->d.set_use_dec(ir->d.data);
|
||||
module_put(ir->d.owner);
|
||||
} else {
|
||||
cleanup(ir);
|
||||
irctls[ir->d.minor] = NULL;
|
||||
kfree(ir);
|
||||
}
|
||||
|
||||
mutex_unlock(&lirc_dev_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_close);
|
||||
|
||||
unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
unsigned int ret;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached) {
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return POLLERR;
|
||||
}
|
||||
|
||||
poll_wait(file, &ir->buf->wait_poll, wait);
|
||||
|
||||
if (ir->buf)
|
||||
if (lirc_buffer_empty(ir->buf))
|
||||
ret = 0;
|
||||
else
|
||||
ret = POLLIN | POLLRDNORM;
|
||||
else
|
||||
ret = POLLERR;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "poll result = %d\n",
|
||||
ir->d.name, ir->d.minor, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_poll);
|
||||
|
||||
long lirc_dev_fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
unsigned long mode;
|
||||
int result = 0;
|
||||
struct irctl *ir = file->private_data;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl called (0x%x)\n",
|
||||
ir->d.name, ir->d.minor, cmd);
|
||||
|
||||
if (ir->d.minor == NOPLUG || !ir->attached) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl result = -ENODEV\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&ir->irctl_lock);
|
||||
|
||||
switch (cmd) {
|
||||
case LIRC_GET_FEATURES:
|
||||
result = put_user(ir->d.features, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(LIRC_REC2MODE
|
||||
(ir->d.features & LIRC_CAN_REC_MASK),
|
||||
(unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_SET_REC_MODE:
|
||||
if (!(ir->d.features & LIRC_CAN_REC_MASK)) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = get_user(mode, (unsigned long *)arg);
|
||||
if (!result && !(LIRC_MODE2REC(mode) & ir->d.features))
|
||||
result = -EINVAL;
|
||||
/*
|
||||
* FIXME: We should actually set the mode somehow but
|
||||
* for now, lirc_serial doesn't support mode changing either
|
||||
*/
|
||||
break;
|
||||
case LIRC_GET_LENGTH:
|
||||
result = put_user(ir->d.code_length, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_MIN_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
ir->d.min_timeout == 0) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.min_timeout, (unsigned long *)arg);
|
||||
break;
|
||||
case LIRC_GET_MAX_TIMEOUT:
|
||||
if (!(ir->d.features & LIRC_CAN_SET_REC_TIMEOUT) ||
|
||||
ir->d.max_timeout == 0) {
|
||||
result = -ENOSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
result = put_user(ir->d.max_timeout, (unsigned long *)arg);
|
||||
break;
|
||||
default:
|
||||
result = -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "ioctl result = %d\n",
|
||||
ir->d.name, ir->d.minor, result);
|
||||
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_ioctl);
|
||||
|
||||
ssize_t lirc_dev_fop_read(struct file *file,
|
||||
char *buffer,
|
||||
size_t length,
|
||||
loff_t *ppos)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
unsigned char buf[ir->chunk_size];
|
||||
int ret = 0, written = 0;
|
||||
DECLARE_WAITQUEUE(wait, current);
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (mutex_lock_interruptible(&ir->irctl_lock))
|
||||
return -ERESTARTSYS;
|
||||
if (!ir->attached) {
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (length % ir->chunk_size) {
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
|
||||
ir->d.name, ir->d.minor);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* we add ourselves to the task queue before buffer check
|
||||
* to avoid losing scan code (in case when queue is awaken somewhere
|
||||
* between while condition checking and scheduling)
|
||||
*/
|
||||
add_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
/*
|
||||
* while we didn't provide 'length' bytes, device is opened in blocking
|
||||
* mode and 'copy_to_user' is happy, wait for data.
|
||||
*/
|
||||
while (written < length && ret == 0) {
|
||||
if (lirc_buffer_empty(ir->buf)) {
|
||||
/* According to the read(2) man page, 'written' can be
|
||||
* returned as less than 'length', instead of blocking
|
||||
* again, returning -EWOULDBLOCK, or returning
|
||||
* -ERESTARTSYS */
|
||||
if (written)
|
||||
break;
|
||||
if (file->f_flags & O_NONBLOCK) {
|
||||
ret = -EWOULDBLOCK;
|
||||
break;
|
||||
}
|
||||
if (signal_pending(current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
schedule();
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (mutex_lock_interruptible(&ir->irctl_lock)) {
|
||||
ret = -ERESTARTSYS;
|
||||
remove_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
goto out_unlocked;
|
||||
}
|
||||
|
||||
if (!ir->attached) {
|
||||
ret = -ENODEV;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
lirc_buffer_read(ir->buf, buf);
|
||||
ret = copy_to_user((void *)buffer+written, buf,
|
||||
ir->buf->chunk_size);
|
||||
written += ir->buf->chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
remove_wait_queue(&ir->buf->wait_poll, &wait);
|
||||
set_current_state(TASK_RUNNING);
|
||||
mutex_unlock(&ir->irctl_lock);
|
||||
|
||||
out_unlocked:
|
||||
dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
|
||||
ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
|
||||
|
||||
return ret ? ret : written;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_read);
|
||||
|
||||
void *lirc_get_pdata(struct file *file)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
if (file && file->f_dentry && file->f_dentry->d_inode &&
|
||||
file->f_dentry->d_inode->i_rdev) {
|
||||
struct irctl *ir;
|
||||
ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
data = ir->d.data;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_get_pdata);
|
||||
|
||||
|
||||
ssize_t lirc_dev_fop_write(struct file *file, const char *buffer,
|
||||
size_t length, loff_t *ppos)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(file->f_dentry->d_inode)];
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "write called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
if (!ir->attached)
|
||||
return -ENODEV;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(lirc_dev_fop_write);
|
||||
|
||||
|
||||
static int __init lirc_dev_init(void)
|
||||
{
|
||||
int retval;
|
||||
|
||||
lirc_class = class_create(THIS_MODULE, "lirc");
|
||||
if (IS_ERR(lirc_class)) {
|
||||
retval = PTR_ERR(lirc_class);
|
||||
printk(KERN_ERR "lirc_dev: class_create failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
retval = alloc_chrdev_region(&lirc_base_dev, 0, MAX_IRCTL_DEVICES,
|
||||
IRCTL_DEV_NAME);
|
||||
if (retval) {
|
||||
class_destroy(lirc_class);
|
||||
printk(KERN_ERR "lirc_dev: alloc_chrdev_region failed\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_INFO "lirc_dev: IR Remote Control driver registered, "
|
||||
"major %d \n", MAJOR(lirc_base_dev));
|
||||
|
||||
error:
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void __exit lirc_dev_exit(void)
|
||||
{
|
||||
class_destroy(lirc_class);
|
||||
unregister_chrdev_region(lirc_base_dev, MAX_IRCTL_DEVICES);
|
||||
printk(KERN_INFO "lirc_dev: module unloaded\n");
|
||||
}
|
||||
|
||||
module_init(lirc_dev_init);
|
||||
module_exit(lirc_dev_exit);
|
||||
|
||||
MODULE_DESCRIPTION("LIRC base driver module");
|
||||
MODULE_AUTHOR("Artur Lipowski");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(debug, "Enable debugging messages");
|
||||
1143
drivers/media/IR/mceusb.c
Normal file
1143
drivers/media/IR/mceusb.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -57,7 +57,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
|
|||
BUG_ON(in_interrupt());
|
||||
|
||||
videobuf_waiton(&buf->vb,0,0);
|
||||
videobuf_dma_unmap(q, dma);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ static void vbi_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
|
||||
static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
|
||||
u32 arbtr_ctrl = saa7146_read(dev, PCI_BT_V1);
|
||||
int ret = 0;
|
||||
|
|
@ -437,7 +437,7 @@ static int vbi_open(struct saa7146_dev *dev, struct file *file)
|
|||
|
||||
static void vbi_close(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
DEB_VBI(("dev:%p, fh:%p\n",dev,fh));
|
||||
|
||||
|
|
|
|||
|
|
@ -1370,7 +1370,7 @@ static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
|
|||
|
||||
static int video_open(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_format *sfmt;
|
||||
|
||||
fh->video_fmt.width = 384;
|
||||
|
|
@ -1394,7 +1394,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
|
|||
|
||||
static void video_close(struct saa7146_dev *dev, struct file *file)
|
||||
{
|
||||
struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
|
||||
struct saa7146_fh *fh = file->private_data;
|
||||
struct saa7146_vv *vv = dev->vv_data;
|
||||
struct videobuf_queue *q = &fh->video_q;
|
||||
int err;
|
||||
|
|
|
|||
|
|
@ -1249,7 +1249,7 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
|||
struct tda18271_config *cfg)
|
||||
{
|
||||
struct tda18271_priv *priv = NULL;
|
||||
int instance;
|
||||
int instance, ret;
|
||||
|
||||
mutex_lock(&tda18271_list_mutex);
|
||||
|
||||
|
|
@ -1268,10 +1268,12 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
|
|||
priv->cal_initialized = false;
|
||||
mutex_init(&priv->lock);
|
||||
|
||||
if (tda_fail(tda18271_get_id(fe)))
|
||||
ret = tda18271_get_id(fe);
|
||||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
||||
if (tda_fail(tda18271_assign_map_layout(fe)))
|
||||
ret = tda18271_assign_map_layout(fe);
|
||||
if (tda_fail(ret))
|
||||
goto fail;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
|
|
|||
|
|
@ -546,14 +546,11 @@ static int simple_set_tv_freq(struct dvb_frontend *fe,
|
|||
struct tuner_simple_priv *priv = fe->tuner_priv;
|
||||
u8 config, cb;
|
||||
u16 div;
|
||||
struct tunertype *tun;
|
||||
u8 buffer[4];
|
||||
int rc, IFPCoff, i;
|
||||
enum param_type desired_type;
|
||||
struct tuner_params *t_params;
|
||||
|
||||
tun = priv->tun;
|
||||
|
||||
/* IFPCoff = Video Intermediate Frequency - Vif:
|
||||
940 =16*58.75 NTSC/J (Japan)
|
||||
732 =16*45.75 M/N STD
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ static int xc_send_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
|
|||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* This routine is never used because the only time we read data from the
|
||||
i2c bus is when we read registers, and we want that to be an atomic i2c
|
||||
transaction in case we are on a multi-master bus */
|
||||
|
|
@ -231,6 +232,27 @@ static int xc_read_i2c_data(struct xc5000_priv *priv, u8 *buf, int len)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
|
||||
{
|
||||
u8 buf[2] = { reg >> 8, reg & 0xff };
|
||||
u8 bval[2] = { 0, 0 };
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = 0, .buf = &buf[0], .len = 2 },
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "xc5000: I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
*val = (bval[0] << 8) | bval[1];
|
||||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static void xc_wait(int wait_ms)
|
||||
{
|
||||
|
|
@ -275,20 +297,14 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
|
|||
if (result == XC_RESULT_SUCCESS) {
|
||||
/* wait for busy flag to clear */
|
||||
while ((WatchDogTimer > 0) && (result == XC_RESULT_SUCCESS)) {
|
||||
buf[0] = 0;
|
||||
buf[1] = XREG_BUSY;
|
||||
|
||||
result = xc_send_i2c_data(priv, buf, 2);
|
||||
result = xc5000_readreg(priv, XREG_BUSY, (u16 *)buf);
|
||||
if (result == XC_RESULT_SUCCESS) {
|
||||
result = xc_read_i2c_data(priv, buf, 2);
|
||||
if (result == XC_RESULT_SUCCESS) {
|
||||
if ((buf[0] == 0) && (buf[1] == 0)) {
|
||||
/* busy flag cleared */
|
||||
if ((buf[0] == 0) && (buf[1] == 0)) {
|
||||
/* busy flag cleared */
|
||||
break;
|
||||
} else {
|
||||
xc_wait(5); /* wait 5 ms */
|
||||
WatchDogTimer--;
|
||||
}
|
||||
} else {
|
||||
xc_wait(5); /* wait 5 ms */
|
||||
WatchDogTimer--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -526,25 +542,6 @@ static int xc_tune_channel(struct xc5000_priv *priv, u32 freq_hz, int mode)
|
|||
return found;
|
||||
}
|
||||
|
||||
static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val)
|
||||
{
|
||||
u8 buf[2] = { reg >> 8, reg & 0xff };
|
||||
u8 bval[2] = { 0, 0 };
|
||||
struct i2c_msg msg[2] = {
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = 0, .buf = &buf[0], .len = 2 },
|
||||
{ .addr = priv->i2c_props.addr,
|
||||
.flags = I2C_M_RD, .buf = &bval[0], .len = 2 },
|
||||
};
|
||||
|
||||
if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) {
|
||||
printk(KERN_WARNING "xc5000: I2C read failed\n");
|
||||
return -EREMOTEIO;
|
||||
}
|
||||
|
||||
*val = (bval[0] << 8) | bval[1];
|
||||
return XC_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
static int xc5000_fwupload(struct dvb_frontend *fe)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -565,7 +565,7 @@ static long dst_ca_ioctl(struct file *file, unsigned int cmd, unsigned long ioct
|
|||
int result = 0;
|
||||
|
||||
lock_kernel();
|
||||
dvbdev = (struct dvb_device *)file->private_data;
|
||||
dvbdev = file->private_data;
|
||||
state = (struct dst_state *)dvbdev->priv;
|
||||
p_ca_message = kmalloc(sizeof (struct ca_msg), GFP_KERNEL);
|
||||
p_ca_slot_info = kmalloc(sizeof (struct ca_slot_info), GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ static int dvb_dvr_release(struct inode *inode, struct file *file)
|
|||
}
|
||||
/* TODO */
|
||||
dvbdev->users--;
|
||||
if(dvbdev->users==-1 && dmxdev->exit==1) {
|
||||
if (dvbdev->users == 1 && dmxdev->exit == 1) {
|
||||
fops_put(file->f_op);
|
||||
file->f_op = NULL;
|
||||
mutex_unlock(&dmxdev->mutex);
|
||||
|
|
|
|||
|
|
@ -1318,8 +1318,11 @@ static ssize_t dvb_ca_en50221_io_write(struct file *file,
|
|||
|
||||
fragbuf[0] = connection_id;
|
||||
fragbuf[1] = ((fragpos + fraglen) < count) ? 0x80 : 0x00;
|
||||
if ((status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen)) != 0)
|
||||
status = copy_from_user(fragbuf + 2, buf + fragpos, fraglen);
|
||||
if (status) {
|
||||
status = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
timeout = jiffies + HZ / 2;
|
||||
written = 0;
|
||||
|
|
@ -1494,8 +1497,11 @@ static ssize_t dvb_ca_en50221_io_read(struct file *file, char __user * buf,
|
|||
|
||||
hdr[0] = slot;
|
||||
hdr[1] = connection_id;
|
||||
if ((status = copy_to_user(buf, hdr, 2)) != 0)
|
||||
status = copy_to_user(buf, hdr, 2);
|
||||
if (status) {
|
||||
status = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
status = pktlen;
|
||||
|
||||
exit:
|
||||
|
|
|
|||
|
|
@ -1130,13 +1130,9 @@ static int dvbdmx_write(struct dmx_demux *demux, const char __user *buf, size_t
|
|||
if ((!demux->frontend) || (demux->frontend->source != DMX_MEMORY_FE))
|
||||
return -EINVAL;
|
||||
|
||||
p = kmalloc(count, GFP_USER);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(p, buf, count)) {
|
||||
kfree(p);
|
||||
return -EFAULT;
|
||||
}
|
||||
p = memdup_user(buf, count);
|
||||
if (IS_ERR(p))
|
||||
return PTR_ERR(p);
|
||||
if (mutex_lock_interruptible(&dvbdemux->mutex)) {
|
||||
kfree(p);
|
||||
return -ERESTARTSYS;
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ static void dvb_frontend_swzigzag(struct dvb_frontend *fe)
|
|||
if ((fepriv->state & FESTATE_SEARCHING_FAST) || (fepriv->state & FESTATE_RETUNE)) {
|
||||
fepriv->delay = fepriv->min_delay;
|
||||
|
||||
/* peform a tune */
|
||||
/* perform a tune */
|
||||
retval = dvb_frontend_swzigzag_autotune(fe,
|
||||
fepriv->check_wrapped);
|
||||
if (retval < 0) {
|
||||
|
|
@ -791,7 +791,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void dvb_frontend_get_frequeny_limits(struct dvb_frontend *fe,
|
||||
static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
|
||||
u32 *freq_min, u32 *freq_max)
|
||||
{
|
||||
*freq_min = max(fe->ops.info.frequency_min, fe->ops.tuner_ops.info.frequency_min);
|
||||
|
|
@ -815,7 +815,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
|
|||
u32 freq_max;
|
||||
|
||||
/* range check: frequency */
|
||||
dvb_frontend_get_frequeny_limits(fe, &freq_min, &freq_max);
|
||||
dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
|
||||
if ((freq_min && parms->frequency < freq_min) ||
|
||||
(freq_max && parms->frequency > freq_max)) {
|
||||
printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
|
||||
|
|
@ -1627,7 +1627,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
case FE_GET_INFO: {
|
||||
struct dvb_frontend_info* info = parg;
|
||||
memcpy(info, &fe->ops.info, sizeof(struct dvb_frontend_info));
|
||||
dvb_frontend_get_frequeny_limits(fe, &info->frequency_min, &info->frequency_max);
|
||||
dvb_frontend_get_frequency_limits(fe, &info->frequency_min, &info->frequency_max);
|
||||
|
||||
/* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
|
||||
* do it, it is done for it. */
|
||||
|
|
@ -1726,7 +1726,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
|||
* (stv0299 for instance) take longer than 8msec to
|
||||
* respond to a set_voltage command. Those switches
|
||||
* need custom routines to switch properly. For all
|
||||
* other frontends, the following shoule work ok.
|
||||
* other frontends, the following should work ok.
|
||||
* Dish network legacy switches (as used by Dish500)
|
||||
* are controlled by sending 9-bit command words
|
||||
* spaced 8msec apart.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ static int a800_identify_state(struct usb_device *udev, struct dvb_usb_device_pr
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_a800_table[] = {
|
||||
static struct ir_scancode ir_codes_a800_table[] = {
|
||||
{ 0x0201, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0200, KEY_POWER }, /* POWER */
|
||||
{ 0x0205, KEY_1 }, /* 1 */
|
||||
|
|
@ -146,10 +146,12 @@ static struct dvb_usb_device_properties a800_properties = {
|
|||
.power_ctrl = a800_power_ctrl,
|
||||
.identify_state = a800_identify_state,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_a800_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table),
|
||||
.rc_query = a800_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_a800_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_a800_table),
|
||||
.rc_query = a800_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug,
|
|||
|
||||
#define deb_decode(args...) dprintk(dvb_usb_af9005_remote_debug,0x01,args)
|
||||
|
||||
struct dvb_usb_rc_key ir_codes_af9005_table[] = {
|
||||
struct ir_scancode ir_codes_af9005_table[] = {
|
||||
|
||||
{0x01b7, KEY_POWER},
|
||||
{0x01a7, KEY_VOLUMEUP},
|
||||
|
|
@ -133,7 +133,7 @@ int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len, u32 * event,
|
|||
for (i = 0; i < ir_codes_af9005_table_size; i++) {
|
||||
if (rc5_custom(&ir_codes_af9005_table[i]) == cust
|
||||
&& rc5_data(&ir_codes_af9005_table[i]) == dat) {
|
||||
*event = ir_codes_af9005_table[i].event;
|
||||
*event = ir_codes_af9005_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
deb_decode
|
||||
("key pressed, event %x\n", *event);
|
||||
|
|
|
|||
|
|
@ -54,50 +54,6 @@ struct af9005_device_state {
|
|||
int led_state;
|
||||
};
|
||||
|
||||
static int af9005_usb_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen,
|
||||
u8 *rbuf, u16 rlen, int delay_ms)
|
||||
{
|
||||
int actlen, ret = -ENOMEM;
|
||||
|
||||
if (wbuf == NULL || wlen == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if ((ret = mutex_lock_interruptible(&d->usb_mutex)))
|
||||
return ret;
|
||||
|
||||
deb_xfer(">>> ");
|
||||
debug_dump(wbuf, wlen, deb_xfer);
|
||||
|
||||
ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
|
||||
2), wbuf, wlen,
|
||||
&actlen, 2000);
|
||||
|
||||
if (ret)
|
||||
err("bulk message failed: %d (%d/%d)", ret, wlen, actlen);
|
||||
else
|
||||
ret = actlen != wlen ? -1 : 0;
|
||||
|
||||
/* an answer is expected, and no error before */
|
||||
if (!ret && rbuf && rlen) {
|
||||
if (delay_ms)
|
||||
msleep(delay_ms);
|
||||
|
||||
ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
|
||||
0x01), rbuf,
|
||||
rlen, &actlen, 2000);
|
||||
|
||||
if (ret)
|
||||
err("recv bulk message failed: %d", ret);
|
||||
else {
|
||||
deb_xfer("<<< ");
|
||||
debug_dump(rbuf, actlen, deb_xfer);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&d->usb_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
|
||||
int readwrite, int type, u8 * values, int len)
|
||||
{
|
||||
|
|
@ -146,7 +102,7 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,
|
|||
obuf[8] = values[0];
|
||||
obuf[7] = command;
|
||||
|
||||
ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -534,7 +490,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,
|
|||
buf[6] = wlen;
|
||||
for (i = 0; i < wlen; i++)
|
||||
buf[7 + i] = wbuf[i];
|
||||
ret = af9005_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
|
||||
ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ibuf[2] != 0x27) {
|
||||
|
|
@ -581,7 +537,7 @@ int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,
|
|||
|
||||
obuf[6] = len;
|
||||
obuf[7] = address;
|
||||
ret = af9005_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (ibuf[2] != 0x2b) {
|
||||
|
|
@ -882,7 +838,7 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)
|
|||
obuf[2] = 0x40; /* read remote */
|
||||
obuf[3] = 1; /* rest of packet length */
|
||||
obuf[4] = st->sequence++; /* sequence number */
|
||||
ret = af9005_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
|
||||
ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0);
|
||||
if (ret) {
|
||||
err("rc query failed");
|
||||
return ret;
|
||||
|
|
@ -1069,10 +1025,15 @@ static struct dvb_usb_device_properties af9005_properties = {
|
|||
|
||||
.i2c_algo = &af9005_i2c_algo,
|
||||
|
||||
.rc_interval = 200,
|
||||
.rc_key_map = NULL,
|
||||
.rc_key_map_size = 0,
|
||||
.rc_query = af9005_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 200,
|
||||
.rc_key_map = NULL,
|
||||
.rc_key_map_size = 0,
|
||||
.rc_query = af9005_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 2,
|
||||
.generic_bulk_ctrl_endpoint_response = 1,
|
||||
|
||||
.num_device_descs = 3,
|
||||
.devices = {
|
||||
|
|
@ -1113,10 +1074,10 @@ static int __init af9005_usb_module_init(void)
|
|||
rc_keys_size = symbol_request(ir_codes_af9005_table_size);
|
||||
if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
|
||||
err("af9005_rc_decode function not found, disabling remote");
|
||||
af9005_properties.rc_query = NULL;
|
||||
af9005_properties.rc.legacy.rc_query = NULL;
|
||||
} else {
|
||||
af9005_properties.rc_key_map = rc_keys;
|
||||
af9005_properties.rc_key_map_size = *rc_keys_size;
|
||||
af9005_properties.rc.legacy.rc_key_map = rc_keys;
|
||||
af9005_properties.rc.legacy.rc_key_map_size = *rc_keys_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3490,7 +3490,7 @@ extern u8 regmask[8];
|
|||
/* remote control decoder */
|
||||
extern int af9005_rc_decode(struct dvb_usb_device *d, u8 * data, int len,
|
||||
u32 * event, int *state);
|
||||
extern struct dvb_usb_rc_key ir_codes_af9005_table[];
|
||||
extern struct ir_scancode ir_codes_af9005_table[];
|
||||
extern int ir_codes_af9005_table_size;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -735,7 +735,7 @@ error:
|
|||
|
||||
struct af9015_setup {
|
||||
unsigned int id;
|
||||
struct dvb_usb_rc_key *rc_key_map;
|
||||
struct ir_scancode *rc_key_map;
|
||||
unsigned int rc_key_map_size;
|
||||
u8 *ir_table;
|
||||
unsigned int ir_table_size;
|
||||
|
|
@ -847,8 +847,8 @@ static void af9015_set_remote_config(struct usb_device *udev,
|
|||
}
|
||||
|
||||
if (table) {
|
||||
props->rc_key_map = table->rc_key_map;
|
||||
props->rc_key_map_size = table->rc_key_map_size;
|
||||
props->rc.legacy.rc_key_map = table->rc_key_map;
|
||||
props->rc.legacy.rc_key_map_size = table->rc_key_map_size;
|
||||
af9015_config.ir_table = table->ir_table;
|
||||
af9015_config.ir_table_size = table->ir_table_size;
|
||||
}
|
||||
|
|
@ -878,8 +878,8 @@ static int af9015_read_config(struct usb_device *udev)
|
|||
deb_info("%s: IR mode:%d\n", __func__, val);
|
||||
for (i = 0; i < af9015_properties_count; i++) {
|
||||
if (val == AF9015_IR_MODE_DISABLED) {
|
||||
af9015_properties[i].rc_key_map = NULL;
|
||||
af9015_properties[i].rc_key_map_size = 0;
|
||||
af9015_properties[i].rc.legacy.rc_key_map = NULL;
|
||||
af9015_properties[i].rc.legacy.rc_key_map_size = 0;
|
||||
} else
|
||||
af9015_set_remote_config(udev, &af9015_properties[i]);
|
||||
}
|
||||
|
|
@ -1063,7 +1063,7 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
{
|
||||
u8 buf[8];
|
||||
struct req_t req = {GET_IR_CODE, 0, 0, 0, 0, sizeof(buf), buf};
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i, ret;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
|
@ -1075,10 +1075,10 @@ static int af9015_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (!buf[1] && rc5_custom(&keymap[i]) == buf[0] &&
|
||||
rc5_data(&keymap[i]) == buf[2]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
break;
|
||||
}
|
||||
|
|
@ -1299,6 +1299,7 @@ static struct usb_device_id af9015_usb_table[] = {
|
|||
{USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
|
||||
/* 30 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
|
||||
{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
|
||||
{USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
|
||||
{0},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, af9015_usb_table);
|
||||
|
|
@ -1353,8 +1354,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
|
|
@ -1460,8 +1463,10 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
|
|
@ -1567,12 +1572,14 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
|
||||
.identify_state = af9015_identify_state,
|
||||
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
.rc.legacy = {
|
||||
.rc_query = af9015_rc_query,
|
||||
.rc_interval = 150,
|
||||
},
|
||||
|
||||
.i2c_algo = &af9015_i2c_algo,
|
||||
|
||||
.num_device_descs = 8, /* max 9 */
|
||||
.num_device_descs = 9, /* max 9 */
|
||||
.devices = {
|
||||
{
|
||||
.name = "AverMedia AVerTV Volar GPS 805 (A805)",
|
||||
|
|
@ -1617,6 +1624,11 @@ static struct dvb_usb_device_properties af9015_properties[] = {
|
|||
.cold_ids = {&af9015_usb_table[30], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
{
|
||||
.name = "AverMedia AVerTV Volar M (A815Mac)",
|
||||
.cold_ids = {&af9015_usb_table[32], NULL},
|
||||
.warm_ids = {NULL},
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ enum af9015_remote {
|
|||
|
||||
/* LeadTek - Y04G0051 */
|
||||
/* Leadtek WinFast DTV Dongle Gold */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_leadtek[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_leadtek[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
|
@ -227,7 +227,7 @@ static u8 af9015_ir_table_leadtek[] = {
|
|||
};
|
||||
|
||||
/* TwinHan AzureWave AD-TU700(704J) */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_twinhan[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_twinhan[] = {
|
||||
{ 0x053f, KEY_POWER },
|
||||
{ 0x0019, KEY_FAVORITES }, /* Favorite List */
|
||||
{ 0x0004, KEY_TEXT }, /* Teletext */
|
||||
|
|
@ -338,7 +338,7 @@ static u8 af9015_ir_table_twinhan[] = {
|
|||
};
|
||||
|
||||
/* A-Link DTU(m) */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_a_link[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_a_link[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
|
@ -381,7 +381,7 @@ static u8 af9015_ir_table_a_link[] = {
|
|||
};
|
||||
|
||||
/* MSI DIGIVOX mini II V3.0 */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_msi[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_msi[] = {
|
||||
{ 0x001e, KEY_1 },
|
||||
{ 0x001f, KEY_2 },
|
||||
{ 0x0020, KEY_3 },
|
||||
|
|
@ -424,7 +424,7 @@ static u8 af9015_ir_table_msi[] = {
|
|||
};
|
||||
|
||||
/* MYGICTV U718 */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_mygictv[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_mygictv[] = {
|
||||
{ 0x003d, KEY_SWITCHVIDEOMODE },
|
||||
/* TV / AV */
|
||||
{ 0x0545, KEY_POWER },
|
||||
|
|
@ -550,7 +550,7 @@ static u8 af9015_ir_table_kworld[] = {
|
|||
};
|
||||
|
||||
/* AverMedia Volar X */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_avermedia[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_avermedia[] = {
|
||||
{ 0x053d, KEY_PROG1 }, /* SOURCE */
|
||||
{ 0x0512, KEY_POWER }, /* POWER */
|
||||
{ 0x051e, KEY_1 }, /* 1 */
|
||||
|
|
@ -656,7 +656,7 @@ static u8 af9015_ir_table_avermedia_ks[] = {
|
|||
};
|
||||
|
||||
/* Digittrade DVB-T USB Stick */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_digittrade[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_digittrade[] = {
|
||||
{ 0x010f, KEY_LAST }, /* RETURN */
|
||||
{ 0x0517, KEY_TEXT }, /* TELETEXT */
|
||||
{ 0x0108, KEY_EPG }, /* EPG */
|
||||
|
|
@ -719,7 +719,7 @@ static u8 af9015_ir_table_digittrade[] = {
|
|||
};
|
||||
|
||||
/* TREKSTOR DVB-T USB Stick */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_trekstor[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_trekstor[] = {
|
||||
{ 0x0704, KEY_AGAIN }, /* Home */
|
||||
{ 0x0705, KEY_MUTE }, /* Mute */
|
||||
{ 0x0706, KEY_UP }, /* Up */
|
||||
|
|
@ -782,7 +782,7 @@ static u8 af9015_ir_table_trekstor[] = {
|
|||
};
|
||||
|
||||
/* MSI DIGIVOX mini III */
|
||||
static struct dvb_usb_rc_key ir_codes_af9015_table_msi_digivox_iii[] = {
|
||||
static struct ir_scancode ir_codes_af9015_table_msi_digivox_iii[] = {
|
||||
{ 0x0713, KEY_POWER }, /* [red power button] */
|
||||
{ 0x073b, KEY_VIDEO }, /* Source */
|
||||
{ 0x073e, KEY_ZOOM }, /* Zoom */
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
u8 buf[] = {CMD_GET_IR_CODE};
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[2];
|
||||
int i, ret;
|
||||
|
||||
|
|
@ -388,10 +388,10 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[0] &&
|
||||
rc5_data(&keymap[i]) == ircode[1]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -399,7 +399,7 @@ static int anysee_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_anysee_table[] = {
|
||||
static struct ir_scancode ir_codes_anysee_table[] = {
|
||||
{ 0x0100, KEY_0 },
|
||||
{ 0x0101, KEY_1 },
|
||||
{ 0x0102, KEY_2 },
|
||||
|
|
@ -463,6 +463,11 @@ static int anysee_probe(struct usb_interface *intf,
|
|||
if (intf->num_altsetting < 1)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Anysee is always warm (its USB-bridge, Cypress FX2, uploads
|
||||
* firmware from eeprom). If dvb_usb_device_init() succeeds that
|
||||
* means d is a valid pointer.
|
||||
*/
|
||||
ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
|
||||
adapter_nr);
|
||||
if (ret)
|
||||
|
|
@ -479,10 +484,7 @@ static int anysee_probe(struct usb_interface *intf,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (d)
|
||||
ret = anysee_init(d);
|
||||
|
||||
return ret;
|
||||
return anysee_init(d);
|
||||
}
|
||||
|
||||
static struct usb_device_id anysee_table[] = {
|
||||
|
|
@ -518,10 +520,12 @@ static struct dvb_usb_device_properties anysee_properties = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_key_map = ir_codes_anysee_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_anysee_table),
|
||||
.rc_query = anysee_rc_query,
|
||||
.rc_interval = 200, /* windows driver uses 500ms */
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_anysee_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_anysee_table),
|
||||
.rc_query = anysee_rc_query,
|
||||
.rc_interval = 200, /* windows driver uses 500ms */
|
||||
},
|
||||
|
||||
.i2c_algo = &anysee_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -386,7 +386,7 @@ static int az6027_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct dvb_usb_rc_key ir_codes_az6027_table[] = {
|
||||
static struct ir_scancode ir_codes_az6027_table[] = {
|
||||
{ 0x01, KEY_1 },
|
||||
{ 0x02, KEY_2 },
|
||||
};
|
||||
|
|
@ -1125,10 +1125,13 @@ static struct dvb_usb_device_properties az6027_properties = {
|
|||
.power_ctrl = az6027_power_ctrl,
|
||||
.read_mac_address = az6027_read_mac_addr,
|
||||
*/
|
||||
.rc_key_map = ir_codes_az6027_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = az6027_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_az6027_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_az6027_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = az6027_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &az6027_i2c_algo,
|
||||
|
||||
.num_device_descs = 5,
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_cinergyt2_table[] = {
|
||||
static struct ir_scancode ir_codes_cinergyt2_table[] = {
|
||||
{ 0x0401, KEY_POWER },
|
||||
{ 0x0402, KEY_1 },
|
||||
{ 0x0403, KEY_2 },
|
||||
|
|
@ -217,10 +217,12 @@ static struct dvb_usb_device_properties cinergyt2_properties = {
|
|||
|
||||
.power_ctrl = cinergyt2_power_ctrl,
|
||||
|
||||
.rc_interval = 50,
|
||||
.rc_key_map = ir_codes_cinergyt2_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table),
|
||||
.rc_query = cinergyt2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 50,
|
||||
.rc_key_map = ir_codes_cinergyt2_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_cinergyt2_table),
|
||||
.rc_query = cinergyt2_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 1,
|
||||
|
||||
|
|
|
|||
|
|
@ -385,7 +385,7 @@ static int cxusb_d680_dmb_streaming_ctrl(
|
|||
|
||||
static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
|
||||
|
|
@ -394,10 +394,10 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[2] &&
|
||||
rc5_data(&keymap[i]) == ircode[3]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
|
@ -410,7 +410,7 @@ static int cxusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[4];
|
||||
int i;
|
||||
struct i2c_msg msg = { .addr = 0x6b, .flags = I2C_M_RD,
|
||||
|
|
@ -422,10 +422,10 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_i2c_xfer(&d->i2c_adap, &msg, 1) != 1)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[1] &&
|
||||
rc5_data(&keymap[i]) == ircode[2]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
|
@ -438,7 +438,7 @@ static int cxusb_bluebird2_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
||||
int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
u8 ircode[2];
|
||||
int i;
|
||||
|
||||
|
|
@ -448,10 +448,10 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
if (cxusb_ctrl_msg(d, 0x10, NULL, 0, ircode, 2) < 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == ircode[0] &&
|
||||
rc5_data(&keymap[i]) == ircode[1]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
|
||||
return 0;
|
||||
|
|
@ -461,7 +461,7 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
|
||||
static struct ir_scancode ir_codes_dvico_mce_table[] = {
|
||||
{ 0xfe02, KEY_TV },
|
||||
{ 0xfe0e, KEY_MP3 },
|
||||
{ 0xfe1a, KEY_DVD },
|
||||
|
|
@ -509,7 +509,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_mce_table[] = {
|
|||
{ 0xfe4e, KEY_POWER },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
|
||||
static struct ir_scancode ir_codes_dvico_portable_table[] = {
|
||||
{ 0xfc02, KEY_SETUP }, /* Profile */
|
||||
{ 0xfc43, KEY_POWER2 },
|
||||
{ 0xfc06, KEY_EPG },
|
||||
|
|
@ -548,7 +548,7 @@ static struct dvb_usb_rc_key ir_codes_dvico_portable_table[] = {
|
|||
{ 0xfc00, KEY_UNKNOWN }, /* HD */
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_d680_dmb_table[] = {
|
||||
static struct ir_scancode ir_codes_d680_dmb_table[] = {
|
||||
{ 0x0038, KEY_UNKNOWN }, /* TV/AV */
|
||||
{ 0x080c, KEY_ZOOM },
|
||||
{ 0x0800, KEY_0 },
|
||||
|
|
@ -923,7 +923,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
return -EIO;
|
||||
|
||||
/* try to determine if there is no IR decoder on the I2C bus */
|
||||
for (i = 0; adap->dev->props.rc_key_map != NULL && i < 5; i++) {
|
||||
for (i = 0; adap->dev->props.rc.legacy.rc_key_map != NULL && i < 5; i++) {
|
||||
msleep(20);
|
||||
if (cxusb_i2c_xfer(&adap->dev->i2c_adap, &msg, 1) != 1)
|
||||
goto no_IR;
|
||||
|
|
@ -931,7 +931,7 @@ static int cxusb_dualdig4_frontend_attach(struct dvb_usb_adapter *adap)
|
|||
continue;
|
||||
if (ircode[2] + ircode[3] != 0xff) {
|
||||
no_IR:
|
||||
adap->dev->props.rc_key_map = NULL;
|
||||
adap->dev->props.rc.legacy.rc_key_map = NULL;
|
||||
info("No IR receiver detected on this device.");
|
||||
break;
|
||||
}
|
||||
|
|
@ -1451,10 +1451,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgh064f_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -1502,10 +1504,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dee1601_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 150,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 150,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -1561,10 +1565,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
.num_device_descs = 1,
|
||||
|
|
@ -1611,10 +1617,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dtt7579_properties = {
|
|||
|
||||
.i2c_algo = &cxusb_i2c_algo,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -1660,10 +1668,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_dualdig4_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
@ -1708,10 +1718,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_bluebird2_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
@ -1758,10 +1770,12 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_portable_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_portable_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
@ -1849,10 +1863,12 @@ struct dvb_usb_device_properties cxusb_bluebird_dualdig4_rev2_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_dvico_mce_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dvico_mce_table),
|
||||
.rc_query = cxusb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
@ -1897,10 +1913,12 @@ static struct dvb_usb_device_properties cxusb_d680_dmb_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
@ -1946,10 +1964,12 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
|
|||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_d680_dmb_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_d680_dmb_table),
|
||||
.rc_query = cxusb_d680_dmb_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ extern int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff);
|
|||
extern struct i2c_algorithm dib0700_i2c_algo;
|
||||
extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
|
||||
struct dvb_usb_device_description **desc, int *cold);
|
||||
extern int dib0700_change_protocol(void *priv, u64 ir_type);
|
||||
|
||||
extern int dib0700_device_count;
|
||||
extern int dvb_usb_dib0700_ir_proto;
|
||||
|
|
|
|||
|
|
@ -13,10 +13,6 @@ int dvb_usb_dib0700_debug;
|
|||
module_param_named(debug,dvb_usb_dib0700_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=fw,4=fwdata,8=data (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
int dvb_usb_dib0700_ir_proto = 1;
|
||||
module_param(dvb_usb_dib0700_ir_proto, int, 0644);
|
||||
MODULE_PARM_DESC(dvb_usb_dib0700_ir_proto, "set ir protocol (0=NEC, 1=RC5 (default), 2=RC6).");
|
||||
|
||||
static int nb_packet_buffer_size = 21;
|
||||
module_param(nb_packet_buffer_size, int, 0644);
|
||||
MODULE_PARM_DESC(nb_packet_buffer_size,
|
||||
|
|
@ -53,7 +49,7 @@ static int dib0700_ctrl_wr(struct dvb_usb_device *d, u8 *tx, u8 txlen)
|
|||
int status;
|
||||
|
||||
deb_data(">>> ");
|
||||
debug_dump(tx,txlen,deb_data);
|
||||
debug_dump(tx, txlen, deb_data);
|
||||
|
||||
status = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev,0),
|
||||
tx[0], USB_TYPE_VENDOR | USB_DIR_OUT, 0, 0, tx, txlen,
|
||||
|
|
@ -98,7 +94,7 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
|
|||
deb_info("ep 0 read error (status = %d)\n",status);
|
||||
|
||||
deb_data("<<< ");
|
||||
debug_dump(rx,rxlen,deb_data);
|
||||
debug_dump(rx, rxlen, deb_data);
|
||||
|
||||
return status; /* length in case of success */
|
||||
}
|
||||
|
|
@ -106,28 +102,29 @@ int dib0700_ctrl_rd(struct dvb_usb_device *d, u8 *tx, u8 txlen, u8 *rx, u8 rxlen
|
|||
int dib0700_set_gpio(struct dvb_usb_device *d, enum dib07x0_gpios gpio, u8 gpio_dir, u8 gpio_val)
|
||||
{
|
||||
u8 buf[3] = { REQUEST_SET_GPIO, gpio, ((gpio_dir & 0x01) << 7) | ((gpio_val & 0x01) << 6) };
|
||||
return dib0700_ctrl_wr(d,buf,3);
|
||||
return dib0700_ctrl_wr(d, buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int dib0700_set_usb_xfer_len(struct dvb_usb_device *d, u16 nb_ts_packets)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 b[3];
|
||||
int ret;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 b[3];
|
||||
int ret;
|
||||
|
||||
if (st->fw_version >= 0x10201) {
|
||||
b[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
b[1] = (nb_ts_packets >> 8)&0xff;
|
||||
b[2] = nb_ts_packets & 0xff;
|
||||
if (st->fw_version >= 0x10201) {
|
||||
b[0] = REQUEST_SET_USB_XFER_LEN;
|
||||
b[1] = (nb_ts_packets >> 8) & 0xff;
|
||||
b[2] = nb_ts_packets & 0xff;
|
||||
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
deb_info("set the USB xfer len to %i Ts packet\n", nb_ts_packets);
|
||||
|
||||
ret = dib0700_ctrl_wr(d, b, 3);
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
return ret;
|
||||
ret = dib0700_ctrl_wr(d, b, sizeof(b));
|
||||
} else {
|
||||
deb_info("this firmware does not allow to change the USB xfer len\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -178,7 +175,8 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
value = ((en_start << 7) | (en_stop << 6) |
|
||||
(msg[i].len & 0x3F)) << 8 | i2c_dest;
|
||||
/* I2C ctrl + FE bus; */
|
||||
index = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
|
||||
index = ((gen_mode << 6) & 0xC0) |
|
||||
((bus_mode << 4) & 0x30);
|
||||
|
||||
result = usb_control_msg(d->udev,
|
||||
usb_rcvctrlpipe(d->udev, 0),
|
||||
|
|
@ -198,11 +196,12 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,
|
|||
} else {
|
||||
/* Write request */
|
||||
buf[0] = REQUEST_NEW_I2C_WRITE;
|
||||
buf[1] = (msg[i].addr << 1);
|
||||
buf[1] = msg[i].addr << 1;
|
||||
buf[2] = (en_start << 7) | (en_stop << 6) |
|
||||
(msg[i].len & 0x3F);
|
||||
/* I2C ctrl + FE bus; */
|
||||
buf[3] = ((gen_mode<<6)&0xC0) | ((bus_mode<<4)&0x30);
|
||||
buf[3] = ((gen_mode << 6) & 0xC0) |
|
||||
((bus_mode << 4) & 0x30);
|
||||
/* The Actual i2c payload */
|
||||
memcpy(&buf[4], msg[i].buf, msg[i].len);
|
||||
|
||||
|
|
@ -240,7 +239,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,
|
|||
|
||||
for (i = 0; i < num; i++) {
|
||||
/* fill in the address */
|
||||
buf[1] = (msg[i].addr << 1);
|
||||
buf[1] = msg[i].addr << 1;
|
||||
/* fill the buffer */
|
||||
memcpy(&buf[2], msg[i].buf, msg[i].len);
|
||||
|
||||
|
|
@ -368,7 +367,8 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
u8 buf[260];
|
||||
|
||||
while ((ret = dvb_usb_get_hexline(fw, &hx, &pos)) > 0) {
|
||||
deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",hx.addr, hx.len, hx.chk);
|
||||
deb_fwdata("writing to address 0x%08x (buffer: 0x%02x %02x)\n",
|
||||
hx.addr, hx.len, hx.chk);
|
||||
|
||||
buf[0] = hx.len;
|
||||
buf[1] = (hx.addr >> 8) & 0xff;
|
||||
|
|
@ -408,16 +408,16 @@ int dib0700_download_firmware(struct usb_device *udev, const struct firmware *fw
|
|||
REQUEST_GET_VERSION,
|
||||
USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
|
||||
b, sizeof(b), USB_CTRL_GET_TIMEOUT);
|
||||
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
fw_version = (b[8] << 24) | (b[9] << 16) | (b[10] << 8) | b[11];
|
||||
|
||||
/* set the buffer size - DVB-USB is allocating URB buffers
|
||||
* only after the firwmare download was successful */
|
||||
for (i = 0; i < dib0700_device_count; i++) {
|
||||
for (adap_num = 0; adap_num < dib0700_devices[i].num_adapters;
|
||||
adap_num++) {
|
||||
if (fw_version >= 0x10201)
|
||||
if (fw_version >= 0x10201) {
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = 188*nb_packet_buffer_size;
|
||||
else {
|
||||
} else {
|
||||
/* for fw version older than 1.20.1,
|
||||
* the buffersize has to be n times 512 */
|
||||
dib0700_devices[i].adapter[adap_num].stream.u.bulk.buffersize = ((188*nb_packet_buffer_size+188/2)/512)*512;
|
||||
|
|
@ -453,7 +453,7 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
if (st->disable_streaming_master_mode == 1)
|
||||
b[2] = 0x00;
|
||||
else
|
||||
b[2] = (0x01 << 4); /* Master mode */
|
||||
b[2] = 0x01 << 4; /* Master mode */
|
||||
|
||||
b[3] = 0x00;
|
||||
|
||||
|
|
@ -466,11 +466,44 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
|
||||
b[2] |= st->channel_state;
|
||||
|
||||
deb_info("data for streaming: %x %x\n",b[1],b[2]);
|
||||
deb_info("data for streaming: %x %x\n", b[1], b[2]);
|
||||
|
||||
return dib0700_ctrl_wr(adap->dev, b, 4);
|
||||
}
|
||||
|
||||
int dib0700_change_protocol(void *priv, u64 ir_type)
|
||||
{
|
||||
struct dvb_usb_device *d = priv;
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = { REQUEST_SET_RC, 0, 0 };
|
||||
int new_proto, ret;
|
||||
|
||||
/* Set the IR mode */
|
||||
if (ir_type == IR_TYPE_RC5)
|
||||
new_proto = 1;
|
||||
else if (ir_type == IR_TYPE_NEC)
|
||||
new_proto = 0;
|
||||
else if (ir_type == IR_TYPE_RC6) {
|
||||
if (st->fw_version < 0x10200)
|
||||
return -EINVAL;
|
||||
|
||||
new_proto = 2;
|
||||
} else
|
||||
return -EINVAL;
|
||||
|
||||
rc_setup[1] = new_proto;
|
||||
|
||||
ret = dib0700_ctrl_wr(d, rc_setup, sizeof(rc_setup));
|
||||
if (ret < 0) {
|
||||
err("ir protocol setup failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
d->props.rc.core.protocol = ir_type;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY_V1_20 10
|
||||
|
||||
|
|
@ -478,7 +511,13 @@ int dib0700_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
struct dib0700_rc_response {
|
||||
u8 report_id;
|
||||
u8 data_state;
|
||||
u16 system;
|
||||
union {
|
||||
u16 system16;
|
||||
struct {
|
||||
u8 system;
|
||||
u8 not_system;
|
||||
};
|
||||
};
|
||||
u8 data;
|
||||
u8 not_data;
|
||||
};
|
||||
|
|
@ -487,14 +526,10 @@ struct dib0700_rc_response {
|
|||
static void dib0700_rc_urb_completion(struct urb *purb)
|
||||
{
|
||||
struct dvb_usb_device *d = purb->context;
|
||||
struct dvb_usb_rc_key *keymap;
|
||||
struct dib0700_state *st;
|
||||
struct dib0700_rc_response poll_reply;
|
||||
u8 *buf;
|
||||
int found = 0;
|
||||
u32 event;
|
||||
int state;
|
||||
int i;
|
||||
struct dib0700_rc_response *poll_reply;
|
||||
u32 uninitialized_var(keycode);
|
||||
u8 toggle;
|
||||
|
||||
deb_info("%s()\n", __func__);
|
||||
if (d == NULL)
|
||||
|
|
@ -506,9 +541,8 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
return;
|
||||
}
|
||||
|
||||
keymap = d->props.rc_key_map;
|
||||
st = d->priv;
|
||||
buf = (u8 *)purb->transfer_buffer;
|
||||
poll_reply = purb->transfer_buffer;
|
||||
|
||||
if (purb->status < 0) {
|
||||
deb_info("discontinuing polling\n");
|
||||
|
|
@ -521,104 +555,52 @@ static void dib0700_rc_urb_completion(struct urb *purb)
|
|||
goto resubmit;
|
||||
}
|
||||
|
||||
/* Set initial results in case we exit the function early */
|
||||
event = 0;
|
||||
state = REMOTE_NO_KEY_PRESSED;
|
||||
deb_data("IR ID = %02X state = %02X System = %02X %02X Cmd = %02X %02X (len %d)\n",
|
||||
poll_reply->report_id, poll_reply->data_state,
|
||||
poll_reply->system, poll_reply->not_system,
|
||||
poll_reply->data, poll_reply->not_data,
|
||||
purb->actual_length);
|
||||
|
||||
deb_data("IR raw %02X %02X %02X %02X %02X %02X (len %d)\n", buf[0],
|
||||
buf[1], buf[2], buf[3], buf[4], buf[5], purb->actual_length);
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0:
|
||||
/* NEC Protocol */
|
||||
poll_reply.report_id = 0;
|
||||
poll_reply.data_state = 1;
|
||||
poll_reply.system = buf[2];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
toggle = 0;
|
||||
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((poll_reply.system == 0x00) && (poll_reply.data == 0x00)
|
||||
&& (poll_reply.not_data == 0xff)) {
|
||||
poll_reply.data_state = 2;
|
||||
if ((poll_reply->system == 0x00) && (poll_reply->data == 0x00)
|
||||
&& (poll_reply->not_data == 0xff)) {
|
||||
poll_reply->data_state = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply->system ^ poll_reply->not_system) != 0xff) {
|
||||
deb_data("NEC extended protocol\n");
|
||||
/* NEC extended code - 24 bits */
|
||||
keycode = poll_reply->system16 << 8 | poll_reply->data;
|
||||
} else {
|
||||
deb_data("NEC normal protocol\n");
|
||||
/* normal NEC code - 16 bits */
|
||||
keycode = poll_reply->system << 8 | poll_reply->data;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
deb_data("RC5 protocol\n");
|
||||
/* RC5 Protocol */
|
||||
poll_reply.report_id = buf[0];
|
||||
poll_reply.data_state = buf[1];
|
||||
poll_reply.system = (buf[2] << 8) | buf[3];
|
||||
poll_reply.data = buf[4];
|
||||
poll_reply.not_data = buf[5];
|
||||
toggle = poll_reply->report_id;
|
||||
keycode = poll_reply->system16 << 8 | poll_reply->data;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ((poll_reply.data + poll_reply.not_data) != 0xff) {
|
||||
if ((poll_reply->data + poll_reply->not_data) != 0xff) {
|
||||
/* Key failed integrity check */
|
||||
err("key failed integrity check: %04x %02x %02x",
|
||||
poll_reply.system,
|
||||
poll_reply.data, poll_reply.not_data);
|
||||
poll_reply->system,
|
||||
poll_reply->data, poll_reply->not_data);
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
deb_data("rid=%02x ds=%02x sm=%04x d=%02x nd=%02x\n",
|
||||
poll_reply.report_id, poll_reply.data_state,
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
|
||||
/* Find the key in the map */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == (poll_reply.system & 0xff) &&
|
||||
rc5_data(&keymap[i]) == poll_reply.data) {
|
||||
event = keymap[i].event;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
err("Unknown remote controller key: %04x %02x %02x",
|
||||
poll_reply.system, poll_reply.data, poll_reply.not_data);
|
||||
d->last_event = 0;
|
||||
goto resubmit;
|
||||
}
|
||||
|
||||
if (poll_reply.data_state == 1) {
|
||||
/* New key hit */
|
||||
st->rc_counter = 0;
|
||||
event = keymap[i].event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
} else if (poll_reply.data_state == 2) {
|
||||
/* Key repeated */
|
||||
st->rc_counter++;
|
||||
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY_V1_20) {
|
||||
event = d->last_event;
|
||||
state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY_V1_20;
|
||||
}
|
||||
} else {
|
||||
err("Unknown data state [%d]", poll_reply.data_state);
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case REMOTE_NO_KEY_PRESSED:
|
||||
break;
|
||||
case REMOTE_KEY_PRESSED:
|
||||
deb_info("key pressed\n");
|
||||
d->last_event = event;
|
||||
case REMOTE_KEY_REPEAT:
|
||||
deb_info("key repeated\n");
|
||||
input_event(d->rc_input_dev, EV_KEY, event, 1);
|
||||
input_sync(d->rc_input_dev);
|
||||
input_event(d->rc_input_dev, EV_KEY, d->last_event, 0);
|
||||
input_sync(d->rc_input_dev);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
|
||||
resubmit:
|
||||
/* Clean the buffer before we requeue */
|
||||
|
|
@ -631,21 +613,10 @@ resubmit:
|
|||
int dib0700_rc_setup(struct dvb_usb_device *d)
|
||||
{
|
||||
struct dib0700_state *st = d->priv;
|
||||
u8 rc_setup[3] = {REQUEST_SET_RC, dvb_usb_dib0700_ir_proto, 0};
|
||||
struct urb *purb;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
if (d->props.rc_key_map == NULL)
|
||||
return 0;
|
||||
|
||||
/* Set the IR mode */
|
||||
i = dib0700_ctrl_wr(d, rc_setup, 3);
|
||||
if (i<0) {
|
||||
err("ir protocol setup failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Poll-based. Don't initialize bulk mode */
|
||||
if (st->fw_version < 0x10200)
|
||||
return 0;
|
||||
|
||||
|
|
@ -653,14 +624,14 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
|
|||
purb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (purb == NULL) {
|
||||
err("rc usb alloc urb failed\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
|
||||
if (purb->transfer_buffer == NULL) {
|
||||
err("rc kzalloc failed\n");
|
||||
usb_free_urb(purb);
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
purb->status = -EINPROGRESS;
|
||||
|
|
@ -669,12 +640,10 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
|
|||
dib0700_rc_urb_completion, d);
|
||||
|
||||
ret = usb_submit_urb(purb, GFP_ATOMIC);
|
||||
if (ret != 0) {
|
||||
if (ret)
|
||||
err("rc submit urb failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dib0700_probe(struct usb_interface *intf,
|
||||
|
|
@ -698,6 +667,15 @@ static int dib0700_probe(struct usb_interface *intf,
|
|||
st->fw_version = fw_version;
|
||||
st->nb_packet_buffer_size = (u32)nb_packet_buffer_size;
|
||||
|
||||
/* Disable polling mode on newer firmwares */
|
||||
if (st->fw_version >= 0x10200)
|
||||
dev->props.rc.core.bulk_mode = true;
|
||||
else
|
||||
dev->props.rc.core.bulk_mode = false;
|
||||
|
||||
/* Need a higher delay, to avoid wrong repeat */
|
||||
dev->rc_input_dev->rep[REP_DELAY] = 500;
|
||||
|
||||
dib0700_rc_setup(dev);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -473,16 +473,19 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };
|
|||
/* Number of keypresses to ignore before start repeating */
|
||||
#define RC_REPEAT_DELAY 6
|
||||
|
||||
static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
/*
|
||||
* This function is used only when firmware is < 1.20 version. Newer
|
||||
* firmwares use bulk mode, with functions implemented at dib0700_core,
|
||||
* at dib0700_rc_urb_completion()
|
||||
*/
|
||||
static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)
|
||||
{
|
||||
u8 key[4];
|
||||
u32 keycode;
|
||||
u8 toggle;
|
||||
int i;
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct dib0700_state *st = d->priv;
|
||||
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
|
||||
if (st->fw_version >= 0x10200) {
|
||||
/* For 1.20 firmware , We need to keep the RC polling
|
||||
callback so we can reuse the input device setup in
|
||||
|
|
@ -491,348 +494,45 @@ static int dib0700_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
return 0;
|
||||
}
|
||||
|
||||
i=dib0700_ctrl_rd(d,rc_request,2,key,4);
|
||||
if (i<=0) {
|
||||
i = dib0700_ctrl_rd(d, rc_request, 2, key, 4);
|
||||
if (i <= 0) {
|
||||
err("RC Query Failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* losing half of KEY_0 events from Philipps rc5 remotes.. */
|
||||
if (key[0]==0 && key[1]==0 && key[2]==0 && key[3]==0) return 0;
|
||||
if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0)
|
||||
return 0;
|
||||
|
||||
/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]); */
|
||||
|
||||
dib0700_rc_setup(d); /* reset ir sensor data to prevent false events */
|
||||
|
||||
switch (dvb_usb_dib0700_ir_proto) {
|
||||
case 0: {
|
||||
d->last_event = 0;
|
||||
switch (d->props.rc.core.protocol) {
|
||||
case IR_TYPE_NEC:
|
||||
/* NEC protocol sends repeat code as 0 0 0 FF */
|
||||
if ((key[3-2] == 0x00) && (key[3-3] == 0x00) &&
|
||||
(key[3] == 0xFF)) {
|
||||
st->rc_counter++;
|
||||
if (st->rc_counter > RC_REPEAT_DELAY) {
|
||||
*event = d->last_event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY;
|
||||
}
|
||||
return 0;
|
||||
(key[3] == 0xff))
|
||||
keycode = d->last_event;
|
||||
else {
|
||||
keycode = key[3-2] << 8 | key[3-3];
|
||||
d->last_event = keycode;
|
||||
}
|
||||
for (i=0;i<d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == key[3-2] &&
|
||||
rc5_data(&keymap[i]) == key[3-3]) {
|
||||
st->rc_counter = 0;
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
d->last_event = keymap[i].event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
/* RC-5 protocol changes toggle bit on new keypress */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&keymap[i]) == key[3-2] &&
|
||||
rc5_data(&keymap[i]) == key[3-3]) {
|
||||
if (d->last_event == keymap[i].event &&
|
||||
key[3-1] == st->rc_toggle) {
|
||||
st->rc_counter++;
|
||||
/* prevents unwanted double hits */
|
||||
if (st->rc_counter > RC_REPEAT_DELAY) {
|
||||
*event = d->last_event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_counter = RC_REPEAT_DELAY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
st->rc_counter = 0;
|
||||
*event = keymap[i].event;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
st->rc_toggle = key[3-1];
|
||||
d->last_event = keymap[i].event;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ir_keydown(d->rc_input_dev, keycode, 0);
|
||||
break;
|
||||
default:
|
||||
/* RC-5 protocol changes toggle bit on new keypress */
|
||||
keycode = key[3-2] << 8 | key[3-3];
|
||||
toggle = key[3-1];
|
||||
ir_keydown(d->rc_input_dev, keycode, toggle);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
err("Unknown remote controller key: %2X %2X %2X %2X", (int) key[3-2], (int) key[3-3], (int) key[3-1], (int) key[3]);
|
||||
d->last_event = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dib0700_table[] = {
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
|
||||
{ 0x0739, KEY_POWER },
|
||||
{ 0x0703, KEY_VOLUMEUP },
|
||||
{ 0x0709, KEY_VOLUMEDOWN },
|
||||
{ 0x0706, KEY_CHANNELUP },
|
||||
{ 0x070c, KEY_CHANNELDOWN },
|
||||
{ 0x070f, KEY_1 },
|
||||
{ 0x0715, KEY_2 },
|
||||
{ 0x0710, KEY_3 },
|
||||
{ 0x0718, KEY_4 },
|
||||
{ 0x071b, KEY_5 },
|
||||
{ 0x071e, KEY_6 },
|
||||
{ 0x0711, KEY_7 },
|
||||
{ 0x0721, KEY_8 },
|
||||
{ 0x0712, KEY_9 },
|
||||
{ 0x0727, KEY_0 },
|
||||
{ 0x0724, KEY_SCREEN }, /* 'Square' key */
|
||||
{ 0x072a, KEY_TEXT }, /* 'T' key */
|
||||
{ 0x072d, KEY_REWIND },
|
||||
{ 0x0730, KEY_PLAY },
|
||||
{ 0x0733, KEY_FASTFORWARD },
|
||||
{ 0x0736, KEY_RECORD },
|
||||
{ 0x073c, KEY_STOP },
|
||||
{ 0x073f, KEY_CANCEL }, /* '?' key */
|
||||
/* Key codes for the Terratec Cinergy DT XS Diversity, similar to cinergyT2.c */
|
||||
{ 0xeb01, KEY_POWER },
|
||||
{ 0xeb02, KEY_1 },
|
||||
{ 0xeb03, KEY_2 },
|
||||
{ 0xeb04, KEY_3 },
|
||||
{ 0xeb05, KEY_4 },
|
||||
{ 0xeb06, KEY_5 },
|
||||
{ 0xeb07, KEY_6 },
|
||||
{ 0xeb08, KEY_7 },
|
||||
{ 0xeb09, KEY_8 },
|
||||
{ 0xeb0a, KEY_9 },
|
||||
{ 0xeb0b, KEY_VIDEO },
|
||||
{ 0xeb0c, KEY_0 },
|
||||
{ 0xeb0d, KEY_REFRESH },
|
||||
{ 0xeb0f, KEY_EPG },
|
||||
{ 0xeb10, KEY_UP },
|
||||
{ 0xeb11, KEY_LEFT },
|
||||
{ 0xeb12, KEY_OK },
|
||||
{ 0xeb13, KEY_RIGHT },
|
||||
{ 0xeb14, KEY_DOWN },
|
||||
{ 0xeb16, KEY_INFO },
|
||||
{ 0xeb17, KEY_RED },
|
||||
{ 0xeb18, KEY_GREEN },
|
||||
{ 0xeb19, KEY_YELLOW },
|
||||
{ 0xeb1a, KEY_BLUE },
|
||||
{ 0xeb1b, KEY_CHANNELUP },
|
||||
{ 0xeb1c, KEY_VOLUMEUP },
|
||||
{ 0xeb1d, KEY_MUTE },
|
||||
{ 0xeb1e, KEY_VOLUMEDOWN },
|
||||
{ 0xeb1f, KEY_CHANNELDOWN },
|
||||
{ 0xeb40, KEY_PAUSE },
|
||||
{ 0xeb41, KEY_HOME },
|
||||
{ 0xeb42, KEY_MENU }, /* DVD Menu */
|
||||
{ 0xeb43, KEY_SUBTITLE },
|
||||
{ 0xeb44, KEY_TEXT }, /* Teletext */
|
||||
{ 0xeb45, KEY_DELETE },
|
||||
{ 0xeb46, KEY_TV },
|
||||
{ 0xeb47, KEY_DVD },
|
||||
{ 0xeb48, KEY_STOP },
|
||||
{ 0xeb49, KEY_VIDEO },
|
||||
{ 0xeb4a, KEY_AUDIO }, /* Music */
|
||||
{ 0xeb4b, KEY_SCREEN }, /* Pic */
|
||||
{ 0xeb4c, KEY_PLAY },
|
||||
{ 0xeb4d, KEY_BACK },
|
||||
{ 0xeb4e, KEY_REWIND },
|
||||
{ 0xeb4f, KEY_FASTFORWARD },
|
||||
{ 0xeb54, KEY_PREVIOUS },
|
||||
{ 0xeb58, KEY_RECORD },
|
||||
{ 0xeb5c, KEY_NEXT },
|
||||
|
||||
/* Key codes for the Haupauge WinTV Nova-TD, copied from nova-t-usb2.c (Nova-T USB2) */
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
{ 0x1e03, KEY_3 },
|
||||
{ 0x1e04, KEY_4 },
|
||||
{ 0x1e05, KEY_5 },
|
||||
{ 0x1e06, KEY_6 },
|
||||
{ 0x1e07, KEY_7 },
|
||||
{ 0x1e08, KEY_8 },
|
||||
{ 0x1e09, KEY_9 },
|
||||
{ 0x1e0a, KEY_KPASTERISK },
|
||||
{ 0x1e0b, KEY_RED },
|
||||
{ 0x1e0c, KEY_RADIO },
|
||||
{ 0x1e0d, KEY_MENU },
|
||||
{ 0x1e0e, KEY_GRAVE }, /* # */
|
||||
{ 0x1e0f, KEY_MUTE },
|
||||
{ 0x1e10, KEY_VOLUMEUP },
|
||||
{ 0x1e11, KEY_VOLUMEDOWN },
|
||||
{ 0x1e12, KEY_CHANNEL },
|
||||
{ 0x1e14, KEY_UP },
|
||||
{ 0x1e15, KEY_DOWN },
|
||||
{ 0x1e16, KEY_LEFT },
|
||||
{ 0x1e17, KEY_RIGHT },
|
||||
{ 0x1e18, KEY_VIDEO },
|
||||
{ 0x1e19, KEY_AUDIO },
|
||||
{ 0x1e1a, KEY_MEDIA },
|
||||
{ 0x1e1b, KEY_EPG },
|
||||
{ 0x1e1c, KEY_TV },
|
||||
{ 0x1e1e, KEY_NEXT },
|
||||
{ 0x1e1f, KEY_BACK },
|
||||
{ 0x1e20, KEY_CHANNELUP },
|
||||
{ 0x1e21, KEY_CHANNELDOWN },
|
||||
{ 0x1e24, KEY_LAST }, /* Skip backwards */
|
||||
{ 0x1e25, KEY_OK },
|
||||
{ 0x1e29, KEY_BLUE},
|
||||
{ 0x1e2e, KEY_GREEN },
|
||||
{ 0x1e30, KEY_PAUSE },
|
||||
{ 0x1e32, KEY_REWIND },
|
||||
{ 0x1e34, KEY_FASTFORWARD },
|
||||
{ 0x1e35, KEY_PLAY },
|
||||
{ 0x1e36, KEY_STOP },
|
||||
{ 0x1e37, KEY_RECORD },
|
||||
{ 0x1e38, KEY_YELLOW },
|
||||
{ 0x1e3b, KEY_GOTO },
|
||||
{ 0x1e3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Leadtek Winfast DTV Dongle */
|
||||
{ 0x0042, KEY_POWER },
|
||||
{ 0x077c, KEY_TUNER },
|
||||
{ 0x0f4e, KEY_PRINT }, /* PREVIEW */
|
||||
{ 0x0840, KEY_SCREEN }, /* full screen toggle*/
|
||||
{ 0x0f71, KEY_DOT }, /* frequency */
|
||||
{ 0x0743, KEY_0 },
|
||||
{ 0x0c41, KEY_1 },
|
||||
{ 0x0443, KEY_2 },
|
||||
{ 0x0b7f, KEY_3 },
|
||||
{ 0x0e41, KEY_4 },
|
||||
{ 0x0643, KEY_5 },
|
||||
{ 0x097f, KEY_6 },
|
||||
{ 0x0d7e, KEY_7 },
|
||||
{ 0x057c, KEY_8 },
|
||||
{ 0x0a40, KEY_9 },
|
||||
{ 0x0e4e, KEY_CLEAR },
|
||||
{ 0x047c, KEY_CHANNEL }, /* show channel number */
|
||||
{ 0x0f41, KEY_LAST }, /* recall */
|
||||
{ 0x0342, KEY_MUTE },
|
||||
{ 0x064c, KEY_RESERVED }, /* PIP button*/
|
||||
{ 0x0172, KEY_SHUFFLE }, /* SNAPSHOT */
|
||||
{ 0x0c4e, KEY_PLAYPAUSE }, /* TIMESHIFT */
|
||||
{ 0x0b70, KEY_RECORD },
|
||||
{ 0x037d, KEY_VOLUMEUP },
|
||||
{ 0x017d, KEY_VOLUMEDOWN },
|
||||
{ 0x0242, KEY_CHANNELUP },
|
||||
{ 0x007d, KEY_CHANNELDOWN },
|
||||
|
||||
/* Key codes for Nova-TD "credit card" remote control. */
|
||||
{ 0x1d00, KEY_0 },
|
||||
{ 0x1d01, KEY_1 },
|
||||
{ 0x1d02, KEY_2 },
|
||||
{ 0x1d03, KEY_3 },
|
||||
{ 0x1d04, KEY_4 },
|
||||
{ 0x1d05, KEY_5 },
|
||||
{ 0x1d06, KEY_6 },
|
||||
{ 0x1d07, KEY_7 },
|
||||
{ 0x1d08, KEY_8 },
|
||||
{ 0x1d09, KEY_9 },
|
||||
{ 0x1d0a, KEY_TEXT },
|
||||
{ 0x1d0d, KEY_MENU },
|
||||
{ 0x1d0f, KEY_MUTE },
|
||||
{ 0x1d10, KEY_VOLUMEUP },
|
||||
{ 0x1d11, KEY_VOLUMEDOWN },
|
||||
{ 0x1d12, KEY_CHANNEL },
|
||||
{ 0x1d14, KEY_UP },
|
||||
{ 0x1d15, KEY_DOWN },
|
||||
{ 0x1d16, KEY_LEFT },
|
||||
{ 0x1d17, KEY_RIGHT },
|
||||
{ 0x1d1c, KEY_TV },
|
||||
{ 0x1d1e, KEY_NEXT },
|
||||
{ 0x1d1f, KEY_BACK },
|
||||
{ 0x1d20, KEY_CHANNELUP },
|
||||
{ 0x1d21, KEY_CHANNELDOWN },
|
||||
{ 0x1d24, KEY_LAST },
|
||||
{ 0x1d25, KEY_OK },
|
||||
{ 0x1d30, KEY_PAUSE },
|
||||
{ 0x1d32, KEY_REWIND },
|
||||
{ 0x1d34, KEY_FASTFORWARD },
|
||||
{ 0x1d35, KEY_PLAY },
|
||||
{ 0x1d36, KEY_STOP },
|
||||
{ 0x1d37, KEY_RECORD },
|
||||
{ 0x1d3b, KEY_GOTO },
|
||||
{ 0x1d3d, KEY_POWER },
|
||||
|
||||
/* Key codes for the Pixelview SBTVD remote (proto NEC) */
|
||||
{ 0x8613, KEY_MUTE },
|
||||
{ 0x8612, KEY_POWER },
|
||||
{ 0x8601, KEY_1 },
|
||||
{ 0x8602, KEY_2 },
|
||||
{ 0x8603, KEY_3 },
|
||||
{ 0x8604, KEY_4 },
|
||||
{ 0x8605, KEY_5 },
|
||||
{ 0x8606, KEY_6 },
|
||||
{ 0x8607, KEY_7 },
|
||||
{ 0x8608, KEY_8 },
|
||||
{ 0x8609, KEY_9 },
|
||||
{ 0x8600, KEY_0 },
|
||||
{ 0x860d, KEY_CHANNELUP },
|
||||
{ 0x8619, KEY_CHANNELDOWN },
|
||||
{ 0x8610, KEY_VOLUMEUP },
|
||||
{ 0x860c, KEY_VOLUMEDOWN },
|
||||
|
||||
{ 0x860a, KEY_CAMERA },
|
||||
{ 0x860b, KEY_ZOOM },
|
||||
{ 0x861b, KEY_BACKSPACE },
|
||||
{ 0x8615, KEY_ENTER },
|
||||
|
||||
{ 0x861d, KEY_UP },
|
||||
{ 0x861e, KEY_DOWN },
|
||||
{ 0x860e, KEY_LEFT },
|
||||
{ 0x860f, KEY_RIGHT },
|
||||
|
||||
{ 0x8618, KEY_RECORD },
|
||||
{ 0x861a, KEY_STOP },
|
||||
|
||||
/* Key codes for the EvolutePC TVWay+ remote (proto NEC) */
|
||||
{ 0x7a00, KEY_MENU },
|
||||
{ 0x7a01, KEY_RECORD },
|
||||
{ 0x7a02, KEY_PLAY },
|
||||
{ 0x7a03, KEY_STOP },
|
||||
{ 0x7a10, KEY_CHANNELUP },
|
||||
{ 0x7a11, KEY_CHANNELDOWN },
|
||||
{ 0x7a12, KEY_VOLUMEUP },
|
||||
{ 0x7a13, KEY_VOLUMEDOWN },
|
||||
{ 0x7a40, KEY_POWER },
|
||||
{ 0x7a41, KEY_MUTE },
|
||||
|
||||
/* Key codes for the Elgato EyeTV Diversity silver remote,
|
||||
set dvb_usb_dib0700_ir_proto=0 */
|
||||
{ 0x4501, KEY_POWER },
|
||||
{ 0x4502, KEY_MUTE },
|
||||
{ 0x4503, KEY_1 },
|
||||
{ 0x4504, KEY_2 },
|
||||
{ 0x4505, KEY_3 },
|
||||
{ 0x4506, KEY_4 },
|
||||
{ 0x4507, KEY_5 },
|
||||
{ 0x4508, KEY_6 },
|
||||
{ 0x4509, KEY_7 },
|
||||
{ 0x450a, KEY_8 },
|
||||
{ 0x450b, KEY_9 },
|
||||
{ 0x450c, KEY_LAST },
|
||||
{ 0x450d, KEY_0 },
|
||||
{ 0x450e, KEY_ENTER },
|
||||
{ 0x450f, KEY_RED },
|
||||
{ 0x4510, KEY_CHANNELUP },
|
||||
{ 0x4511, KEY_GREEN },
|
||||
{ 0x4512, KEY_VOLUMEDOWN },
|
||||
{ 0x4513, KEY_OK },
|
||||
{ 0x4514, KEY_VOLUMEUP },
|
||||
{ 0x4515, KEY_YELLOW },
|
||||
{ 0x4516, KEY_CHANNELDOWN },
|
||||
{ 0x4517, KEY_BLUE },
|
||||
{ 0x4518, KEY_LEFT }, /* Skip backwards */
|
||||
{ 0x4519, KEY_PLAYPAUSE },
|
||||
{ 0x451a, KEY_RIGHT }, /* Skip forward */
|
||||
{ 0x451b, KEY_REWIND },
|
||||
{ 0x451c, KEY_L }, /* Live */
|
||||
{ 0x451d, KEY_FASTFORWARD },
|
||||
{ 0x451e, KEY_STOP }, /* 'Reveal' for Teletext */
|
||||
{ 0x451f, KEY_MENU }, /* KEY_TEXT for Teletext */
|
||||
{ 0x4540, KEY_RECORD }, /* Font 'Size' for Teletext */
|
||||
{ 0x4541, KEY_SCREEN }, /* Full screen toggle, 'Hold' for Teletext */
|
||||
{ 0x4542, KEY_SELECT }, /* Select video input, 'Select' for Teletext */
|
||||
};
|
||||
|
||||
/* STK7700P: Hauppauge Nova-T Stick, AVerMedia Volar */
|
||||
static struct dibx000_agc_config stk7700p_7000m_mt2060_agc_config = {
|
||||
BAND_UHF | BAND_VHF,
|
||||
|
|
@ -2168,10 +1868,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
|
@ -2197,10 +1904,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
|
@ -2251,11 +1965,17 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
|
@ -2288,10 +2008,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
|
@ -2358,11 +2086,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
|
@ -2397,11 +2132,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
|
|
@ -2431,7 +2173,7 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 7,
|
||||
.num_device_descs = 6,
|
||||
.devices = {
|
||||
{ "DiBcom STK7070PD reference design",
|
||||
{ &dib0700_usb_id_table[17], NULL },
|
||||
|
|
@ -2458,15 +2200,69 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ &dib0700_usb_id_table[44], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
{
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.pid_filter = stk70x0p_pid_filter,
|
||||
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
|
||||
.frontend_attach = stk7070pd_frontend_attach0,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}, {
|
||||
.caps = DVB_USB_ADAP_HAS_PID_FILTER | DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
|
||||
.pid_filter_count = 32,
|
||||
.pid_filter = stk70x0p_pid_filter,
|
||||
.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
|
||||
.frontend_attach = stk7070pd_frontend_attach1,
|
||||
.tuner_attach = dib7070p_tuner_attach,
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
|
||||
|
||||
.size_of_priv = sizeof(struct dib0700_adapter_state),
|
||||
}
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{ "Elgato EyeTV Diversity",
|
||||
{ &dib0700_usb_id_table[68], NULL },
|
||||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
|
||||
.num_adapters = 1,
|
||||
|
|
@ -2525,10 +2321,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
|
@ -2554,10 +2359,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
|
@ -2615,10 +2429,19 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
{ NULL },
|
||||
},
|
||||
},
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
|
@ -2653,11 +2476,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_NEC_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 2,
|
||||
.adapter = {
|
||||
|
|
@ -2697,10 +2527,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
|
||||
.num_adapters = 1,
|
||||
.adapter = {
|
||||
|
|
@ -2728,10 +2566,18 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
|||
},
|
||||
},
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dib0700_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dib0700_table),
|
||||
.rc_query = dib0700_rc_query
|
||||
.rc.core = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_codes = RC_MAP_DIB0700_RC5_TABLE,
|
||||
.module_name = "dib0700",
|
||||
.rc_query = dib0700_rc_query_old_firmware,
|
||||
.rc_props = {
|
||||
.allowed_protos = IR_TYPE_RC5 |
|
||||
IR_TYPE_RC6 |
|
||||
IR_TYPE_NEC,
|
||||
.change_protocol = dib0700_change_protocol,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -327,7 +327,7 @@ EXPORT_SYMBOL(dibusb_dib3000mc_tuner_attach);
|
|||
/*
|
||||
* common remote control stuff
|
||||
*/
|
||||
struct dvb_usb_rc_key ir_codes_dibusb_table[] = {
|
||||
struct ir_scancode ir_codes_dibusb_table[] = {
|
||||
/* Key codes for the little Artec T1/Twinhan/HAMA/ remote. */
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
|
|
|
|||
|
|
@ -211,10 +211,12 @@ static struct dvb_usb_device_properties dibusb1_1_properties = {
|
|||
|
||||
.power_ctrl = dibusb_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
@ -295,10 +297,12 @@ static struct dvb_usb_device_properties dibusb1_1_an2235_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
@ -359,10 +363,12 @@ static struct dvb_usb_device_properties dibusb2_0b_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
@ -416,10 +422,12 @@ static struct dvb_usb_device_properties artec_t1_usb2_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* wow, that is ugly ... I want to load it to the driver dynamically */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -81,10 +81,12 @@ static struct dvb_usb_device_properties dibusb_mc_properties = {
|
|||
},
|
||||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = DEFAULT_RC_INTERVAL,
|
||||
.rc_key_map = ir_codes_dibusb_table,
|
||||
.rc_key_map_size = 111, /* FIXME */
|
||||
.rc_query = dibusb_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ extern int dibusb2_0_power_ctrl(struct dvb_usb_device *, int);
|
|||
#define DEFAULT_RC_INTERVAL 150
|
||||
//#define DEFAULT_RC_INTERVAL 100000
|
||||
|
||||
extern struct dvb_usb_rc_key ir_codes_dibusb_table[];
|
||||
extern struct ir_scancode ir_codes_dibusb_table[];
|
||||
extern int dibusb_rc_query(struct dvb_usb_device *, u32 *, int *);
|
||||
extern int dibusb_read_eeprom_byte(struct dvb_usb_device *, u8, u8 *);
|
||||
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_digitv_table[] = {
|
||||
static struct ir_scancode ir_codes_digitv_table[] = {
|
||||
{ 0x5f55, KEY_0 },
|
||||
{ 0x6f55, KEY_1 },
|
||||
{ 0x9f55, KEY_2 },
|
||||
|
|
@ -237,10 +237,10 @@ static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
/* if something is inside the buffer, simulate key press */
|
||||
if (key[1] != 0)
|
||||
{
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc_key_map[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc_key_map[i]) == key[2]) {
|
||||
*event = d->props.rc_key_map[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
if (rc5_custom(&d->props.rc.legacy.rc_key_map[i]) == key[1] &&
|
||||
rc5_data(&d->props.rc.legacy.rc_key_map[i]) == key[2]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -310,10 +310,12 @@ static struct dvb_usb_device_properties digitv_properties = {
|
|||
},
|
||||
.identify_state = digitv_identify_state,
|
||||
|
||||
.rc_interval = 1000,
|
||||
.rc_key_map = ir_codes_digitv_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table),
|
||||
.rc_query = digitv_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 1000,
|
||||
.rc_key_map = ir_codes_digitv_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_digitv_table),
|
||||
.rc_query = digitv_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &digitv_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
|
|||
|
||||
/* remote control */
|
||||
/* key list for the tiny remote control (Yakumo, don't know about the others) */
|
||||
static struct dvb_usb_rc_key ir_codes_dtt200u_table[] = {
|
||||
static struct ir_scancode ir_codes_dtt200u_table[] = {
|
||||
{ 0x8001, KEY_MUTE },
|
||||
{ 0x8002, KEY_CHANNELDOWN },
|
||||
{ 0x8003, KEY_VOLUMEDOWN },
|
||||
|
|
@ -161,10 +161,12 @@ static struct dvb_usb_device_properties dtt200u_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -206,10 +208,12 @@ static struct dvb_usb_device_properties wt220u_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -251,10 +255,12 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
@ -296,10 +302,12 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {
|
|||
},
|
||||
.power_ctrl = dtt200u_power_ctrl,
|
||||
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 300,
|
||||
.rc_key_map = ir_codes_dtt200u_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dtt200u_table),
|
||||
.rc_query = dtt200u_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x01,
|
||||
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@
|
|||
#define USB_PID_AVERMEDIA_A310 0xa310
|
||||
#define USB_PID_AVERMEDIA_A850 0x850a
|
||||
#define USB_PID_AVERMEDIA_A805 0xa805
|
||||
#define USB_PID_AVERMEDIA_A815M 0x815a
|
||||
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
|
||||
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
|
||||
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
/* debug */
|
||||
int dvb_usb_debug;
|
||||
module_param_named(debug,dvb_usb_debug, int, 0644);
|
||||
module_param_named(debug, dvb_usb_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,pll=4,ts=8,err=16,rc=32,fw=64,mem=128,uxfer=256 (or-able))." DVB_USB_DEBUG_STATUS);
|
||||
|
||||
int dvb_usb_disable_rc_polling;
|
||||
|
|
@ -29,7 +29,7 @@ MODULE_PARM_DESC(force_pid_filter_usage, "force all dvb-usb-devices to use a PID
|
|||
static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
||||
{
|
||||
struct dvb_usb_adapter *adap;
|
||||
int ret,n;
|
||||
int ret, n;
|
||||
|
||||
for (n = 0; n < d->props.num_adapters; n++) {
|
||||
adap = &d->adapter[n];
|
||||
|
|
@ -38,7 +38,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
|
||||
memcpy(&adap->props, &d->props.adapter[n], sizeof(struct dvb_usb_adapter_properties));
|
||||
|
||||
/* speed - when running at FULL speed we need a HW PID filter */
|
||||
/* speed - when running at FULL speed we need a HW PID filter */
|
||||
if (d->udev->speed == USB_SPEED_FULL && !(adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
|
||||
err("This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)");
|
||||
return -ENODEV;
|
||||
|
|
@ -46,7 +46,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
|
||||
if ((d->udev->speed == USB_SPEED_FULL && adap->props.caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
|
||||
(adap->props.caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
|
||||
info("will use the device's hardware PID filter (table count: %d).",adap->props.pid_filter_count);
|
||||
info("will use the device's hardware PID filter (table count: %d).", adap->props.pid_filter_count);
|
||||
adap->pid_filtering = 1;
|
||||
adap->max_feed_count = adap->props.pid_filter_count;
|
||||
} else {
|
||||
|
|
@ -64,9 +64,9 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
}
|
||||
|
||||
if (adap->props.size_of_priv > 0) {
|
||||
adap->priv = kzalloc(adap->props.size_of_priv,GFP_KERNEL);
|
||||
adap->priv = kzalloc(adap->props.size_of_priv, GFP_KERNEL);
|
||||
if (adap->priv == NULL) {
|
||||
err("no memory for priv for adapter %d.",n);
|
||||
err("no memory for priv for adapter %d.", n);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
|
@ -86,8 +86,8 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
* sometimes a timeout occures, this helps
|
||||
*/
|
||||
if (d->props.generic_bulk_ctrl_endpoint != 0) {
|
||||
usb_clear_halt(d->udev,usb_sndbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev,usb_rcvbulkpipe(d->udev,d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev, usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -96,6 +96,7 @@ static int dvb_usb_adapter_init(struct dvb_usb_device *d, short *adapter_nrs)
|
|||
static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (n = 0; n < d->num_adapters_initialized; n++) {
|
||||
dvb_usb_adapter_frontend_exit(&d->adapter[n]);
|
||||
dvb_usb_adapter_dvb_exit(&d->adapter[n]);
|
||||
|
|
@ -111,11 +112,11 @@ static int dvb_usb_adapter_exit(struct dvb_usb_device *d)
|
|||
/* general initialization functions */
|
||||
static int dvb_usb_exit(struct dvb_usb_device *d)
|
||||
{
|
||||
deb_info("state before exiting everything: %x\n",d->state);
|
||||
deb_info("state before exiting everything: %x\n", d->state);
|
||||
dvb_usb_remote_exit(d);
|
||||
dvb_usb_adapter_exit(d);
|
||||
dvb_usb_i2c_exit(d);
|
||||
deb_info("state should be zero now: %x\n",d->state);
|
||||
deb_info("state should be zero now: %x\n", d->state);
|
||||
d->state = DVB_USB_STATE_INIT;
|
||||
kfree(d->priv);
|
||||
kfree(d);
|
||||
|
|
@ -132,14 +133,14 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
|
|||
d->state = DVB_USB_STATE_INIT;
|
||||
|
||||
if (d->props.size_of_priv > 0) {
|
||||
d->priv = kzalloc(d->props.size_of_priv,GFP_KERNEL);
|
||||
d->priv = kzalloc(d->props.size_of_priv, GFP_KERNEL);
|
||||
if (d->priv == NULL) {
|
||||
err("no memory for priv in 'struct dvb_usb_device'");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
/* check the capabilities and set appropriate variables */
|
||||
/* check the capabilities and set appropriate variables */
|
||||
dvb_usb_device_power_ctrl(d, 1);
|
||||
|
||||
if ((ret = dvb_usb_i2c_init(d)) ||
|
||||
|
|
@ -157,16 +158,17 @@ static int dvb_usb_init(struct dvb_usb_device *d, short *adapter_nums)
|
|||
}
|
||||
|
||||
/* determine the name and the state of the just found USB device */
|
||||
static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device *udev,struct dvb_usb_device_properties *props, int *cold)
|
||||
static struct dvb_usb_device_description *dvb_usb_find_device(struct usb_device *udev, struct dvb_usb_device_properties *props, int *cold)
|
||||
{
|
||||
int i,j;
|
||||
int i, j;
|
||||
struct dvb_usb_device_description *desc = NULL;
|
||||
|
||||
*cold = -1;
|
||||
|
||||
for (i = 0; i < props->num_device_descs; i++) {
|
||||
|
||||
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].cold_ids[j] != NULL; j++) {
|
||||
deb_info("check for cold %x %x\n",props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
|
||||
deb_info("check for cold %x %x\n", props->devices[i].cold_ids[j]->idVendor, props->devices[i].cold_ids[j]->idProduct);
|
||||
if (props->devices[i].cold_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||
props->devices[i].cold_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||
*cold = 1;
|
||||
|
|
@ -179,7 +181,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
|
|||
break;
|
||||
|
||||
for (j = 0; j < DVB_USB_ID_MAX_NUM && props->devices[i].warm_ids[j] != NULL; j++) {
|
||||
deb_info("check for warm %x %x\n",props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
|
||||
deb_info("check for warm %x %x\n", props->devices[i].warm_ids[j]->idVendor, props->devices[i].warm_ids[j]->idProduct);
|
||||
if (props->devices[i].warm_ids[j]->idVendor == le16_to_cpu(udev->descriptor.idVendor) &&
|
||||
props->devices[i].warm_ids[j]->idProduct == le16_to_cpu(udev->descriptor.idProduct)) {
|
||||
*cold = 0;
|
||||
|
|
@ -190,7 +192,7 @@ static struct dvb_usb_device_description * dvb_usb_find_device(struct usb_device
|
|||
}
|
||||
|
||||
if (desc != NULL && props->identify_state != NULL)
|
||||
props->identify_state(udev,props,&desc,cold);
|
||||
props->identify_state(udev, props, &desc, cold);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
|
@ -202,7 +204,7 @@ int dvb_usb_device_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
else
|
||||
d->powered--;
|
||||
|
||||
if (d->powered == 0 || (onoff && d->powered == 1)) { // when switching from 1 to 0 or from 0 to 1
|
||||
if (d->powered == 0 || (onoff && d->powered == 1)) { /* when switching from 1 to 0 or from 0 to 1 */
|
||||
deb_info("power control: %d\n", onoff);
|
||||
if (d->props.power_ctrl)
|
||||
return d->props.power_ctrl(d, onoff);
|
||||
|
|
@ -222,32 +224,32 @@ int dvb_usb_device_init(struct usb_interface *intf,
|
|||
struct dvb_usb_device *d = NULL;
|
||||
struct dvb_usb_device_description *desc = NULL;
|
||||
|
||||
int ret = -ENOMEM,cold=0;
|
||||
int ret = -ENOMEM, cold = 0;
|
||||
|
||||
if (du != NULL)
|
||||
*du = NULL;
|
||||
|
||||
if ((desc = dvb_usb_find_device(udev,props,&cold)) == NULL) {
|
||||
if ((desc = dvb_usb_find_device(udev, props, &cold)) == NULL) {
|
||||
deb_err("something went very wrong, device was not found in current device list - let's see what comes next.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (cold) {
|
||||
info("found a '%s' in cold state, will try to load a firmware",desc->name);
|
||||
ret = dvb_usb_download_firmware(udev,props);
|
||||
info("found a '%s' in cold state, will try to load a firmware", desc->name);
|
||||
ret = dvb_usb_download_firmware(udev, props);
|
||||
if (!props->no_reconnect || ret != 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
info("found a '%s' in warm state.",desc->name);
|
||||
d = kzalloc(sizeof(struct dvb_usb_device),GFP_KERNEL);
|
||||
info("found a '%s' in warm state.", desc->name);
|
||||
d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
|
||||
if (d == NULL) {
|
||||
err("no memory for 'struct dvb_usb_device'");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
d->udev = udev;
|
||||
memcpy(&d->props,props,sizeof(struct dvb_usb_device_properties));
|
||||
memcpy(&d->props, props, sizeof(struct dvb_usb_device_properties));
|
||||
d->desc = desc;
|
||||
d->owner = owner;
|
||||
|
||||
|
|
@ -259,9 +261,9 @@ int dvb_usb_device_init(struct usb_interface *intf,
|
|||
ret = dvb_usb_init(d, adapter_nums);
|
||||
|
||||
if (ret == 0)
|
||||
info("%s successfully initialized and connected.",desc->name);
|
||||
info("%s successfully initialized and connected.", desc->name);
|
||||
else
|
||||
info("%s error while loading driver (%d)",desc->name,ret);
|
||||
info("%s error while loading driver (%d)", desc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_device_init);
|
||||
|
|
@ -271,12 +273,12 @@ void dvb_usb_device_exit(struct usb_interface *intf)
|
|||
struct dvb_usb_device *d = usb_get_intfdata(intf);
|
||||
const char *name = "generic DVB-USB module";
|
||||
|
||||
usb_set_intfdata(intf,NULL);
|
||||
usb_set_intfdata(intf, NULL);
|
||||
if (d != NULL && d->desc != NULL) {
|
||||
name = d->desc->name;
|
||||
dvb_usb_exit(d);
|
||||
}
|
||||
info("%s successfully deinitialized and disconnected.",name);
|
||||
info("%s successfully deinitialized and disconnected.", name);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(dvb_usb_device_exit);
|
||||
|
|
|
|||
|
|
@ -8,29 +8,29 @@
|
|||
#include "dvb-usb-common.h"
|
||||
#include <linux/usb/input.h>
|
||||
|
||||
static int dvb_usb_getkeycode(struct input_dev *dev,
|
||||
static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
|
||||
unsigned int scancode, unsigned int *keycode)
|
||||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i;
|
||||
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].scan == scancode) {
|
||||
*keycode = keymap[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
*keycode = keymap[i].keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If is there extra space, returns KEY_RESERVED,
|
||||
* otherwise, input core won't let dvb_usb_setkeycode
|
||||
* otherwise, input core won't let legacy_dvb_usb_setkeycode
|
||||
* to work
|
||||
*/
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].event == KEY_RESERVED ||
|
||||
keymap[i].event == KEY_UNKNOWN) {
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
*keycode = KEY_RESERVED;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -38,27 +38,27 @@ static int dvb_usb_getkeycode(struct input_dev *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dvb_usb_setkeycode(struct input_dev *dev,
|
||||
static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
|
||||
unsigned int scancode, unsigned int keycode)
|
||||
{
|
||||
struct dvb_usb_device *d = input_get_drvdata(dev);
|
||||
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int i;
|
||||
|
||||
/* Search if it is replacing an existing keycode */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].scan == scancode) {
|
||||
keymap[i].event = keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].scancode == scancode) {
|
||||
keymap[i].keycode = keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Search if is there a clean entry. If so, use it */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (keymap[i].event == KEY_RESERVED ||
|
||||
keymap[i].event == KEY_UNKNOWN) {
|
||||
keymap[i].scan = scancode;
|
||||
keymap[i].event = keycode;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (keymap[i].keycode == KEY_RESERVED ||
|
||||
keymap[i].keycode == KEY_UNKNOWN) {
|
||||
keymap[i].scancode = scancode;
|
||||
keymap[i].keycode = keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +78,7 @@ static int dvb_usb_setkeycode(struct input_dev *dev,
|
|||
*
|
||||
* TODO: Fix the repeat rate of the input device.
|
||||
*/
|
||||
static void dvb_usb_read_remote_control(struct work_struct *work)
|
||||
static void legacy_dvb_usb_read_remote_control(struct work_struct *work)
|
||||
{
|
||||
struct dvb_usb_device *d =
|
||||
container_of(work, struct dvb_usb_device, rc_query_work.work);
|
||||
|
|
@ -92,7 +92,7 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
if (dvb_usb_disable_rc_polling)
|
||||
return;
|
||||
|
||||
if (d->props.rc_query(d,&event,&state)) {
|
||||
if (d->props.rc.legacy.rc_query(d,&event,&state)) {
|
||||
err("error while querying for an remote control event.");
|
||||
goto schedule;
|
||||
}
|
||||
|
|
@ -151,18 +151,117 @@ static void dvb_usb_read_remote_control(struct work_struct *work)
|
|||
*/
|
||||
|
||||
schedule:
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc.legacy.rc_interval));
|
||||
}
|
||||
|
||||
static int legacy_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
{
|
||||
int i, err, rc_interval;
|
||||
|
||||
input_dev->getkeycode = legacy_dvb_usb_getkeycode;
|
||||
input_dev->setkeycode = legacy_dvb_usb_setkeycode;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc.legacy.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc.legacy.rc_key_map[i].keycode, i);
|
||||
set_bit(d->props.rc.legacy.rc_key_map[i].keycode, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
input_dev->rep[REP_PERIOD] = d->props.rc.legacy.rc_interval;
|
||||
input_dev->rep[REP_DELAY] = d->props.rc.legacy.rc_interval + 150;
|
||||
|
||||
input_set_drvdata(input_dev, d);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err)
|
||||
input_free_device(input_dev);
|
||||
|
||||
rc_interval = d->props.rc.legacy.rc_interval;
|
||||
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, legacy_dvb_usb_read_remote_control);
|
||||
|
||||
info("schedule remote query interval to %d msecs.", rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(rc_interval));
|
||||
|
||||
d->state |= DVB_USB_STATE_REMOTE;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Remote-control poll function - called every dib->rc_query_interval ms to see
|
||||
* whether the remote control has received anything.
|
||||
*
|
||||
* TODO: Fix the repeat rate of the input device.
|
||||
*/
|
||||
static void dvb_usb_read_remote_control(struct work_struct *work)
|
||||
{
|
||||
struct dvb_usb_device *d =
|
||||
container_of(work, struct dvb_usb_device, rc_query_work.work);
|
||||
int err;
|
||||
|
||||
/* TODO: need a lock here. We can simply skip checking for the remote control
|
||||
if we're busy. */
|
||||
|
||||
/* when the parameter has been set to 1 via sysfs while the
|
||||
* driver was running, or when bulk mode is enabled after IR init
|
||||
*/
|
||||
if (dvb_usb_disable_rc_polling || d->props.rc.core.bulk_mode)
|
||||
return;
|
||||
|
||||
err = d->props.rc.core.rc_query(d);
|
||||
if (err)
|
||||
err("error %d while querying for an remote control event.", err);
|
||||
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(d->props.rc.core.rc_interval));
|
||||
}
|
||||
|
||||
static int rc_core_dvb_usb_remote_init(struct dvb_usb_device *d,
|
||||
struct input_dev *input_dev)
|
||||
{
|
||||
int err, rc_interval;
|
||||
|
||||
d->props.rc.core.rc_props.priv = d;
|
||||
err = ir_input_register(input_dev,
|
||||
d->props.rc.core.rc_codes,
|
||||
&d->props.rc.core.rc_props,
|
||||
d->props.rc.core.module_name);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!d->props.rc.core.rc_query || d->props.rc.core.bulk_mode)
|
||||
return 0;
|
||||
|
||||
/* Polling mode - initialize a work queue for handling it */
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
|
||||
|
||||
rc_interval = d->props.rc.core.rc_interval;
|
||||
|
||||
info("schedule remote query interval to %d msecs.", rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,
|
||||
msecs_to_jiffies(rc_interval));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dvb_usb_remote_init(struct dvb_usb_device *d)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int i;
|
||||
int err;
|
||||
|
||||
if (d->props.rc_key_map == NULL ||
|
||||
d->props.rc_query == NULL ||
|
||||
dvb_usb_disable_rc_polling)
|
||||
if (dvb_usb_disable_rc_polling)
|
||||
return 0;
|
||||
|
||||
if (d->props.rc.legacy.rc_key_map && d->props.rc.legacy.rc_query)
|
||||
d->props.rc.mode = DVB_RC_LEGACY;
|
||||
else if (d->props.rc.core.rc_codes)
|
||||
d->props.rc.mode = DVB_RC_CORE;
|
||||
else
|
||||
return 0;
|
||||
|
||||
usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
|
||||
|
|
@ -177,39 +276,19 @@ int dvb_usb_remote_init(struct dvb_usb_device *d)
|
|||
input_dev->phys = d->rc_phys;
|
||||
usb_to_input_id(d->udev, &input_dev->id);
|
||||
input_dev->dev.parent = &d->udev->dev;
|
||||
input_dev->getkeycode = dvb_usb_getkeycode;
|
||||
input_dev->setkeycode = dvb_usb_setkeycode;
|
||||
|
||||
/* set the bits for the keys */
|
||||
deb_rc("key map size: %d\n", d->props.rc_key_map_size);
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++) {
|
||||
deb_rc("setting bit for event %d item %d\n",
|
||||
d->props.rc_key_map[i].event, i);
|
||||
set_bit(d->props.rc_key_map[i].event, input_dev->keybit);
|
||||
}
|
||||
|
||||
/* Start the remote-control polling. */
|
||||
if (d->props.rc_interval < 40)
|
||||
d->props.rc_interval = 100; /* default */
|
||||
|
||||
/* setting these two values to non-zero, we have to manage key repeats */
|
||||
input_dev->rep[REP_PERIOD] = d->props.rc_interval;
|
||||
input_dev->rep[REP_DELAY] = d->props.rc_interval + 150;
|
||||
|
||||
input_set_drvdata(input_dev, d);
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
input_free_device(input_dev);
|
||||
return err;
|
||||
}
|
||||
if (d->props.rc.legacy.rc_interval < 40)
|
||||
d->props.rc.legacy.rc_interval = 100; /* default */
|
||||
|
||||
d->rc_input_dev = input_dev;
|
||||
|
||||
INIT_DELAYED_WORK(&d->rc_query_work, dvb_usb_read_remote_control);
|
||||
|
||||
info("schedule remote query interval to %d msecs.", d->props.rc_interval);
|
||||
schedule_delayed_work(&d->rc_query_work,msecs_to_jiffies(d->props.rc_interval));
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
err = legacy_dvb_usb_remote_init(d, input_dev);
|
||||
else
|
||||
err = rc_core_dvb_usb_remote_init(d, input_dev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
d->state |= DVB_USB_STATE_REMOTE;
|
||||
|
||||
|
|
@ -221,7 +300,10 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
|
|||
if (d->state & DVB_USB_STATE_REMOTE) {
|
||||
cancel_rearming_delayed_work(&d->rc_query_work);
|
||||
flush_scheduled_work();
|
||||
input_unregister_device(d->rc_input_dev);
|
||||
if (d->props.rc.mode == DVB_RC_LEGACY)
|
||||
input_unregister_device(d->rc_input_dev);
|
||||
else
|
||||
ir_input_unregister(d->rc_input_dev);
|
||||
}
|
||||
d->state &= ~DVB_USB_STATE_REMOTE;
|
||||
return 0;
|
||||
|
|
@ -234,7 +316,7 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
u8 keybuf[5], u32 *event, int *state)
|
||||
{
|
||||
int i;
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
*event = 0;
|
||||
*state = REMOTE_NO_KEY_PRESSED;
|
||||
switch (keybuf[0]) {
|
||||
|
|
@ -247,10 +329,10 @@ int dvb_usb_nec_rc_key_to_event(struct dvb_usb_device *d,
|
|||
break;
|
||||
}
|
||||
/* See if we can match the raw key code. */
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (rc5_custom(&keymap[i]) == keybuf[1] &&
|
||||
rc5_data(&keymap[i]) == keybuf[3]) {
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <linux/usb.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_demux.h"
|
||||
|
|
@ -74,30 +75,19 @@ struct dvb_usb_device_description {
|
|||
struct usb_device_id *warm_ids[DVB_USB_ID_MAX_NUM];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_usb_rc_key - a remote control key and its input-event
|
||||
* @custom: the vendor/custom part of the key
|
||||
* @data: the actual key part
|
||||
* @event: the input event assigned to key identified by custom and data
|
||||
*/
|
||||
struct dvb_usb_rc_key {
|
||||
u16 scan;
|
||||
u32 event;
|
||||
};
|
||||
|
||||
static inline u8 rc5_custom(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_custom(struct ir_scancode *key)
|
||||
{
|
||||
return (key->scan >> 8) & 0xff;
|
||||
return (key->scancode >> 8) & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_data(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_data(struct ir_scancode *key)
|
||||
{
|
||||
return key->scan & 0xff;
|
||||
return key->scancode & 0xff;
|
||||
}
|
||||
|
||||
static inline u8 rc5_scan(struct dvb_usb_rc_key *key)
|
||||
static inline u8 rc5_scan(struct ir_scancode *key)
|
||||
{
|
||||
return key->scan & 0xffff;
|
||||
return key->scancode & 0xffff;
|
||||
}
|
||||
|
||||
struct dvb_usb_device;
|
||||
|
|
@ -167,6 +157,55 @@ struct dvb_usb_adapter_properties {
|
|||
unsigned int, void *, unsigned int);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_rc_legacy - old properties of remote controller
|
||||
* @rc_key_map: a hard-wired array of struct ir_scancode (NULL to disable
|
||||
* remote control handling).
|
||||
* @rc_key_map_size: number of items in @rc_key_map.
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
*/
|
||||
struct dvb_rc_legacy {
|
||||
/* remote control properties */
|
||||
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||
#define REMOTE_KEY_PRESSED 0x01
|
||||
#define REMOTE_KEY_REPEAT 0x02
|
||||
struct ir_scancode *rc_key_map;
|
||||
int rc_key_map_size;
|
||||
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||
int rc_interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_rc properties of remote controller, using rc-core
|
||||
* @rc_codes: name of rc codes table
|
||||
* @protocol: type of protocol(s) currently used by the driver
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
* @rc_props: remote controller properties
|
||||
* @bulk_mode: device supports bulk mode for RC (disable polling mode)
|
||||
*/
|
||||
struct dvb_rc {
|
||||
char *rc_codes;
|
||||
u64 protocol;
|
||||
char *module_name;
|
||||
int (*rc_query) (struct dvb_usb_device *d);
|
||||
int rc_interval;
|
||||
struct ir_dev_props rc_props;
|
||||
bool bulk_mode; /* uses bulk mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dvb_usb_mode - Specifies if it is using a legacy driver or a new one
|
||||
* based on rc-core
|
||||
* This is initialized/used only inside dvb-usb-remote.c.
|
||||
* It shouldn't be set by the drivers.
|
||||
*/
|
||||
enum dvb_usb_mode {
|
||||
DVB_RC_LEGACY,
|
||||
DVB_RC_CORE,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dvb_usb_device_properties - properties of a dvb-usb-device
|
||||
* @usb_ctrl: which USB device-side controller is in use. Needed for firmware
|
||||
|
|
@ -185,11 +224,7 @@ struct dvb_usb_adapter_properties {
|
|||
* @identify_state: called to determine the state (cold or warm), when it
|
||||
* is not distinguishable by the USB IDs.
|
||||
*
|
||||
* @rc_key_map: a hard-wired array of struct dvb_usb_rc_key (NULL to disable
|
||||
* remote control handling).
|
||||
* @rc_key_map_size: number of items in @rc_key_map.
|
||||
* @rc_query: called to query an event event.
|
||||
* @rc_interval: time in ms between two queries.
|
||||
* @rc: remote controller properties
|
||||
*
|
||||
* @i2c_algo: i2c_algorithm if the device has I2CoverUSB.
|
||||
*
|
||||
|
|
@ -233,14 +268,11 @@ struct dvb_usb_device_properties {
|
|||
int (*identify_state) (struct usb_device *, struct dvb_usb_device_properties *,
|
||||
struct dvb_usb_device_description **, int *);
|
||||
|
||||
/* remote control properties */
|
||||
#define REMOTE_NO_KEY_PRESSED 0x00
|
||||
#define REMOTE_KEY_PRESSED 0x01
|
||||
#define REMOTE_KEY_REPEAT 0x02
|
||||
struct dvb_usb_rc_key *rc_key_map;
|
||||
int rc_key_map_size;
|
||||
int (*rc_query) (struct dvb_usb_device *, u32 *, int *);
|
||||
int rc_interval;
|
||||
struct {
|
||||
enum dvb_usb_mode mode; /* Drivers shouldn't touch on it */
|
||||
struct dvb_rc_legacy legacy;
|
||||
struct dvb_rc core;
|
||||
} rc;
|
||||
|
||||
struct i2c_algorithm *i2c_algo;
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@
|
|||
"on firmware-problems."
|
||||
|
||||
struct ir_codes_dvb_usb_table_table {
|
||||
struct dvb_usb_rc_key *rc_keys;
|
||||
struct ir_scancode *rc_keys;
|
||||
int rc_keys_size;
|
||||
};
|
||||
|
||||
|
|
@ -948,7 +948,7 @@ static int dw3101_tuner_attach(struct dvb_usb_adapter *adap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
|
||||
static struct ir_scancode ir_codes_dw210x_table[] = {
|
||||
{ 0xf80a, KEY_Q }, /*power*/
|
||||
{ 0xf80c, KEY_M }, /*mute*/
|
||||
{ 0xf811, KEY_1 },
|
||||
|
|
@ -982,7 +982,7 @@ static struct dvb_usb_rc_key ir_codes_dw210x_table[] = {
|
|||
{ 0xf81b, KEY_B }, /*recall*/
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
|
||||
static struct ir_scancode ir_codes_tevii_table[] = {
|
||||
{ 0xf80a, KEY_POWER },
|
||||
{ 0xf80c, KEY_MUTE },
|
||||
{ 0xf811, KEY_1 },
|
||||
|
|
@ -1032,7 +1032,7 @@ static struct dvb_usb_rc_key ir_codes_tevii_table[] = {
|
|||
{ 0xf858, KEY_SWITCHVIDEOMODE },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tbs_table[] = {
|
||||
static struct ir_scancode ir_codes_tbs_table[] = {
|
||||
{ 0xf884, KEY_POWER },
|
||||
{ 0xf894, KEY_MUTE },
|
||||
{ 0xf887, KEY_1 },
|
||||
|
|
@ -1075,8 +1075,8 @@ static struct ir_codes_dvb_usb_table_table keys_tables[] = {
|
|||
|
||||
static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
||||
{
|
||||
struct dvb_usb_rc_key *keymap = d->props.rc_key_map;
|
||||
int keymap_size = d->props.rc_key_map_size;
|
||||
struct ir_scancode *keymap = d->props.rc.legacy.rc_key_map;
|
||||
int keymap_size = d->props.rc.legacy.rc_key_map_size;
|
||||
u8 key[2];
|
||||
struct i2c_msg msg = {
|
||||
.addr = DW2102_RC_QUERY,
|
||||
|
|
@ -1096,7 +1096,7 @@ static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < keymap_size ; i++) {
|
||||
if (rc5_data(&keymap[i]) == msg.buf[0]) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = keymap[i].event;
|
||||
*event = keymap[i].keycode;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1185,13 +1185,13 @@ static int dw2102_load_firmware(struct usb_device *dev,
|
|||
/* init registers */
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case USB_PID_PROF_1100:
|
||||
s6x0_properties.rc_key_map = ir_codes_tbs_table;
|
||||
s6x0_properties.rc_key_map_size =
|
||||
s6x0_properties.rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
s6x0_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tbs_table);
|
||||
break;
|
||||
case USB_PID_TEVII_S650:
|
||||
dw2104_properties.rc_key_map = ir_codes_tevii_table;
|
||||
dw2104_properties.rc_key_map_size =
|
||||
dw2104_properties.rc.legacy.rc_key_map = ir_codes_tevii_table;
|
||||
dw2104_properties.rc.legacy.rc_key_map_size =
|
||||
ARRAY_SIZE(ir_codes_tevii_table);
|
||||
case USB_PID_DW2104:
|
||||
reset = 1;
|
||||
|
|
@ -1255,10 +1255,13 @@ static struct dvb_usb_device_properties dw2102_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw2102_serit_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
|
@ -1306,10 +1309,12 @@ static struct dvb_usb_device_properties dw2104_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw2104_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
|
@ -1353,10 +1358,12 @@ static struct dvb_usb_device_properties dw3101_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &dw3101_i2c_algo,
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_dw210x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_dw210x_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
|
@ -1396,10 +1403,12 @@ static struct dvb_usb_device_properties s6x0_properties = {
|
|||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &s6x0_i2c_algo,
|
||||
.rc_key_map = ir_codes_tevii_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_tevii_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tevii_table),
|
||||
.rc_interval = 150,
|
||||
.rc_query = dw2102_rc_query,
|
||||
},
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
|
|
@ -1459,8 +1468,8 @@ static int dw2102_probe(struct usb_interface *intf,
|
|||
/* fill only different fields */
|
||||
p7500->firmware = "dvb-usb-p7500.fw";
|
||||
p7500->devices[0] = d7500;
|
||||
p7500->rc_key_map = ir_codes_tbs_table;
|
||||
p7500->rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
|
||||
p7500->rc.legacy.rc_key_map = ir_codes_tbs_table;
|
||||
p7500->rc.legacy.rc_key_map_size = ARRAY_SIZE(ir_codes_tbs_table);
|
||||
p7500->adapter->frontend_attach = prof_7500_frontend_attach;
|
||||
|
||||
if (0 == dvb_usb_device_init(intf, &dw2102_properties,
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ static struct dvb_frontend_ops gp8psk_fe_ops = {
|
|||
* FE_CAN_QAM_16 is for compatibility
|
||||
* (Myth incorrectly detects Turbo-QPSK as plain QAM-16)
|
||||
*/
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16
|
||||
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_TURBO_FEC
|
||||
},
|
||||
|
||||
.release = gp8psk_fe_release,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ static int m920x_init(struct dvb_usb_device *d, struct m920x_inits *rc_seq)
|
|||
int adap_enabled[M9206_MAX_ADAPTERS] = { 0 };
|
||||
|
||||
/* Remote controller init. */
|
||||
if (d->props.rc_query) {
|
||||
if (d->props.rc.legacy.rc_query) {
|
||||
deb("Initialising remote control\n");
|
||||
while (rc_seq->address) {
|
||||
if ((ret = m920x_write(d->udev, M9206_CORE,
|
||||
|
|
@ -142,9 +142,9 @@ static int m920x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
if ((ret = m920x_read(d->udev, M9206_CORE, 0x0, M9206_RC_KEY, rc_state + 1, 1)) != 0)
|
||||
goto unlock;
|
||||
|
||||
for (i = 0; i < d->props.rc_key_map_size; i++)
|
||||
if (rc5_data(&d->props.rc_key_map[i]) == rc_state[1]) {
|
||||
*event = d->props.rc_key_map[i].event;
|
||||
for (i = 0; i < d->props.rc.legacy.rc_key_map_size; i++)
|
||||
if (rc5_data(&d->props.rc.legacy.rc_key_map[i]) == rc_state[1]) {
|
||||
*event = d->props.rc.legacy.rc_key_map[i].keycode;
|
||||
|
||||
switch(rc_state[0]) {
|
||||
case 0x80:
|
||||
|
|
@ -589,7 +589,7 @@ static struct m920x_inits pinnacle310e_init[] = {
|
|||
};
|
||||
|
||||
/* ir keymaps */
|
||||
static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
|
||||
static struct ir_scancode ir_codes_megasky_table[] = {
|
||||
{ 0x0012, KEY_POWER },
|
||||
{ 0x001e, KEY_CYCLEWINDOWS }, /* min/max */
|
||||
{ 0x0002, KEY_CHANNELUP },
|
||||
|
|
@ -608,7 +608,7 @@ static struct dvb_usb_rc_key ir_codes_megasky_table [] = {
|
|||
{ 0x000e, KEY_COFFEE }, /* "MTS" */
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
|
||||
static struct ir_scancode ir_codes_tvwalkertwin_table[] = {
|
||||
{ 0x0001, KEY_ZOOM }, /* Full Screen */
|
||||
{ 0x0002, KEY_CAMERA }, /* snapshot */
|
||||
{ 0x0003, KEY_MUTE },
|
||||
|
|
@ -628,7 +628,7 @@ static struct dvb_usb_rc_key ir_codes_tvwalkertwin_table [] = {
|
|||
{ 0x001e, KEY_VOLUMEUP },
|
||||
};
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_pinnacle310e_table[] = {
|
||||
static struct ir_scancode ir_codes_pinnacle310e_table[] = {
|
||||
{ 0x16, KEY_POWER },
|
||||
{ 0x17, KEY_FAVORITES },
|
||||
{ 0x0f, KEY_TEXT },
|
||||
|
|
@ -784,10 +784,12 @@ static struct dvb_usb_device_properties megasky_properties = {
|
|||
.firmware = "dvb-usb-megasky-02.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_megasky_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_megasky_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_megasky_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
|
@ -885,10 +887,12 @@ static struct dvb_usb_device_properties tvwalkertwin_properties = {
|
|||
.firmware = "dvb-usb-tvwalkert.fw",
|
||||
.download_firmware = m920x_firmware_download,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_tvwalkertwin_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_tvwalkertwin_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_tvwalkertwin_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
|
@ -992,10 +996,12 @@ static struct dvb_usb_device_properties pinnacle_pctv310e_properties = {
|
|||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.download_firmware = NULL,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_pinnacle310e_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_pinnacle310e_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_pinnacle310e_table),
|
||||
.rc_query = m920x_rc_query,
|
||||
},
|
||||
|
||||
.size_of_priv = sizeof(struct m920x_state),
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
|||
#define deb_ee(args...) dprintk(debug,0x02,args)
|
||||
|
||||
/* Hauppauge NOVA-T USB2 keys */
|
||||
static struct dvb_usb_rc_key ir_codes_haupp_table [] = {
|
||||
static struct ir_scancode ir_codes_haupp_table[] = {
|
||||
{ 0x1e00, KEY_0 },
|
||||
{ 0x1e01, KEY_1 },
|
||||
{ 0x1e02, KEY_2 },
|
||||
|
|
@ -98,7 +98,7 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
deb_rc("c: %x, d: %x\n", rc5_data(&ir_codes_haupp_table[i]),
|
||||
rc5_custom(&ir_codes_haupp_table[i]));
|
||||
|
||||
*event = ir_codes_haupp_table[i].event;
|
||||
*event = ir_codes_haupp_table[i].keycode;
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
if (st->old_toggle == toggle) {
|
||||
if (st->last_repeat_count++ < 2)
|
||||
|
|
@ -195,10 +195,12 @@ static struct dvb_usb_device_properties nova_t_properties = {
|
|||
.power_ctrl = dibusb2_0_power_ctrl,
|
||||
.read_mac_address = nova_t_read_mac_address,
|
||||
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_haupp_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table),
|
||||
.rc_query = nova_t_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 100,
|
||||
.rc_key_map = ir_codes_haupp_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_haupp_table),
|
||||
.rc_query = nova_t_rc_query,
|
||||
},
|
||||
|
||||
.i2c_algo = &dibusb_i2c_algo,
|
||||
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ static int opera1_pid_filter_control(struct dvb_usb_adapter *adap, int onoff)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct dvb_usb_rc_key ir_codes_opera1_table[] = {
|
||||
static struct ir_scancode ir_codes_opera1_table[] = {
|
||||
{0x5fa0, KEY_1},
|
||||
{0x51af, KEY_2},
|
||||
{0x5da2, KEY_3},
|
||||
|
|
@ -407,9 +407,9 @@ static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_opera1_table); i++) {
|
||||
if (rc5_scan(&ir_codes_opera1_table[i]) == (send_key & 0xffff)) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_opera1_table[i].event;
|
||||
*event = ir_codes_opera1_table[i].keycode;
|
||||
opst->last_key_pressed =
|
||||
ir_codes_opera1_table[i].event;
|
||||
ir_codes_opera1_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
opst->last_key_pressed = 0;
|
||||
|
|
@ -498,10 +498,12 @@ static struct dvb_usb_device_properties opera1_properties = {
|
|||
.power_ctrl = opera1_power_ctrl,
|
||||
.i2c_algo = &opera1_i2c_algo,
|
||||
|
||||
.rc_key_map = ir_codes_opera1_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
|
||||
.rc_interval = 200,
|
||||
.rc_query = opera1_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_opera1_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_opera1_table),
|
||||
.rc_interval = 200,
|
||||
.rc_query = opera1_rc_query,
|
||||
},
|
||||
.read_mac_address = opera1_read_mac_address,
|
||||
.generic_bulk_ctrl_endpoint = 0x00,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ static int vp702x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
|
|||
}
|
||||
|
||||
/* keys for the enclosed remote control */
|
||||
static struct dvb_usb_rc_key ir_codes_vp702x_table[] = {
|
||||
static struct ir_scancode ir_codes_vp702x_table[] = {
|
||||
{ 0x0001, KEY_1 },
|
||||
{ 0x0002, KEY_2 },
|
||||
};
|
||||
|
|
@ -200,7 +200,7 @@ static int vp702x_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp702x_table); i++)
|
||||
if (rc5_custom(&ir_codes_vp702x_table[i]) == key[1]) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp702x_table[i].event;
|
||||
*event = ir_codes_vp702x_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -283,10 +283,12 @@ static struct dvb_usb_device_properties vp702x_properties = {
|
|||
},
|
||||
.read_mac_address = vp702x_read_mac_addr,
|
||||
|
||||
.rc_key_map = ir_codes_vp702x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = vp702x_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_key_map = ir_codes_vp702x_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp702x_table),
|
||||
.rc_interval = 400,
|
||||
.rc_query = vp702x_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ static int vp7045_power_ctrl(struct dvb_usb_device *d, int onoff)
|
|||
|
||||
/* The keymapping struct. Somehow this should be loaded to the driver, but
|
||||
* currently it is hardcoded. */
|
||||
static struct dvb_usb_rc_key ir_codes_vp7045_table[] = {
|
||||
static struct ir_scancode ir_codes_vp7045_table[] = {
|
||||
{ 0x0016, KEY_POWER },
|
||||
{ 0x0010, KEY_MUTE },
|
||||
{ 0x0003, KEY_1 },
|
||||
|
|
@ -168,7 +168,7 @@ static int vp7045_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
|
|||
for (i = 0; i < ARRAY_SIZE(ir_codes_vp7045_table); i++)
|
||||
if (rc5_data(&ir_codes_vp7045_table[i]) == key) {
|
||||
*state = REMOTE_KEY_PRESSED;
|
||||
*event = ir_codes_vp7045_table[i].event;
|
||||
*event = ir_codes_vp7045_table[i].keycode;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -259,10 +259,12 @@ static struct dvb_usb_device_properties vp7045_properties = {
|
|||
.power_ctrl = vp7045_power_ctrl,
|
||||
.read_mac_address = vp7045_read_mac_addr,
|
||||
|
||||
.rc_interval = 400,
|
||||
.rc_key_map = ir_codes_vp7045_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table),
|
||||
.rc_query = vp7045_rc_query,
|
||||
.rc.legacy = {
|
||||
.rc_interval = 400,
|
||||
.rc_key_map = ir_codes_vp7045_table,
|
||||
.rc_key_map_size = ARRAY_SIZE(ir_codes_vp7045_table),
|
||||
.rc_query = vp7045_rc_query,
|
||||
},
|
||||
|
||||
.num_device_descs = 2,
|
||||
.devices = {
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@ config DVB_LGS8GL5
|
|||
config DVB_LGS8GXX
|
||||
tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
|
||||
depends on DVB_CORE && I2C
|
||||
select FW_LOADER
|
||||
default m if DVB_FE_CUSTOMISE
|
||||
help
|
||||
A DMB-TH tuner module. Say Y when you want to support this frontend.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
|
@ -761,6 +761,10 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
state->frequency = params->frequency;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
/* program CFOE coefficients */
|
||||
ret = af9013_set_coeff(state, params->u.ofdm.bandwidth);
|
||||
if (ret)
|
||||
|
|
@ -791,10 +795,6 @@ static int af9013_set_frontend(struct dvb_frontend *fe,
|
|||
if (ret)
|
||||
goto error;
|
||||
|
||||
/* program tuner */
|
||||
if (fe->ops.tuner_ops.set_params)
|
||||
fe->ops.tuner_ops.set_params(fe, params);
|
||||
|
||||
/* program TPS and bandwidth, check if auto mode needed */
|
||||
ret = af9013_set_ofdm_params(state, ¶ms->u.ofdm, &auto_mode);
|
||||
if (ret)
|
||||
|
|
@ -1184,21 +1184,43 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
u8 tmp;
|
||||
*status = 0;
|
||||
|
||||
/* TPS lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_VITERBI | FE_HAS_CARRIER | FE_HAS_SIGNAL;
|
||||
|
||||
/* MPEG2 lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd507, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
|
||||
FE_HAS_SYNC | FE_HAS_LOCK;
|
||||
|
||||
if (!(*status & FE_HAS_SIGNAL)) {
|
||||
if (!*status) {
|
||||
/* TPS lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd330, 3, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER |
|
||||
FE_HAS_VITERBI;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* CFO lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* SFOE lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_SIGNAL | FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!*status) {
|
||||
/* AGC lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd1a0, 6, 1, &tmp);
|
||||
if (ret)
|
||||
|
|
@ -1207,24 +1229,6 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
*status |= FE_HAS_SIGNAL;
|
||||
}
|
||||
|
||||
if (!(*status & FE_HAS_CARRIER)) {
|
||||
/* CFO lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd333, 7, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
if (!(*status & FE_HAS_CARRIER)) {
|
||||
/* SFOE lock */
|
||||
ret = af9013_read_reg_bits(state, 0xd334, 6, 1, &tmp);
|
||||
if (ret)
|
||||
goto error;
|
||||
if (tmp)
|
||||
*status |= FE_HAS_CARRIER;
|
||||
}
|
||||
|
||||
ret = af9013_update_statistics(fe);
|
||||
|
||||
error:
|
||||
|
|
@ -1574,7 +1578,7 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
{
|
||||
int ret;
|
||||
struct af9013_state *state = NULL;
|
||||
u8 buf[3], i;
|
||||
u8 buf[4], i;
|
||||
|
||||
/* allocate memory for the internal state */
|
||||
state = kzalloc(sizeof(struct af9013_state), GFP_KERNEL);
|
||||
|
|
@ -1607,12 +1611,12 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
|
|||
}
|
||||
|
||||
/* firmware version */
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = af9013_read_reg(state, 0x5103 + i, &buf[i]);
|
||||
if (ret)
|
||||
goto error;
|
||||
}
|
||||
info("firmware version:%d.%d.%d", buf[0], buf[1], buf[2]);
|
||||
info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
|
||||
|
||||
/* settings for mp2if */
|
||||
if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
|
||||
* Afatech AF9013 demodulator driver
|
||||
*
|
||||
* Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
|
||||
*
|
||||
|
|
@ -132,6 +132,8 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd740, 2, 1, 0x00 },
|
||||
{ 0xd740, 3, 1, 0x01 },
|
||||
{ 0xd3c1, 4, 1, 0x01 },
|
||||
{ 0x9124, 0, 8, 0x58 },
|
||||
{ 0x9125, 0, 2, 0x02 },
|
||||
{ 0xd3a2, 0, 8, 0x00 },
|
||||
{ 0xd3a3, 0, 8, 0x04 },
|
||||
{ 0xd305, 0, 8, 0x32 },
|
||||
|
|
@ -143,7 +145,7 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0x911b, 0, 1, 0x01 },
|
||||
{ 0x9bce, 0, 4, 0x02 },
|
||||
{ 0x9116, 0, 1, 0x01 },
|
||||
{ 0x9bd1, 0, 1, 0x01 },
|
||||
{ 0x9122, 0, 8, 0xd0 },
|
||||
{ 0xd2e0, 0, 8, 0xd0 },
|
||||
{ 0xd2e9, 0, 4, 0x0d },
|
||||
{ 0xd38c, 0, 8, 0xfc },
|
||||
|
|
@ -165,7 +167,6 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd081, 4, 4, 0x09 },
|
||||
{ 0xd098, 4, 4, 0x0f },
|
||||
{ 0xd098, 0, 4, 0x03 },
|
||||
{ 0xdbc0, 3, 1, 0x01 },
|
||||
{ 0xdbc0, 4, 1, 0x01 },
|
||||
{ 0xdbc7, 0, 8, 0x08 },
|
||||
{ 0xdbc8, 4, 4, 0x00 },
|
||||
|
|
@ -179,6 +180,7 @@ static struct regdesc ofsm_init[] = {
|
|||
{ 0xd0f0, 0, 7, 0x1a },
|
||||
{ 0xd0f1, 4, 1, 0x01 },
|
||||
{ 0xd0f2, 0, 8, 0x0c },
|
||||
{ 0xd101, 5, 3, 0x06 },
|
||||
{ 0xd103, 0, 4, 0x08 },
|
||||
{ 0xd0f8, 0, 7, 0x20 },
|
||||
{ 0xd111, 5, 1, 0x00 },
|
||||
|
|
|
|||
|
|
@ -38,11 +38,10 @@
|
|||
#define DRIVER_DESC "DiBcom 3000M-B DVB-T demodulator"
|
||||
#define DRIVER_AUTHOR "Patrick Boettcher, [email protected]"
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-able)).");
|
||||
#endif
|
||||
|
||||
#define deb_info(args...) dprintk(0x01,args)
|
||||
#define deb_i2c(args...) dprintk(0x02,args)
|
||||
#define deb_srch(args...) dprintk(0x04,args)
|
||||
|
|
@ -51,12 +50,6 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
|
|||
#define deb_setf(args...) dprintk(0x04,args)
|
||||
#define deb_getf(args...) dprintk(0x08,args)
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
static int debug;
|
||||
module_param(debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info,2=i2c,4=srch (|-able)).");
|
||||
#endif
|
||||
|
||||
static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
|
||||
{
|
||||
u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
|
||||
|
|
|
|||
|
|
@ -37,12 +37,8 @@
|
|||
|
||||
/* debug */
|
||||
|
||||
#ifdef CONFIG_DVB_DIBCOM_DEBUG
|
||||
#define dprintk(level,args...) \
|
||||
do { if ((debug & level)) { printk(args); } } while (0)
|
||||
#else
|
||||
#define dprintk(args...) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* mask for enabling a specific pid for the pid_filter */
|
||||
#define DIB3000_ACTIVATE_PID_FILTERING (0x2000)
|
||||
|
|
|
|||
|
|
@ -822,7 +822,7 @@ int dib3000mc_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defa
|
|||
|
||||
dmcst = kzalloc(sizeof(struct dib3000mc_state), GFP_KERNEL);
|
||||
if (dmcst == NULL)
|
||||
return -ENODEV;
|
||||
return -ENOMEM;
|
||||
|
||||
dmcst->i2c_adap = i2c;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
/*
|
||||
* Support for LGDT3305 - VSB/QAM
|
||||
* Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
|
||||
*
|
||||
* Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
|
||||
* Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
|
||||
*
|
||||
* LGDT3304 support by Jarod Wilson <jarod@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -65,6 +67,8 @@ struct lgdt3305_state {
|
|||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* FIXME: verify & document the LGDT3304 registers */
|
||||
|
||||
#define LGDT3305_GEN_CTRL_1 0x0000
|
||||
#define LGDT3305_GEN_CTRL_2 0x0001
|
||||
#define LGDT3305_GEN_CTRL_3 0x0002
|
||||
|
|
@ -358,7 +362,12 @@ static int lgdt3305_rfagc_loop(struct lgdt3305_state *state,
|
|||
case QAM_256:
|
||||
agcdelay = 0x046b;
|
||||
rfbw = 0x8889;
|
||||
ifbw = 0x8888;
|
||||
/* FIXME: investigate optimal ifbw & rfbw values for the
|
||||
* DT3304 and re-write this switch..case block */
|
||||
if (state->cfg->demod_chip == LGDT3304)
|
||||
ifbw = 0x6666;
|
||||
else /* (state->cfg->demod_chip == LGDT3305) */
|
||||
ifbw = 0x8888;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -410,8 +419,18 @@ static int lgdt3305_agc_setup(struct lgdt3305_state *state,
|
|||
lg_dbg("lockdten = %d, acqen = %d\n", lockdten, acqen);
|
||||
|
||||
/* control agc function */
|
||||
lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
||||
switch (state->cfg->demod_chip) {
|
||||
case LGDT3304:
|
||||
lgdt3305_write_reg(state, 0x0314, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, 0x030e, 2, acqen);
|
||||
break;
|
||||
case LGDT3305:
|
||||
lgdt3305_write_reg(state, LGDT3305_AGC_CTRL_4, 0xe1 | lockdten << 1);
|
||||
lgdt3305_set_reg_bit(state, LGDT3305_AGC_CTRL_1, 2, acqen);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return lgdt3305_rfagc_loop(state, param);
|
||||
}
|
||||
|
|
@ -577,61 +596,79 @@ static int lgdt3305_init(struct dvb_frontend *fe)
|
|||
struct lgdt3305_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
static struct lgdt3305_reg lgdt3304_init_data[] = {
|
||||
{ .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
|
||||
{ .reg = 0x000d, .val = 0x02, },
|
||||
{ .reg = 0x000e, .val = 0x02, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7, .val = 0xf9, },
|
||||
{ .reg = 0x0112, .val = 0x17, },
|
||||
{ .reg = 0x0113, .val = 0x15, },
|
||||
{ .reg = 0x0114, .val = 0x18, },
|
||||
{ .reg = 0x0115, .val = 0xff, },
|
||||
{ .reg = 0x0116, .val = 0x3c, },
|
||||
{ .reg = 0x0214, .val = 0x67, },
|
||||
{ .reg = 0x0424, .val = 0x8d, },
|
||||
{ .reg = 0x0427, .val = 0x12, },
|
||||
{ .reg = 0x0428, .val = 0x4f, },
|
||||
{ .reg = LGDT3305_IFBW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2, .val = 0x00, },
|
||||
{ .reg = 0x030a, .val = 0x08, },
|
||||
{ .reg = 0x030b, .val = 0x9b, },
|
||||
{ .reg = 0x030d, .val = 0x00, },
|
||||
{ .reg = 0x030e, .val = 0x1c, },
|
||||
{ .reg = 0x0314, .val = 0xe1, },
|
||||
{ .reg = 0x000d, .val = 0x82, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x5b, },
|
||||
};
|
||||
|
||||
static struct lgdt3305_reg lgdt3305_init_data[] = {
|
||||
{ .reg = LGDT3305_GEN_CTRL_1,
|
||||
.val = 0x03, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_2,
|
||||
.val = 0xb0, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_3,
|
||||
.val = 0x01, },
|
||||
{ .reg = LGDT3305_GEN_CONTROL,
|
||||
.val = 0x6f, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_4,
|
||||
.val = 0x03, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1,
|
||||
.val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2,
|
||||
.val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7,
|
||||
.val = 0x79, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_1,
|
||||
.val = 0x32, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_2,
|
||||
.val = 0xc4, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_1,
|
||||
.val = 0x0d, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_2,
|
||||
.val = 0x30, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1,
|
||||
.val = 0x80, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_IFBW_1,
|
||||
.val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2,
|
||||
.val = 0x00, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_1,
|
||||
.val = 0x30, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_4,
|
||||
.val = 0x61, },
|
||||
{ .reg = LGDT3305_FEC_BLOCK_CTRL,
|
||||
.val = 0xff, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1,
|
||||
.val = 0x1b, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_1, .val = 0x03, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_2, .val = 0xb0, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_3, .val = 0x01, },
|
||||
{ .reg = LGDT3305_GEN_CONTROL, .val = 0x6f, },
|
||||
{ .reg = LGDT3305_GEN_CTRL_4, .val = 0x03, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_DGTL_AGC_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_1, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_3, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTR_FREQ_4, .val = 0x00, },
|
||||
{ .reg = LGDT3305_CR_CTRL_7, .val = 0x79, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_1, .val = 0x32, },
|
||||
{ .reg = LGDT3305_AGC_POWER_REF_2, .val = 0xc4, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_1, .val = 0x0d, },
|
||||
{ .reg = LGDT3305_AGC_DELAY_PT_2, .val = 0x30, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_RFAGC_LOOP_FLTR_BW_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_IFBW_1, .val = 0x80, },
|
||||
{ .reg = LGDT3305_IFBW_2, .val = 0x00, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_1, .val = 0x30, },
|
||||
{ .reg = LGDT3305_AGC_CTRL_4, .val = 0x61, },
|
||||
{ .reg = LGDT3305_FEC_BLOCK_CTRL, .val = 0xff, },
|
||||
{ .reg = LGDT3305_TP_CTRL_1, .val = 0x1b, },
|
||||
};
|
||||
|
||||
lg_dbg("\n");
|
||||
|
||||
ret = lgdt3305_write_regs(state, lgdt3305_init_data,
|
||||
ARRAY_SIZE(lgdt3305_init_data));
|
||||
switch (state->cfg->demod_chip) {
|
||||
case LGDT3304:
|
||||
ret = lgdt3305_write_regs(state, lgdt3304_init_data,
|
||||
ARRAY_SIZE(lgdt3304_init_data));
|
||||
break;
|
||||
case LGDT3305:
|
||||
ret = lgdt3305_write_regs(state, lgdt3305_init_data,
|
||||
ARRAY_SIZE(lgdt3305_init_data));
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -640,6 +677,76 @@ fail:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int lgdt3304_set_parameters(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *param)
|
||||
{
|
||||
struct lgdt3305_state *state = fe->demodulator_priv;
|
||||
int ret;
|
||||
|
||||
lg_dbg("(%d, %d)\n", param->frequency, param->u.vsb.modulation);
|
||||
|
||||
if (fe->ops.tuner_ops.set_params) {
|
||||
ret = fe->ops.tuner_ops.set_params(fe, param);
|
||||
if (fe->ops.i2c_gate_ctrl)
|
||||
fe->ops.i2c_gate_ctrl(fe, 0);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
state->current_frequency = param->frequency;
|
||||
}
|
||||
|
||||
ret = lgdt3305_set_modulation(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = lgdt3305_passband_digital_agc(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
ret = lgdt3305_agc_setup(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* reg 0x030d is 3304-only... seen in vsb and qam usbsnoops... */
|
||||
switch (param->u.vsb.modulation) {
|
||||
case VSB_8:
|
||||
lgdt3305_write_reg(state, 0x030d, 0x00);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_1, 0x4f);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_2, 0x0c);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_3, 0xac);
|
||||
lgdt3305_write_reg(state, LGDT3305_CR_CTR_FREQ_4, 0xba);
|
||||
break;
|
||||
case QAM_64:
|
||||
case QAM_256:
|
||||
lgdt3305_write_reg(state, 0x030d, 0x14);
|
||||
ret = lgdt3305_set_if(state, param);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
||||
ret = lgdt3305_spectral_inversion(state, param,
|
||||
state->cfg->spectral_inversion
|
||||
? 1 : 0);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
state->current_modulation = param->u.vsb.modulation;
|
||||
|
||||
ret = lgdt3305_mpeg_mode(state, state->cfg->mpeg_mode);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
||||
/* lgdt3305_mpeg_mode_polarity calls lgdt3305_soft_reset */
|
||||
ret = lgdt3305_mpeg_mode_polarity(state,
|
||||
state->cfg->tpclk_edge,
|
||||
state->cfg->tpvalid_polarity);
|
||||
fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int lgdt3305_set_parameters(struct dvb_frontend *fe,
|
||||
struct dvb_frontend_parameters *param)
|
||||
{
|
||||
|
|
@ -848,6 +955,10 @@ static int lgdt3305_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
switch (state->current_modulation) {
|
||||
case QAM_256:
|
||||
case QAM_64:
|
||||
/* signal bit is unreliable on the DT3304 in QAM mode */
|
||||
if (((LGDT3304 == state->cfg->demod_chip)) && (cr_lock))
|
||||
*status |= FE_HAS_SIGNAL;
|
||||
|
||||
ret = lgdt3305_read_fec_lock_status(state, &fec_lock);
|
||||
if (lg_fail(ret))
|
||||
goto fail;
|
||||
|
|
@ -993,6 +1104,7 @@ static void lgdt3305_release(struct dvb_frontend *fe)
|
|||
kfree(state);
|
||||
}
|
||||
|
||||
static struct dvb_frontend_ops lgdt3304_ops;
|
||||
static struct dvb_frontend_ops lgdt3305_ops;
|
||||
|
||||
struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
||||
|
|
@ -1013,11 +1125,21 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|||
state->cfg = config;
|
||||
state->i2c_adap = i2c_adap;
|
||||
|
||||
memcpy(&state->frontend.ops, &lgdt3305_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
switch (config->demod_chip) {
|
||||
case LGDT3304:
|
||||
memcpy(&state->frontend.ops, &lgdt3304_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
case LGDT3305:
|
||||
memcpy(&state->frontend.ops, &lgdt3305_ops,
|
||||
sizeof(struct dvb_frontend_ops));
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
state->frontend.demodulator_priv = state;
|
||||
|
||||
/* verify that we're talking to a lg dt3305 */
|
||||
/* verify that we're talking to a lg dt3304/5 */
|
||||
ret = lgdt3305_read_reg(state, LGDT3305_GEN_CTRL_2, &val);
|
||||
if ((lg_fail(ret)) | (val == 0))
|
||||
goto fail;
|
||||
|
|
@ -1036,12 +1158,35 @@ struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
|
|||
|
||||
return &state->frontend;
|
||||
fail:
|
||||
lg_warn("unable to detect LGDT3305 hardware\n");
|
||||
lg_warn("unable to detect %s hardware\n",
|
||||
config->demod_chip ? "LGDT3304" : "LGDT3305");
|
||||
kfree(state);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(lgdt3305_attach);
|
||||
|
||||
static struct dvb_frontend_ops lgdt3304_ops = {
|
||||
.info = {
|
||||
.name = "LG Electronics LGDT3304 VSB/QAM Frontend",
|
||||
.type = FE_ATSC,
|
||||
.frequency_min = 54000000,
|
||||
.frequency_max = 858000000,
|
||||
.frequency_stepsize = 62500,
|
||||
.caps = FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB
|
||||
},
|
||||
.i2c_gate_ctrl = lgdt3305_i2c_gate_ctrl,
|
||||
.init = lgdt3305_init,
|
||||
.set_frontend = lgdt3304_set_parameters,
|
||||
.get_frontend = lgdt3305_get_frontend,
|
||||
.get_tune_settings = lgdt3305_get_tune_settings,
|
||||
.read_status = lgdt3305_read_status,
|
||||
.read_ber = lgdt3305_read_ber,
|
||||
.read_signal_strength = lgdt3305_read_signal_strength,
|
||||
.read_snr = lgdt3305_read_snr,
|
||||
.read_ucblocks = lgdt3305_read_ucblocks,
|
||||
.release = lgdt3305_release,
|
||||
};
|
||||
|
||||
static struct dvb_frontend_ops lgdt3305_ops = {
|
||||
.info = {
|
||||
.name = "LG Electronics LGDT3305 VSB/QAM Frontend",
|
||||
|
|
@ -1065,10 +1210,10 @@ static struct dvb_frontend_ops lgdt3305_ops = {
|
|||
.release = lgdt3305_release,
|
||||
};
|
||||
|
||||
MODULE_DESCRIPTION("LG Electronics LGDT3305 ATSC/QAM-B Demodulator Driver");
|
||||
MODULE_DESCRIPTION("LG Electronics LGDT3304/5 ATSC/QAM-B Demodulator Driver");
|
||||
MODULE_AUTHOR("Michael Krufky <[email protected]>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.1");
|
||||
MODULE_VERSION("0.2");
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Support for LGDT3305 - VSB/QAM
|
||||
* Support for LG Electronics LGDT3304 and LGDT3305 - VSB/QAM
|
||||
*
|
||||
* Copyright (C) 2008, 2009 Michael Krufky <mkrufky@linuxtv.org>
|
||||
* Copyright (C) 2008, 2009, 2010 Michael Krufky <mkrufky@linuxtv.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
@ -41,6 +41,11 @@ enum lgdt3305_tp_valid_polarity {
|
|||
LGDT3305_TP_VALID_HIGH = 1,
|
||||
};
|
||||
|
||||
enum lgdt_demod_chip_type {
|
||||
LGDT3305 = 0,
|
||||
LGDT3304 = 1,
|
||||
};
|
||||
|
||||
struct lgdt3305_config {
|
||||
u8 i2c_addr;
|
||||
|
||||
|
|
@ -65,6 +70,7 @@ struct lgdt3305_config {
|
|||
enum lgdt3305_mpeg_mode mpeg_mode;
|
||||
enum lgdt3305_tp_clock_edge tpclk_edge;
|
||||
enum lgdt3305_tp_valid_polarity tpvalid_polarity;
|
||||
enum lgdt_demod_chip_type demod_chip;
|
||||
};
|
||||
|
||||
#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "dvb_frontend.h"
|
||||
|
||||
|
|
@ -46,42 +47,6 @@ module_param(fake_signal_str, int, 0644);
|
|||
MODULE_PARM_DESC(fake_signal_str, "fake signal strength for LGS8913."
|
||||
"Signal strength calculation is slow.(default:on).");
|
||||
|
||||
static const u8 lgs8g75_initdat[] = {
|
||||
0x01, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE4, 0xF5, 0xA8, 0xF5, 0xB8, 0xF5, 0x88, 0xF5,
|
||||
0x89, 0xF5, 0x87, 0x75, 0xD0, 0x00, 0x11, 0x50,
|
||||
0x11, 0x50, 0xF4, 0xF5, 0x80, 0xF5, 0x90, 0xF5,
|
||||
0xA0, 0xF5, 0xB0, 0x75, 0x81, 0x30, 0x80, 0x01,
|
||||
0x32, 0x90, 0x80, 0x12, 0x74, 0xFF, 0xF0, 0x90,
|
||||
0x80, 0x13, 0x74, 0x1F, 0xF0, 0x90, 0x80, 0x23,
|
||||
0x74, 0x01, 0xF0, 0x90, 0x80, 0x22, 0xF0, 0x90,
|
||||
0x00, 0x48, 0x74, 0x00, 0xF0, 0x90, 0x80, 0x4D,
|
||||
0x74, 0x05, 0xF0, 0x90, 0x80, 0x09, 0xE0, 0x60,
|
||||
0x21, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x1B, 0x12,
|
||||
0x00, 0xDD, 0x14, 0x60, 0x15, 0x12, 0x00, 0xDD,
|
||||
0x14, 0x60, 0x0F, 0x12, 0x00, 0xDD, 0x14, 0x60,
|
||||
0x09, 0x12, 0x00, 0xDD, 0x14, 0x60, 0x03, 0x12,
|
||||
0x00, 0xDD, 0x90, 0x80, 0x42, 0xE0, 0x60, 0x0B,
|
||||
0x14, 0x60, 0x0C, 0x14, 0x60, 0x0D, 0x14, 0x60,
|
||||
0x0E, 0x01, 0xB3, 0x74, 0x04, 0x01, 0xB9, 0x74,
|
||||
0x05, 0x01, 0xB9, 0x74, 0x07, 0x01, 0xB9, 0x74,
|
||||
0x0A, 0xC0, 0xE0, 0x74, 0xC8, 0x12, 0x00, 0xE2,
|
||||
0xD0, 0xE0, 0x14, 0x70, 0xF4, 0x90, 0x80, 0x09,
|
||||
0xE0, 0x70, 0xAE, 0x12, 0x00, 0xF6, 0x12, 0x00,
|
||||
0xFE, 0x90, 0x00, 0x48, 0xE0, 0x04, 0xF0, 0x90,
|
||||
0x80, 0x4E, 0xF0, 0x01, 0x73, 0x90, 0x80, 0x08,
|
||||
0xF0, 0x22, 0xF8, 0x7A, 0x0C, 0x79, 0xFD, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD9,
|
||||
0xF6, 0xDA, 0xF2, 0xD8, 0xEE, 0x22, 0x90, 0x80,
|
||||
0x65, 0xE0, 0x54, 0xFD, 0xF0, 0x22, 0x90, 0x80,
|
||||
0x65, 0xE0, 0x44, 0xC2, 0xF0, 0x22
|
||||
};
|
||||
|
||||
/* LGS8GXX internal helper functions */
|
||||
|
||||
static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data)
|
||||
|
|
@ -627,9 +592,14 @@ static int lgs8913_init(struct lgs8gxx_state *priv)
|
|||
|
||||
static int lgs8g75_init_data(struct lgs8gxx_state *priv)
|
||||
{
|
||||
const u8 *p = lgs8g75_initdat;
|
||||
const struct firmware *fw;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
rc = request_firmware(&fw, "lgs8g75.fw", &priv->i2c->dev);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
lgs8gxx_write_reg(priv, 0xC6, 0x40);
|
||||
|
||||
lgs8gxx_write_reg(priv, 0x3D, 0x04);
|
||||
|
|
@ -640,16 +610,16 @@ static int lgs8g75_init_data(struct lgs8gxx_state *priv)
|
|||
lgs8gxx_write_reg(priv, 0x3B, 0x00);
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
|
||||
for (i = 0; i < sizeof(lgs8g75_initdat); i++) {
|
||||
for (i = 0; i < fw->size; i++) {
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
lgs8gxx_write_reg(priv, 0x3A, (u8)(i&0xff));
|
||||
lgs8gxx_write_reg(priv, 0x3B, (u8)(i>>8));
|
||||
lgs8gxx_write_reg(priv, 0x3C, *p);
|
||||
p++;
|
||||
lgs8gxx_write_reg(priv, 0x3C, fw->data[i]);
|
||||
}
|
||||
|
||||
lgs8gxx_write_reg(priv, 0x38, 0x00);
|
||||
|
||||
release_firmware(fw);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1833,7 +1833,6 @@ static struct dvb_frontend_ops mb86a16_ops = {
|
|||
|
||||
.get_frontend_algo = mb86a16_frontend_algo,
|
||||
.search = mb86a16_search,
|
||||
.read_status = mb86a16_read_status,
|
||||
.init = mb86a16_init,
|
||||
.sleep = mb86a16_sleep,
|
||||
.read_status = mb86a16_read_status,
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/math64.h>
|
||||
#include <asm/div64.h>
|
||||
#include "dvb_frontend.h"
|
||||
#include "dvb_math.h"
|
||||
|
|
@ -49,8 +50,8 @@
|
|||
#define TDA10048_CONF_C4_1 0x1E
|
||||
#define TDA10048_CONF_C4_2 0x1F
|
||||
#define TDA10048_CODE_IN_RAM 0x20
|
||||
#define TDA10048_CHANNEL_INFO_1_R 0x22
|
||||
#define TDA10048_CHANNEL_INFO_2_R 0x23
|
||||
#define TDA10048_CHANNEL_INFO1_R 0x22
|
||||
#define TDA10048_CHANNEL_INFO2_R 0x23
|
||||
#define TDA10048_CHANNEL_INFO1 0x24
|
||||
#define TDA10048_CHANNEL_INFO2 0x25
|
||||
#define TDA10048_TIME_ERROR_R 0x26
|
||||
|
|
@ -63,8 +64,8 @@
|
|||
#define TDA10048_IT_STAT 0x32
|
||||
#define TDA10048_DSP_AD_LSB 0x3C
|
||||
#define TDA10048_DSP_AD_MSB 0x3D
|
||||
#define TDA10048_DSP_REF_LSB 0x3E
|
||||
#define TDA10048_DSP_REF_MSB 0x3F
|
||||
#define TDA10048_DSP_REG_LSB 0x3E
|
||||
#define TDA10048_DSP_REG_MSB 0x3F
|
||||
#define TDA10048_CONF_TRISTATE1 0x44
|
||||
#define TDA10048_CONF_TRISTATE2 0x45
|
||||
#define TDA10048_CONF_POLARITY 0x46
|
||||
|
|
@ -112,7 +113,7 @@
|
|||
#define TDA10048_FREE_REG_1 0xB2
|
||||
#define TDA10048_FREE_REG_2 0xB3
|
||||
#define TDA10048_CONF_C3_1 0xC0
|
||||
#define TDA10048_CYBER_CTRL 0xC2
|
||||
#define TDA10048_CVBER_CTRL 0xC2
|
||||
#define TDA10048_CBER_NMAX_LSB 0xC4
|
||||
#define TDA10048_CBER_NMAX_MSB 0xC5
|
||||
#define TDA10048_CBER_LSB 0xC6
|
||||
|
|
@ -120,7 +121,7 @@
|
|||
#define TDA10048_VBER_LSB 0xC8
|
||||
#define TDA10048_VBER_MID 0xC9
|
||||
#define TDA10048_VBER_MSB 0xCA
|
||||
#define TDA10048_CYBER_LUT 0xCC
|
||||
#define TDA10048_CVBER_LUT 0xCC
|
||||
#define TDA10048_UNCOR_CTRL 0xCD
|
||||
#define TDA10048_UNCOR_CPT_LSB 0xCE
|
||||
#define TDA10048_UNCOR_CPT_MSB 0xCF
|
||||
|
|
@ -183,7 +184,7 @@ static struct init_tab {
|
|||
{ TDA10048_AGC_IF_MAX, 0xff },
|
||||
{ TDA10048_AGC_THRESHOLD_MSB, 0x00 },
|
||||
{ TDA10048_AGC_THRESHOLD_LSB, 0x70 },
|
||||
{ TDA10048_CYBER_CTRL, 0x38 },
|
||||
{ TDA10048_CVBER_CTRL, 0x38 },
|
||||
{ TDA10048_AGC_GAINS, 0x12 },
|
||||
{ TDA10048_CONF_XO, 0x00 },
|
||||
{ TDA10048_CONF_TS1, 0x07 },
|
||||
|
|
@ -688,7 +689,7 @@ static int tda10048_get_tps(struct tda10048_state *state,
|
|||
p->guard_interval = GUARD_INTERVAL_1_4;
|
||||
break;
|
||||
}
|
||||
switch (val & 0x02) {
|
||||
switch (val & 0x03) {
|
||||
case 0:
|
||||
p->transmission_mode = TRANSMISSION_MODE_2K;
|
||||
break;
|
||||
|
|
@ -765,6 +766,8 @@ static int tda10048_set_frontend(struct dvb_frontend *fe,
|
|||
|
||||
/* Enable demod TPS auto detection and begin acquisition */
|
||||
tda10048_writereg(state, TDA10048_AUTO, 0x57);
|
||||
/* trigger cber and vber acquisition */
|
||||
tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x3B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -830,12 +833,27 @@ static int tda10048_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|||
static int tda10048_read_ber(struct dvb_frontend *fe, u32 *ber)
|
||||
{
|
||||
struct tda10048_state *state = fe->demodulator_priv;
|
||||
static u32 cber_current;
|
||||
u32 cber_nmax;
|
||||
u64 cber_tmp;
|
||||
|
||||
dprintk(1, "%s()\n", __func__);
|
||||
|
||||
/* TODO: A reset may be required here */
|
||||
*ber = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_LSB);
|
||||
/* update cber on interrupt */
|
||||
if (tda10048_readreg(state, TDA10048_SOFT_IT_C3) & 0x01) {
|
||||
cber_tmp = tda10048_readreg(state, TDA10048_CBER_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_LSB);
|
||||
cber_nmax = tda10048_readreg(state, TDA10048_CBER_NMAX_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_CBER_NMAX_LSB);
|
||||
cber_tmp *= 100000000;
|
||||
cber_tmp *= 2;
|
||||
cber_tmp = div_u64(cber_tmp, (cber_nmax * 32) + 1);
|
||||
cber_current = (u32)cber_tmp;
|
||||
/* retrigger cber acquisition */
|
||||
tda10048_writereg(state, TDA10048_CVBER_CTRL, 0x39);
|
||||
}
|
||||
/* actual cber is (*ber)/1e8 */
|
||||
*ber = cber_current;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1015,6 +1033,9 @@ static int tda10048_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
|
|||
|
||||
*ucblocks = tda10048_readreg(state, TDA10048_UNCOR_CPT_MSB) << 8 |
|
||||
tda10048_readreg(state, TDA10048_UNCOR_CPT_LSB);
|
||||
/* clear the uncorrected TS packets counter when saturated */
|
||||
if (*ucblocks == 0xFFFF)
|
||||
tda10048_writereg(state, TDA10048_UNCOR_CTRL, 0x80);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,15 @@ config MANTIS_CORE
|
|||
config DVB_MANTIS
|
||||
tristate "MANTIS based cards"
|
||||
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
|
||||
select DVB_MB86A16
|
||||
select DVB_ZL10353
|
||||
select DVB_STV0299
|
||||
select DVB_MB86A16 if !DVB_FE_CUSTOMISE
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STV0299 if !DVB_FE_CUSTOMISE
|
||||
select DVB_LNBP21 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB0899 if !DVB_FE_CUSTOMISE
|
||||
select DVB_STB6100 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA665x if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10021 if !DVB_FE_CUSTOMISE
|
||||
select DVB_TDA10023 if !DVB_FE_CUSTOMISE
|
||||
select DVB_PLL
|
||||
help
|
||||
Support for PCI cards based on the Mantis PCI bridge.
|
||||
|
|
@ -23,7 +29,7 @@ config DVB_MANTIS
|
|||
config DVB_HOPPER
|
||||
tristate "HOPPER based cards"
|
||||
depends on MANTIS_CORE && DVB_CORE && PCI && I2C
|
||||
select DVB_ZL10353
|
||||
select DVB_ZL10353 if !DVB_FE_CUSTOMISE
|
||||
select DVB_PLL
|
||||
help
|
||||
Support for PCI cards based on the Hopper PCI bridge.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-common.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "dmxdev.h"
|
||||
|
|
@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(ir_mantis);
|
|||
int mantis_input_init(struct mantis_pci *mantis)
|
||||
{
|
||||
struct input_dev *rc;
|
||||
struct ir_input_state rc_state;
|
||||
char name[80], dev[80];
|
||||
int err;
|
||||
|
||||
|
|
@ -120,8 +119,6 @@ int mantis_input_init(struct mantis_pci *mantis)
|
|||
rc->name = name;
|
||||
rc->phys = dev;
|
||||
|
||||
ir_input_init(rc, &rc_state, IR_TYPE_OTHER);
|
||||
|
||||
rc->id.bustype = BUS_PCI;
|
||||
rc->id.vendor = mantis->vendor_id;
|
||||
rc->id.product = mantis->device_id;
|
||||
|
|
|
|||
|
|
@ -64,9 +64,11 @@ static struct sms_board sms_boards[] = {
|
|||
.type = SMS_NOVA_B0,
|
||||
.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
|
||||
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
|
||||
.rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW,
|
||||
.board_cfg.leds_power = 26,
|
||||
.board_cfg.led0 = 27,
|
||||
.board_cfg.led1 = 28,
|
||||
.board_cfg.ir = 9,
|
||||
.led_power = 26,
|
||||
.led_lo = 27,
|
||||
.led_hi = 28,
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ struct sms_board {
|
|||
enum sms_device_type_st type;
|
||||
char *name, *fw[DEVICE_MODE_MAX];
|
||||
struct sms_board_gpio_cfg board_cfg;
|
||||
enum ir_kb_type ir_kb_type;
|
||||
char *rc_codes; /* Name of IR codes table */
|
||||
|
||||
/* gpios */
|
||||
int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
|
||||
|
|
|
|||
|
|
@ -116,9 +116,7 @@ static struct smscore_registry_entry_t *smscore_find_registry(char *devpath)
|
|||
return entry;
|
||||
}
|
||||
}
|
||||
entry = (struct smscore_registry_entry_t *)
|
||||
kmalloc(sizeof(struct smscore_registry_entry_t),
|
||||
GFP_KERNEL);
|
||||
entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL);
|
||||
if (entry) {
|
||||
entry->mode = default_mode;
|
||||
strcpy(entry->devpath, devpath);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@
|
|||
MDTV receiver kernel modules.
|
||||
Copyright (C) 2006-2009, Uri Shkolnik
|
||||
|
||||
Copyright (c) 2010 - Mauro Carvalho Chehab
|
||||
- Ported the driver to use rc-core
|
||||
- IR raw event decoding is now done at rc-core
|
||||
- Code almost re-written
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
|
|
@ -27,226 +32,28 @@
|
|||
#include "smsir.h"
|
||||
#include "sms-cards.h"
|
||||
|
||||
/* In order to add new IR remote control -
|
||||
* 1) Add it to the <enum ir_kb_type> @ smsir,h,
|
||||
* 2) Add its map to keyboard_layout_maps below
|
||||
* 3) Set your board (sms-cards sub-module) to use it
|
||||
*/
|
||||
|
||||
static struct keyboard_layout_map_t keyboard_layout_maps[] = {
|
||||
[SMS_IR_KB_DEFAULT_TV] = {
|
||||
.ir_protocol = IR_RC5,
|
||||
.rc5_kbd_address = KEYBOARD_ADDRESS_TV1,
|
||||
.keyboard_layout_map = {
|
||||
KEY_0, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5,
|
||||
KEY_6, KEY_7, KEY_8,
|
||||
KEY_9, 0, 0, KEY_POWER,
|
||||
KEY_MUTE, 0, 0,
|
||||
KEY_VOLUMEUP, KEY_VOLUMEDOWN,
|
||||
KEY_BRIGHTNESSUP,
|
||||
KEY_BRIGHTNESSDOWN, KEY_CHANNELUP,
|
||||
KEY_CHANNELDOWN,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}
|
||||
},
|
||||
[SMS_IR_KB_HCW_SILVER] = {
|
||||
.ir_protocol = IR_RC5,
|
||||
.rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1,
|
||||
.keyboard_layout_map = {
|
||||
KEY_0, KEY_1, KEY_2,
|
||||
KEY_3, KEY_4, KEY_5,
|
||||
KEY_6, KEY_7, KEY_8,
|
||||
KEY_9, KEY_TEXT, KEY_RED,
|
||||
KEY_RADIO, KEY_MENU,
|
||||
KEY_SUBTITLE,
|
||||
KEY_MUTE, KEY_VOLUMEUP,
|
||||
KEY_VOLUMEDOWN, KEY_PREVIOUS, 0,
|
||||
KEY_UP, KEY_DOWN, KEY_LEFT,
|
||||
KEY_RIGHT, KEY_VIDEO, KEY_AUDIO,
|
||||
KEY_MHP, KEY_EPG, KEY_TV,
|
||||
0, KEY_NEXTSONG, KEY_EXIT,
|
||||
KEY_CHANNELUP, KEY_CHANNELDOWN,
|
||||
KEY_CHANNEL, 0,
|
||||
KEY_PREVIOUSSONG, KEY_ENTER,
|
||||
KEY_SLEEP, 0, 0, KEY_BLUE,
|
||||
0, 0, 0, 0, KEY_GREEN, 0,
|
||||
KEY_PAUSE, 0, KEY_REWIND,
|
||||
0, KEY_FASTFORWARD, KEY_PLAY,
|
||||
KEY_STOP, KEY_RECORD,
|
||||
KEY_YELLOW, 0, 0, KEY_SELECT,
|
||||
KEY_ZOOM, KEY_POWER, 0, 0
|
||||
}
|
||||
},
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
static u32 ir_pos;
|
||||
static u32 ir_word;
|
||||
static u32 ir_toggle;
|
||||
|
||||
#define RC5_PUSH_BIT(dst, bit, pos) \
|
||||
{ dst <<= 1; dst |= bit; pos++; }
|
||||
|
||||
|
||||
static void sms_ir_rc5_event(struct smscore_device_t *coredev,
|
||||
u32 toggle, u32 addr, u32 cmd)
|
||||
{
|
||||
bool toggle_changed;
|
||||
u16 keycode;
|
||||
|
||||
sms_log("IR RC5 word: address %d, command %d, toggle %d",
|
||||
addr, cmd, toggle);
|
||||
|
||||
toggle_changed = ir_toggle != toggle;
|
||||
/* keep toggle */
|
||||
ir_toggle = toggle;
|
||||
|
||||
if (addr !=
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address)
|
||||
return; /* Check for valid address */
|
||||
|
||||
keycode =
|
||||
keyboard_layout_maps
|
||||
[coredev->ir.ir_kb_type].keyboard_layout_map[cmd];
|
||||
|
||||
if (!toggle_changed &&
|
||||
(keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN))
|
||||
return; /* accept only repeated volume, reject other keys */
|
||||
|
||||
sms_log("kernel input keycode (from ir) %d", keycode);
|
||||
input_report_key(coredev->ir.input_dev, keycode, 1);
|
||||
input_sync(coredev->ir.input_dev);
|
||||
|
||||
}
|
||||
|
||||
/* decode raw bit pattern to RC5 code */
|
||||
/* taken from ir-functions.c */
|
||||
static u32 ir_rc5_decode(unsigned int code)
|
||||
{
|
||||
/* unsigned int org_code = code;*/
|
||||
unsigned int pair;
|
||||
unsigned int rc5 = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 14; ++i) {
|
||||
pair = code & 0x3;
|
||||
code >>= 2;
|
||||
|
||||
rc5 <<= 1;
|
||||
switch (pair) {
|
||||
case 0:
|
||||
case 2:
|
||||
break;
|
||||
case 1:
|
||||
rc5 |= 1;
|
||||
break;
|
||||
case 3:
|
||||
/* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/
|
||||
sms_log("bad code");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
dprintk(1, "ir-common: code=%x, rc5=%x, start=%x,
|
||||
toggle=%x, address=%x, "
|
||||
"instr=%x\n", rc5, org_code, RC5_START(rc5),
|
||||
RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5));
|
||||
*/
|
||||
return rc5;
|
||||
}
|
||||
|
||||
static void sms_rc5_parse_word(struct smscore_device_t *coredev)
|
||||
{
|
||||
#define RC5_START(x) (((x)>>12)&3)
|
||||
#define RC5_TOGGLE(x) (((x)>>11)&1)
|
||||
#define RC5_ADDR(x) (((x)>>6)&0x1F)
|
||||
#define RC5_INSTR(x) ((x)&0x3F)
|
||||
|
||||
int i, j;
|
||||
u32 rc5_word = 0;
|
||||
|
||||
/* Reverse the IR word direction */
|
||||
for (i = 0 ; i < 28 ; i++)
|
||||
RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j)
|
||||
|
||||
rc5_word = ir_rc5_decode(rc5_word);
|
||||
/* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */
|
||||
|
||||
sms_ir_rc5_event(coredev,
|
||||
RC5_TOGGLE(rc5_word),
|
||||
RC5_ADDR(rc5_word),
|
||||
RC5_INSTR(rc5_word));
|
||||
}
|
||||
|
||||
|
||||
static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev,
|
||||
s32 ir_sample)
|
||||
{
|
||||
#define RC5_TIME_GRANULARITY 200
|
||||
#define RC5_DEF_BIT_TIME 889
|
||||
#define RC5_MAX_SAME_BIT_CONT 4
|
||||
#define RC5_WORD_LEN 27 /* 28 bit */
|
||||
|
||||
u32 i, j;
|
||||
s32 delta_time;
|
||||
u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample);
|
||||
u32 level = (ir_sample < 0) ? 0 : 1;
|
||||
|
||||
for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) {
|
||||
delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY;
|
||||
if (delta_time < 0)
|
||||
continue; /* not so many consecutive bits */
|
||||
if (delta_time > (2 * RC5_TIME_GRANULARITY)) {
|
||||
/* timeout */
|
||||
if (ir_pos == (RC5_WORD_LEN-1))
|
||||
/* complete last bit */
|
||||
RC5_PUSH_BIT(ir_word, level, ir_pos)
|
||||
|
||||
if (ir_pos == RC5_WORD_LEN)
|
||||
sms_rc5_parse_word(coredev);
|
||||
else if (ir_pos) /* timeout within a word */
|
||||
sms_log("IR error parsing a word");
|
||||
|
||||
ir_pos = 0;
|
||||
ir_word = 0;
|
||||
/* sms_log("timeout %d", time); */
|
||||
break;
|
||||
}
|
||||
/* The time is within the range of this number of bits */
|
||||
for (j = 0 ; j < i ; j++)
|
||||
RC5_PUSH_BIT(ir_word, level, ir_pos)
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
#define MODULE_NAME "smsmdtv"
|
||||
|
||||
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
|
||||
{
|
||||
#define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */
|
||||
u32 i;
|
||||
enum ir_protocol ir_protocol =
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type]
|
||||
.ir_protocol;
|
||||
s32 *samples;
|
||||
int count = len>>2;
|
||||
int i;
|
||||
const s32 *samples = (const void *)buf;
|
||||
|
||||
samples = (s32 *)buf;
|
||||
/* sms_log("IR buffer received, length = %d", count);*/
|
||||
for (i = 0; i < len >> 2; i++) {
|
||||
struct ir_raw_event ev;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
if (ir_protocol == IR_RC5)
|
||||
sms_rc5_accumulate_bits(coredev, samples[i]);
|
||||
/* IR_RCMM not implemented */
|
||||
ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
|
||||
ev.pulse = (samples[i] > 0) ? false : true;
|
||||
|
||||
ir_raw_event_store(coredev->ir.input_dev, &ev);
|
||||
}
|
||||
ir_raw_event_handle(coredev->ir.input_dev);
|
||||
}
|
||||
|
||||
int sms_ir_init(struct smscore_device_t *coredev)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int board_id = smscore_get_board_id(coredev);
|
||||
|
||||
sms_log("Allocating input device");
|
||||
input_dev = input_allocate_device();
|
||||
|
|
@ -256,33 +63,38 @@ int sms_ir_init(struct smscore_device_t *coredev)
|
|||
}
|
||||
|
||||
coredev->ir.input_dev = input_dev;
|
||||
coredev->ir.ir_kb_type =
|
||||
sms_get_board(smscore_get_board_id(coredev))->ir_kb_type;
|
||||
coredev->ir.keyboard_layout_map =
|
||||
keyboard_layout_maps[coredev->ir.ir_kb_type].
|
||||
keyboard_layout_map;
|
||||
sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type);
|
||||
|
||||
coredev->ir.controller = 0; /* Todo: vega/nova SPI number */
|
||||
coredev->ir.timeout = IR_DEFAULT_TIMEOUT;
|
||||
sms_log("IR port %d, timeout %d ms",
|
||||
coredev->ir.controller, coredev->ir.timeout);
|
||||
|
||||
snprintf(coredev->ir.name,
|
||||
IR_DEV_NAME_MAX_LEN,
|
||||
"SMS IR w/kbd type %d",
|
||||
coredev->ir.ir_kb_type);
|
||||
snprintf(coredev->ir.name, sizeof(coredev->ir.name),
|
||||
"SMS IR (%s)", sms_get_board(board_id)->name);
|
||||
|
||||
strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys));
|
||||
strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys));
|
||||
|
||||
input_dev->name = coredev->ir.name;
|
||||
input_dev->phys = coredev->ir.name;
|
||||
input_dev->phys = coredev->ir.phys;
|
||||
input_dev->dev.parent = coredev->device;
|
||||
|
||||
/* Key press events only */
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY);
|
||||
input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0);
|
||||
#if 0
|
||||
/* TODO: properly initialize the parameters bellow */
|
||||
input_dev->id.bustype = BUS_USB;
|
||||
input_dev->id.version = 1;
|
||||
input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
|
||||
input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
|
||||
#endif
|
||||
|
||||
coredev->ir.props.priv = coredev;
|
||||
coredev->ir.props.driver_type = RC_DRIVER_IR_RAW;
|
||||
coredev->ir.props.allowed_protos = IR_TYPE_ALL;
|
||||
|
||||
sms_log("Input device (IR) %s is set for key events", input_dev->name);
|
||||
|
||||
if (input_register_device(input_dev)) {
|
||||
if (ir_input_register(input_dev, sms_get_board(board_id)->rc_codes,
|
||||
&coredev->ir.props, MODULE_NAME)) {
|
||||
sms_err("Failed to register device");
|
||||
input_free_device(input_dev);
|
||||
return -EACCES;
|
||||
|
|
@ -294,8 +106,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
|
|||
void sms_ir_exit(struct smscore_device_t *coredev)
|
||||
{
|
||||
if (coredev->ir.input_dev)
|
||||
input_unregister_device(coredev->ir.input_dev);
|
||||
ir_input_unregister(coredev->ir.input_dev);
|
||||
|
||||
sms_log("");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,11 @@ Siano Mobile Silicon, Inc.
|
|||
MDTV receiver kernel modules.
|
||||
Copyright (C) 2006-2009, Uri Shkolnik
|
||||
|
||||
Copyright (c) 2010 - Mauro Carvalho Chehab
|
||||
- Ported the driver to use rc-core
|
||||
- IR raw event decoding is now done at rc-core
|
||||
- Code almost re-written
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
|
|
@ -23,63 +28,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#define __SMS_IR_H__
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */
|
||||
#define IR_KEYBOARD_LAYOUT_SIZE 64
|
||||
#define IR_DEFAULT_TIMEOUT 100
|
||||
|
||||
enum ir_kb_type {
|
||||
SMS_IR_KB_DEFAULT_TV,
|
||||
SMS_IR_KB_HCW_SILVER
|
||||
};
|
||||
|
||||
enum rc5_keyboard_address {
|
||||
KEYBOARD_ADDRESS_TV1 = 0,
|
||||
KEYBOARD_ADDRESS_TV2 = 1,
|
||||
KEYBOARD_ADDRESS_TELETEXT = 2,
|
||||
KEYBOARD_ADDRESS_VIDEO = 3,
|
||||
KEYBOARD_ADDRESS_LV1 = 4,
|
||||
KEYBOARD_ADDRESS_VCR1 = 5,
|
||||
KEYBOARD_ADDRESS_VCR2 = 6,
|
||||
KEYBOARD_ADDRESS_EXPERIMENTAL = 7,
|
||||
KEYBOARD_ADDRESS_SAT1 = 8,
|
||||
KEYBOARD_ADDRESS_CAMERA = 9,
|
||||
KEYBOARD_ADDRESS_SAT2 = 10,
|
||||
KEYBOARD_ADDRESS_CDV = 12,
|
||||
KEYBOARD_ADDRESS_CAMCORDER = 13,
|
||||
KEYBOARD_ADDRESS_PRE_AMP = 16,
|
||||
KEYBOARD_ADDRESS_TUNER = 17,
|
||||
KEYBOARD_ADDRESS_RECORDER1 = 18,
|
||||
KEYBOARD_ADDRESS_PRE_AMP1 = 19,
|
||||
KEYBOARD_ADDRESS_CD_PLAYER = 20,
|
||||
KEYBOARD_ADDRESS_PHONO = 21,
|
||||
KEYBOARD_ADDRESS_SATA = 22,
|
||||
KEYBOARD_ADDRESS_RECORDER2 = 23,
|
||||
KEYBOARD_ADDRESS_CDR = 26,
|
||||
KEYBOARD_ADDRESS_LIGHTING = 29,
|
||||
KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */
|
||||
KEYBOARD_ADDRESS_PHONE = 31,
|
||||
KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF
|
||||
};
|
||||
|
||||
enum ir_protocol {
|
||||
IR_RC5,
|
||||
IR_RCMM
|
||||
};
|
||||
|
||||
struct keyboard_layout_map_t {
|
||||
enum ir_protocol ir_protocol;
|
||||
enum rc5_keyboard_address rc5_kbd_address;
|
||||
u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE];
|
||||
};
|
||||
|
||||
struct smscore_device_t;
|
||||
|
||||
struct ir_t {
|
||||
struct input_dev *input_dev;
|
||||
enum ir_kb_type ir_kb_type;
|
||||
char name[IR_DEV_NAME_MAX_LEN+1];
|
||||
u16 *keyboard_layout_map;
|
||||
char name[40];
|
||||
char phys[32];
|
||||
|
||||
char *rc_codes;
|
||||
u64 protocol;
|
||||
struct ir_dev_props props;
|
||||
|
||||
u32 timeout;
|
||||
u32 controller;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -352,8 +352,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
|
|||
params.num_buffers = MAX_BUFFERS;
|
||||
params.sendrequest_handler = smsusb_sendrequest;
|
||||
params.context = dev;
|
||||
snprintf(params.devpath, sizeof(params.devpath),
|
||||
"usb\\%d-%s", dev->udev->bus->busnum, dev->udev->devpath);
|
||||
usb_make_path(dev->udev, params.devpath, sizeof(params.devpath));
|
||||
|
||||
/* register in smscore */
|
||||
rc = smscore_register_device(¶ms, &dev->coredev);
|
||||
|
|
|
|||
|
|
@ -748,7 +748,7 @@ static int si470x_vidioc_s_tuner(struct file *file, void *priv,
|
|||
struct v4l2_tuner *tuner)
|
||||
{
|
||||
struct si470x_device *radio = video_drvdata(file);
|
||||
int retval = -EINVAL;
|
||||
int retval = 0;
|
||||
|
||||
/* safety checks */
|
||||
retval = si470x_disconnect_check(radio);
|
||||
|
|
|
|||
|
|
@ -1009,8 +1009,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
|
|||
goto exit;
|
||||
}
|
||||
rval = copy_from_user(ps_name, control->string, len);
|
||||
if (rval < 0)
|
||||
if (rval) {
|
||||
rval = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
ps_name[len] = '\0';
|
||||
|
||||
if (strlen(ps_name) % vqc.step) {
|
||||
|
|
@ -1031,8 +1033,10 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
|
|||
goto exit;
|
||||
}
|
||||
rval = copy_from_user(radio_text, control->string, len);
|
||||
if (rval < 0)
|
||||
if (rval) {
|
||||
rval = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
radio_text[len] = '\0';
|
||||
|
||||
if (strlen(radio_text) % vqc.step) {
|
||||
|
|
@ -1367,6 +1371,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
|
|||
}
|
||||
rval = copy_to_user(control->string, sdev->rds_info.ps_name,
|
||||
strlen(sdev->rds_info.ps_name) + 1);
|
||||
if (rval)
|
||||
rval = -EFAULT;
|
||||
break;
|
||||
|
||||
case V4L2_CID_RDS_TX_RADIO_TEXT:
|
||||
|
|
@ -1377,6 +1383,8 @@ static int si4713_read_econtrol_string(struct si4713_device *sdev,
|
|||
}
|
||||
rval = copy_to_user(control->string, sdev->rds_info.radio_text,
|
||||
strlen(sdev->rds_info.radio_text) + 1);
|
||||
if (rval)
|
||||
rval = -EFAULT;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -517,19 +517,6 @@ config VIDEO_UPD64083
|
|||
|
||||
endmenu # encoder / decoder chips
|
||||
|
||||
config DISPLAY_DAVINCI_DM646X_EVM
|
||||
tristate "DM646x EVM Video Display"
|
||||
depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
select VIDEO_DAVINCI_VPIF
|
||||
select VIDEO_ADV7343
|
||||
select VIDEO_THS7303
|
||||
help
|
||||
Support for DM6467 based display device.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif_display.
|
||||
|
||||
config VIDEO_SH_VOU
|
||||
tristate "SuperH VOU video output driver"
|
||||
depends on VIDEO_DEV && ARCH_SHMOBILE
|
||||
|
|
@ -537,29 +524,22 @@ config VIDEO_SH_VOU
|
|||
help
|
||||
Support for the Video Output Unit (VOU) on SuperH SoCs.
|
||||
|
||||
config CAPTURE_DAVINCI_DM646X_EVM
|
||||
tristate "DM646x EVM Video Capture"
|
||||
depends on VIDEO_DEV && MACH_DAVINCI_DM6467_EVM
|
||||
config VIDEO_VIU
|
||||
tristate "Freescale VIU Video Driver"
|
||||
depends on VIDEO_V4L2 && PPC_MPC512x
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
select VIDEO_DAVINCI_VPIF
|
||||
help
|
||||
Support for DM6467 based capture device.
|
||||
default y
|
||||
---help---
|
||||
Support for Freescale VIU video driver. This device captures
|
||||
video data, or overlays video on DIU frame buffer.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif_capture.
|
||||
|
||||
config VIDEO_DAVINCI_VPIF
|
||||
tristate "DaVinci VPIF Driver"
|
||||
depends on DISPLAY_DAVINCI_DM646X_EVM
|
||||
help
|
||||
Support for DaVinci VPIF Driver.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpif.
|
||||
Say Y here if you want to enable VIU device on MPC5121e Rev2+.
|
||||
In doubt, say N.
|
||||
|
||||
config VIDEO_VIVI
|
||||
tristate "Virtual Video Driver"
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FONTS
|
||||
depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
|
||||
depends on (FRAMEBUFFER_CONSOLE || STI_CONSOLE) && FONTS
|
||||
select FONT_8x16
|
||||
select VIDEOBUF_VMALLOC
|
||||
default n
|
||||
|
|
@ -570,66 +550,7 @@ config VIDEO_VIVI
|
|||
Say Y here if you want to test video apps or debug V4L devices.
|
||||
In doubt, say N.
|
||||
|
||||
config VIDEO_VPSS_SYSTEM
|
||||
tristate "VPSS System module driver"
|
||||
depends on ARCH_DAVINCI
|
||||
help
|
||||
Support for vpss system module for video driver
|
||||
|
||||
config VIDEO_VPFE_CAPTURE
|
||||
tristate "VPFE Video Capture Driver"
|
||||
depends on VIDEO_V4L2 && ARCH_DAVINCI
|
||||
select VIDEOBUF_DMA_CONTIG
|
||||
help
|
||||
Support for DMXXXX VPFE based frame grabber. This is the
|
||||
common V4L2 module for following DMXXX SoCs from Texas
|
||||
Instruments:- DM6446 & DM355.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe-capture.
|
||||
|
||||
config VIDEO_DM6446_CCDC
|
||||
tristate "DM6446 CCDC HW module"
|
||||
depends on ARCH_DAVINCI_DM644x && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables DaVinci CCD hw module. DaVinci CCDC hw interfaces
|
||||
with decoder modules such as TVP5146 over BT656 or
|
||||
sensor module such as MT9T001 over a raw interface. This
|
||||
module configures the interface and CCDC/ISIF to do
|
||||
video frame capture from slave decoders.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
config VIDEO_DM355_CCDC
|
||||
tristate "DM355 CCDC HW module"
|
||||
depends on ARCH_DAVINCI_DM355 && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables DM355 CCD hw module. DM355 CCDC hw interfaces
|
||||
with decoder modules such as TVP5146 over BT656 or
|
||||
sensor module such as MT9T001 over a raw interface. This
|
||||
module configures the interface and CCDC/ISIF to do
|
||||
video frame capture from a slave decoders
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
|
||||
config VIDEO_ISIF
|
||||
tristate "ISIF HW module"
|
||||
depends on ARCH_DAVINCI_DM365 && VIDEO_VPFE_CAPTURE
|
||||
select VIDEO_VPSS_SYSTEM
|
||||
default y
|
||||
help
|
||||
Enables ISIF hw module. This is the hardware module for
|
||||
configuring ISIF in VPFE to capture Raw Bayer RGB data from
|
||||
a image sensor or YUV data from a YUV source.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called vpfe.
|
||||
source "drivers/media/video/davinci/Kconfig"
|
||||
|
||||
source "drivers/media/video/omap/Kconfig"
|
||||
|
||||
|
|
@ -955,6 +876,12 @@ config VIDEO_PXA27x
|
|||
---help---
|
||||
This is a v4l2 driver for the PXA27x Quick Capture Interface
|
||||
|
||||
config VIDEO_SH_MOBILE_CSI2
|
||||
tristate "SuperH Mobile MIPI CSI-2 Interface driver"
|
||||
depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
|
||||
---help---
|
||||
This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
|
||||
|
||||
config VIDEO_SH_MOBILE_CEU
|
||||
tristate "SuperH Mobile CEU Interface driver"
|
||||
depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
|
||||
|
|
@ -1013,61 +940,6 @@ source "drivers/media/video/usbvideo/Kconfig"
|
|||
|
||||
source "drivers/media/video/et61x251/Kconfig"
|
||||
|
||||
config VIDEO_OVCAMCHIP
|
||||
tristate "OmniVision Camera Chip support (DEPRECATED)"
|
||||
depends on I2C && VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
you need atleast version 0.6.0 of libv4l and for the w9968cf
|
||||
atleast version 0.6.3 of libv4l.
|
||||
|
||||
Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
|
||||
This driver is intended to be used with the ov511 and w9968cf USB
|
||||
camera drivers.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ovcamchip.
|
||||
|
||||
config USB_W9968CF
|
||||
tristate "USB W996[87]CF JPEG Dual Mode Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the w9968cf support of the gspca module
|
||||
you need atleast version 0.6.3 of libv4l.
|
||||
|
||||
Say Y here if you want support for cameras based on OV681 or
|
||||
Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
|
||||
|
||||
This driver has an optional plugin, which is distributed as a
|
||||
separate module only (released under GPL). It allows to use higher
|
||||
resolutions and framerates, but cannot be included in the official
|
||||
Linux kernel for performance purposes.
|
||||
|
||||
See <file:Documentation/video4linux/w9968cf.txt> for more info.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called w9968cf.
|
||||
|
||||
config USB_OV511
|
||||
tristate "USB OV511 Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca ov519 module
|
||||
instead. Note that for the ov511 / ov518 support of the gspca module
|
||||
you need atleast version 0.6.0 of libv4l.
|
||||
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. See <file:Documentation/video4linux/ov511.txt>
|
||||
for more information and for a list of supported cameras.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov511.
|
||||
|
||||
config USB_SE401
|
||||
tristate "USB SE401 Camera support"
|
||||
depends on VIDEO_V4L1
|
||||
|
|
@ -1081,25 +953,6 @@ config USB_SE401
|
|||
|
||||
source "drivers/media/video/sn9c102/Kconfig"
|
||||
|
||||
config USB_STV680
|
||||
tristate "USB STV680 (Pencam) Camera support (DEPRECATED)"
|
||||
depends on VIDEO_V4L1
|
||||
default n
|
||||
---help---
|
||||
This driver is DEPRECATED please use the gspca stv0680 module
|
||||
instead. Note that for the gspca stv0680 module you need
|
||||
atleast version 0.6.3 of libv4l.
|
||||
|
||||
Say Y here if you want to connect this type of camera to your
|
||||
computer's USB port. This includes the Pencam line of cameras.
|
||||
See <file:Documentation/video4linux/stv680.txt> for more information
|
||||
and for a list of supported cameras.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called stv680.
|
||||
|
||||
source "drivers/media/video/zc0301/Kconfig"
|
||||
|
||||
source "drivers/media/video/pwc/Kconfig"
|
||||
|
||||
config USB_ZR364XX
|
||||
|
|
|
|||
|
|
@ -105,7 +105,6 @@ obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
|
|||
obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
|
||||
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
|
||||
obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
|
||||
obj-$(CONFIG_VIDEO_OVCAMCHIP) += ovcamchip/
|
||||
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
|
||||
obj-$(CONFIG_VIDEO_MXB) += mxb.o
|
||||
obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
|
||||
|
|
@ -127,17 +126,13 @@ obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
|
|||
obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
|
||||
|
||||
obj-$(CONFIG_USB_DABUSB) += dabusb.o
|
||||
obj-$(CONFIG_USB_OV511) += ov511.o
|
||||
obj-$(CONFIG_USB_SE401) += se401.o
|
||||
obj-$(CONFIG_USB_STV680) += stv680.o
|
||||
obj-$(CONFIG_USB_W9968CF) += w9968cf.o
|
||||
obj-$(CONFIG_USB_ZR364XX) += zr364xx.o
|
||||
obj-$(CONFIG_USB_STKWEBCAM) += stkwebcam.o
|
||||
|
||||
obj-$(CONFIG_USB_SN9C102) += sn9c102/
|
||||
obj-$(CONFIG_USB_ET61X251) += et61x251/
|
||||
obj-$(CONFIG_USB_PWC) += pwc/
|
||||
obj-$(CONFIG_USB_ZC0301) += zc0301/
|
||||
obj-$(CONFIG_USB_GSPCA) += gspca/
|
||||
|
||||
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
|
||||
|
|
@ -151,6 +146,7 @@ obj-$(CONFIG_USB_S2255) += s2255drv.o
|
|||
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
|
||||
obj-$(CONFIG_VIDEO_CX18) += cx18/
|
||||
|
||||
obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
|
||||
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
|
||||
obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885/
|
||||
|
|
@ -165,6 +161,7 @@ obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
|
|||
obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
|
||||
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
|
||||
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
|
||||
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
|
||||
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
|
||||
|
|
@ -178,7 +175,7 @@ obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
|
|||
|
||||
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
|
||||
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
|
||||
obj-y += davinci/
|
||||
|
||||
obj-$(CONFIG_ARCH_OMAP) += omap/
|
||||
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ static int ak881x_try_g_mbus_fmt(struct v4l2_subdev *sd,
|
|||
v4l_bound_align_image(&mf->width, 0, 720, 2,
|
||||
&mf->height, 0, ak881x->lines, 1, 0);
|
||||
mf->field = V4L2_FIELD_INTERLACED;
|
||||
mf->code = V4L2_MBUS_FMT_YUYV8_2X8_LE;
|
||||
mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
|
||||
mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
|
||||
|
||||
return 0;
|
||||
|
|
@ -136,7 +136,7 @@ static int ak881x_s_mbus_fmt(struct v4l2_subdev *sd,
|
|||
struct v4l2_mbus_framefmt *mf)
|
||||
{
|
||||
if (mf->field != V4L2_FIELD_INTERLACED ||
|
||||
mf->code != V4L2_MBUS_FMT_YUYV8_2X8_LE)
|
||||
mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
|
||||
return -EINVAL;
|
||||
|
||||
return ak881x_try_g_mbus_fmt(sd, mf);
|
||||
|
|
@ -148,7 +148,7 @@ static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
|
|||
if (index)
|
||||
return -EINVAL;
|
||||
|
||||
*code = V4L2_MBUS_FMT_YUYV8_2X8_LE;
|
||||
*code = V4L2_MBUS_FMT_YUYV8_2X8;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o
|
||||
au0828-objs := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-video.o au0828-vbi.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_AU0828) += au0828.o
|
||||
|
||||
|
|
|
|||
138
drivers/media/video/au0828/au0828-vbi.c
Normal file
138
drivers/media/video/au0828/au0828-vbi.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
au0828-vbi.c - VBI driver for au0828
|
||||
|
||||
Copyright (C) 2010 Devin Heitmueller <dheitmueller@kernellabs.com>
|
||||
|
||||
This work was sponsored by GetWellNetwork Inc.
|
||||
|
||||
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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "au0828.h"
|
||||
|
||||
static unsigned int vbibufs = 5;
|
||||
module_param(vbibufs, int, 0644);
|
||||
MODULE_PARM_DESC(vbibufs, "number of vbi buffers, range 2-32");
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static void
|
||||
free_buffer(struct videobuf_queue *vq, struct au0828_buffer *buf)
|
||||
{
|
||||
struct au0828_fh *fh = vq->priv_data;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
unsigned long flags = 0;
|
||||
if (in_interrupt())
|
||||
BUG();
|
||||
|
||||
/* We used to wait for the buffer to finish here, but this didn't work
|
||||
because, as we were keeping the state as VIDEOBUF_QUEUED,
|
||||
videobuf_queue_cancel marked it as finished for us.
|
||||
(Also, it could wedge forever if the hardware was misconfigured.)
|
||||
|
||||
This should be safe; by the time we get here, the buffer isn't
|
||||
queued anymore. If we ever start marking the buffers as
|
||||
VIDEOBUF_ACTIVE, it won't be, though.
|
||||
*/
|
||||
spin_lock_irqsave(&dev->slock, flags);
|
||||
if (dev->isoc_ctl.vbi_buf == buf)
|
||||
dev->isoc_ctl.vbi_buf = NULL;
|
||||
spin_unlock_irqrestore(&dev->slock, flags);
|
||||
|
||||
videobuf_vmalloc_free(&buf->vb);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
}
|
||||
|
||||
static int
|
||||
vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
|
||||
{
|
||||
struct au0828_fh *fh = q->priv_data;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
|
||||
*size = dev->vbi_width * dev->vbi_height * 2;
|
||||
|
||||
if (0 == *count)
|
||||
*count = vbibufs;
|
||||
if (*count < 2)
|
||||
*count = 2;
|
||||
if (*count > 32)
|
||||
*count = 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
|
||||
enum v4l2_field field)
|
||||
{
|
||||
struct au0828_fh *fh = q->priv_data;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
|
||||
int rc = 0;
|
||||
|
||||
buf->vb.size = dev->vbi_width * dev->vbi_height * 2;
|
||||
|
||||
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
|
||||
return -EINVAL;
|
||||
|
||||
buf->vb.width = dev->vbi_width;
|
||||
buf->vb.height = dev->vbi_height;
|
||||
buf->vb.field = field;
|
||||
|
||||
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
|
||||
rc = videobuf_iolock(q, &buf->vb, NULL);
|
||||
if (rc < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
buf->vb.state = VIDEOBUF_PREPARED;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
free_buffer(q, buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
|
||||
{
|
||||
struct au0828_buffer *buf = container_of(vb,
|
||||
struct au0828_buffer,
|
||||
vb);
|
||||
struct au0828_fh *fh = vq->priv_data;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
struct au0828_dmaqueue *vbiq = &dev->vbiq;
|
||||
|
||||
buf->vb.state = VIDEOBUF_QUEUED;
|
||||
list_add_tail(&buf->vb.queue, &vbiq->active);
|
||||
}
|
||||
|
||||
static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
|
||||
{
|
||||
struct au0828_buffer *buf = container_of(vb, struct au0828_buffer, vb);
|
||||
free_buffer(q, buf);
|
||||
}
|
||||
|
||||
struct videobuf_queue_ops au0828_vbi_qops = {
|
||||
.buf_setup = vbi_setup,
|
||||
.buf_prepare = vbi_prepare,
|
||||
.buf_queue = vbi_queue,
|
||||
.buf_release = vbi_release,
|
||||
};
|
||||
|
|
@ -314,6 +314,23 @@ static inline void buffer_filled(struct au0828_dev *dev,
|
|||
wake_up(&buf->vb.done);
|
||||
}
|
||||
|
||||
static inline void vbi_buffer_filled(struct au0828_dev *dev,
|
||||
struct au0828_dmaqueue *dma_q,
|
||||
struct au0828_buffer *buf)
|
||||
{
|
||||
/* Advice that buffer was filled */
|
||||
au0828_isocdbg("[%p/%d] wakeup\n", buf, buf->vb.i);
|
||||
|
||||
buf->vb.state = VIDEOBUF_DONE;
|
||||
buf->vb.field_count++;
|
||||
do_gettimeofday(&buf->vb.ts);
|
||||
|
||||
dev->isoc_ctl.vbi_buf = NULL;
|
||||
|
||||
list_del(&buf->vb.queue);
|
||||
wake_up(&buf->vb.done);
|
||||
}
|
||||
|
||||
/*
|
||||
* Identify the buffer header type and properly handles
|
||||
*/
|
||||
|
|
@ -327,6 +344,9 @@ static void au0828_copy_video(struct au0828_dev *dev,
|
|||
int linesdone, currlinedone, offset, lencopy, remain;
|
||||
int bytesperline = dev->width << 1; /* Assumes 16-bit depth @@@@ */
|
||||
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (dma_q->pos + len > buf->vb.size)
|
||||
len = buf->vb.size - dma_q->pos;
|
||||
|
||||
|
|
@ -414,17 +434,98 @@ static inline void get_next_buf(struct au0828_dmaqueue *dma_q,
|
|||
return;
|
||||
}
|
||||
|
||||
static void au0828_copy_vbi(struct au0828_dev *dev,
|
||||
struct au0828_dmaqueue *dma_q,
|
||||
struct au0828_buffer *buf,
|
||||
unsigned char *p,
|
||||
unsigned char *outp, unsigned long len)
|
||||
{
|
||||
unsigned char *startwrite, *startread;
|
||||
int bytesperline;
|
||||
int i, j = 0;
|
||||
|
||||
if (dev == NULL) {
|
||||
au0828_isocdbg("dev is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dma_q == NULL) {
|
||||
au0828_isocdbg("dma_q is null\n");
|
||||
return;
|
||||
}
|
||||
if (buf == NULL)
|
||||
return;
|
||||
if (p == NULL) {
|
||||
au0828_isocdbg("p is null\n");
|
||||
return;
|
||||
}
|
||||
if (outp == NULL) {
|
||||
au0828_isocdbg("outp is null\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bytesperline = dev->vbi_width;
|
||||
|
||||
if (dma_q->pos + len > buf->vb.size)
|
||||
len = buf->vb.size - dma_q->pos;
|
||||
|
||||
startread = p;
|
||||
startwrite = outp + (dma_q->pos / 2);
|
||||
|
||||
/* Make sure the bottom field populates the second half of the frame */
|
||||
if (buf->top_field == 0)
|
||||
startwrite += bytesperline * dev->vbi_height;
|
||||
|
||||
for (i = 0; i < len; i += 2)
|
||||
startwrite[j++] = startread[i+1];
|
||||
|
||||
dma_q->pos += len;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* video-buf generic routine to get the next available VBI buffer
|
||||
*/
|
||||
static inline void vbi_get_next_buf(struct au0828_dmaqueue *dma_q,
|
||||
struct au0828_buffer **buf)
|
||||
{
|
||||
struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vbiq);
|
||||
char *outp;
|
||||
|
||||
if (list_empty(&dma_q->active)) {
|
||||
au0828_isocdbg("No active queue to serve\n");
|
||||
dev->isoc_ctl.vbi_buf = NULL;
|
||||
*buf = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get the next buffer */
|
||||
*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
|
||||
/* Cleans up buffer - Usefull for testing for frame/URB loss */
|
||||
outp = videobuf_to_vmalloc(&(*buf)->vb);
|
||||
memset(outp, 0x00, (*buf)->vb.size);
|
||||
|
||||
dev->isoc_ctl.vbi_buf = *buf;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Controls the isoc copy of each urb packet
|
||||
*/
|
||||
static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
|
||||
{
|
||||
struct au0828_buffer *buf;
|
||||
struct au0828_buffer *vbi_buf;
|
||||
struct au0828_dmaqueue *dma_q = urb->context;
|
||||
struct au0828_dmaqueue *vbi_dma_q = &dev->vbiq;
|
||||
unsigned char *outp = NULL;
|
||||
unsigned char *vbioutp = NULL;
|
||||
int i, len = 0, rc = 1;
|
||||
unsigned char *p;
|
||||
unsigned char fbyte;
|
||||
unsigned int vbi_field_size;
|
||||
unsigned int remain, lencopy;
|
||||
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
|
@ -443,6 +544,10 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
|
|||
if (buf != NULL)
|
||||
outp = videobuf_to_vmalloc(&buf->vb);
|
||||
|
||||
vbi_buf = dev->isoc_ctl.vbi_buf;
|
||||
if (vbi_buf != NULL)
|
||||
vbioutp = videobuf_to_vmalloc(&vbi_buf->vb);
|
||||
|
||||
for (i = 0; i < urb->number_of_packets; i++) {
|
||||
int status = urb->iso_frame_desc[i].status;
|
||||
|
||||
|
|
@ -472,6 +577,19 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
|
|||
au0828_isocdbg("Video frame %s\n",
|
||||
(fbyte & 0x40) ? "odd" : "even");
|
||||
if (!(fbyte & 0x40)) {
|
||||
/* VBI */
|
||||
if (vbi_buf != NULL)
|
||||
vbi_buffer_filled(dev,
|
||||
vbi_dma_q,
|
||||
vbi_buf);
|
||||
vbi_get_next_buf(vbi_dma_q, &vbi_buf);
|
||||
if (vbi_buf == NULL)
|
||||
vbioutp = NULL;
|
||||
else
|
||||
vbioutp = videobuf_to_vmalloc(
|
||||
&vbi_buf->vb);
|
||||
|
||||
/* Video */
|
||||
if (buf != NULL)
|
||||
buffer_filled(dev, dma_q, buf);
|
||||
get_next_buf(dma_q, &buf);
|
||||
|
|
@ -488,9 +606,36 @@ static inline int au0828_isoc_copy(struct au0828_dev *dev, struct urb *urb)
|
|||
buf->top_field = 0;
|
||||
}
|
||||
|
||||
if (vbi_buf != NULL) {
|
||||
if (fbyte & 0x40)
|
||||
vbi_buf->top_field = 1;
|
||||
else
|
||||
vbi_buf->top_field = 0;
|
||||
}
|
||||
|
||||
dev->vbi_read = 0;
|
||||
vbi_dma_q->pos = 0;
|
||||
dma_q->pos = 0;
|
||||
}
|
||||
if (buf != NULL)
|
||||
|
||||
vbi_field_size = dev->vbi_width * dev->vbi_height * 2;
|
||||
if (dev->vbi_read < vbi_field_size) {
|
||||
remain = vbi_field_size - dev->vbi_read;
|
||||
if (len < remain)
|
||||
lencopy = len;
|
||||
else
|
||||
lencopy = remain;
|
||||
|
||||
if (vbi_buf != NULL)
|
||||
au0828_copy_vbi(dev, vbi_dma_q, vbi_buf, p,
|
||||
vbioutp, len);
|
||||
|
||||
len -= lencopy;
|
||||
p += lencopy;
|
||||
dev->vbi_read += lencopy;
|
||||
}
|
||||
|
||||
if (dev->vbi_read >= vbi_field_size && buf != NULL)
|
||||
au0828_copy_video(dev, dma_q, buf, p, outp, len);
|
||||
}
|
||||
return rc;
|
||||
|
|
@ -642,7 +787,7 @@ int au0828_analog_stream_enable(struct au0828_dev *d)
|
|||
au0828_writereg(d, 0x114, 0xa0);
|
||||
au0828_writereg(d, 0x115, 0x05);
|
||||
/* set y position */
|
||||
au0828_writereg(d, 0x112, 0x02);
|
||||
au0828_writereg(d, 0x112, 0x00);
|
||||
au0828_writereg(d, 0x113, 0x00);
|
||||
au0828_writereg(d, 0x116, 0xf2);
|
||||
au0828_writereg(d, 0x117, 0x00);
|
||||
|
|
@ -703,47 +848,83 @@ void au0828_analog_unregister(struct au0828_dev *dev)
|
|||
|
||||
|
||||
/* Usage lock check functions */
|
||||
static int res_get(struct au0828_fh *fh)
|
||||
static int res_get(struct au0828_fh *fh, unsigned int bit)
|
||||
{
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
int rc = 0;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
|
||||
/* This instance already has stream_on */
|
||||
if (fh->stream_on)
|
||||
return rc;
|
||||
if (fh->resources & bit)
|
||||
/* have it already allocated */
|
||||
return 1;
|
||||
|
||||
if (dev->stream_on)
|
||||
return -EBUSY;
|
||||
|
||||
dev->stream_on = 1;
|
||||
fh->stream_on = 1;
|
||||
return rc;
|
||||
/* is it free? */
|
||||
mutex_lock(&dev->lock);
|
||||
if (dev->resources & bit) {
|
||||
/* no, someone else uses it */
|
||||
mutex_unlock(&dev->lock);
|
||||
return 0;
|
||||
}
|
||||
/* it's free, grab it */
|
||||
fh->resources |= bit;
|
||||
dev->resources |= bit;
|
||||
dprintk(1, "res: get %d\n", bit);
|
||||
mutex_unlock(&dev->lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int res_check(struct au0828_fh *fh)
|
||||
static int res_check(struct au0828_fh *fh, unsigned int bit)
|
||||
{
|
||||
return fh->stream_on;
|
||||
return fh->resources & bit;
|
||||
}
|
||||
|
||||
static void res_free(struct au0828_fh *fh)
|
||||
static int res_locked(struct au0828_dev *dev, unsigned int bit)
|
||||
{
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
return dev->resources & bit;
|
||||
}
|
||||
|
||||
fh->stream_on = 0;
|
||||
dev->stream_on = 0;
|
||||
static void res_free(struct au0828_fh *fh, unsigned int bits)
|
||||
{
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
|
||||
BUG_ON((fh->resources & bits) != bits);
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
fh->resources &= ~bits;
|
||||
dev->resources &= ~bits;
|
||||
dprintk(1, "res: put %d\n", bits);
|
||||
mutex_unlock(&dev->lock);
|
||||
}
|
||||
|
||||
static int get_ressource(struct au0828_fh *fh)
|
||||
{
|
||||
switch (fh->type) {
|
||||
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
|
||||
return AU0828_RESOURCE_VIDEO;
|
||||
case V4L2_BUF_TYPE_VBI_CAPTURE:
|
||||
return AU0828_RESOURCE_VBI;
|
||||
default:
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int au0828_v4l2_open(struct file *filp)
|
||||
{
|
||||
int ret = 0;
|
||||
struct video_device *vdev = video_devdata(filp);
|
||||
struct au0828_dev *dev = video_drvdata(filp);
|
||||
struct au0828_fh *fh;
|
||||
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
int type;
|
||||
|
||||
#ifdef VBI_IS_WORKING
|
||||
if (video_devdata(filp)->vfl_type == VFL_TYPE_GRABBER)
|
||||
switch (vdev->vfl_type) {
|
||||
case VFL_TYPE_GRABBER:
|
||||
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
break;
|
||||
case VFL_TYPE_VBI:
|
||||
type = V4L2_BUF_TYPE_VBI_CAPTURE;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fh = kzalloc(sizeof(struct au0828_fh), GFP_KERNEL);
|
||||
if (NULL == fh) {
|
||||
|
|
@ -781,10 +962,21 @@ static int au0828_v4l2_open(struct file *filp)
|
|||
dev->users++;
|
||||
|
||||
videobuf_queue_vmalloc_init(&fh->vb_vidq, &au0828_video_qops,
|
||||
NULL, &dev->slock, fh->type,
|
||||
NULL, &dev->slock,
|
||||
V4L2_BUF_TYPE_VIDEO_CAPTURE,
|
||||
V4L2_FIELD_INTERLACED,
|
||||
sizeof(struct au0828_buffer), fh);
|
||||
|
||||
/* VBI Setup */
|
||||
dev->vbi_width = 720;
|
||||
dev->vbi_height = 1;
|
||||
videobuf_queue_vmalloc_init(&fh->vb_vbiq, &au0828_vbi_qops,
|
||||
NULL, &dev->slock,
|
||||
V4L2_BUF_TYPE_VBI_CAPTURE,
|
||||
V4L2_FIELD_SEQ_TB,
|
||||
sizeof(struct au0828_buffer), fh);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -794,17 +986,19 @@ static int au0828_v4l2_close(struct file *filp)
|
|||
struct au0828_fh *fh = filp->private_data;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
if (res_check(fh))
|
||||
res_free(fh);
|
||||
if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
|
||||
videobuf_stop(&fh->vb_vidq);
|
||||
res_free(fh, AU0828_RESOURCE_VIDEO);
|
||||
}
|
||||
|
||||
if (res_check(fh, AU0828_RESOURCE_VBI)) {
|
||||
videobuf_stop(&fh->vb_vbiq);
|
||||
res_free(fh, AU0828_RESOURCE_VBI);
|
||||
}
|
||||
|
||||
if (dev->users == 1) {
|
||||
videobuf_stop(&fh->vb_vidq);
|
||||
videobuf_mmap_free(&fh->vb_vidq);
|
||||
|
||||
if (dev->dev_state & DEV_DISCONNECTED) {
|
||||
au0828_analog_unregister(dev);
|
||||
mutex_unlock(&dev->lock);
|
||||
kfree(dev);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -823,10 +1017,11 @@ static int au0828_v4l2_close(struct file *filp)
|
|||
printk(KERN_INFO "Au0828 can't set alternate to 0!\n");
|
||||
}
|
||||
|
||||
videobuf_mmap_free(&fh->vb_vidq);
|
||||
videobuf_mmap_free(&fh->vb_vbiq);
|
||||
kfree(fh);
|
||||
dev->users--;
|
||||
wake_up_interruptible_nr(&dev->open, 1);
|
||||
mutex_unlock(&dev->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -842,16 +1037,21 @@ static ssize_t au0828_v4l2_read(struct file *filp, char __user *buf,
|
|||
return rc;
|
||||
|
||||
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
mutex_lock(&dev->lock);
|
||||
rc = res_get(fh);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
if (unlikely(rc < 0))
|
||||
return rc;
|
||||
if (res_locked(dev, AU0828_RESOURCE_VIDEO))
|
||||
return -EBUSY;
|
||||
|
||||
return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
|
||||
filp->f_flags & O_NONBLOCK);
|
||||
}
|
||||
|
||||
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||
if (!res_get(fh, AU0828_RESOURCE_VBI))
|
||||
return -EBUSY;
|
||||
|
||||
return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
|
||||
filp->f_flags & O_NONBLOCK);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -865,17 +1065,17 @@ static unsigned int au0828_v4l2_poll(struct file *filp, poll_table *wait)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
rc = res_get(fh);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
if (unlikely(rc < 0))
|
||||
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
if (!res_get(fh, AU0828_RESOURCE_VIDEO))
|
||||
return POLLERR;
|
||||
return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
|
||||
} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||
if (!res_get(fh, AU0828_RESOURCE_VBI))
|
||||
return POLLERR;
|
||||
return videobuf_poll_stream(filp, &fh->vb_vbiq, wait);
|
||||
} else {
|
||||
return POLLERR;
|
||||
|
||||
if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
|
||||
return POLLERR;
|
||||
|
||||
return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
|
||||
}
|
||||
}
|
||||
|
||||
static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
|
|
@ -888,14 +1088,10 @@ static int au0828_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
rc = res_get(fh);
|
||||
mutex_unlock(&dev->lock);
|
||||
|
||||
if (unlikely(rc < 0))
|
||||
return rc;
|
||||
|
||||
rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
|
||||
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
|
||||
else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||
rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -911,14 +1107,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
|
|||
maxwidth = 720;
|
||||
maxheight = 480;
|
||||
|
||||
#ifdef VBI_IS_WORKING
|
||||
if (format->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
|
||||
dprintk(1, "VBI format set: to be supported!\n");
|
||||
return 0;
|
||||
}
|
||||
if (format->type == V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||
return 0;
|
||||
#endif
|
||||
if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
@ -999,9 +1187,7 @@ static int vidioc_querycap(struct file *file, void *priv,
|
|||
|
||||
/*set the device capabilities */
|
||||
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
|
||||
#ifdef VBI_IS_WORKING
|
||||
V4L2_CAP_VBI_CAPTURE |
|
||||
#endif
|
||||
V4L2_CAP_AUDIO |
|
||||
V4L2_CAP_READWRITE |
|
||||
V4L2_CAP_STREAMING |
|
||||
|
|
@ -1056,20 +1242,21 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
|
|||
struct au0828_dev *dev = fh->dev;
|
||||
int rc;
|
||||
|
||||
rc = check_dev(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
|
||||
if (videobuf_queue_is_busy(&fh->vb_vidq)) {
|
||||
printk(KERN_INFO "%s queue busy\n", __func__);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (dev->stream_on && !fh->stream_on) {
|
||||
printk(KERN_INFO "%s device in use by another fh\n", __func__);
|
||||
rc = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return au0828_set_format(dev, VIDIOC_S_FMT, f);
|
||||
rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
|
||||
out:
|
||||
mutex_unlock(&dev->lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
@ -1300,6 +1487,29 @@ static int vidioc_s_frequency(struct file *file, void *priv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* RAW VBI ioctls */
|
||||
|
||||
static int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
|
||||
struct v4l2_format *format)
|
||||
{
|
||||
struct au0828_fh *fh = priv;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
|
||||
format->fmt.vbi.samples_per_line = dev->vbi_width;
|
||||
format->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
|
||||
format->fmt.vbi.offset = 0;
|
||||
format->fmt.vbi.flags = 0;
|
||||
format->fmt.vbi.sampling_rate = 6750000 * 4 / 2;
|
||||
|
||||
format->fmt.vbi.count[0] = dev->vbi_height;
|
||||
format->fmt.vbi.count[1] = dev->vbi_height;
|
||||
format->fmt.vbi.start[0] = 21;
|
||||
format->fmt.vbi.start[1] = 284;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vidioc_g_chip_ident(struct file *file, void *priv,
|
||||
struct v4l2_dbg_chip_ident *chip)
|
||||
{
|
||||
|
|
@ -1345,25 +1555,32 @@ static int vidioc_cropcap(struct file *file, void *priv,
|
|||
static int vidioc_streamon(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
struct au0828_fh *fh = priv;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
int rc;
|
||||
struct au0828_fh *fh = priv;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
int rc = -EINVAL;
|
||||
|
||||
rc = check_dev(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (unlikely(type != fh->type))
|
||||
return -EINVAL;
|
||||
|
||||
dprintk(1, "vidioc_streamon fh=%p t=%d fh->res=%d dev->res=%d\n",
|
||||
fh, type, fh->resources, dev->resources);
|
||||
|
||||
if (unlikely(!res_get(fh, get_ressource(fh))))
|
||||
return -EBUSY;
|
||||
|
||||
if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
au0828_analog_stream_enable(dev);
|
||||
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
|
||||
}
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
rc = res_get(fh);
|
||||
|
||||
if (likely(rc >= 0))
|
||||
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
rc = videobuf_streamon(&fh->vb_vidq);
|
||||
mutex_unlock(&dev->lock);
|
||||
else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||
rc = videobuf_streamon(&fh->vb_vbiq);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1371,38 +1588,42 @@ static int vidioc_streamon(struct file *file, void *priv,
|
|||
static int vidioc_streamoff(struct file *file, void *priv,
|
||||
enum v4l2_buf_type type)
|
||||
{
|
||||
struct au0828_fh *fh = priv;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
int i;
|
||||
int ret;
|
||||
int rc;
|
||||
struct au0828_fh *fh = priv;
|
||||
struct au0828_dev *dev = fh->dev;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
rc = check_dev(dev);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
|
||||
if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
|
||||
fh->type != V4L2_BUF_TYPE_VBI_CAPTURE)
|
||||
return -EINVAL;
|
||||
if (type != fh->type)
|
||||
return -EINVAL;
|
||||
|
||||
if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
dprintk(1, "vidioc_streamoff fh=%p t=%d fh->res=%d dev->res=%d\n",
|
||||
fh, type, fh->resources, dev->resources);
|
||||
|
||||
if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
|
||||
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
|
||||
ret = au0828_stream_interrupt(dev);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
}
|
||||
rc = au0828_stream_interrupt(dev);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
for (i = 0; i < AU0828_MAX_INPUT; i++) {
|
||||
if (AUVI_INPUT(i).audio_setup == NULL)
|
||||
continue;
|
||||
(AUVI_INPUT(i).audio_setup)(dev, 0);
|
||||
}
|
||||
for (i = 0; i < AU0828_MAX_INPUT; i++) {
|
||||
if (AUVI_INPUT(i).audio_setup == NULL)
|
||||
continue;
|
||||
(AUVI_INPUT(i).audio_setup)(dev, 0);
|
||||
}
|
||||
|
||||
mutex_lock(&dev->lock);
|
||||
videobuf_streamoff(&fh->vb_vidq);
|
||||
res_free(fh);
|
||||
mutex_unlock(&dev->lock);
|
||||
videobuf_streamoff(&fh->vb_vidq);
|
||||
res_free(fh, AU0828_RESOURCE_VIDEO);
|
||||
} else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
|
||||
videobuf_streamoff(&fh->vb_vbiq);
|
||||
res_free(fh, AU0828_RESOURCE_VBI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1527,19 +1748,11 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
|
|||
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
|
||||
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
|
||||
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
|
||||
#ifdef VBI_IS_WORKING
|
||||
.vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
|
||||
.vidioc_try_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
|
||||
.vidioc_s_fmt_vbi_cap = vidioc_s_fmt_vbi_cap,
|
||||
#endif
|
||||
.vidioc_s_fmt_vbi_cap = vidioc_g_fmt_vbi_cap,
|
||||
.vidioc_g_audio = vidioc_g_audio,
|
||||
.vidioc_s_audio = vidioc_s_audio,
|
||||
.vidioc_cropcap = vidioc_cropcap,
|
||||
#ifdef VBI_IS_WORKING
|
||||
.vidioc_g_fmt_sliced_vbi_cap = vidioc_g_fmt_sliced_vbi_cap,
|
||||
.vidioc_try_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
|
||||
.vidioc_s_fmt_sliced_vbi_cap = vidioc_try_set_sliced_vbi_cap,
|
||||
#endif
|
||||
.vidioc_reqbufs = vidioc_reqbufs,
|
||||
.vidioc_querybuf = vidioc_querybuf,
|
||||
.vidioc_qbuf = vidioc_qbuf,
|
||||
|
|
@ -1621,8 +1834,11 @@ int au0828_analog_register(struct au0828_dev *dev,
|
|||
spin_lock_init(&dev->slock);
|
||||
mutex_init(&dev->lock);
|
||||
|
||||
/* init video dma queues */
|
||||
INIT_LIST_HEAD(&dev->vidq.active);
|
||||
INIT_LIST_HEAD(&dev->vidq.queued);
|
||||
INIT_LIST_HEAD(&dev->vbiq.active);
|
||||
INIT_LIST_HEAD(&dev->vbiq.queued);
|
||||
|
||||
dev->width = NTSC_STD_W;
|
||||
dev->height = NTSC_STD_H;
|
||||
|
|
@ -1638,26 +1854,23 @@ int au0828_analog_register(struct au0828_dev *dev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
#ifdef VBI_IS_WORKING
|
||||
/* allocate the VBI struct */
|
||||
dev->vbi_dev = video_device_alloc();
|
||||
if (NULL == dev->vbi_dev) {
|
||||
dprintk(1, "Can't allocate vbi_device.\n");
|
||||
kfree(dev->vdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fill the video capture device struct */
|
||||
*dev->vdev = au0828_video_template;
|
||||
dev->vdev->parent = &dev->usbdev->dev;
|
||||
strcpy(dev->vdev->name, "au0828a video");
|
||||
|
||||
#ifdef VBI_IS_WORKING
|
||||
/* Setup the VBI device */
|
||||
*dev->vbi_dev = au0828_video_template;
|
||||
dev->vbi_dev->parent = &dev->usbdev->dev;
|
||||
strcpy(dev->vbi_dev->name, "au0828a vbi");
|
||||
#endif
|
||||
|
||||
/* Register the v4l2 device */
|
||||
video_set_drvdata(dev->vdev, dev);
|
||||
|
|
@ -1669,7 +1882,6 @@ int au0828_analog_register(struct au0828_dev *dev,
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
#ifdef VBI_IS_WORKING
|
||||
/* Register the vbi device */
|
||||
video_set_drvdata(dev->vbi_dev, dev);
|
||||
retval = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, -1);
|
||||
|
|
@ -1680,7 +1892,6 @@ int au0828_analog_register(struct au0828_dev *dev,
|
|||
video_device_release(dev->vdev);
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
dprintk(1, "%s completed!\n", __func__);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,10 @@
|
|||
|
||||
#define AU0828_MAX_INPUT 4
|
||||
|
||||
/* au0828 resource types (used for res_get/res_lock etc */
|
||||
#define AU0828_RESOURCE_VIDEO 0x01
|
||||
#define AU0828_RESOURCE_VBI 0x02
|
||||
|
||||
enum au0828_itype {
|
||||
AU0828_VMUX_UNDEFINED = 0,
|
||||
AU0828_VMUX_COMPOSITE,
|
||||
|
|
@ -115,8 +119,10 @@ enum au0828_dev_state {
|
|||
|
||||
struct au0828_fh {
|
||||
struct au0828_dev *dev;
|
||||
unsigned int stream_on:1; /* Locks streams */
|
||||
unsigned int resources;
|
||||
|
||||
struct videobuf_queue vb_vidq;
|
||||
struct videobuf_queue vb_vbiq;
|
||||
enum v4l2_buf_type type;
|
||||
};
|
||||
|
||||
|
|
@ -145,7 +151,8 @@ struct au0828_usb_isoc_ctl {
|
|||
int tmp_buf_len;
|
||||
|
||||
/* Stores already requested buffers */
|
||||
struct au0828_buffer *buf;
|
||||
struct au0828_buffer *buf;
|
||||
struct au0828_buffer *vbi_buf;
|
||||
|
||||
/* Stores the number of received fields */
|
||||
int nfields;
|
||||
|
|
@ -194,11 +201,14 @@ struct au0828_dev {
|
|||
/* Analog */
|
||||
struct v4l2_device v4l2_dev;
|
||||
int users;
|
||||
unsigned int stream_on:1; /* Locks streams */
|
||||
unsigned int resources; /* resources in use */
|
||||
struct video_device *vdev;
|
||||
struct video_device *vbi_dev;
|
||||
int width;
|
||||
int height;
|
||||
int vbi_width;
|
||||
int vbi_height;
|
||||
u32 vbi_read;
|
||||
u32 field_size;
|
||||
u32 frame_size;
|
||||
u32 bytesperline;
|
||||
|
|
@ -219,6 +229,7 @@ struct au0828_dev {
|
|||
|
||||
/* Isoc control struct */
|
||||
struct au0828_dmaqueue vidq;
|
||||
struct au0828_dmaqueue vbiq;
|
||||
struct au0828_usb_isoc_ctl isoc_ctl;
|
||||
spinlock_t slock;
|
||||
|
||||
|
|
@ -278,6 +289,9 @@ void au0828_analog_unregister(struct au0828_dev *dev);
|
|||
extern int au0828_dvb_register(struct au0828_dev *dev);
|
||||
extern void au0828_dvb_unregister(struct au0828_dev *dev);
|
||||
|
||||
/* au0828-vbi.c */
|
||||
extern struct videobuf_queue_ops au0828_vbi_qops;
|
||||
|
||||
#define dprintk(level, fmt, arg...)\
|
||||
do { if (au0828_debug & level)\
|
||||
printk(KERN_DEBUG DRIVER_NAME "/0: " fmt, ## arg);\
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf
|
|||
|
||||
BUG_ON(in_interrupt());
|
||||
videobuf_waiton(&buf->vb,0,0);
|
||||
videobuf_dma_unmap(q, dma);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
btcx_riscmem_free(btv->c.pci,&buf->bottom);
|
||||
btcx_riscmem_free(btv->c.pci,&buf->top);
|
||||
|
|
|
|||
|
|
@ -584,7 +584,6 @@ static void cpia_disconnect(struct usb_interface *intf)
|
|||
{
|
||||
struct cam_data *cam = usb_get_intfdata(intf);
|
||||
struct usb_cpia *ucpia;
|
||||
struct usb_device *udev;
|
||||
|
||||
usb_set_intfdata(intf, NULL);
|
||||
if (!cam)
|
||||
|
|
@ -606,8 +605,6 @@ static void cpia_disconnect(struct usb_interface *intf)
|
|||
if (waitqueue_active(&ucpia->wq_stream))
|
||||
wake_up_interruptible(&ucpia->wq_stream);
|
||||
|
||||
udev = interface_to_usbdev(intf);
|
||||
|
||||
ucpia->curbuff = ucpia->workbuff = NULL;
|
||||
|
||||
vfree(ucpia->buffers[2]);
|
||||
|
|
|
|||
|
|
@ -1081,7 +1081,7 @@ long cx18_v4l2_ioctl(struct file *filp, unsigned int cmd,
|
|||
unsigned long arg)
|
||||
{
|
||||
struct video_device *vfd = video_devdata(filp);
|
||||
struct cx18_open_id *id = (struct cx18_open_id *)filp->private_data;
|
||||
struct cx18_open_id *id = filp->private_data;
|
||||
struct cx18 *cx = id->cx;
|
||||
long res;
|
||||
|
||||
|
|
|
|||
|
|
@ -406,10 +406,18 @@ struct cx23885_subid cx23885_subids[] = {
|
|||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2215,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1275,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x221d,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1275,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2251,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1255,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2259,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1255,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2291,
|
||||
|
|
@ -418,6 +426,38 @@ struct cx23885_subid cx23885_subids[] = {
|
|||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2295,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x2299,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x229d,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f0,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f1,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1255,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f2,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1275,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f3,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f4,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210,
|
||||
}, {
|
||||
.subvendor = 0x0070,
|
||||
.subdevice = 0x22f5,
|
||||
.card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */
|
||||
}, {
|
||||
.subvendor = 0x14f1,
|
||||
.subdevice = 0x8651,
|
||||
|
|
|
|||
|
|
@ -1142,7 +1142,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
|
|||
|
||||
BUG_ON(in_interrupt());
|
||||
videobuf_waiton(&buf->vb, 0, 0);
|
||||
videobuf_dma_unmap(q, dma);
|
||||
videobuf_dma_unmap(q->dev, dma);
|
||||
videobuf_dma_free(dma);
|
||||
btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
|
||||
buf->vb.state = VIDEOBUF_NEEDS_INIT;
|
||||
|
|
@ -1953,8 +1953,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
|
|||
goto fail_irq;
|
||||
}
|
||||
|
||||
err = request_irq(pci_dev->irq, cx23885_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
|
||||
if (!pci_enable_msi(pci_dev))
|
||||
err = request_irq(pci_dev->irq, cx23885_irq,
|
||||
IRQF_DISABLED, dev->name, dev);
|
||||
else
|
||||
err = request_irq(pci_dev->irq, cx23885_irq,
|
||||
IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
|
||||
if (err < 0) {
|
||||
printk(KERN_ERR "%s: can't get IRQ %d\n",
|
||||
dev->name, pci_dev->irq);
|
||||
|
|
@ -2000,6 +2004,7 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
|
|||
|
||||
/* unregister stuff */
|
||||
free_irq(pci_dev->irq, dev);
|
||||
pci_disable_msi(pci_dev);
|
||||
|
||||
cx23885_dev_unregister(dev);
|
||||
v4l2_device_unregister(v4l2_dev);
|
||||
|
|
|
|||
|
|
@ -991,7 +991,7 @@ static int dvb_register(struct cx23885_tsport *port)
|
|||
ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
|
||||
&dev->pci->dev, adapter_nr, 0,
|
||||
cx23885_dvb_fe_ioctl_override);
|
||||
if (!ret)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* init CI & MAC */
|
||||
|
|
|
|||
|
|
@ -37,161 +37,55 @@
|
|||
|
||||
#include <linux/input.h>
|
||||
#include <linux/slab.h>
|
||||
#include <media/ir-common.h>
|
||||
#include <media/ir-core.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
|
||||
#include "cx23885.h"
|
||||
|
||||
#define RC5_BITS 14
|
||||
#define RC5_HALF_BITS (2*RC5_BITS)
|
||||
#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1)
|
||||
|
||||
#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */
|
||||
#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */
|
||||
|
||||
#define RC5_EXTENDED_COMMAND_OFFSET 64
|
||||
|
||||
#define MODULE_NAME "cx23885"
|
||||
|
||||
static inline unsigned int rc5_command(u32 rc5_baseband)
|
||||
static void convert_measurement(u32 x, struct ir_raw_event *y)
|
||||
{
|
||||
return RC5_INSTR(rc5_baseband) +
|
||||
((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED)
|
||||
? RC5_EXTENDED_COMMAND_OFFSET : 0);
|
||||
if (x == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
|
||||
y->pulse = false;
|
||||
y->duration = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
|
||||
return;
|
||||
}
|
||||
|
||||
y->pulse = (x & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? true : false;
|
||||
y->duration = x & V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
|
||||
}
|
||||
|
||||
static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev)
|
||||
static void cx23885_input_process_measurements(struct cx23885_dev *dev,
|
||||
bool overrun)
|
||||
{
|
||||
struct card_ir *ir_input = dev->ir_input;
|
||||
unsigned int code, command;
|
||||
u32 rc5;
|
||||
struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;
|
||||
struct ir_raw_event kernel_ir_event;
|
||||
|
||||
/* Ignore codes that are too short to be valid RC-5 */
|
||||
if (ir_input->last_bit < (RC5_HALF_BITS - 1))
|
||||
return;
|
||||
|
||||
/* The library has the manchester coding backwards; XOR to adapt. */
|
||||
code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK;
|
||||
rc5 = ir_rc5_decode(code);
|
||||
|
||||
switch (RC5_START(rc5)) {
|
||||
case RC5_START_BITS_NORMAL:
|
||||
break;
|
||||
case RC5_START_BITS_EXTENDED:
|
||||
/* Don't allow if the remote only emits standard commands */
|
||||
if (ir_input->start == RC5_START_BITS_NORMAL)
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (ir_input->addr != RC5_ADDR(rc5))
|
||||
return;
|
||||
|
||||
/* Don't generate a keypress for RC-5 auto-repeated keypresses */
|
||||
command = rc5_command(rc5);
|
||||
if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) ||
|
||||
command != rc5_command(ir_input->last_rc5) ||
|
||||
/* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */
|
||||
RC5_START(ir_input->last_rc5) == 0) {
|
||||
/* This keypress is differnet: not an auto repeat */
|
||||
ir_input_nokey(ir_input->dev, &ir_input->ir);
|
||||
ir_input_keydown(ir_input->dev, &ir_input->ir, command);
|
||||
}
|
||||
ir_input->last_rc5 = rc5;
|
||||
|
||||
/* Schedule when we should do the key up event: ir_input_nokey() */
|
||||
mod_timer(&ir_input->timer_keyup,
|
||||
jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout));
|
||||
}
|
||||
|
||||
static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev,
|
||||
u32 ns_pulse)
|
||||
{
|
||||
const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */
|
||||
struct card_ir *ir_input = dev->ir_input;
|
||||
int i, level, quarterbits, halfbits;
|
||||
|
||||
if (!ir_input->active) {
|
||||
ir_input->active = 1;
|
||||
/* assume an initial space that we may not detect or measure */
|
||||
ir_input->code = 0;
|
||||
ir_input->last_bit = 0;
|
||||
}
|
||||
|
||||
if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) {
|
||||
ir_input->last_bit++; /* Account for the final space */
|
||||
ir_input->active = 0;
|
||||
cx23885_input_process_raw_rc5(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0;
|
||||
|
||||
/* Skip any leading space to sync to the start bit */
|
||||
if (ir_input->last_bit == 0 && level == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* With valid RC-5 we can get up to two consecutive half-bits in a
|
||||
* single pulse measurment. Experiments have shown that the duration
|
||||
* of a half-bit can vary. Make sure we always end up with an even
|
||||
* number of quarter bits at the same level (mark or space).
|
||||
*/
|
||||
ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS;
|
||||
quarterbits = ns_pulse / rc5_quarterbit_ns;
|
||||
if (quarterbits & 1)
|
||||
quarterbits++;
|
||||
halfbits = quarterbits / 2;
|
||||
|
||||
for (i = 0; i < halfbits; i++) {
|
||||
ir_input->last_bit++;
|
||||
ir_input->code |= (level << ir_input->last_bit);
|
||||
|
||||
if (ir_input->last_bit >= RC5_HALF_BITS-1) {
|
||||
ir_input->active = 0;
|
||||
cx23885_input_process_raw_rc5(dev);
|
||||
/*
|
||||
* If level is 1, a leading mark is invalid for RC5.
|
||||
* If level is 0, we scan past extra intial space.
|
||||
* Either way we don't want to reactivate collecting
|
||||
* marks or spaces here with any left over half-bits.
|
||||
*/
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev,
|
||||
bool add_eom)
|
||||
{
|
||||
struct card_ir *ir_input = dev->ir_input;
|
||||
struct ir_input_state *ir_input_state = &ir_input->ir;
|
||||
|
||||
u32 ns_pulse[RC5_HALF_BITS+1];
|
||||
ssize_t num = 0;
|
||||
u32 sd_ir_data[64];
|
||||
ssize_t num;
|
||||
int count, i;
|
||||
bool handle = false;
|
||||
|
||||
do {
|
||||
v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse,
|
||||
sizeof(ns_pulse), &num);
|
||||
num = 0;
|
||||
v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) sd_ir_data,
|
||||
sizeof(sd_ir_data), &num);
|
||||
|
||||
count = num / sizeof(u32);
|
||||
|
||||
/* Append an end of Rx seq, if the caller requested */
|
||||
if (add_eom && count < ARRAY_SIZE(ns_pulse)) {
|
||||
ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END;
|
||||
count++;
|
||||
for (i = 0; i < count; i++) {
|
||||
convert_measurement(sd_ir_data[i], &kernel_ir_event);
|
||||
ir_raw_event_store(kernel_ir->inp_dev,
|
||||
&kernel_ir_event);
|
||||
handle = true;
|
||||
}
|
||||
|
||||
/* Just drain the Rx FIFO, if we're called, but not RC-5 */
|
||||
if (ir_input_state->ir_type != IR_TYPE_RC5)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]);
|
||||
} while (num != 0);
|
||||
|
||||
if (overrun)
|
||||
ir_raw_event_reset(kernel_ir->inp_dev);
|
||||
else if (handle)
|
||||
ir_raw_event_handle(kernel_ir->inp_dev);
|
||||
}
|
||||
|
||||
void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
|
||||
|
|
@ -230,7 +124,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
|
|||
}
|
||||
|
||||
if (data_available)
|
||||
cx23885_input_process_pulse_widths_rc5(dev, overrun);
|
||||
cx23885_input_process_measurements(dev, overrun);
|
||||
|
||||
if (overrun) {
|
||||
/* If there was a FIFO overrun, clear & restart the device */
|
||||
|
|
@ -241,34 +135,15 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
|
|||
}
|
||||
}
|
||||
|
||||
static void cx23885_input_ir_start(struct cx23885_dev *dev)
|
||||
static int cx23885_input_ir_start(struct cx23885_dev *dev)
|
||||
{
|
||||
struct card_ir *ir_input = dev->ir_input;
|
||||
struct ir_input_state *ir_input_state = &ir_input->ir;
|
||||
struct v4l2_subdev_ir_parameters params;
|
||||
|
||||
if (dev->sd_ir == NULL)
|
||||
return;
|
||||
return -ENODEV;
|
||||
|
||||
atomic_set(&dev->ir_input_stopping, 0);
|
||||
|
||||
/* keyup timer set up, if needed */
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1290:
|
||||
setup_timer(&ir_input->timer_keyup,
|
||||
ir_rc5_timer_keyup, /* Not actually RC-5 specific */
|
||||
(unsigned long) ir_input);
|
||||
if (ir_input_state->ir_type == IR_TYPE_RC5) {
|
||||
/*
|
||||
* RC-5 repeats a held key every
|
||||
* 64 bits * (2 * 32/36000) sec/bit = 113.778 ms
|
||||
*/
|
||||
ir_input->rc5_key_timeout = 115;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms);
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
|
|
@ -299,11 +174,21 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev)
|
|||
break;
|
||||
}
|
||||
v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cx23885_input_ir_open(void *priv)
|
||||
{
|
||||
struct cx23885_kernel_ir *kernel_ir = priv;
|
||||
|
||||
if (kernel_ir->cx == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
return cx23885_input_ir_start(kernel_ir->cx);
|
||||
}
|
||||
|
||||
static void cx23885_input_ir_stop(struct cx23885_dev *dev)
|
||||
{
|
||||
struct card_ir *ir_input = dev->ir_input;
|
||||
struct v4l2_subdev_ir_parameters params;
|
||||
|
||||
if (dev->sd_ir == NULL)
|
||||
|
|
@ -327,21 +212,26 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev)
|
|||
}
|
||||
|
||||
flush_scheduled_work();
|
||||
}
|
||||
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1290:
|
||||
del_timer_sync(&ir_input->timer_keyup);
|
||||
break;
|
||||
}
|
||||
static void cx23885_input_ir_close(void *priv)
|
||||
{
|
||||
struct cx23885_kernel_ir *kernel_ir = priv;
|
||||
|
||||
if (kernel_ir->cx != NULL)
|
||||
cx23885_input_ir_stop(kernel_ir->cx);
|
||||
}
|
||||
|
||||
int cx23885_input_init(struct cx23885_dev *dev)
|
||||
{
|
||||
struct card_ir *ir;
|
||||
struct input_dev *input_dev;
|
||||
char *ir_codes = NULL;
|
||||
int ir_type, ir_addr, ir_start;
|
||||
struct cx23885_kernel_ir *kernel_ir;
|
||||
struct input_dev *inp_dev;
|
||||
struct ir_dev_props *props;
|
||||
|
||||
char *rc_map;
|
||||
enum rc_driver_type driver_type;
|
||||
unsigned long allowed_protos;
|
||||
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
|
@ -354,53 +244,59 @@ int cx23885_input_init(struct cx23885_dev *dev)
|
|||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1290:
|
||||
/* Parameters for the grey Hauppauge remote for the HVR-1850 */
|
||||
ir_codes = RC_MAP_HAUPPAUGE_NEW;
|
||||
ir_type = IR_TYPE_RC5;
|
||||
ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */
|
||||
ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */
|
||||
/* Integrated CX23888 IR controller */
|
||||
driver_type = RC_DRIVER_IR_RAW;
|
||||
allowed_protos = IR_TYPE_ALL;
|
||||
/* The grey Hauppauge RC-5 remote */
|
||||
rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
|
||||
break;
|
||||
}
|
||||
if (ir_codes == NULL)
|
||||
default:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
|
||||
input_dev = input_allocate_device();
|
||||
if (!ir || !input_dev) {
|
||||
/* cx23885 board instance kernel IR state */
|
||||
kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL);
|
||||
if (kernel_ir == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
kernel_ir->cx = dev;
|
||||
kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)",
|
||||
cx23885_boards[dev->board].name);
|
||||
kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0",
|
||||
pci_name(dev->pci));
|
||||
|
||||
/* input device */
|
||||
inp_dev = input_allocate_device();
|
||||
if (inp_dev == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err_out_free;
|
||||
}
|
||||
|
||||
ir->dev = input_dev;
|
||||
ir->addr = ir_addr;
|
||||
ir->start = ir_start;
|
||||
|
||||
/* init input device */
|
||||
snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)",
|
||||
cx23885_boards[dev->board].name);
|
||||
snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci));
|
||||
|
||||
ret = ir_input_init(input_dev, &ir->ir, ir_type);
|
||||
if (ret < 0)
|
||||
goto err_out_free;
|
||||
|
||||
input_dev->name = ir->name;
|
||||
input_dev->phys = ir->phys;
|
||||
input_dev->id.bustype = BUS_PCI;
|
||||
input_dev->id.version = 1;
|
||||
kernel_ir->inp_dev = inp_dev;
|
||||
inp_dev->name = kernel_ir->name;
|
||||
inp_dev->phys = kernel_ir->phys;
|
||||
inp_dev->id.bustype = BUS_PCI;
|
||||
inp_dev->id.version = 1;
|
||||
if (dev->pci->subsystem_vendor) {
|
||||
input_dev->id.vendor = dev->pci->subsystem_vendor;
|
||||
input_dev->id.product = dev->pci->subsystem_device;
|
||||
inp_dev->id.vendor = dev->pci->subsystem_vendor;
|
||||
inp_dev->id.product = dev->pci->subsystem_device;
|
||||
} else {
|
||||
input_dev->id.vendor = dev->pci->vendor;
|
||||
input_dev->id.product = dev->pci->device;
|
||||
inp_dev->id.vendor = dev->pci->vendor;
|
||||
inp_dev->id.product = dev->pci->device;
|
||||
}
|
||||
input_dev->dev.parent = &dev->pci->dev;
|
||||
inp_dev->dev.parent = &dev->pci->dev;
|
||||
|
||||
dev->ir_input = ir;
|
||||
cx23885_input_ir_start(dev);
|
||||
/* kernel ir device properties */
|
||||
props = &kernel_ir->props;
|
||||
props->driver_type = driver_type;
|
||||
props->allowed_protos = allowed_protos;
|
||||
props->priv = kernel_ir;
|
||||
props->open = cx23885_input_ir_open;
|
||||
props->close = cx23885_input_ir_close;
|
||||
|
||||
ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME);
|
||||
/* Go */
|
||||
dev->kernel_ir = kernel_ir;
|
||||
ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME);
|
||||
if (ret)
|
||||
goto err_out_stop;
|
||||
|
||||
|
|
@ -408,9 +304,12 @@ int cx23885_input_init(struct cx23885_dev *dev)
|
|||
|
||||
err_out_stop:
|
||||
cx23885_input_ir_stop(dev);
|
||||
dev->ir_input = NULL;
|
||||
dev->kernel_ir = NULL;
|
||||
/* TODO: double check clean-up of kernel_ir->inp_dev */
|
||||
err_out_free:
|
||||
kfree(ir);
|
||||
kfree(kernel_ir->phys);
|
||||
kfree(kernel_ir->name);
|
||||
kfree(kernel_ir);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -419,9 +318,11 @@ void cx23885_input_fini(struct cx23885_dev *dev)
|
|||
/* Always stop the IR hardware from generating interrupts */
|
||||
cx23885_input_ir_stop(dev);
|
||||
|
||||
if (dev->ir_input == NULL)
|
||||
if (dev->kernel_ir == NULL)
|
||||
return;
|
||||
ir_input_unregister(dev->ir_input->dev);
|
||||
kfree(dev->ir_input);
|
||||
dev->ir_input = NULL;
|
||||
ir_input_unregister(dev->kernel_ir->inp_dev);
|
||||
kfree(dev->kernel_ir->phys);
|
||||
kfree(dev->kernel_ir->name);
|
||||
kfree(dev->kernel_ir);
|
||||
dev->kernel_ir = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ void cx23885_ir_rx_work_handler(struct work_struct *work)
|
|||
if (events == 0)
|
||||
return;
|
||||
|
||||
if (dev->ir_input)
|
||||
if (dev->kernel_ir)
|
||||
cx23885_input_rx_work_handler(dev, events);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <media/tveeprom.h>
|
||||
#include <media/videobuf-dma-sg.h>
|
||||
#include <media/videobuf-dvb.h>
|
||||
#include <media/ir-core.h>
|
||||
|
||||
#include "btcx-risc.h"
|
||||
#include "cx23885-reg.h"
|
||||
|
|
@ -304,6 +305,15 @@ struct cx23885_tsport {
|
|||
void *port_priv;
|
||||
};
|
||||
|
||||
struct cx23885_kernel_ir {
|
||||
struct cx23885_dev *cx;
|
||||
char *name;
|
||||
char *phys;
|
||||
|
||||
struct input_dev *inp_dev;
|
||||
struct ir_dev_props props;
|
||||
};
|
||||
|
||||
struct cx23885_dev {
|
||||
atomic_t refcount;
|
||||
struct v4l2_device v4l2_dev;
|
||||
|
|
@ -363,7 +373,7 @@ struct cx23885_dev {
|
|||
struct work_struct ir_tx_work;
|
||||
unsigned long ir_tx_notifications;
|
||||
|
||||
struct card_ir *ir_input;
|
||||
struct cx23885_kernel_ir *kernel_ir;
|
||||
atomic_t ir_input_stopping;
|
||||
|
||||
/* V4l */
|
||||
|
|
|
|||
|
|
@ -54,6 +54,12 @@
|
|||
Data type declarations - Can be moded to a header file later
|
||||
****************************************************************************/
|
||||
|
||||
struct cx88_audio_buffer {
|
||||
unsigned int bpl;
|
||||
struct btcx_riscmem risc;
|
||||
struct videobuf_dmabuf dma;
|
||||
};
|
||||
|
||||
struct cx88_audio_dev {
|
||||
struct cx88_core *core;
|
||||
struct cx88_dmaqueue q;
|
||||
|
|
@ -75,7 +81,7 @@ struct cx88_audio_dev {
|
|||
|
||||
struct videobuf_dmabuf *dma_risc;
|
||||
|
||||
struct cx88_buffer *buf;
|
||||
struct cx88_audio_buffer *buf;
|
||||
|
||||
struct snd_pcm_substream *substream;
|
||||
};
|
||||
|
|
@ -123,7 +129,7 @@ MODULE_PARM_DESC(debug,"enable debug messages");
|
|||
|
||||
static int _cx88_start_audio_dma(snd_cx88_card_t *chip)
|
||||
{
|
||||
struct cx88_buffer *buf = chip->buf;
|
||||
struct cx88_audio_buffer *buf = chip->buf;
|
||||
struct cx88_core *core=chip->core;
|
||||
struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25];
|
||||
|
||||
|
|
@ -283,7 +289,7 @@ static int dsp_buffer_free(snd_cx88_card_t *chip)
|
|||
BUG_ON(!chip->dma_size);
|
||||
|
||||
dprintk(2,"Freeing buffer\n");
|
||||
videobuf_sg_dma_unmap(&chip->pci->dev, chip->dma_risc);
|
||||
videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
|
||||
videobuf_dma_free(chip->dma_risc);
|
||||
btcx_riscmem_free(chip->pci,&chip->buf->risc);
|
||||
kfree(chip->buf);
|
||||
|
|
@ -376,7 +382,7 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
|
|||
snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
|
||||
struct videobuf_dmabuf *dma;
|
||||
|
||||
struct cx88_buffer *buf;
|
||||
struct cx88_audio_buffer *buf;
|
||||
int ret;
|
||||
|
||||
if (substream->runtime->dma_area) {
|
||||
|
|
@ -391,30 +397,25 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
|
|||
BUG_ON(!chip->dma_size);
|
||||
BUG_ON(chip->num_periods & (chip->num_periods-1));
|
||||
|
||||
buf = videobuf_sg_alloc(sizeof(*buf));
|
||||
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
|
||||
if (NULL == buf)
|
||||
return -ENOMEM;
|
||||
|
||||
buf->vb.memory = V4L2_MEMORY_MMAP;
|
||||
buf->vb.field = V4L2_FIELD_NONE;
|
||||
buf->vb.width = chip->period_size;
|
||||
buf->bpl = chip->period_size;
|
||||
buf->vb.height = chip->num_periods;
|
||||
buf->vb.size = chip->dma_size;
|
||||
buf->bpl = chip->period_size;
|
||||
|
||||
dma = videobuf_to_dma(&buf->vb);
|
||||
dma = &buf->dma;
|
||||
videobuf_dma_init(dma);
|
||||
ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
|
||||
(PAGE_ALIGN(buf->vb.size) >> PAGE_SHIFT));
|
||||
(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = videobuf_sg_dma_map(&chip->pci->dev, dma);
|
||||
ret = videobuf_dma_map(&chip->pci->dev, dma);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
|
||||
buf->vb.width, buf->vb.height, 1);
|
||||
chip->period_size, chip->num_periods, 1);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
|
|
@ -422,12 +423,10 @@ static int snd_cx88_hw_params(struct snd_pcm_substream * substream,
|
|||
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
|
||||
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
|
||||
|
||||
buf->vb.state = VIDEOBUF_PREPARED;
|
||||
|
||||
chip->buf = buf;
|
||||
chip->dma_risc = dma;
|
||||
|
||||
substream->runtime->dma_area = chip->dma_risc->vmalloc;
|
||||
substream->runtime->dma_area = chip->dma_risc->vaddr;
|
||||
substream->runtime->dma_bytes = chip->dma_size;
|
||||
substream->runtime->dma_addr = 0;
|
||||
return 0;
|
||||
|
|
@ -740,7 +739,7 @@ static int __devinit snd_cx88_create(struct snd_card *card,
|
|||
|
||||
pci_set_master(pci);
|
||||
|
||||
chip = (snd_cx88_card_t *) card->private_data;
|
||||
chip = card->private_data;
|
||||
|
||||
core = cx88_core_get(pci);
|
||||
if (NULL == core) {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue