From c1e13971b19324305b35fafc080b527465214d3c Mon Sep 17 00:00:00 2001 From: Ian Armstrong Date: Fri, 18 Mar 2011 19:23:05 -0300 Subject: [PATCH] [media] af9015: enhance RC 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 Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9015.c | 39 +++++++++++++++++++++--------- drivers/media/dvb/dvb-usb/af9015.h | 1 + 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c index 8671ca362c81..6457d042b1a0 100644 --- a/drivers/media/dvb/dvb-usb/af9015.c +++ b/drivers/media/dvb/dvb-usb/af9015.c @@ -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]; diff --git a/drivers/media/dvb/dvb-usb/af9015.h b/drivers/media/dvb/dvb-usb/af9015.h index f20cfa6ed690..beb3004f00ba 100644 --- a/drivers/media/dvb/dvb-usb/af9015.h +++ b/drivers/media/dvb/dvb-usb/af9015.h @@ -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 { -- GitLab