forked from Minki/linux
[PATCH] dvb: cinergyT2: remote control fixes
IR RC fixes: - EVIOCSKEYCODE is not supported by this driver, fix potential crash when it is used by not setting rc_input_dev->keycodesize - fix key repeat handling (hopefully) - reduce default poll internal to 50msec (necessary for key repeat handling) Signed-off-by: Johannes Stezenbach <js@linuxtv.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
2d6e7322b5
commit
6d78933c29
@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
|
||||
config DVB_CINERGYT2_RC_QUERY_INTERVAL
|
||||
int "Infrared Remote Controller update interval [milliseconds]"
|
||||
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
|
||||
default "100"
|
||||
default "50"
|
||||
help
|
||||
If you have a very fast-repeating remote control you can try lower
|
||||
values, for normal consumer receivers the default value should be
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "dvb_demux.h"
|
||||
#include "dvb_net.h"
|
||||
|
||||
|
||||
#ifdef CONFIG_DVB_CINERGYT2_TUNING
|
||||
#define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
|
||||
#define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
|
||||
@ -48,7 +47,7 @@
|
||||
#define STREAM_URB_COUNT (32)
|
||||
#define STREAM_BUF_SIZE (512) /* bytes */
|
||||
#define ENABLE_RC (1)
|
||||
#define RC_QUERY_INTERVAL (100) /* milliseconds */
|
||||
#define RC_QUERY_INTERVAL (50) /* milliseconds */
|
||||
#define QUERY_INTERVAL (333) /* milliseconds */
|
||||
#endif
|
||||
|
||||
@ -141,6 +140,8 @@ struct cinergyt2 {
|
||||
struct input_dev rc_input_dev;
|
||||
struct work_struct rc_query_work;
|
||||
int rc_input_event;
|
||||
u32 rc_last_code;
|
||||
unsigned long last_event_jiffies;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -155,7 +156,7 @@ struct cinergyt2_rc_event {
|
||||
uint32_t value;
|
||||
} __attribute__((packed));
|
||||
|
||||
static const uint32_t rc_keys [] = {
|
||||
static const uint32_t rc_keys[] = {
|
||||
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER,
|
||||
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
|
||||
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
|
||||
@ -684,52 +685,68 @@ static struct dvb_device cinergyt2_fe_template = {
|
||||
#ifdef ENABLE_RC
|
||||
static void cinergyt2_query_rc (void *data)
|
||||
{
|
||||
struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data;
|
||||
char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS };
|
||||
struct cinergyt2 *cinergyt2 = data;
|
||||
char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
|
||||
struct cinergyt2_rc_event rc_events[12];
|
||||
int n, len;
|
||||
int n, len, i;
|
||||
|
||||
if (down_interruptible(&cinergyt2->sem))
|
||||
return;
|
||||
|
||||
len = cinergyt2_command(cinergyt2, buf, sizeof(buf),
|
||||
(char *) rc_events, sizeof(rc_events));
|
||||
(char *) rc_events, sizeof(rc_events));
|
||||
if (len < 0)
|
||||
goto out;
|
||||
if (len == 0) {
|
||||
if (time_after(jiffies, cinergyt2->last_event_jiffies +
|
||||
msecs_to_jiffies(150))) {
|
||||
/* stop key repeat */
|
||||
if (cinergyt2->rc_input_event != KEY_MAX) {
|
||||
dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event);
|
||||
input_report_key(&cinergyt2->rc_input_dev,
|
||||
cinergyt2->rc_input_event, 0);
|
||||
cinergyt2->rc_input_event = KEY_MAX;
|
||||
}
|
||||
cinergyt2->rc_last_code = ~0;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
cinergyt2->last_event_jiffies = jiffies;
|
||||
|
||||
for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
|
||||
int i;
|
||||
|
||||
/* dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/
|
||||
for (n = 0; n < (len / sizeof(rc_events[0])); n++) {
|
||||
dprintk(1, "rc_events[%d].value = %x, type=%x\n",
|
||||
n, le32_to_cpu(rc_events[n].value), rc_events[n].type);
|
||||
|
||||
if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
|
||||
rc_events[n].value == ~0)
|
||||
{
|
||||
/**
|
||||
* keyrepeat bit. If we would handle this properly
|
||||
* we would need to emit down events as long the
|
||||
* keyrepeat goes, a up event if no further
|
||||
* repeat bits occur. Would need a timer to implement
|
||||
* and no other driver does this, so we simply
|
||||
* emit the last key up/down sequence again.
|
||||
*/
|
||||
rc_events[n].value == ~0) {
|
||||
/* keyrepeat bit -> just repeat last rc_input_event */
|
||||
} else {
|
||||
cinergyt2->rc_input_event = KEY_MAX;
|
||||
for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) {
|
||||
if (rc_keys[i+0] == rc_events[n].type &&
|
||||
rc_keys[i+1] == le32_to_cpu(rc_events[n].value))
|
||||
{
|
||||
cinergyt2->rc_input_event = rc_keys[i+2];
|
||||
for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
|
||||
if (rc_keys[i + 0] == rc_events[n].type &&
|
||||
rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
|
||||
cinergyt2->rc_input_event = rc_keys[i + 2];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cinergyt2->rc_input_event != KEY_MAX) {
|
||||
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1);
|
||||
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0);
|
||||
input_sync(&cinergyt2->rc_input_dev);
|
||||
if (rc_events[n].value == cinergyt2->rc_last_code &&
|
||||
cinergyt2->rc_last_code != ~0) {
|
||||
/* emit a key-up so the double event is recognized */
|
||||
dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event);
|
||||
input_report_key(&cinergyt2->rc_input_dev,
|
||||
cinergyt2->rc_input_event, 0);
|
||||
}
|
||||
dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event);
|
||||
input_report_key(&cinergyt2->rc_input_dev,
|
||||
cinergyt2->rc_input_event, 1);
|
||||
cinergyt2->rc_last_code = rc_events[n].value;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
schedule_delayed_work(&cinergyt2->rc_query_work,
|
||||
msecs_to_jiffies(RC_QUERY_INTERVAL));
|
||||
|
||||
@ -771,7 +788,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
struct cinergyt2 *cinergyt2;
|
||||
int i, err;
|
||||
int err;
|
||||
#ifdef ENABLE_RC
|
||||
int i;
|
||||
#endif
|
||||
|
||||
if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
|
||||
dprintk(1, "out of memory?!?\n");
|
||||
@ -827,19 +847,18 @@ static int cinergyt2_probe (struct usb_interface *intf,
|
||||
DVB_DEVICE_FRONTEND);
|
||||
|
||||
#ifdef ENABLE_RC
|
||||
init_input_dev(&cinergyt2->rc_input_dev);
|
||||
|
||||
cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY);
|
||||
cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
|
||||
cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
|
||||
cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
|
||||
cinergyt2->rc_input_dev.keycodesize = 0;
|
||||
cinergyt2->rc_input_dev.keycodemax = 0;
|
||||
cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
|
||||
|
||||
for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3)
|
||||
set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit);
|
||||
for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
|
||||
set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
|
||||
|
||||
input_register_device(&cinergyt2->rc_input_dev);
|
||||
|
||||
cinergyt2->rc_input_event = KEY_MAX;
|
||||
cinergyt2->rc_last_code = ~0;
|
||||
|
||||
INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
|
||||
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);
|
||||
|
Loading…
Reference in New Issue
Block a user