Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6d78933c authored by Johannes Stezenbach's avatar Johannes Stezenbach Committed by Linus Torvalds
Browse files

[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: default avatarJohannes Stezenbach <js@linuxtv.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 2d6e7322
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+56 −37
Original line number Diff line number Diff line
@@ -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
};

@@ -684,39 +685,46 @@ static struct dvb_device cinergyt2_fe_template = {
#ifdef ENABLE_RC
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 };
	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));
	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))
				{
				    rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) {
					cinergyt2->rc_input_event = rc_keys[i + 2];
					break;
				}
@@ -724,12 +732,21 @@ static void cinergyt2_query_rc (void *data)
		}

		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,11 +847,9 @@ 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)
@@ -840,6 +858,7 @@ static int cinergyt2_probe (struct usb_interface *intf,
	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);