]> git.karo-electronics.de Git - linux-beck.git/commitdiff
[media] af9015: enhance RC
authorIan Armstrong <ian@iarmst.demon.co.uk>
Fri, 18 Mar 2011 22:23:05 +0000 (19:23 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Tue, 22 Mar 2011 07:54:52 +0000 (04:54 -0300)
Patch from Ian Armstrong.

I've encountered a couple of problems with the current af9015 driver as
supplied with the 2.6.37 kernel, that the attached patch appears to fix. (I've
generated this patch against the current v4l-dvb git).

Some key-presses are lost. A key-press is only generated upon 'valid' data
(buf[14] == (u8) ~buf[15]), but the buffer is wiped before this check.
Sometimes the 15th byte has not been set at the time of read, so the data
isn't valid & ignored. On the next poll the 15th byte has been set, but the
rest of the data was wiped previously, so the data is still invalid & the key
is lost.

Weird repeat error, where an old key press is sometimes repeated in error. ie.
button sequence '1 (pause) 2 (pause) 3 (pause) 4' generates output like '1
(pause) 2 (pause) 23 (pause) 4'. The current driver zeroes the data for the
key pushed, but sometimes this data is already zero but with other bytes set
suggesting a repeat code. This results in the last key being incorrectly
repeated.

This patch attempts to reduce the risk of a missed key-press & also stop the
random repeat of an old key-press when a new key is pressed.

Signed-off-by: Ian Armstrong <ian@iarmst.demon.co.uk>
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/dvb-usb/af9015.c
drivers/media/dvb/dvb-usb/af9015.h

index 8671ca362c81f858f0a644ddf461c347e7974b80..6457d042b1a0861060d8fc9cc7d98f16b273e7b8 100644 (file)
@@ -479,6 +479,9 @@ static int af9015_init_endpoint(struct dvb_usb_device *d)
                ret = af9015_set_reg_bit(d, 0xd50b, 0);
        else
                ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0x98e9, 0xff);
 error:
        if (ret)
                err("endpoint init failed:%d", ret);
@@ -1016,22 +1019,35 @@ static int af9015_rc_query(struct dvb_usb_device *d)
 {
        struct af9015_state *priv = d->priv;
        int ret;
-       u8 buf[16];
+       u8 buf[17];
 
        /* read registers needed to detect remote controller code */
        ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
        if (ret)
                goto error;
 
-       if (buf[14] || buf[15]) {
+       /* If any of these are non-zero, assume invalid data */
+       if (buf[1] || buf[2] || buf[3])
+               return ret;
+
+       /* Check for repeat of previous code */
+       if ((priv->rc_repeat != buf[6] || buf[0]) &&
+                                       !memcmp(&buf[12], priv->rc_last, 4)) {
+               deb_rc("%s: key repeated\n", __func__);
+               rc_keydown(d->rc_dev, priv->rc_keycode, 0);
+               priv->rc_repeat = buf[6];
+               return ret;
+       }
+
+       /* Only process key if canary killed */
+       if (buf[16] != 0xff && buf[0] != 0x01) {
+               /* Reset the canary */
+               af9015_write_reg(d, 0x98e9, 0xff);
                deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__,
                        buf[12], buf[13], buf[14], buf[15]);
 
-               /* clean IR code from mem */
-               ret = af9015_write_regs(d, 0x98e5, "\x00\x00\x00\x00", 4);
-               if (ret)
-                       goto error;
-
+               /* Remember this key */
+               memcpy(priv->rc_last, &buf[12], 4);
                if (buf[14] == (u8) ~buf[15]) {
                        if (buf[12] == (u8) ~buf[13]) {
                                /* NEC */
@@ -1041,15 +1057,16 @@ static int af9015_rc_query(struct dvb_usb_device *d)
                                priv->rc_keycode = buf[12] << 16 |
                                        buf[13] << 8 | buf[14];
                        }
-                       rc_keydown(d->rc_dev, priv->rc_keycode, 0);
                } else {
-                       priv->rc_keycode = 0; /* clear just for sure */
+                       priv->rc_keycode = buf[12] << 24 | buf[13] << 16 |
+                                       buf[14] << 8 | buf[15];
                }
-       } else if (priv->rc_repeat != buf[6] || buf[0]) {
-               deb_rc("%s: key repeated\n", __func__);
                rc_keydown(d->rc_dev, priv->rc_keycode, 0);
        } else {
                deb_rc("%s: no key press\n", __func__);
+               /* Invalidate last keypress */
+               /* Not really needed, but helps with debug */
+               priv->rc_last[2] = priv->rc_last[3];
        }
 
        priv->rc_repeat = buf[6];
index f20cfa6ed6901ce04cbdd06525fc8a09bf68f494..beb3004f00ba31640aab86399fd7ef4889469d14 100644 (file)
@@ -102,6 +102,7 @@ struct af9015_state {
        struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
        u8 rc_repeat;
        u32 rc_keycode;
+       u8 rc_last[4];
 };
 
 struct af9015_config {