Skip to content

Commit

Permalink
[media] rc-core: merge rc5 and streamzap decoders
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David Härdeman authored and Mauro Carvalho Chehab committed Jul 25, 2014
1 parent 9d2f1d3 commit e87b540
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 218 deletions.
12 changes: 0 additions & 12 deletions drivers/media/rc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -84,18 +84,6 @@ config IR_SONY_DECODER
Enable this option if you have an infrared remote control which
uses the Sony protocol, and you need software decoding support.

config IR_RC5_SZ_DECODER
tristate "Enable IR raw decoder for the RC-5 (streamzap) protocol"
depends on RC_CORE
select BITREVERSE
default y

---help---
Enable this option if you have IR with RC-5 (streamzap) protocol,
and if the IR is decoded in software. (The Streamzap PC Remote
uses an IR protocol that is almost standard RC-5, but not quite,
as it uses an additional bit).

config IR_SANYO_DECODER
tristate "Enable IR raw decoder for the Sanyo protocol"
depends on RC_CORE
Expand Down
1 change: 0 additions & 1 deletion drivers/media/rc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ obj-$(CONFIG_IR_RC5_DECODER) += ir-rc5-decoder.o
obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o
obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o
obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o
obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o
obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o
obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o
obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o
Expand Down
72 changes: 41 additions & 31 deletions drivers/media/rc/ir-rc5-decoder.c
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -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))
Expand All @@ -80,12 +80,15 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)

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;

Expand All @@ -100,9 +103,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
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;
Expand All @@ -112,21 +113,18 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)

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;

case STATE_FINISHED:
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)) {
Expand All @@ -141,10 +139,7 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
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)) {
Expand All @@ -158,32 +153,47 @@ static int ir_rc5_decode(struct rc_dev *dev, struct ir_raw_event ev)
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;
return 0;
}

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,
};

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;
}

Expand All @@ -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");
154 changes: 0 additions & 154 deletions drivers/media/rc/ir-rc5-sz-decoder.c

This file was deleted.

4 changes: 1 addition & 3 deletions drivers/media/rc/keymaps/rc-streamzap.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
static struct rc_map_table streamzap[] = {
/*
* The Streamzap remote is almost, but not quite, RC-5, as it has an extra
* bit in it, which throws the in-kernel RC-5 decoder for a loop. Currently,
* an additional RC-5-sz decoder is being deployed to support it, but it
* may be possible to merge it back with the standard RC-5 decoder.
* bit in it.
*/
{ 0x28c0, KEY_NUMERIC_0 },
{ 0x28c1, KEY_NUMERIC_1 },
Expand Down
8 changes: 1 addition & 7 deletions drivers/media/rc/rc-core-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct ir_raw_event_ctrl {
int state;
u32 bits;
unsigned count;
unsigned wanted_bits;
bool is_rc5x;
} rc5;
struct rc6_dec {
int state;
Expand All @@ -77,12 +77,6 @@ struct ir_raw_event_ctrl {
bool first;
bool toggle;
} jvc;
struct rc5_sz_dec {
int state;
u32 bits;
unsigned count;
unsigned wanted_bits;
} rc5_sz;
struct sanyo_dec {
int state;
unsigned count;
Expand Down
Loading

0 comments on commit e87b540

Please sign in to comment.