* [PATCH 0/8] Series short description
@ 2010-04-15 21:45 David Härdeman
2010-04-15 21:46 ` [PATCH 1/8] ir-core: change duration to be coded as a u32 integer David Härdeman
` (8 more replies)
0 siblings, 9 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:45 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
The following series implements the suggested change to ir-core
to use a 1:31 struct for pulse/space durations, adds two new
raw decoders, converts two users of ir-functions to plain ir-core
and fixes a few small bugs in ir-core.
---
David Härdeman (8):
ir-core: change duration to be coded as a u32 integer
ir-core: Add JVC support to ir-core
ir-core: Add Sony support to ir-core
ir-core: remove ir-functions usage from dm1105
ir-core: convert mantis from ir-functions.c
ir-core: fix double spinlock init in drivers/media/IR/rc-map.c
ir-core: fix table resize during keymap init
ir-core: fix some confusing comments
drivers/media/IR/Kconfig | 18 ++
drivers/media/IR/Makefile | 2
drivers/media/IR/ir-core-priv.h | 63 ++++---
drivers/media/IR/ir-jvc-decoder.c | 320 ++++++++++++++++++++++++++++++++++++
drivers/media/IR/ir-keytable.c | 12 +
drivers/media/IR/ir-nec-decoder.c | 120 ++++++++------
drivers/media/IR/ir-raw-event.c | 32 ++--
drivers/media/IR/ir-rc5-decoder.c | 105 ++++++------
drivers/media/IR/ir-rc6-decoder.c | 221 +++++++++++++------------
drivers/media/IR/ir-sony-decoder.c | 312 +++++++++++++++++++++++++++++++++++
drivers/media/IR/ir-sysfs.c | 12 +
drivers/media/IR/rc-map.c | 5 -
12 files changed, 955 insertions(+), 267 deletions(-)
create mode 100644 drivers/media/IR/ir-jvc-decoder.c
create mode 100644 drivers/media/IR/ir-sony-decoder.c
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/8] ir-core: change duration to be coded as a u32 integer
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 2/8] ir-core: Add JVC support to ir-core David Härdeman
` (7 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
This patch implements the agreed upon 1:31 integer encoded pulse/duration
struct for ir-core raw decoders. All decoders have been tested after the
change. Comments are welcome.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/ir-core-priv.h | 49 ++++----
drivers/media/IR/ir-nec-decoder.c | 120 +++++++++++---------
drivers/media/IR/ir-raw-event.c | 30 +++--
drivers/media/IR/ir-rc5-decoder.c | 105 ++++++++----------
drivers/media/IR/ir-rc6-decoder.c | 221 +++++++++++++++++++------------------
5 files changed, 271 insertions(+), 254 deletions(-)
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index ef7f543..707beeb 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -21,7 +21,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);
};
@@ -35,26 +35,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-keytable.c to be used internally on ir-core and decoders
@@ -76,11 +78,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);
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 14609d9..ba79233 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;
}
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 674442b..59f173c 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -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)
@@ -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;
@@ -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)
@@ -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;
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
index dd5a4d5..23cdb1b 100644
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ b/drivers/media/IR/ir-rc5-decoder.c
@@ -25,8 +25,10 @@
#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_BIT_START (1 * RC5_UNIT)
+#define RC5_BIT_END (1 * RC5_UNIT)
+#define RC5X_SPACE (4 * RC5_UNIT)
/* Used to register rc5_decoder clients */
static LIST_HEAD(decoder_list);
@@ -48,7 +50,7 @@ struct decoder_data {
/* State machine control */
enum rc5_state state;
u32 rc5_bits;
- int last_unit;
+ struct ir_raw_event prev_ev;
unsigned count;
unsigned wanted_bits;
};
@@ -124,17 +126,16 @@ static struct attribute_group decoder_attribute_group = {
/**
* ir_rc5_decode() - Decode one RC-5 pulse or space
* @input_dev: the struct input_dev descriptor of the device
- * @duration: duration of pulse/space in ns
+ * @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
-static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
+static int ir_rc5_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);
u8 toggle;
u32 scancode;
- int u;
data = get_decoder_data(ir_dev);
if (!data)
@@ -143,76 +144,65 @@ static int ir_rc5_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, RC5_UNIT);
- if (DURATION(u) == 0)
+ if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
goto out;
again:
- IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
- if (DURATION(u) == 0 && data->state != STATE_FINISHED)
+ if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
return 0;
switch (data->state) {
case STATE_INACTIVE:
- if (IS_PULSE(u)) {
- 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(u, 1);
- goto again;
- }
- break;
+ if (!ev.pulse)
+ break;
+
+ 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 (DURATION(u) == 1) {
- data->rc5_bits <<= 1;
- if (IS_SPACE(u))
- data->rc5_bits |= 1;
- data->count++;
- data->last_unit = u;
-
- /*
- * If the last bit is zero, a space will merge
- * with the silence after the command.
- */
- if (IS_PULSE(u) && data->count == data->wanted_bits) {
- data->state = STATE_FINISHED;
- goto again;
- }
-
- data->state = STATE_BIT_END;
- return 0;
- }
- break;
+ if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
+ break;
+
+ data->rc5_bits <<= 1;
+ if (!ev.pulse)
+ data->rc5_bits |= 1;
+ data->count++;
+ data->prev_ev = ev;
+ data->state = STATE_BIT_END;
+ return 0;
case STATE_BIT_END:
- if (IS_TRANSITION(u, data->last_unit)) {
- if (data->count == data->wanted_bits)
- data->state = STATE_FINISHED;
- else if (data->count == CHECK_RC5X_NBITS)
- data->state = STATE_CHECK_RC5X;
- else
- data->state = STATE_BIT_START;
-
- DECREASE_DURATION(u, 1);
- goto again;
- }
- break;
+ if (!is_transition(&ev, &data->prev_ev))
+ break;
+
+ if (data->count == data->wanted_bits)
+ data->state = STATE_FINISHED;
+ else if (data->count == CHECK_RC5X_NBITS)
+ data->state = STATE_CHECK_RC5X;
+ else
+ data->state = STATE_BIT_START;
+
+ decrease_duration(&ev, RC5_BIT_END);
+ goto again;
case STATE_CHECK_RC5X:
- if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) {
+ if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
/* RC5X */
data->wanted_bits = RC5X_NBITS;
- DECREASE_DURATION(u, DURATION(RC5X_SPACE));
+ decrease_duration(&ev, RC5X_SPACE);
} else {
/* RC5 */
data->wanted_bits = RC5_NBITS;
@@ -221,6 +211,9 @@ again:
goto again;
case STATE_FINISHED:
+ if (ev.pulse)
+ break;
+
if (data->wanted_bits == RC5X_NBITS) {
/* RC5X */
u8 xdata, command, system;
@@ -253,8 +246,8 @@ again:
}
out:
- IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index ccc5be2..2bf479f 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -26,8 +26,12 @@
#define RC6_0_NBITS 16
#define RC6_6A_SMALL_NBITS 24
#define RC6_6A_LARGE_NBITS 32
-#define RC6_PREFIX_PULSE PULSE(6)
-#define RC6_PREFIX_SPACE SPACE(2)
+#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
+#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
+#define RC6_BIT_START (1 * RC6_UNIT)
+#define RC6_BIT_END (1 * RC6_UNIT)
+#define RC6_TOGGLE_START (2 * RC6_UNIT)
+#define RC6_TOGGLE_END (2 * RC6_UNIT)
#define RC6_MODE_MASK 0x07 /* for the header bits */
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
@@ -63,7 +67,7 @@ struct decoder_data {
enum rc6_state state;
u8 header;
u32 body;
- int last_unit;
+ struct ir_raw_event prev_ev;
bool toggle;
unsigned count;
unsigned wanted_bits;
@@ -152,17 +156,16 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
/**
* ir_rc6_decode() - Decode one RC6 pulse or space
* @input_dev: the struct input_dev descriptor of the device
- * @duration: duration of pulse/space in ns
+ * @ev: the struct ir_raw_event descriptor of the pulse/space
*
* This function returns -EINVAL if the pulse violates the state machine
*/
-static int ir_rc6_decode(struct input_dev *input_dev, s64 duration)
+static int ir_rc6_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);
u32 scancode;
u8 toggle;
- int u;
data = get_decoder_data(ir_dev);
if (!data)
@@ -171,140 +174,144 @@ static int ir_rc6_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, RC6_UNIT);
- if (DURATION(u) == 0)
+ if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
goto out;
again:
- IR_dprintk(2, "RC6 decode started at state %i (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
- if (DURATION(u) == 0 && data->state != STATE_FINISHED)
+ if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
return 0;
switch (data->state) {
case STATE_INACTIVE:
- if (u >= RC6_PREFIX_PULSE - 1 && u <= RC6_PREFIX_PULSE + 1) {
- data->state = STATE_PREFIX_SPACE;
- data->count = 0;
- return 0;
- }
- break;
+ if (!ev.pulse)
+ break;
+
+ /* Note: larger margin on first pulse since each RC6_UNIT
+ is quite short and some hardware takes some time to
+ adjust to the signal */
+ if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
+ break;
+
+ data->state = STATE_PREFIX_SPACE;
+ data->count = 0;
+ return 0;
case STATE_PREFIX_SPACE:
- if (u == RC6_PREFIX_SPACE) {
- data->state = STATE_HEADER_BIT_START;
- return 0;
- }
- break;
+ if (ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
+ break;
+
+ data->state = STATE_HEADER_BIT_START;
+ return 0;
case STATE_HEADER_BIT_START:
- if (DURATION(u) == 1) {
- data->header <<= 1;
- if (IS_PULSE(u))
- data->header |= 1;
- data->count++;
- data->last_unit = u;
- data->state = STATE_HEADER_BIT_END;
- return 0;
- }
- break;
+ if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
+ break;
+
+ data->header <<= 1;
+ if (ev.pulse)
+ data->header |= 1;
+ data->count++;
+ data->prev_ev = ev;
+ data->state = STATE_HEADER_BIT_END;
+ return 0;
case STATE_HEADER_BIT_END:
- if (IS_TRANSITION(u, data->last_unit)) {
- if (data->count == RC6_HEADER_NBITS)
- data->state = STATE_TOGGLE_START;
- else
- data->state = STATE_HEADER_BIT_START;
+ if (!is_transition(&ev, &data->prev_ev))
+ break;
- DECREASE_DURATION(u, 1);
- goto again;
- }
- break;
+ if (data->count == RC6_HEADER_NBITS)
+ data->state = STATE_TOGGLE_START;
+ else
+ data->state = STATE_HEADER_BIT_START;
+
+ decrease_duration(&ev, RC6_BIT_END);
+ goto again;
case STATE_TOGGLE_START:
- if (DURATION(u) == 2) {
- data->toggle = IS_PULSE(u);
- data->last_unit = u;
- data->state = STATE_TOGGLE_END;
- return 0;
- }
- break;
+ if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
+ break;
+
+ data->toggle = ev.pulse;
+ data->prev_ev = ev;
+ data->state = STATE_TOGGLE_END;
+ return 0;
case STATE_TOGGLE_END:
- if (IS_TRANSITION(u, data->last_unit) && DURATION(u) >= 2) {
- data->state = STATE_BODY_BIT_START;
- data->last_unit = u;
- DECREASE_DURATION(u, 2);
- data->count = 0;
+ if (!is_transition(&ev, &data->prev_ev) ||
+ !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
+ break;
- if (!(data->header & RC6_STARTBIT_MASK)) {
- IR_dprintk(1, "RC6 invalid start bit\n");
- break;
- }
+ if (!(data->header & RC6_STARTBIT_MASK)) {
+ IR_dprintk(1, "RC6 invalid start bit\n");
+ break;
+ }
- switch (rc6_mode(data)) {
- case RC6_MODE_0:
- data->wanted_bits = RC6_0_NBITS;
- break;
- case RC6_MODE_6A:
- /* This might look weird, but we basically
- check the value of the first body bit to
- determine the number of bits in mode 6A */
- if ((DURATION(u) == 0 && IS_SPACE(data->last_unit)) || DURATION(u) > 0)
- data->wanted_bits = RC6_6A_LARGE_NBITS;
- else
- data->wanted_bits = RC6_6A_SMALL_NBITS;
- break;
- default:
- IR_dprintk(1, "RC6 unknown mode\n");
- goto out;
- }
- goto again;
+ data->state = STATE_BODY_BIT_START;
+ data->prev_ev = ev;
+ decrease_duration(&ev, RC6_TOGGLE_END);
+ data->count = 0;
+
+ switch (rc6_mode(data)) {
+ case RC6_MODE_0:
+ data->wanted_bits = RC6_0_NBITS;
+ break;
+ case RC6_MODE_6A:
+ /* This might look weird, but we basically
+ check the value of the first body bit to
+ determine the number of bits in mode 6A */
+ if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
+ geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
+ data->wanted_bits = RC6_6A_LARGE_NBITS;
+ else
+ data->wanted_bits = RC6_6A_SMALL_NBITS;
+ break;
+ default:
+ IR_dprintk(1, "RC6 unknown mode\n");
+ goto out;
}
- break;
+ goto again;
case STATE_BODY_BIT_START:
- if (DURATION(u) == 1) {
- data->body <<= 1;
- if (IS_PULSE(u))
- data->body |= 1;
- data->count++;
- data->last_unit = u;
-
- /*
- * If the last bit is one, a space will merge
- * with the silence after the command.
- */
- if (IS_PULSE(u) && data->count == data->wanted_bits) {
- data->state = STATE_FINISHED;
- goto again;
- }
+ if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
+ break;
- data->state = STATE_BODY_BIT_END;
- return 0;
- }
- break;
+ data->body <<= 1;
+ if (ev.pulse)
+ data->body |= 1;
+ data->count++;
+ data->prev_ev = ev;
+
+ data->state = STATE_BODY_BIT_END;
+ return 0;
case STATE_BODY_BIT_END:
- if (IS_TRANSITION(u, data->last_unit)) {
- if (data->count == data->wanted_bits)
- data->state = STATE_FINISHED;
- else
- data->state = STATE_BODY_BIT_START;
+ if (!is_transition(&ev, &data->prev_ev))
+ break;
- DECREASE_DURATION(u, 1);
- goto again;
- }
- break;
+ if (data->count == data->wanted_bits)
+ data->state = STATE_FINISHED;
+ else
+ data->state = STATE_BODY_BIT_START;
+
+ decrease_duration(&ev, RC6_BIT_END);
+ goto again;
case STATE_FINISHED:
+ if (ev.pulse)
+ break;
+
switch (rc6_mode(data)) {
case RC6_MODE_0:
scancode = data->body & 0xffff;
@@ -335,8 +342,8 @@ again:
}
out:
- IR_dprintk(1, "RC6 decode failed at state %i (%i units, %ius)\n",
- data->state, u, TO_US(duration));
+ IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
data->state = STATE_INACTIVE;
return -EINVAL;
}
diff --git a/include/media/ir-core.h b/include/media/ir-core.h
index ab3bd30..26110cc 100644
--- a/include/media/ir-core.h
+++ b/include/media/ir-core.h
@@ -127,9 +127,21 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle);
/* From ir-raw-event.c */
+struct ir_raw_event {
+ unsigned pulse:1;
+ unsigned duration:31;
+};
+
+#define IR_MAX_DURATION 0x7FFFFFFF /* a bit more than 2 seconds */
+
void ir_raw_event_handle(struct input_dev *input_dev);
-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);
int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type);
-
+static inline void ir_raw_event_reset(struct input_dev *input_dev)
+{
+ struct ir_raw_event ev = { .pulse = false, .duration = 0 };
+ ir_raw_event_store(input_dev, &ev);
+ ir_raw_event_handle(input_dev);
+}
#endif /* _IR_CORE */
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/8] ir-core: Add JVC support to ir-core
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
2010-04-15 21:46 ` [PATCH 1/8] ir-core: change duration to be coded as a u32 integer David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 3/8] ir-core: Add Sony " David Härdeman
` (6 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
This patch adds a JVC decoder to ir-core.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/Kconfig | 9 +
drivers/media/IR/Makefile | 1
drivers/media/IR/ir-core-priv.h | 7 +
drivers/media/IR/ir-jvc-decoder.c | 320 +++++++++++++++++++++++++++++++++++++
drivers/media/IR/ir-raw-event.c | 1
drivers/media/IR/ir-sysfs.c | 4
6 files changed, 342 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/IR/ir-jvc-decoder.c
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index ee66d16..179e4c3 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -36,3 +36,12 @@ config IR_RC6_DECODER
---help---
Enable this option if you have an infrared remote control which
uses the RC6 protocol, and you need software decoding support.
+
+config IR_JVC_DECODER
+ tristate "Enable IR raw decoder for the JVC protocol"
+ depends on IR_CORE
+ default y
+
+ ---help---
+ Enable this option if you have an infrared remote control which
+ uses the JVC protocol, and you need software decoding support.
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
index 792d9ca..8d0098f 100644
--- a/drivers/media/IR/Makefile
+++ b/drivers/media/IR/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_VIDEO_IR) += ir-common.o
obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
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
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 707beeb..4b1a21d 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -111,4 +111,11 @@ void ir_raw_init(void);
#define load_rc6_decode() 0
#endif
+/* from ir-jvc-decoder.c */
+#ifdef CONFIG_IR_JVC_DECODER_MODULE
+#define load_jvc_decode() request_module("ir-jvc-decoder")
+#else
+#define load_jvc_decode() 0
+#endif
+
#endif /* _IR_RAW_EVENT */
diff --git a/drivers/media/IR/ir-jvc-decoder.c b/drivers/media/IR/ir-jvc-decoder.c
new file mode 100644
index 0000000..0b80494
--- /dev/null
+++ b/drivers/media/IR/ir-jvc-decoder.c
@@ -0,0 +1,320 @@
+/* ir-jvc-decoder.c - handle JVC IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
+ *
+ * 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
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitrev.h>
+#include "ir-core-priv.h"
+
+#define JVC_NBITS 16 /* dev(8) + func(8) */
+#define JVC_UNIT 525000 /* ns */
+#define JVC_HEADER_PULSE (16 * JVC_UNIT) /* lack of header -> repeat */
+#define JVC_HEADER_SPACE (8 * JVC_UNIT)
+#define JVC_BIT_PULSE (1 * JVC_UNIT)
+#define JVC_BIT_0_SPACE (1 * JVC_UNIT)
+#define JVC_BIT_1_SPACE (3 * JVC_UNIT)
+#define JVC_TRAILER_PULSE (1 * JVC_UNIT)
+#define JVC_TRAILER_SPACE (35 * JVC_UNIT)
+
+/* Used to register jvc_decoder clients */
+static LIST_HEAD(decoder_list);
+DEFINE_SPINLOCK(decoder_lock);
+
+enum jvc_state {
+ STATE_INACTIVE,
+ STATE_HEADER_SPACE,
+ STATE_BIT_PULSE,
+ STATE_BIT_SPACE,
+ STATE_TRAILER_PULSE,
+ STATE_TRAILER_SPACE,
+};
+
+struct decoder_data {
+ struct list_head list;
+ struct ir_input_dev *ir_dev;
+ int enabled:1;
+
+ /* State machine control */
+ enum jvc_state state;
+ u16 jvc_bits;
+ u16 jvc_old_bits;
+ unsigned count;
+ bool first;
+ bool toggle;
+};
+
+
+/**
+ * get_decoder_data() - gets decoder data
+ * @input_dev: input device
+ *
+ * Returns the struct decoder_data that corresponds to a device
+ */
+static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
+{
+ struct decoder_data *data = NULL;
+
+ spin_lock(&decoder_lock);
+ list_for_each_entry(data, &decoder_list, list) {
+ if (data->ir_dev == ir_dev)
+ break;
+ }
+ spin_unlock(&decoder_lock);
+ return data;
+}
+
+static ssize_t store_enabled(struct device *d,
+ struct device_attribute *mattr,
+ const char *buf,
+ size_t len)
+{
+ unsigned long value;
+ struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+ struct decoder_data *data = get_decoder_data(ir_dev);
+
+ if (!data)
+ return -EINVAL;
+
+ if (strict_strtoul(buf, 10, &value) || value > 1)
+ return -EINVAL;
+
+ data->enabled = value;
+
+ return len;
+}
+
+static ssize_t show_enabled(struct device *d,
+ struct device_attribute *mattr, char *buf)
+{
+ struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+ struct decoder_data *data = get_decoder_data(ir_dev);
+
+ if (!data)
+ return -EINVAL;
+
+ if (data->enabled)
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
+
+static struct attribute *decoder_attributes[] = {
+ &dev_attr_enabled.attr,
+ NULL
+};
+
+static struct attribute_group decoder_attribute_group = {
+ .name = "jvc_decoder",
+ .attrs = decoder_attributes,
+};
+
+/**
+ * ir_jvc_decode() - Decode one JVC pulse or space
+ * @input_dev: the struct input_dev descriptor of the device
+ * @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_jvc_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);
+
+ data = get_decoder_data(ir_dev);
+ if (!data)
+ return -EINVAL;
+
+ if (!data->enabled)
+ return 0;
+
+ if (IS_RESET(ev)) {
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ if (!geq_margin(ev.duration, JVC_UNIT, JVC_UNIT / 2))
+ goto out;
+
+ IR_dprintk(2, "JVC 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 (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
+ break;
+
+ data->count = 0;
+ data->first = true;
+ data->toggle = !data->toggle;
+ data->state = STATE_HEADER_SPACE;
+ return 0;
+
+ case STATE_HEADER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, JVC_HEADER_SPACE, JVC_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_PULSE;
+ return 0;
+
+ case STATE_BIT_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, JVC_BIT_PULSE, JVC_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_SPACE;
+ return 0;
+
+ case STATE_BIT_SPACE:
+ if (ev.pulse)
+ break;
+
+ data->jvc_bits <<= 1;
+ if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
+ data->jvc_bits |= 1;
+ decrease_duration(&ev, JVC_BIT_1_SPACE);
+ } else if (eq_margin(ev.duration, JVC_BIT_0_SPACE, JVC_UNIT / 2))
+ decrease_duration(&ev, JVC_BIT_0_SPACE);
+ else
+ break;
+ data->count++;
+
+ if (data->count == JVC_NBITS)
+ data->state = STATE_TRAILER_PULSE;
+ else
+ data->state = STATE_BIT_PULSE;
+ return 0;
+
+ case STATE_TRAILER_PULSE:
+ if (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, JVC_TRAILER_PULSE, JVC_UNIT / 2))
+ break;
+
+ data->state = STATE_TRAILER_SPACE;
+ return 0;
+
+ case STATE_TRAILER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, JVC_TRAILER_SPACE, JVC_UNIT / 2))
+ break;
+
+ if (data->first) {
+ u32 scancode;
+ scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
+ (bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
+ IR_dprintk(1, "JVC scancode 0x%04x\n", scancode);
+ ir_keydown(input_dev, scancode, data->toggle);
+ data->first = false;
+ data->jvc_old_bits = data->jvc_bits;
+ } else if (data->jvc_bits == data->jvc_old_bits) {
+ IR_dprintk(1, "JVC repeat\n");
+ ir_repeat(input_dev);
+ } else {
+ IR_dprintk(1, "JVC invalid repeat msg\n");
+ break;
+ }
+
+ data->count = 0;
+ data->state = STATE_BIT_PULSE;
+ return 0;
+ }
+
+out:
+ IR_dprintk(1, "JVC decode failed at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static int ir_jvc_register(struct input_dev *input_dev)
+{
+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+ struct decoder_data *data;
+ int rc;
+
+ rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+ if (rc < 0)
+ return rc;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+ return -ENOMEM;
+ }
+
+ data->ir_dev = ir_dev;
+ data->enabled = 1;
+
+ spin_lock(&decoder_lock);
+ list_add_tail(&data->list, &decoder_list);
+ spin_unlock(&decoder_lock);
+
+ return 0;
+}
+
+static int ir_jvc_unregister(struct input_dev *input_dev)
+{
+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+ static struct decoder_data *data;
+
+ data = get_decoder_data(ir_dev);
+ if (!data)
+ return 0;
+
+ sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+
+ spin_lock(&decoder_lock);
+ list_del(&data->list);
+ spin_unlock(&decoder_lock);
+
+ return 0;
+}
+
+static struct ir_raw_handler jvc_handler = {
+ .decode = ir_jvc_decode,
+ .raw_register = ir_jvc_register,
+ .raw_unregister = ir_jvc_unregister,
+};
+
+static int __init ir_jvc_decode_init(void)
+{
+ ir_raw_handler_register(&jvc_handler);
+
+ printk(KERN_INFO "IR JVC protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_jvc_decode_exit(void)
+{
+ ir_raw_handler_unregister(&jvc_handler);
+}
+
+module_init(ir_jvc_decode_init);
+module_exit(ir_jvc_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("JVC IR protocol decoder");
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 59f173c..7eef6bf 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -233,6 +233,7 @@ static void init_decoders(struct work_struct *work)
load_nec_decode();
load_rc5_decode();
load_rc6_decode();
+ load_jvc_decode();
/* If needed, we may later add some init code. In this case,
it is needed to change the CONFIG_MODULE test at ir-core.h
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index d7ec973..8e2751e 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -62,6 +62,8 @@ static ssize_t show_protocol(struct device *d,
s = "nec";
else if (ir_type == IR_TYPE_RC6)
s = "rc6";
+ else if (ir_type == IR_TYPE_JVC)
+ s = "jvc";
else
s = "other";
@@ -99,6 +101,8 @@ static ssize_t store_protocol(struct device *d,
ir_type |= IR_TYPE_PD;
if (!strcasecmp(buf, "nec"))
ir_type |= IR_TYPE_NEC;
+ if (!strcasecmp(buf, "jvc"))
+ ir_type |= IR_TYPE_JVC;
}
if (!ir_type) {
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 11f6618..214f072 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -16,6 +16,7 @@
#define IR_TYPE_PD (1 << 1) /* Pulse distance encoded IR */
#define IR_TYPE_NEC (1 << 2)
#define IR_TYPE_RC6 (1 << 3) /* Philips RC6 protocol */
+#define IR_TYPE_JVC (1 << 4) /* JVC protocol */
#define IR_TYPE_OTHER (1u << 31)
struct ir_scancode {
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/8] ir-core: Add Sony support to ir-core
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
2010-04-15 21:46 ` [PATCH 1/8] ir-core: change duration to be coded as a u32 integer David Härdeman
2010-04-15 21:46 ` [PATCH 2/8] ir-core: Add JVC support to ir-core David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 4/8] ir-core: remove ir-functions usage from dm1105 David Härdeman
` (5 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
This patch adds a Sony12/15/20 decoder to ir-core.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/Kconfig | 9 +
drivers/media/IR/Makefile | 1
drivers/media/IR/ir-core-priv.h | 7 +
drivers/media/IR/ir-raw-event.c | 1
drivers/media/IR/ir-sony-decoder.c | 312 ++++++++++++++++++++++++++++++++++++
drivers/media/IR/ir-sysfs.c | 4
6 files changed, 334 insertions(+), 0 deletions(-)
create mode 100644 drivers/media/IR/ir-sony-decoder.c
diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig
index 179e4c3..25e10b5 100644
--- a/drivers/media/IR/Kconfig
+++ b/drivers/media/IR/Kconfig
@@ -45,3 +45,12 @@ config IR_JVC_DECODER
---help---
Enable this option if you have an infrared remote control which
uses the JVC protocol, and you need software decoding support.
+
+config IR_SONY_DECODER
+ tristate "Enable IR raw decoder for the Sony protocol"
+ depends on IR_CORE
+ default y
+
+ ---help---
+ Enable this option if you have an infrared remote control which
+ uses the Sony protocol, and you need software decoding support.
diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
index 8d0098f..a12ee37 100644
--- a/drivers/media/IR/Makefile
+++ b/drivers/media/IR/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_IR_NEC_DECODER) += ir-nec-decoder.o
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
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 4b1a21d..04962a6 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -118,4 +118,11 @@ void ir_raw_init(void);
#define load_jvc_decode() 0
#endif
+/* from ir-sony-decoder.c */
+#ifdef CONFIG_IR_SONY_DECODER_MODULE
+#define load_sony_decode() request_module("ir-sony-decoder")
+#else
+#define load_sony_decode() 0
+#endif
+
#endif /* _IR_RAW_EVENT */
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 7eef6bf..ea68a3f 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -234,6 +234,7 @@ static void init_decoders(struct work_struct *work)
load_rc5_decode();
load_rc6_decode();
load_jvc_decode();
+ load_sony_decode();
/* If needed, we may later add some init code. In this case,
it is needed to change the CONFIG_MODULE test at ir-core.h
diff --git a/drivers/media/IR/ir-sony-decoder.c b/drivers/media/IR/ir-sony-decoder.c
new file mode 100644
index 0000000..9f440c5
--- /dev/null
+++ b/drivers/media/IR/ir-sony-decoder.c
@@ -0,0 +1,312 @@
+/* ir-sony-decoder.c - handle Sony IR Pulse/Space protocol
+ *
+ * Copyright (C) 2010 by David Härdeman <david@hardeman.nu>
+ *
+ * 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
+ * the Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitrev.h>
+#include "ir-core-priv.h"
+
+#define SONY_UNIT 600000 /* ns */
+#define SONY_HEADER_PULSE (4 * SONY_UNIT)
+#define SONY_HEADER_SPACE (1 * SONY_UNIT)
+#define SONY_BIT_0_PULSE (1 * SONY_UNIT)
+#define SONY_BIT_1_PULSE (2 * SONY_UNIT)
+#define SONY_BIT_SPACE (1 * SONY_UNIT)
+#define SONY_TRAILER_SPACE (10 * SONY_UNIT) /* minimum */
+
+/* Used to register sony_decoder clients */
+static LIST_HEAD(decoder_list);
+static DEFINE_SPINLOCK(decoder_lock);
+
+enum sony_state {
+ STATE_INACTIVE,
+ STATE_HEADER_SPACE,
+ STATE_BIT_PULSE,
+ STATE_BIT_SPACE,
+ STATE_FINISHED,
+};
+
+struct decoder_data {
+ struct list_head list;
+ struct ir_input_dev *ir_dev;
+ int enabled:1;
+
+ /* State machine control */
+ enum sony_state state;
+ u32 sony_bits;
+ unsigned count;
+};
+
+
+/**
+ * get_decoder_data() - gets decoder data
+ * @input_dev: input device
+ *
+ * Returns the struct decoder_data that corresponds to a device
+ */
+static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
+{
+ struct decoder_data *data = NULL;
+
+ spin_lock(&decoder_lock);
+ list_for_each_entry(data, &decoder_list, list) {
+ if (data->ir_dev == ir_dev)
+ break;
+ }
+ spin_unlock(&decoder_lock);
+ return data;
+}
+
+static ssize_t store_enabled(struct device *d,
+ struct device_attribute *mattr,
+ const char *buf,
+ size_t len)
+{
+ unsigned long value;
+ struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+ struct decoder_data *data = get_decoder_data(ir_dev);
+
+ if (!data)
+ return -EINVAL;
+
+ if (strict_strtoul(buf, 10, &value) || value > 1)
+ return -EINVAL;
+
+ data->enabled = value;
+
+ return len;
+}
+
+static ssize_t show_enabled(struct device *d,
+ struct device_attribute *mattr, char *buf)
+{
+ struct ir_input_dev *ir_dev = dev_get_drvdata(d);
+ struct decoder_data *data = get_decoder_data(ir_dev);
+
+ if (!data)
+ return -EINVAL;
+
+ if (data->enabled)
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled);
+
+static struct attribute *decoder_attributes[] = {
+ &dev_attr_enabled.attr,
+ NULL
+};
+
+static struct attribute_group decoder_attribute_group = {
+ .name = "sony_decoder",
+ .attrs = decoder_attributes,
+};
+
+/**
+ * ir_sony_decode() - Decode one Sony pulse or space
+ * @input_dev: the struct input_dev descriptor of the device
+ * @ev: the struct ir_raw_event descriptor of the pulse/space
+ *
+ * This function returns -EINVAL if the pulse violates the state machine
+ */
+static int ir_sony_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);
+ u32 scancode;
+ u8 device, subdevice, function;
+
+ data = get_decoder_data(ir_dev);
+ if (!data)
+ return -EINVAL;
+
+ if (!data->enabled)
+ return 0;
+
+ if (IS_RESET(ev)) {
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+ if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2))
+ goto out;
+
+ IR_dprintk(2, "Sony 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 (!ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SONY_HEADER_PULSE, SONY_UNIT / 2))
+ break;
+
+ data->count = 0;
+ data->state = STATE_HEADER_SPACE;
+ return 0;
+
+ case STATE_HEADER_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!eq_margin(ev.duration, SONY_HEADER_SPACE, SONY_UNIT / 2))
+ break;
+
+ data->state = STATE_BIT_PULSE;
+ return 0;
+
+ case STATE_BIT_PULSE:
+ if (!ev.pulse)
+ break;
+
+ data->sony_bits <<= 1;
+ if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
+ data->sony_bits |= 1;
+ else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
+ break;
+
+ data->count++;
+ data->state = STATE_BIT_SPACE;
+ return 0;
+
+ case STATE_BIT_SPACE:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, SONY_BIT_SPACE, SONY_UNIT / 2))
+ break;
+
+ decrease_duration(&ev, SONY_BIT_SPACE);
+
+ if (!geq_margin(ev.duration, SONY_UNIT, SONY_UNIT / 2)) {
+ data->state = STATE_BIT_PULSE;
+ return 0;
+ }
+
+ data->state = STATE_FINISHED;
+ /* Fall through */
+
+ case STATE_FINISHED:
+ if (ev.pulse)
+ break;
+
+ if (!geq_margin(ev.duration, SONY_TRAILER_SPACE, SONY_UNIT / 2))
+ break;
+
+ switch (data->count) {
+ case 12:
+ device = bitrev8((data->sony_bits << 3) & 0xF8);
+ subdevice = 0;
+ function = bitrev8((data->sony_bits >> 4) & 0xFE);
+ break;
+ case 15:
+ device = bitrev8((data->sony_bits >> 0) & 0xFF);
+ subdevice = 0;
+ function = bitrev8((data->sony_bits >> 7) & 0xFD);
+ break;
+ case 20:
+ device = bitrev8((data->sony_bits >> 5) & 0xF8);
+ subdevice = bitrev8((data->sony_bits >> 0) & 0xFF);
+ function = bitrev8((data->sony_bits >> 12) & 0xFE);
+ break;
+ default:
+ IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
+ goto out;
+ }
+
+ scancode = device << 16 | subdevice << 8 | function;
+ IR_dprintk(1, "Sony(%u) scancode 0x%05x\n", data->count, scancode);
+ ir_keydown(input_dev, scancode, 0);
+ data->state = STATE_INACTIVE;
+ return 0;
+ }
+
+out:
+ IR_dprintk(1, "Sony decode failed at state %d (%uus %s)\n",
+ data->state, TO_US(ev.duration), TO_STR(ev.pulse));
+ data->state = STATE_INACTIVE;
+ return -EINVAL;
+}
+
+static int ir_sony_register(struct input_dev *input_dev)
+{
+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+ struct decoder_data *data;
+ int rc;
+
+ rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+ if (rc < 0)
+ return rc;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data) {
+ sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+ return -ENOMEM;
+ }
+
+ data->ir_dev = ir_dev;
+ data->enabled = 1;
+
+ spin_lock(&decoder_lock);
+ list_add_tail(&data->list, &decoder_list);
+ spin_unlock(&decoder_lock);
+
+ return 0;
+}
+
+static int ir_sony_unregister(struct input_dev *input_dev)
+{
+ struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
+ static struct decoder_data *data;
+
+ data = get_decoder_data(ir_dev);
+ if (!data)
+ return 0;
+
+ sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group);
+
+ spin_lock(&decoder_lock);
+ list_del(&data->list);
+ spin_unlock(&decoder_lock);
+
+ return 0;
+}
+
+static struct ir_raw_handler sony_handler = {
+ .decode = ir_sony_decode,
+ .raw_register = ir_sony_register,
+ .raw_unregister = ir_sony_unregister,
+};
+
+static int __init ir_sony_decode_init(void)
+{
+ ir_raw_handler_register(&sony_handler);
+
+ printk(KERN_INFO "IR Sony protocol handler initialized\n");
+ return 0;
+}
+
+static void __exit ir_sony_decode_exit(void)
+{
+ ir_raw_handler_unregister(&sony_handler);
+}
+
+module_init(ir_sony_decode_init);
+module_exit(ir_sony_decode_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("David Härdeman <david@hardeman.nu>");
+MODULE_DESCRIPTION("Sony IR protocol decoder");
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 8e2751e..dfd45fa 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -64,6 +64,8 @@ static ssize_t show_protocol(struct device *d,
s = "rc6";
else if (ir_type == IR_TYPE_JVC)
s = "jvc";
+ else if (ir_type == IR_TYPE_SONY)
+ s = "sony";
else
s = "other";
@@ -103,6 +105,8 @@ static ssize_t store_protocol(struct device *d,
ir_type |= IR_TYPE_NEC;
if (!strcasecmp(buf, "jvc"))
ir_type |= IR_TYPE_JVC;
+ if (!strcasecmp(buf, "sony"))
+ ir_type |= IR_TYPE_SONY;
}
if (!ir_type) {
diff --git a/include/media/rc-map.h b/include/media/rc-map.h
index 214f072..67af24e 100644
--- a/include/media/rc-map.h
+++ b/include/media/rc-map.h
@@ -17,6 +17,7 @@
#define IR_TYPE_NEC (1 << 2)
#define IR_TYPE_RC6 (1 << 3) /* Philips RC6 protocol */
#define IR_TYPE_JVC (1 << 4) /* JVC protocol */
+#define IR_TYPE_SONY (1 << 5) /* Sony12/15/20 protocol */
#define IR_TYPE_OTHER (1u << 31)
struct ir_scancode {
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/8] ir-core: remove ir-functions usage from dm1105
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (2 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 3/8] ir-core: Add Sony " David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 5/8] ir-core: convert mantis from ir-functions.c David Härdeman
` (4 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
Convert drivers/media/dvb/dm1105/dm1105.c to not rely on
ir-functions.c.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
0 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/drivers/media/dvb/dm1105/dm1105.c b/drivers/media/dvb/dm1105/dm1105.c
index 333d7b1..89f1eca 100644
--- a/drivers/media/dvb/dm1105/dm1105.c
+++ b/drivers/media/dvb/dm1105/dm1105.c
@@ -27,7 +27,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/input.h>
-#include <media/ir-common.h>
+#include <media/ir-core.h>
#include "demux.h"
#include "dmxdev.h"
@@ -266,7 +266,6 @@ static void dm1105_card_list(struct pci_dev *pci)
/* infrared remote control */
struct infrared {
struct input_dev *input_dev;
- struct ir_input_state ir;
char input_phys[32];
struct work_struct work;
u32 ir_command;
@@ -532,8 +531,7 @@ static void dm1105_emit_key(struct work_struct *work)
data = (ircom >> 8) & 0x7f;
- ir_input_keydown(ir->input_dev, &ir->ir, data);
- ir_input_nokey(ir->input_dev, &ir->ir);
+ ir_keydown(ir->input_dev, data, 0);
}
/* work handler */
@@ -596,7 +594,6 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
{
struct input_dev *input_dev;
char *ir_codes = NULL;
- u64 ir_type = IR_TYPE_OTHER;
int err = -ENOMEM;
input_dev = input_allocate_device();
@@ -607,12 +604,6 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
snprintf(dm1105->ir.input_phys, sizeof(dm1105->ir.input_phys),
"pci-%s/ir0", pci_name(dm1105->pdev));
- err = ir_input_init(input_dev, &dm1105->ir.ir, ir_type);
- if (err < 0) {
- input_free_device(input_dev);
- return err;
- }
-
input_dev->name = "DVB on-card IR receiver";
input_dev->phys = dm1105->ir.input_phys;
input_dev->id.bustype = BUS_PCI;
@@ -630,8 +621,12 @@ int __devinit dm1105_ir_init(struct dm1105_dev *dm1105)
INIT_WORK(&dm1105->ir.work, dm1105_emit_key);
err = ir_input_register(input_dev, ir_codes, NULL, MODULE_NAME);
+ if (err < 0) {
+ input_free_device(input_dev);
+ return err;
+ }
- return err;
+ return 0;
}
void __devexit dm1105_ir_exit(struct dm1105_dev *dm1105)
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/8] ir-core: convert mantis from ir-functions.c
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (3 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 4/8] ir-core: remove ir-functions usage from dm1105 David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 23:17 ` Manu Abraham
2010-04-15 21:46 ` [PATCH 6/8] ir-core: fix double spinlock init in drivers/media/IR/rc-map.c David Härdeman
` (3 subsequent siblings)
8 siblings, 1 reply; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
Convert drivers/media/dvb/mantis/mantis_input.c to not use ir-functions.c
(The driver is anyway not complete enough to actually use the subsystem yet).
Signed-off-by: David Härdeman <david@hardeman.nu>
---
0 files changed, 0 insertions(+), 0 deletions(-)
diff --git a/drivers/media/dvb/mantis/mantis_input.c b/drivers/media/dvb/mantis/mantis_input.c
index 3d4e466..a99489b 100644
--- a/drivers/media/dvb/mantis/mantis_input.c
+++ b/drivers/media/dvb/mantis/mantis_input.c
@@ -19,7 +19,7 @@
*/
#include <linux/input.h>
-#include <media/ir-common.h>
+#include <media/ir-core.h>
#include <linux/pci.h>
#include "dmxdev.h"
@@ -104,7 +104,6 @@ EXPORT_SYMBOL_GPL(ir_mantis);
int mantis_input_init(struct mantis_pci *mantis)
{
struct input_dev *rc;
- struct ir_input_state rc_state;
char name[80], dev[80];
int err;
@@ -120,8 +119,6 @@ int mantis_input_init(struct mantis_pci *mantis)
rc->name = name;
rc->phys = dev;
- ir_input_init(rc, &rc_state, IR_TYPE_OTHER);
-
rc->id.bustype = BUS_PCI;
rc->id.vendor = mantis->vendor_id;
rc->id.product = mantis->device_id;
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/8] ir-core: fix double spinlock init in drivers/media/IR/rc-map.c
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (4 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 5/8] ir-core: convert mantis from ir-functions.c David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 7/8] ir-core: fix table resize during keymap init David Härdeman
` (2 subsequent siblings)
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
Fix a double initialization of the same spinlock in drivers/media/IR/rc-map.c.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/ir-sysfs.c | 2 --
drivers/media/IR/rc-map.c | 5 -----
2 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index dfd45fa..876baae 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -294,8 +294,6 @@ static int __init ir_core_init(void)
/* Initialize/load the decoders/keymap code that will be used */
ir_raw_init();
- rc_map_init();
-
return 0;
}
diff --git a/drivers/media/IR/rc-map.c b/drivers/media/IR/rc-map.c
index 1a3f4b1..caf6a27 100644
--- a/drivers/media/IR/rc-map.c
+++ b/drivers/media/IR/rc-map.c
@@ -81,8 +81,3 @@ void ir_unregister_map(struct rc_keymap *map)
}
EXPORT_SYMBOL_GPL(ir_unregister_map);
-void rc_map_init(void)
-{
- spin_lock_init(&rc_map_lock);
-
-}
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 7/8] ir-core: fix table resize during keymap init
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (5 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 6/8] ir-core: fix double spinlock init in drivers/media/IR/rc-map.c David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:46 ` [PATCH 8/8] ir-core: fix some confusing comments David Härdeman
2010-04-15 21:59 ` [PATCH 0/8] Series short description David Härdeman
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
drivers/media/IR/ir-keytable.c would alloc a suitably sized keymap table
only to have it resized as it is populated with the initial keymap.
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/ir-keytable.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index 01bddc4..b8baf8f 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -77,6 +77,7 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
* @rc_tab: the struct ir_scancode_table to set the keycode in
* @scancode: the scancode for the ir command
* @keycode: the keycode for the ir command
+ * @resize: whether the keytable may be shrunk
* @return: -EINVAL if the keycode could not be inserted, otherwise zero.
*
* This routine is used internally to manipulate the scancode->keycode table.
@@ -84,7 +85,8 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
*/
static int ir_do_setkeycode(struct input_dev *dev,
struct ir_scancode_table *rc_tab,
- int scancode, int keycode)
+ int scancode, int keycode,
+ bool resize)
{
unsigned int i;
int old_keycode = KEY_RESERVED;
@@ -128,7 +130,7 @@ static int ir_do_setkeycode(struct input_dev *dev,
if (old_keycode == KEY_RESERVED) {
/* No previous mapping found, we might need to grow the table */
- if (ir_resize_table(rc_tab))
+ if (resize && ir_resize_table(rc_tab))
return -ENOMEM;
IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
@@ -176,7 +178,7 @@ static int ir_setkeycode(struct input_dev *dev,
struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
spin_lock_irqsave(&rc_tab->lock, flags);
- rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode);
+ rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
spin_unlock_irqrestore(&rc_tab->lock, flags);
return rc;
}
@@ -203,7 +205,7 @@ static int ir_setkeytable(struct input_dev *dev,
spin_lock_irqsave(&rc_tab->lock, flags);
for (i = 0; i < from->size; i++) {
rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
- from->scan[i].keycode);
+ from->scan[i].keycode, false);
if (rc)
break;
}
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 8/8] ir-core: fix some confusing comments
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (6 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 7/8] ir-core: fix table resize during keymap init David Härdeman
@ 2010-04-15 21:46 ` David Härdeman
2010-04-15 21:59 ` [PATCH 0/8] Series short description David Härdeman
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:46 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
Fix some confusing comments in drivers/media/IR/*
Signed-off-by: David Härdeman <david@hardeman.nu>
---
drivers/media/IR/ir-keytable.c | 2 +-
drivers/media/IR/ir-sysfs.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c
index b8baf8f..de923fc 100644
--- a/drivers/media/IR/ir-keytable.c
+++ b/drivers/media/IR/ir-keytable.c
@@ -1,4 +1,4 @@
-/* ir-register.c - handle IR scancode->keycode tables
+/* ir-keytable.c - handle IR scancode->keycode tables
*
* Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com>
*
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 876baae..501dc2f 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -1,4 +1,4 @@
-/* ir-register.c - handle IR scancode->keycode tables
+/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc)
*
* Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
*
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 0/8] Series short description
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
` (7 preceding siblings ...)
2010-04-15 21:46 ` [PATCH 8/8] ir-core: fix some confusing comments David Härdeman
@ 2010-04-15 21:59 ` David Härdeman
8 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-15 21:59 UTC (permalink / raw)
To: mchehab; +Cc: linux-media, linux-input
On Thu, Apr 15, 2010 at 11:45:55PM +0200, David Härdeman wrote:
> The following series implements the suggested change to ir-core
> to use a 1:31 struct for pulse/space durations, adds two new
> raw decoders, converts two users of ir-functions to plain ir-core
> and fixes a few small bugs in ir-core.
Sorry about the subject of this mail...missed filling in that field :)
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/8] ir-core: convert mantis from ir-functions.c
2010-04-15 21:46 ` [PATCH 5/8] ir-core: convert mantis from ir-functions.c David Härdeman
@ 2010-04-15 23:17 ` Manu Abraham
2010-04-16 20:56 ` David Härdeman
0 siblings, 1 reply; 14+ messages in thread
From: Manu Abraham @ 2010-04-15 23:17 UTC (permalink / raw)
To: David Härdeman; +Cc: mchehab, linux-media, linux-input
On Fri, Apr 16, 2010 at 1:46 AM, David Härdeman <david@hardeman.nu> wrote:
> Convert drivers/media/dvb/mantis/mantis_input.c to not use ir-functions.c
> (The driver is anyway not complete enough to actually use the subsystem yet).
Huh ? I don't follow what you imply here ..
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/8] ir-core: convert mantis from ir-functions.c
2010-04-15 23:17 ` Manu Abraham
@ 2010-04-16 20:56 ` David Härdeman
2010-04-16 21:27 ` Manu Abraham
0 siblings, 1 reply; 14+ messages in thread
From: David Härdeman @ 2010-04-16 20:56 UTC (permalink / raw)
To: Manu Abraham; +Cc: mchehab, linux-media, linux-input
On Fri, Apr 16, 2010 at 03:17:35AM +0400, Manu Abraham wrote:
> On Fri, Apr 16, 2010 at 1:46 AM, David Härdeman <david@hardeman.nu> wrote:
> > Convert drivers/media/dvb/mantis/mantis_input.c to not use ir-functions.c
> > (The driver is anyway not complete enough to actually use the subsystem yet).
>
> Huh ? I don't follow what you imply here ..
>
The mantis_input.c file seems to be a skeleton as far as I could
tell...not actually in use yet. Or am I mistaken?
--
David Härdeman
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/8] ir-core: convert mantis from ir-functions.c
2010-04-16 20:56 ` David Härdeman
@ 2010-04-16 21:27 ` Manu Abraham
2010-04-19 9:58 ` David Härdeman
0 siblings, 1 reply; 14+ messages in thread
From: Manu Abraham @ 2010-04-16 21:27 UTC (permalink / raw)
To: David Härdeman; +Cc: mchehab, linux-media, linux-input
On Sat, Apr 17, 2010 at 12:56 AM, David Härdeman <david@hardeman.nu> wrote:
> On Fri, Apr 16, 2010 at 03:17:35AM +0400, Manu Abraham wrote:
>> On Fri, Apr 16, 2010 at 1:46 AM, David Härdeman <david@hardeman.nu> wrote:
>> > Convert drivers/media/dvb/mantis/mantis_input.c to not use ir-functions.c
>> > (The driver is anyway not complete enough to actually use the subsystem yet).
>>
>> Huh ? I don't follow what you imply here ..
>>
>
> The mantis_input.c file seems to be a skeleton as far as I could
> tell...not actually in use yet. Or am I mistaken?
Only the input related parts of the IR stuff is there in
mantis_input.c, the hardware handling is done by mantis_uart.c/h.
There is a small bit which has not gone upstream yet, which is
pending;
http://jusst.de/hg/mantis-v4l-dvb/rev/ad8b00c9edc2
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 5/8] ir-core: convert mantis from ir-functions.c
2010-04-16 21:27 ` Manu Abraham
@ 2010-04-19 9:58 ` David Härdeman
0 siblings, 0 replies; 14+ messages in thread
From: David Härdeman @ 2010-04-19 9:58 UTC (permalink / raw)
To: Manu Abraham; +Cc: mchehab, linux-media, linux-input
On Sat, Apr 17, 2010 at 01:27:05AM +0400, Manu Abraham wrote:
> On Sat, Apr 17, 2010 at 12:56 AM, David Härdeman <david@hardeman.nu> wrote:
> > On Fri, Apr 16, 2010 at 03:17:35AM +0400, Manu Abraham wrote:
> >> On Fri, Apr 16, 2010 at 1:46 AM, David Härdeman <david@hardeman.nu> wrote:
> >> > Convert drivers/media/dvb/mantis/mantis_input.c to not use ir-functions.c
> >> > (The driver is anyway not complete enough to actually use the subsystem yet).
> >>
> >> Huh ? I don't follow what you imply here ..
> >>
> >
> > The mantis_input.c file seems to be a skeleton as far as I could
> > tell...not actually in use yet. Or am I mistaken?
>
> Only the input related parts of the IR stuff is there in
> mantis_input.c, the hardware handling is done by mantis_uart.c/h.
> There is a small bit which has not gone upstream yet, which is
> pending;
> http://jusst.de/hg/mantis-v4l-dvb/rev/ad8b00c9edc2
>
Yes, and that patch includes actually calling mantis_input_init(), which
wasn't called previously, so mantis_input.c wasn't actually in use.
Anyways, my patch still applies (or the principle at least) - use the
functionality of ir-core and not ir-functions.c (which is going away).
And on a related note, the above patch adds keytables with entries like
KEY_0, they should probably be KEY_NUMERIC_* instead.
--
David Härdeman
--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2010-04-19 9:58 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-04-15 21:45 [PATCH 0/8] Series short description David Härdeman
2010-04-15 21:46 ` [PATCH 1/8] ir-core: change duration to be coded as a u32 integer David Härdeman
2010-04-15 21:46 ` [PATCH 2/8] ir-core: Add JVC support to ir-core David Härdeman
2010-04-15 21:46 ` [PATCH 3/8] ir-core: Add Sony " David Härdeman
2010-04-15 21:46 ` [PATCH 4/8] ir-core: remove ir-functions usage from dm1105 David Härdeman
2010-04-15 21:46 ` [PATCH 5/8] ir-core: convert mantis from ir-functions.c David Härdeman
2010-04-15 23:17 ` Manu Abraham
2010-04-16 20:56 ` David Härdeman
2010-04-16 21:27 ` Manu Abraham
2010-04-19 9:58 ` David Härdeman
2010-04-15 21:46 ` [PATCH 6/8] ir-core: fix double spinlock init in drivers/media/IR/rc-map.c David Härdeman
2010-04-15 21:46 ` [PATCH 7/8] ir-core: fix table resize during keymap init David Härdeman
2010-04-15 21:46 ` [PATCH 8/8] ir-core: fix some confusing comments David Härdeman
2010-04-15 21:59 ` [PATCH 0/8] Series short description David Härdeman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).