dect
/
linux-2.6
Archived
13
0
Fork 0

[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:
Johannes Stezenbach 2005-09-09 13:03:05 -07:00 committed by Linus Torvalds
parent 2d6e7322b5
commit 6d78933c29
2 changed files with 57 additions and 38 deletions

View File

@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
config DVB_CINERGYT2_RC_QUERY_INTERVAL config DVB_CINERGYT2_RC_QUERY_INTERVAL
int "Infrared Remote Controller update interval [milliseconds]" int "Infrared Remote Controller update interval [milliseconds]"
depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE
default "100" default "50"
help help
If you have a very fast-repeating remote control you can try lower If you have a very fast-repeating remote control you can try lower
values, for normal consumer receivers the default value should be values, for normal consumer receivers the default value should be

View File

@ -35,7 +35,6 @@
#include "dvb_demux.h" #include "dvb_demux.h"
#include "dvb_net.h" #include "dvb_net.h"
#ifdef CONFIG_DVB_CINERGYT2_TUNING #ifdef CONFIG_DVB_CINERGYT2_TUNING
#define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT)
#define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE)
@ -48,7 +47,7 @@
#define STREAM_URB_COUNT (32) #define STREAM_URB_COUNT (32)
#define STREAM_BUF_SIZE (512) /* bytes */ #define STREAM_BUF_SIZE (512) /* bytes */
#define ENABLE_RC (1) #define ENABLE_RC (1)
#define RC_QUERY_INTERVAL (100) /* milliseconds */ #define RC_QUERY_INTERVAL (50) /* milliseconds */
#define QUERY_INTERVAL (333) /* milliseconds */ #define QUERY_INTERVAL (333) /* milliseconds */
#endif #endif
@ -141,6 +140,8 @@ struct cinergyt2 {
struct input_dev rc_input_dev; struct input_dev rc_input_dev;
struct work_struct rc_query_work; struct work_struct rc_query_work;
int rc_input_event; int rc_input_event;
u32 rc_last_code;
unsigned long last_event_jiffies;
#endif #endif
}; };
@ -155,7 +156,7 @@ struct cinergyt2_rc_event {
uint32_t value; uint32_t value;
} __attribute__((packed)); } __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, 0xfe01eb04, KEY_POWER,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1,
CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2,
@ -684,52 +685,68 @@ static struct dvb_device cinergyt2_fe_template = {
#ifdef ENABLE_RC #ifdef ENABLE_RC
static void cinergyt2_query_rc (void *data) static void cinergyt2_query_rc (void *data)
{ {
struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; struct cinergyt2 *cinergyt2 = data;
char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS }; char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS };
struct cinergyt2_rc_event rc_events[12]; struct cinergyt2_rc_event rc_events[12];
int n, len; int n, len, i;
if (down_interruptible(&cinergyt2->sem)) if (down_interruptible(&cinergyt2->sem))
return; return;
len = cinergyt2_command(cinergyt2, buf, sizeof(buf), 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++) { for (n = 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);
/* 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 && if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC &&
rc_events[n].value == ~0) rc_events[n].value == ~0) {
{ /* keyrepeat bit -> just repeat last rc_input_event */
/**
* 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.
*/
} else { } else {
cinergyt2->rc_input_event = KEY_MAX; cinergyt2->rc_input_event = KEY_MAX;
for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) { for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) {
if (rc_keys[i+0] == rc_events[n].type && if (rc_keys[i + 0] == rc_events[n].type &&
rc_keys[i+1] == le32_to_cpu(rc_events[n].value)) rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
{ cinergyt2->rc_input_event = rc_keys[i + 2];
cinergyt2->rc_input_event = rc_keys[i+2];
break; break;
} }
} }
} }
if (cinergyt2->rc_input_event != KEY_MAX) { if (cinergyt2->rc_input_event != KEY_MAX) {
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1); if (rc_events[n].value == cinergyt2->rc_last_code &&
input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0); cinergyt2->rc_last_code != ~0) {
input_sync(&cinergyt2->rc_input_dev); /* 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, schedule_delayed_work(&cinergyt2->rc_query_work,
msecs_to_jiffies(RC_QUERY_INTERVAL)); msecs_to_jiffies(RC_QUERY_INTERVAL));
@ -771,7 +788,10 @@ static int cinergyt2_probe (struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct cinergyt2 *cinergyt2; struct cinergyt2 *cinergyt2;
int i, err; int err;
#ifdef ENABLE_RC
int i;
#endif
if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) {
dprintk(1, "out of memory?!?\n"); dprintk(1, "out of memory?!?\n");
@ -827,19 +847,18 @@ static int cinergyt2_probe (struct usb_interface *intf,
DVB_DEVICE_FRONTEND); DVB_DEVICE_FRONTEND);
#ifdef ENABLE_RC #ifdef ENABLE_RC
init_input_dev(&cinergyt2->rc_input_dev); cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
cinergyt2->rc_input_dev.keycodesize = 0;
cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY); cinergyt2->rc_input_dev.keycodemax = 0;
cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char);
cinergyt2->rc_input_dev.keycodemax = KEY_MAX;
cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control"; cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control";
for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3)
set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit); set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit);
input_register_device(&cinergyt2->rc_input_dev); input_register_device(&cinergyt2->rc_input_dev);
cinergyt2->rc_input_event = KEY_MAX; cinergyt2->rc_input_event = KEY_MAX;
cinergyt2->rc_last_code = ~0;
INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2);
schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2);