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 <[EMAIL PROTECTED]>

 drivers/media/dvb/cinergyT2/Kconfig     |    2 
 drivers/media/dvb/cinergyT2/cinergyT2.c |   93 +++++++++++++++++++-------------
 2 files changed, 57 insertions(+), 38 deletions(-)

--- linux-2.6.13-git4.orig/drivers/media/dvb/cinergyT2/Kconfig  2005-09-04 
22:03:40.000000000 +0200
+++ linux-2.6.13-git4/drivers/media/dvb/cinergyT2/Kconfig       2005-09-04 
22:30:53.000000000 +0200
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEV
 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
--- linux-2.6.13-git4.orig/drivers/media/dvb/cinergyT2/cinergyT2.c      
2005-09-04 22:27:49.000000000 +0200
+++ linux-2.6.13-git4/drivers/media/dvb/cinergyT2/cinergyT2.c   2005-09-04 
22:30:53.000000000 +0200
@@ -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_te
 #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));
-
-       for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) {
-               int i;
+                               (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;
 
-/*             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_i
                  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_i
                            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);

--

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to