aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-nec-decoder.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/IR/ir-nec-decoder.c')
-rw-r--r--drivers/media/IR/ir-nec-decoder.c120
1 files changed, 67 insertions, 53 deletions
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 14609d9580a8..ba79233112ef 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -17,13 +17,15 @@
#define NEC_NBITS 32
#define NEC_UNIT 562500 /* ns */
-#define NEC_HEADER_PULSE PULSE(16)
-#define NECX_HEADER_PULSE PULSE(8) /* Less common NEC variant */
-#define NEC_HEADER_SPACE SPACE(8)
-#define NEC_REPEAT_SPACE SPACE(4)
-#define NEC_BIT_PULSE PULSE(1)
-#define NEC_BIT_0_SPACE SPACE(1)
-#define NEC_BIT_1_SPACE SPACE(3)
+#define NEC_HEADER_PULSE (16 * NEC_UNIT)
+#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
+#define NEC_HEADER_SPACE (8 * NEC_UNIT)
+#define NEC_REPEAT_SPACE (8 * NEC_UNIT)
+#define NEC_BIT_PULSE (1 * NEC_UNIT)
+#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
+#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
+#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
+#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
/* Used to register nec_decoder clients */
static LIST_HEAD(decoder_list);
@@ -119,15 +121,14 @@ static struct attribute_group decoder_attribute_group = {
/**
* ir_nec_decode() - Decode one NEC pulse or space
* @input_dev: the struct input_dev descriptor of the device
- * @duration: duration in ns of pulse/space
+ * @duration: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
-static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
+static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{
struct decoder_data *data;
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
- int u;
u32 scancode;
u8 address, not_address, command, not_command;
@@ -138,59 +139,88 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
if (!data->enabled)
return 0;
- if (IS_RESET(duration)) {
+ if (IS_RESET(ev)) {
data->state = STATE_INACTIVE;
return 0;
}
- u = TO_UNITS(duration, NEC_UNIT);
- if (DURATION(u) == 0)
- goto out;
-
- IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
switch (data->state) {
case STATE_INACTIVE:
- if (u == NEC_HEADER_PULSE || u == NECX_HEADER_PULSE) {
- data->count = 0;
- data->state = STATE_HEADER_SPACE;
- }
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) &&
+ !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
+ break;
+
+ data->count = 0;
+ data->state = STATE_HEADER_SPACE;
return 0;
case STATE_HEADER_SPACE:
- if (u == NEC_HEADER_SPACE) {
+ if (ev.pulse)
+ break;
+
+ if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
data->state = STATE_BIT_PULSE;
return 0;
- } else if (u == NEC_REPEAT_SPACE) {
+ } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
ir_repeat(input_dev);
IR_dprintk(1, "Repeat last key\n");
data->state = STATE_TRAILER_PULSE;
return 0;
}
+
break;
case STATE_BIT_PULSE:
- if (u == NEC_BIT_PULSE) {
- data->state = STATE_BIT_SPACE;
- return 0;
- }
- break;
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_SPACE;
+ return 0;
case STATE_BIT_SPACE:
- if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE)
+ if (ev.pulse)
break;
data->nec_bits <<= 1;
- if (u == NEC_BIT_1_SPACE)
+ if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
data->nec_bits |= 1;
+ else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
+ break;
data->count++;
- if (data->count != NEC_NBITS) {
+ if (data->count == NEC_NBITS)
+ data->state = STATE_TRAILER_PULSE;
+ else
data->state = STATE_BIT_PULSE;
- return 0;
- }
+
+ return 0;
+
+ case STATE_TRAILER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
+ break;
+
+ data->state = STATE_TRAILER_SPACE;
+ return 0;
+
+ case STATE_TRAILER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
+ break;
address = bitrev8((data->nec_bits >> 24) & 0xff);
not_address = bitrev8((data->nec_bits >> 16) & 0xff);
@@ -210,34 +240,18 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
command;
IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
} else {
- /* normal NEC */
+ /* Normal NEC */
scancode = address << 8 | command;
IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
}
ir_keydown(input_dev, scancode, 0);
- data->state = STATE_TRAILER_PULSE;
+ data->state = STATE_INACTIVE;
return 0;
-
- case STATE_TRAILER_PULSE:
- if (u > 0) {
- data->state = STATE_TRAILER_SPACE;
- return 0;
- }
- break;
-
- case STATE_TRAILER_SPACE:
- if (u < 0) {
- data->state = STATE_INACTIVE;
- return 0;
- }
-
- break;
}
-out:
- IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}