Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 193007
b: refs/heads/master
c: e40b112
h: refs/heads/master
i:
  193005: 65c4661
  193003: 47d0ef8
  192999: a2be6d2
  192991: 6438cd5
v: v3
  • Loading branch information
David Härdeman authored and Mauro Carvalho Chehab committed May 19, 2010
1 parent 734a807 commit 46523ec
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 257 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 21677cfc562a27e099719d413287bc8d1d24deb7
refs/heads/master: e40b1127f994a427568319d1be9b9e5ab1f58dd1
49 changes: 23 additions & 26 deletions trunk/drivers/media/IR/ir-core-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
struct ir_raw_handler {
struct list_head list;

int (*decode)(struct input_dev *input_dev, s64 duration);
int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
int (*raw_register)(struct input_dev *input_dev);
int (*raw_unregister)(struct input_dev *input_dev);
};
Expand All @@ -36,26 +36,28 @@ struct ir_raw_event_ctrl {
};

/* macros for IR decoders */
#define PULSE(units) ((units))
#define SPACE(units) (-(units))
#define IS_RESET(duration) ((duration) == 0)
#define IS_PULSE(duration) ((duration) > 0)
#define IS_SPACE(duration) ((duration) < 0)
#define DURATION(duration) (abs((duration)))
#define IS_TRANSITION(x, y) ((x) * (y) < 0)
#define DECREASE_DURATION(duration, amount) \
do { \
if (IS_SPACE(duration)) \
duration += (amount); \
else if (IS_PULSE(duration)) \
duration -= (amount); \
} while (0)

#define TO_UNITS(duration, unit_len) \
((int)((duration) > 0 ? \
DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\
-DIV_ROUND_CLOSEST(abs((duration)), (unit_len))))
#define TO_US(duration) ((int)TO_UNITS(duration, 1000))
static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) {
return d1 > (d2 - margin);
}

static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) {
return ((d1 > (d2 - margin)) && (d1 < (d2 + margin)));
}

static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) {
return x->pulse != y->pulse;
}

static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) {
if (duration > ev->duration)
ev->duration = 0;
else
ev->duration -= duration;
}

#define TO_US(duration) (((duration) + 500) / 1000)
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
#define IS_RESET(ev) (ev.duration == 0)

/*
* Routines from ir-sysfs.c - Meant to be called only internally inside
Expand All @@ -70,11 +72,6 @@ void ir_unregister_class(struct input_dev *input_dev);
*/
int ir_raw_event_register(struct input_dev *input_dev);
void ir_raw_event_unregister(struct input_dev *input_dev);
static inline void ir_raw_event_reset(struct input_dev *input_dev)
{
ir_raw_event_store(input_dev, 0);
ir_raw_event_handle(input_dev);
}
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
void ir_raw_init(void);
Expand Down
120 changes: 67 additions & 53 deletions trunk/drivers/media/IR/ir-nec-decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
30 changes: 18 additions & 12 deletions trunk/drivers/media/IR/ir-raw-event.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ static struct work_struct wq_load;

static void ir_raw_event_work(struct work_struct *work)
{
s64 d;
struct ir_raw_event ev;
struct ir_raw_event_ctrl *raw =
container_of(work, struct ir_raw_event_ctrl, rx_work);

while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d))
RUN_DECODER(decode, raw->input_dev, d);
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
RUN_DECODER(decode, raw->input_dev, ev);
}

int ir_raw_event_register(struct input_dev *input_dev)
Expand Down Expand Up @@ -114,21 +114,21 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
/**
* ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
* @input_dev: the struct input_dev device descriptor
* @duration: duration of the pulse or space in ns
* @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This routine (which may be called from an interrupt context) stores a
* pulse/space duration for the raw ir decoding state machines. Pulses are
* signalled as positive values and spaces as negative values. A zero value
* will reset the decoding state machines.
*/
int ir_raw_event_store(struct input_dev *input_dev, s64 duration)
int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
{
struct ir_input_dev *ir = input_get_drvdata(input_dev);

if (!ir->raw)
return -EINVAL;

if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration))
if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
return -ENOMEM;

return 0;
Expand All @@ -151,6 +151,7 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
struct ir_input_dev *ir = input_get_drvdata(input_dev);
ktime_t now;
s64 delta; /* ns */
struct ir_raw_event ev;
int rc = 0;

if (!ir->raw)
Expand All @@ -163,16 +164,21 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
* being called for the first time, note that delta can't
* possibly be negative.
*/
if (delta > NSEC_PER_SEC || !ir->raw->last_type)
ev.duration = 0;
if (delta > IR_MAX_DURATION || !ir->raw->last_type)
type |= IR_START_EVENT;
else
ev.duration = delta;

if (type & IR_START_EVENT)
ir_raw_event_reset(input_dev);
else if (ir->raw->last_type & IR_SPACE)
rc = ir_raw_event_store(input_dev, -delta);
else if (ir->raw->last_type & IR_PULSE)
rc = ir_raw_event_store(input_dev, delta);
else
else if (ir->raw->last_type & IR_SPACE) {
ev.pulse = false;
rc = ir_raw_event_store(input_dev, &ev);
} else if (ir->raw->last_type & IR_PULSE) {
ev.pulse = true;
rc = ir_raw_event_store(input_dev, &ev);
} else
return 0;

ir->raw->last_event = now;
Expand Down
Loading

0 comments on commit 46523ec

Please sign in to comment.