aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/rc/ir-rc5-decoder.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2014-04-03 20:32:31 -0300
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-07-25 19:10:44 -0300
commite87b540be2dd02552fb9244d50ae8b4e4619a34b (patch)
tree4440e341a8b937890c7a772fa709a1063ade3ef9 /drivers/media/rc/ir-rc5-decoder.c
parent[media] rc-core: rename dev->scanmask to dev->scancode_mask (diff)
downloadlinux-dev-e87b540be2dd02552fb9244d50ae8b4e4619a34b.tar.xz
linux-dev-e87b540be2dd02552fb9244d50ae8b4e4619a34b.zip
[media] rc-core: merge rc5 and streamzap decoders
Now that the protocol is part of the scancode, it is pretty easy to merge the rc5 and streamzap decoders. An additional advantage is that the decoder is now stricter as it waits for the trailing silence before determining that a command is a valid rc5/streamzap command (which avoids collisions that I've seen with e.g. Sony protocols). Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/rc/ir-rc5-decoder.c')
-rw-r--r--drivers/media/rc/ir-rc5-decoder.c72
1 files changed, 41 insertions, 31 deletions
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 04ce42fa9eec..93168daf82eb 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -1,6 +1,7 @@
-/* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
+/* ir-rc5-decoder.c - decoder for RC5(x) and StreamZap protocols
*
* Copyright (C) 2010 by Mauro Carvalho Chehab
+ * Copyright (C) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -13,23 +14,22 @@
*/
/*
- * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
- * There are other variants that use a different number of bits.
- * This is currently unsupported.
- * It considers a carrier of 36 kHz, with a total of 14/20 bits, where
- * the first two bits are start bits, and a third one is a filing bit
+ * This decoder handles the 14 bit RC5 protocol, 15 bit "StreamZap" protocol
+ * and 20 bit RC5x protocol.
*/
#include "rc-core-priv.h"
#include <linux/module.h>
#define RC5_NBITS 14
+#define RC5_SZ_NBITS 15
#define RC5X_NBITS 20
#define CHECK_RC5X_NBITS 8
#define RC5_UNIT 888888 /* ns */
#define RC5_BIT_START (1 * RC5_UNIT)
#define RC5_BIT_END (1 * RC5_UNIT)
#define RC5X_SPACE (4 * RC5_UNIT)
+#define RC5_TRAILER (10 * RC5_UNIT) /* In reality, approx 100 */
enum rc5_state {
STATE_INACTIVE,
@@ -66,7 +66,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
goto out;
again:
- IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+ IR_dprintk(2, "RC5(x/sz) decode started at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
@@ -80,12 +80,15 @@ again:
data->state = STATE_BIT_START;
data->count = 1;
- /* We just need enough bits to get to STATE_CHECK_RC5X */
- data->wanted_bits = RC5X_NBITS;
decrease_duration(&ev, RC5_BIT_START);
goto again;
case STATE_BIT_START:
+ if (!ev.pulse && geq_margin(ev.duration, RC5_TRAILER, RC5_UNIT / 2)) {
+ data->state = STATE_FINISHED;
+ goto again;
+ }
+
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
break;
@@ -100,9 +103,7 @@ again:
if (!is_transition(&ev, &dev->raw->prev_ev))
break;
- if (data->count == data->wanted_bits)
- data->state = STATE_FINISHED;
- else if (data->count == CHECK_RC5X_NBITS)
+ if (data->count == CHECK_RC5X_NBITS)
data->state = STATE_CHECK_RC5X;
else
data->state = STATE_BIT_START;
@@ -112,13 +113,10 @@ again:
case STATE_CHECK_RC5X:
if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
- /* RC5X */
- data->wanted_bits = RC5X_NBITS;
+ data->is_rc5x = true;
decrease_duration(&ev, RC5X_SPACE);
- } else {
- /* RC5 */
- data->wanted_bits = RC5_NBITS;
- }
+ } else
+ data->is_rc5x = false;
data->state = STATE_BIT_START;
goto again;
@@ -126,7 +124,7 @@ again:
if (ev.pulse)
break;
- if (data->wanted_bits == RC5X_NBITS) {
+ if (data->is_rc5x && data->count == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
if (!(dev->enabled_protocols & RC_BIT_RC5X)) {
@@ -141,10 +139,7 @@ again:
scancode = system << 16 | command << 8 | xdata;
protocol = RC_TYPE_RC5X;
- IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
- scancode, toggle);
-
- } else {
+ } else if (!data->is_rc5x && data->count == RC5_NBITS) {
/* RC5 */
u8 command, system;
if (!(dev->enabled_protocols & RC_BIT_RC5)) {
@@ -158,9 +153,24 @@ again:
scancode = system << 8 | command;
protocol = RC_TYPE_RC5;
- IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
- scancode, toggle);
- }
+ } else if (!data->is_rc5x && data->count == RC5_SZ_NBITS) {
+ /* RC5 StreamZap */
+ u8 command, system;
+ if (!(dev->enabled_protocols & RC_BIT_RC5_SZ)) {
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+ command = (data->bits & 0x0003F) >> 0;
+ system = (data->bits & 0x02FC0) >> 6;
+ toggle = (data->bits & 0x01000) ? 1 : 0;
+ scancode = system << 6 | command;
+ protocol = RC_TYPE_RC5_SZ;
+
+ } else
+ break;
+
+ IR_dprintk(1, "RC5(x/sz) scancode 0x%06x (p: %u, t: %u)\n",
+ scancode, protocol, toggle);
rc_keydown(dev, protocol, scancode, toggle);
data->state = STATE_INACTIVE;
@@ -168,14 +178,14 @@ again:
}
out:
- IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
+ IR_dprintk(1, "RC5(x/sz) decode failed at state %i (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
static struct ir_raw_handler rc5_handler = {
- .protocols = RC_BIT_RC5 | RC_BIT_RC5X,
+ .protocols = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
.decode = ir_rc5_decode,
};
@@ -183,7 +193,7 @@ static int __init ir_rc5_decode_init(void)
{
ir_raw_handler_register(&rc5_handler);
- printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
+ printk(KERN_INFO "IR RC5(x/sz) protocol handler initialized\n");
return 0;
}
@@ -196,6 +206,6 @@ module_init(ir_rc5_decode_init);
module_exit(ir_rc5_decode_exit);
MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab");
+MODULE_AUTHOR("Mauro Carvalho Chehab and Jarod Wilson");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
-MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
+MODULE_DESCRIPTION("RC5(x/sz) IR protocol decoder");