V4L/DVB: ir-core: move decoding state to ir_raw_event_ctrl
This patch moves the state from each raw decoder into the ir_raw_event_ctrl struct. This allows the removal of code like this: 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; which is currently run for each decoder on each event in order to get the client-specific decoding state data. In addition, ir decoding modules and ir driver module load order is now independent. Centralizing the data also allows for a nice code reduction of about 30% per raw decoder as client lists and client registration callbacks are no longer necessary (but still kept around for the benefit of the lirc decoder). Out-of-tree modules can still use a similar trick to what the raw decoders did before this patch until they are merged. Signed-off-by: David Härdeman <david@hardeman.nu> Acked-by: Jarod Wilson <jarod@redhat.com> Tested-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
de8592bd53
commit
c216369e61
7 changed files with 118 additions and 464 deletions
|
@ -24,17 +24,55 @@ struct ir_raw_handler {
|
|||
|
||||
u64 protocols; /* which are handled by this handler */
|
||||
int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
|
||||
|
||||
/* These two should only be used by the lirc decoder */
|
||||
int (*raw_register)(struct input_dev *input_dev);
|
||||
int (*raw_unregister)(struct input_dev *input_dev);
|
||||
};
|
||||
|
||||
struct ir_raw_event_ctrl {
|
||||
struct list_head list; /* to keep track of raw clients */
|
||||
struct work_struct rx_work; /* for the rx decoding workqueue */
|
||||
struct kfifo kfifo; /* fifo for the pulse/space durations */
|
||||
ktime_t last_event; /* when last event occurred */
|
||||
enum raw_event_type last_type; /* last event type */
|
||||
struct input_dev *input_dev; /* pointer to the parent input_dev */
|
||||
u64 enabled_protocols; /* enabled raw protocol decoders */
|
||||
|
||||
/* raw decoder state follows */
|
||||
struct ir_raw_event prev_ev;
|
||||
struct nec_dec {
|
||||
int state;
|
||||
unsigned count;
|
||||
u32 bits;
|
||||
} nec;
|
||||
struct rc5_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc5;
|
||||
struct rc6_dec {
|
||||
int state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
} rc6;
|
||||
struct sony_dec {
|
||||
int state;
|
||||
u32 bits;
|
||||
unsigned count;
|
||||
} sony;
|
||||
struct jvc_dec {
|
||||
int state;
|
||||
u16 bits;
|
||||
u16 old_bits;
|
||||
unsigned count;
|
||||
bool first;
|
||||
bool toggle;
|
||||
} jvc;
|
||||
};
|
||||
|
||||
/* macros for IR decoders */
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
#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,
|
||||
|
@ -38,39 +34,6 @@ enum jvc_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_jvc_decode() - Decode one JVC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -80,12 +43,8 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
|||
*/
|
||||
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;
|
||||
struct jvc_dec *data = &ir_dev->raw->jvc;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_JVC))
|
||||
return 0;
|
||||
|
@ -140,9 +99,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->jvc_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, JVC_BIT_1_SPACE, JVC_UNIT / 2)) {
|
||||
data->jvc_bits |= 1;
|
||||
data->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);
|
||||
|
@ -175,13 +134,13 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
if (data->first) {
|
||||
u32 scancode;
|
||||
scancode = (bitrev8((data->jvc_bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->jvc_bits >> 0) & 0xff) << 0);
|
||||
scancode = (bitrev8((data->bits >> 8) & 0xff) << 8) |
|
||||
(bitrev8((data->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) {
|
||||
data->old_bits = data->bits;
|
||||
} else if (data->bits == data->old_bits) {
|
||||
IR_dprintk(1, "JVC repeat\n");
|
||||
ir_repeat(input_dev);
|
||||
} else {
|
||||
|
@ -201,45 +160,9 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
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;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
|
||||
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;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler jvc_handler = {
|
||||
.protocols = IR_TYPE_JVC,
|
||||
.decode = ir_jvc_decode,
|
||||
.raw_register = ir_jvc_register,
|
||||
.raw_unregister = ir_jvc_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_jvc_decode_init(void)
|
||||
|
|
|
@ -27,10 +27,6 @@
|
|||
#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);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum nec_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_HEADER_SPACE,
|
||||
|
@ -40,36 +36,6 @@ enum nec_state {
|
|||
STATE_TRAILER_SPACE,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
|
||||
/* State machine control */
|
||||
enum nec_state state;
|
||||
u32 nec_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_nec_decode() - Decode one NEC pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -79,15 +45,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
|||
*/
|
||||
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);
|
||||
struct nec_dec *data = &ir_dev->raw->nec;
|
||||
u32 scancode;
|
||||
u8 address, not_address, command, not_command;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_NEC))
|
||||
return 0;
|
||||
|
||||
|
@ -143,9 +105,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (ev.pulse)
|
||||
break;
|
||||
|
||||
data->nec_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
|
||||
data->nec_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
|
||||
break;
|
||||
data->count++;
|
||||
|
@ -174,14 +136,14 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
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);
|
||||
command = bitrev8((data->nec_bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->nec_bits >> 0) & 0xff);
|
||||
address = bitrev8((data->bits >> 24) & 0xff);
|
||||
not_address = bitrev8((data->bits >> 16) & 0xff);
|
||||
command = bitrev8((data->bits >> 8) & 0xff);
|
||||
not_command = bitrev8((data->bits >> 0) & 0xff);
|
||||
|
||||
if ((command ^ not_command) != 0xff) {
|
||||
IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
|
||||
data->nec_bits);
|
||||
data->bits);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -208,45 +170,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_nec_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_nec_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;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler nec_handler = {
|
||||
.protocols = IR_TYPE_NEC,
|
||||
.decode = ir_nec_decode,
|
||||
.raw_register = ir_nec_register,
|
||||
.raw_unregister = ir_nec_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_nec_decode_init(void)
|
||||
|
|
|
@ -20,36 +20,14 @@
|
|||
/* Define the max number of pulse/space transitions to buffer */
|
||||
#define MAX_IR_EVENT_SIZE 512
|
||||
|
||||
/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
|
||||
static LIST_HEAD(ir_raw_client_list);
|
||||
|
||||
/* Used to handle IR raw handler extensions */
|
||||
static DEFINE_SPINLOCK(ir_raw_handler_lock);
|
||||
static LIST_HEAD(ir_raw_handler_list);
|
||||
static u64 available_protocols;
|
||||
|
||||
/**
|
||||
* RUN_DECODER() - runs an operation on all IR decoders
|
||||
* @ops: IR raw handler operation to be called
|
||||
* @arg: arguments to be passed to the callback
|
||||
*
|
||||
* Calls ir_raw_handler::ops for all registered IR handlers. It prevents
|
||||
* new decode addition/removal while running, by locking ir_raw_handler_lock
|
||||
* mutex. If an error occurs, we keep going, as in the decode case, each
|
||||
* decoder must have a crack at decoding the data. We return a sum of the
|
||||
* return codes, which will be either 0 or negative for current callers.
|
||||
*/
|
||||
#define RUN_DECODER(ops, ...) ({ \
|
||||
struct ir_raw_handler *_ir_raw_handler; \
|
||||
int _sumrc = 0, _rc; \
|
||||
spin_lock(&ir_raw_handler_lock); \
|
||||
list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \
|
||||
if (_ir_raw_handler->ops) { \
|
||||
_rc = _ir_raw_handler->ops(__VA_ARGS__); \
|
||||
_sumrc += _rc; \
|
||||
} \
|
||||
} \
|
||||
spin_unlock(&ir_raw_handler_lock); \
|
||||
_sumrc; \
|
||||
})
|
||||
|
||||
#ifdef MODULE
|
||||
/* Used to load the decoders */
|
||||
static struct work_struct wq_load;
|
||||
|
@ -58,11 +36,17 @@ static struct work_struct wq_load;
|
|||
static void ir_raw_event_work(struct work_struct *work)
|
||||
{
|
||||
struct ir_raw_event ev;
|
||||
struct ir_raw_handler *handler;
|
||||
struct ir_raw_event_ctrl *raw =
|
||||
container_of(work, struct ir_raw_event_ctrl, rx_work);
|
||||
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
|
||||
RUN_DECODER(decode, raw->input_dev, ev);
|
||||
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
handler->decode(raw->input_dev, ev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
raw->prev_ev = ev;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -176,6 +160,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
|
|||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
int rc;
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
|
||||
if (!ir->raw)
|
||||
|
@ -192,26 +177,32 @@ int ir_raw_event_register(struct input_dev *input_dev)
|
|||
return rc;
|
||||
}
|
||||
|
||||
rc = RUN_DECODER(raw_register, input_dev);
|
||||
if (rc < 0) {
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
ir->raw = NULL;
|
||||
return rc;
|
||||
}
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir->raw->list, &ir_raw_client_list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_register)
|
||||
handler->raw_register(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ir_raw_event_unregister(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir = input_get_drvdata(input_dev);
|
||||
struct ir_raw_handler *handler;
|
||||
|
||||
if (!ir->raw)
|
||||
return;
|
||||
|
||||
cancel_work_sync(&ir->raw->rx_work);
|
||||
RUN_DECODER(raw_unregister, input_dev);
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir->raw->list);
|
||||
list_for_each_entry(handler, &ir_raw_handler_list, list)
|
||||
if (handler->raw_unregister)
|
||||
handler->raw_unregister(ir->raw->input_dev);
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
kfifo_free(&ir->raw->kfifo);
|
||||
kfree(ir->raw);
|
||||
|
@ -224,8 +215,13 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
|
|||
|
||||
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
|
||||
if (ir_raw_handler->raw_register)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_register(raw->input_dev);
|
||||
available_protocols |= ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
|
||||
|
@ -235,8 +231,13 @@ EXPORT_SYMBOL(ir_raw_handler_register);
|
|||
|
||||
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
|
||||
{
|
||||
struct ir_raw_event_ctrl *raw;
|
||||
|
||||
spin_lock(&ir_raw_handler_lock);
|
||||
list_del(&ir_raw_handler->list);
|
||||
if (ir_raw_handler->raw_unregister)
|
||||
list_for_each_entry(raw, &ir_raw_client_list, list)
|
||||
ir_raw_handler->raw_unregister(raw->input_dev);
|
||||
available_protocols &= ~ir_raw_handler->protocols;
|
||||
spin_unlock(&ir_raw_handler_lock);
|
||||
}
|
||||
|
|
|
@ -30,10 +30,6 @@
|
|||
#define RC5_BIT_END (1 * RC5_UNIT)
|
||||
#define RC5X_SPACE (4 * RC5_UNIT)
|
||||
|
||||
/* Used to register rc5_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc5_state {
|
||||
STATE_INACTIVE,
|
||||
STATE_BIT_START,
|
||||
|
@ -42,39 +38,6 @@ enum rc5_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
|
||||
/* State machine control */
|
||||
enum rc5_state state;
|
||||
u32 rc5_bits;
|
||||
struct ir_raw_event prev_ev;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_rc5_decode() - Decode one RC-5 pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -84,15 +47,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
|||
*/
|
||||
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);
|
||||
struct rc5_dec *data = &ir_dev->raw->rc5;
|
||||
u8 toggle;
|
||||
u32 scancode;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC5))
|
||||
return 0;
|
||||
|
||||
|
@ -128,16 +87,15 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
|
||||
break;
|
||||
|
||||
data->rc5_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (!ev.pulse)
|
||||
data->rc5_bits |= 1;
|
||||
data->bits |= 1;
|
||||
data->count++;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_BIT_END;
|
||||
return 0;
|
||||
|
||||
case STATE_BIT_END:
|
||||
if (!is_transition(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
@ -169,11 +127,11 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (data->wanted_bits == RC5X_NBITS) {
|
||||
/* RC5X */
|
||||
u8 xdata, command, system;
|
||||
xdata = (data->rc5_bits & 0x0003F) >> 0;
|
||||
command = (data->rc5_bits & 0x00FC0) >> 6;
|
||||
system = (data->rc5_bits & 0x1F000) >> 12;
|
||||
toggle = (data->rc5_bits & 0x20000) ? 1 : 0;
|
||||
command += (data->rc5_bits & 0x01000) ? 0 : 0x40;
|
||||
xdata = (data->bits & 0x0003F) >> 0;
|
||||
command = (data->bits & 0x00FC0) >> 6;
|
||||
system = (data->bits & 0x1F000) >> 12;
|
||||
toggle = (data->bits & 0x20000) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 16 | command << 8 | xdata;
|
||||
|
||||
IR_dprintk(1, "RC5X scancode 0x%06x (toggle: %u)\n",
|
||||
|
@ -182,10 +140,10 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
} 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;
|
||||
command = (data->bits & 0x0003F) >> 0;
|
||||
system = (data->bits & 0x007C0) >> 6;
|
||||
toggle = (data->bits & 0x00800) ? 1 : 0;
|
||||
command += (data->bits & 0x01000) ? 0 : 0x40;
|
||||
scancode = system << 8 | command;
|
||||
|
||||
IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n",
|
||||
|
@ -204,45 +162,9 @@ static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc5_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc5_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;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc5_handler = {
|
||||
.protocols = IR_TYPE_RC5,
|
||||
.decode = ir_rc5_decode,
|
||||
.raw_register = ir_rc5_register,
|
||||
.raw_unregister = ir_rc5_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc5_decode_init(void)
|
||||
|
|
|
@ -36,10 +36,6 @@
|
|||
#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
|
||||
#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
|
||||
|
||||
/* Used to register rc6_decoder clients */
|
||||
static LIST_HEAD(decoder_list);
|
||||
static DEFINE_SPINLOCK(decoder_lock);
|
||||
|
||||
enum rc6_mode {
|
||||
RC6_MODE_0,
|
||||
RC6_MODE_6A,
|
||||
|
@ -58,41 +54,8 @@ enum rc6_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
|
||||
/* State machine control */
|
||||
enum rc6_state state;
|
||||
u8 header;
|
||||
u32 body;
|
||||
struct ir_raw_event prev_ev;
|
||||
bool toggle;
|
||||
unsigned count;
|
||||
unsigned wanted_bits;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static enum rc6_mode rc6_mode(struct rc6_dec *data)
|
||||
{
|
||||
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 enum rc6_mode rc6_mode(struct decoder_data *data) {
|
||||
switch (data->header & RC6_MODE_MASK) {
|
||||
case 0:
|
||||
return RC6_MODE_0;
|
||||
|
@ -114,15 +77,11 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
|
|||
*/
|
||||
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);
|
||||
struct rc6_dec *data = &ir_dev->raw->rc6;
|
||||
u32 scancode;
|
||||
u8 toggle;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_RC6))
|
||||
return 0;
|
||||
|
||||
|
@ -175,12 +134,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
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(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == RC6_HEADER_NBITS)
|
||||
|
@ -196,12 +154,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
break;
|
||||
|
||||
data->toggle = ev.pulse;
|
||||
data->prev_ev = ev;
|
||||
data->state = STATE_TOGGLE_END;
|
||||
return 0;
|
||||
|
||||
case STATE_TOGGLE_END:
|
||||
if (!is_transition(&ev, &data->prev_ev) ||
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev) ||
|
||||
!geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
@ -211,7 +168,6 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
}
|
||||
|
||||
data->state = STATE_BODY_BIT_START;
|
||||
data->prev_ev = ev;
|
||||
decrease_duration(&ev, RC6_TOGGLE_END);
|
||||
data->count = 0;
|
||||
|
||||
|
@ -243,13 +199,11 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
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(&ev, &data->prev_ev))
|
||||
if (!is_transition(&ev, &ir_dev->raw->prev_ev))
|
||||
break;
|
||||
|
||||
if (data->count == data->wanted_bits)
|
||||
|
@ -300,45 +254,9 @@ static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ir_rc6_register(struct input_dev *input_dev)
|
||||
{
|
||||
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
|
||||
struct decoder_data *data;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_add_tail(&data->list, &decoder_list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ir_rc6_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;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler rc6_handler = {
|
||||
.protocols = IR_TYPE_RC6,
|
||||
.decode = ir_rc6_decode,
|
||||
.raw_register = ir_rc6_register,
|
||||
.raw_unregister = ir_rc6_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_rc6_decode_init(void)
|
||||
|
|
|
@ -23,10 +23,6 @@
|
|||
#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,
|
||||
|
@ -35,36 +31,6 @@ enum sony_state {
|
|||
STATE_FINISHED,
|
||||
};
|
||||
|
||||
struct decoder_data {
|
||||
struct list_head list;
|
||||
struct ir_input_dev *ir_dev;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* ir_sony_decode() - Decode one Sony pulse or space
|
||||
* @input_dev: the struct input_dev descriptor of the device
|
||||
|
@ -74,15 +40,11 @@ static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev)
|
|||
*/
|
||||
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);
|
||||
struct sony_dec *data = &ir_dev->raw->sony;
|
||||
u32 scancode;
|
||||
u8 device, subdevice, function;
|
||||
|
||||
data = get_decoder_data(ir_dev);
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_SONY))
|
||||
return 0;
|
||||
|
||||
|
@ -124,9 +86,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
if (!ev.pulse)
|
||||
break;
|
||||
|
||||
data->sony_bits <<= 1;
|
||||
data->bits <<= 1;
|
||||
if (eq_margin(ev.duration, SONY_BIT_1_PULSE, SONY_UNIT / 2))
|
||||
data->sony_bits |= 1;
|
||||
data->bits |= 1;
|
||||
else if (!eq_margin(ev.duration, SONY_BIT_0_PULSE, SONY_UNIT / 2))
|
||||
break;
|
||||
|
||||
|
@ -160,19 +122,19 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
|
||||
switch (data->count) {
|
||||
case 12:
|
||||
device = bitrev8((data->sony_bits << 3) & 0xF8);
|
||||
device = bitrev8((data->bits << 3) & 0xF8);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 4) & 0xFE);
|
||||
function = bitrev8((data->bits >> 4) & 0xFE);
|
||||
break;
|
||||
case 15:
|
||||
device = bitrev8((data->sony_bits >> 0) & 0xFF);
|
||||
device = bitrev8((data->bits >> 0) & 0xFF);
|
||||
subdevice = 0;
|
||||
function = bitrev8((data->sony_bits >> 7) & 0xFD);
|
||||
function = bitrev8((data->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);
|
||||
device = bitrev8((data->bits >> 5) & 0xF8);
|
||||
subdevice = bitrev8((data->bits >> 0) & 0xFF);
|
||||
function = bitrev8((data->bits >> 12) & 0xFE);
|
||||
break;
|
||||
default:
|
||||
IR_dprintk(1, "Sony invalid bitcount %u\n", data->count);
|
||||
|
@ -193,45 +155,9 @@ static int ir_sony_decode(struct input_dev *input_dev, struct ir_raw_event ev)
|
|||
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;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
data->ir_dev = ir_dev;
|
||||
|
||||
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;
|
||||
|
||||
spin_lock(&decoder_lock);
|
||||
list_del(&data->list);
|
||||
spin_unlock(&decoder_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct ir_raw_handler sony_handler = {
|
||||
.protocols = IR_TYPE_SONY,
|
||||
.decode = ir_sony_decode,
|
||||
.raw_register = ir_sony_register,
|
||||
.raw_unregister = ir_sony_unregister,
|
||||
};
|
||||
|
||||
static int __init ir_sony_decode_init(void)
|
||||
|
|
Loading…
Reference in a new issue