Commit 733419b5 authored by David Härdeman's avatar David Härdeman Committed by Mauro Carvalho Chehab

V4L/DVB: Add RC5x support to ir-core

This patch adds RC5x support to drivers/media/IR/ir-rc5-decoder.c
Signed-off-by: default avatarDavid Härdeman <david@hardeman.nu>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 450df222
/* ir-rc5-decoder.c - handle RC-5 IR Pulse/Space protocol /* ir-rc5-decoder.c - handle RC5(x) IR Pulse/Space protocol
* *
* Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
* *
...@@ -13,15 +13,19 @@ ...@@ -13,15 +13,19 @@
*/ */
/* /*
* This code only handles 14 bits RC-5 protocols. There are other variants * This code handles 14 bits RC5 protocols and 20 bits RC5x protocols.
* that use a different number of bits. This is currently unsupported * There are other variants that use a different number of bits.
* It considers a carrier of 36 kHz, with a total of 14 bits, where * 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 * the first two bits are start bits, and a third one is a filing bit
*/ */
#include "ir-core-priv.h" #include "ir-core-priv.h"
#define RC5_NBITS 14 #define RC5_NBITS 14
#define RC5X_NBITS 20
#define CHECK_RC5X_NBITS 8
#define RC5X_SPACE SPACE(4)
#define RC5_UNIT 888888 /* ns */ #define RC5_UNIT 888888 /* ns */
/* Used to register rc5_decoder clients */ /* Used to register rc5_decoder clients */
...@@ -32,6 +36,7 @@ enum rc5_state { ...@@ -32,6 +36,7 @@ enum rc5_state {
STATE_INACTIVE, STATE_INACTIVE,
STATE_BIT_START, STATE_BIT_START,
STATE_BIT_END, STATE_BIT_END,
STATE_CHECK_RC5X,
STATE_FINISHED, STATE_FINISHED,
}; };
...@@ -45,6 +50,7 @@ struct decoder_data { ...@@ -45,6 +50,7 @@ struct decoder_data {
u32 rc5_bits; u32 rc5_bits;
int last_unit; int last_unit;
unsigned count; unsigned count;
unsigned wanted_bits;
}; };
...@@ -126,7 +132,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -126,7 +132,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
{ {
struct decoder_data *data; struct decoder_data *data;
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
u8 command, system, toggle; u8 toggle;
u32 scancode; u32 scancode;
int u; int u;
...@@ -147,7 +153,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -147,7 +153,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
goto out; goto out;
again: again:
IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n",
data->state, u, TO_US(duration)); data->state, u, TO_US(duration));
if (DURATION(u) == 0 && data->state != STATE_FINISHED) if (DURATION(u) == 0 && data->state != STATE_FINISHED)
...@@ -159,6 +165,8 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -159,6 +165,8 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
if (IS_PULSE(u)) { if (IS_PULSE(u)) {
data->state = STATE_BIT_START; data->state = STATE_BIT_START;
data->count = 1; data->count = 1;
/* We just need enough bits to get to STATE_CHECK_RC5X */
data->wanted_bits = RC5X_NBITS;
DECREASE_DURATION(u, 1); DECREASE_DURATION(u, 1);
goto again; goto again;
} }
...@@ -176,7 +184,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -176,7 +184,7 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
* If the last bit is zero, a space will merge * If the last bit is zero, a space will merge
* with the silence after the command. * with the silence after the command.
*/ */
if (IS_PULSE(u) && data->count == RC5_NBITS) { if (IS_PULSE(u) && data->count == data->wanted_bits) {
data->state = STATE_FINISHED; data->state = STATE_FINISHED;
goto again; goto again;
} }
...@@ -188,8 +196,10 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -188,8 +196,10 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
case STATE_BIT_END: case STATE_BIT_END:
if (IS_TRANSITION(u, data->last_unit)) { if (IS_TRANSITION(u, data->last_unit)) {
if (data->count == RC5_NBITS) if (data->count == data->wanted_bits)
data->state = STATE_FINISHED; data->state = STATE_FINISHED;
else if (data->count == CHECK_RC5X_NBITS)
data->state = STATE_CHECK_RC5X;
else else
data->state = STATE_BIT_START; data->state = STATE_BIT_START;
...@@ -198,22 +208,52 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) ...@@ -198,22 +208,52 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
} }
break; break;
case STATE_CHECK_RC5X:
if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) {
/* RC5X */
data->wanted_bits = RC5X_NBITS;
DECREASE_DURATION(u, DURATION(RC5X_SPACE));
} else {
/* RC5 */
data->wanted_bits = RC5_NBITS;
}
data->state = STATE_BIT_START;
goto again;
case STATE_FINISHED: case STATE_FINISHED:
command = (data->rc5_bits & 0x0003F) >> 0; if (data->wanted_bits == RC5X_NBITS) {
system = (data->rc5_bits & 0x007C0) >> 6; /* RC5X */
toggle = (data->rc5_bits & 0x00800) ? 1 : 0; u8 xdata, command, system;
command += (data->rc5_bits & 0x01000) ? 0 : 0x40; xdata = (data->rc5_bits & 0x0003F) >> 0;
scancode = system << 8 | command; command = (data->rc5_bits & 0x00FC0) >> 6;
system = (data->rc5_bits & 0x1F000) >> 12;
IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
scancode, toggle); command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
scancode = system << 16 | command << 8 | xdata;
IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
scancode, toggle);
} else {
/* RC5 */
u8 command, system;
command = (data->rc5_bits & 0x0003F) >> 0;
system = (data->rc5_bits & 0x007C0) >> 6;
toggle = (data->rc5_bits & 0x00800) ? 1 : 0;
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
scancode = system << 8 | command;
IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
scancode, toggle);
}
ir_keydown(input_dev, scancode, toggle); ir_keydown(input_dev, scancode, toggle);
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
} }
out: out:
IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n",
data->state, u, TO_US(duration)); data->state, u, TO_US(duration));
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return -EINVAL; return -EINVAL;
...@@ -273,7 +313,7 @@ static int __init ir_rc5_decode_init(void) ...@@ -273,7 +313,7 @@ static int __init ir_rc5_decode_init(void)
{ {
ir_raw_handler_register(&rc5_handler); ir_raw_handler_register(&rc5_handler);
printk(KERN_INFO "IR RC-5 protocol handler initialized\n"); printk(KERN_INFO "IR RC5(x) protocol handler initialized\n");
return 0; return 0;
} }
...@@ -288,4 +328,4 @@ module_exit(ir_rc5_decode_exit); ...@@ -288,4 +328,4 @@ module_exit(ir_rc5_decode_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("RC-5 IR protocol decoder"); MODULE_DESCRIPTION("RC5(x) IR protocol decoder");
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment