Re: [PATCH 04/15] V4L/DVB: ir-core: Add logic to decode IR protocols at the IR core

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2010-04-01 at 14:56 -0300, Mauro Carvalho Chehab wrote:
> Adds a method to pass IR raw pulse/code events into ir-core. This is
> needed in order to support LIRC. It also helps to move common code
> from the drivers into the core.
> 
> In order to allow testing, it implements a simple NEC protocol decoder
> at ir-nec-decoder.c file. The logic is about the same used at saa7134
> driver that handles Avermedia M135A and Encore FM53 boards.
> 
> Signed-off-by: Mauro Carvalho Chehab <mchehab@xxxxxxxxxx>
> 
>  create mode 100644 drivers/media/IR/ir-nec-decoder.c
>  create mode 100644 drivers/media/IR/ir-raw-event.c

Hi Mauro,

I haven't taken a very hard look at this since I'm very busy this month.

It looks OK so far.  I do have some comments....


> diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile
> index 171890e..18794c7 100644
> --- a/drivers/media/IR/Makefile
> +++ b/drivers/media/IR/Makefile
> @@ -1,5 +1,5 @@
>  ir-common-objs  := ir-functions.o ir-keymaps.o
> -ir-core-objs	:= ir-keytable.o ir-sysfs.o
> +ir-core-objs	:= ir-keytable.o ir-sysfs.o ir-raw-event.o ir-nec-decoder.o
>  
>  obj-$(CONFIG_IR_CORE) += ir-core.o
>  obj-$(CONFIG_VIDEO_IR) += ir-common.o
> diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
> new file mode 100644
> index 0000000..16360eb
> --- /dev/null
> +++ b/drivers/media/IR/ir-nec-decoder.c
> @@ -0,0 +1,131 @@
> +/* ir-raw-event.c - handle IR Pulse/Space event
> + *
> + * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@xxxxxxxxxx>
> + *
> + * 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 <media/ir-core.h>
> +
> +/* Start time: 4.5 ms  */
> +#define MIN_START_TIME	3900000
> +#define MAX_START_TIME	5100000

Hmmm.

An NEC header pulse is nominally        16 * 560 us = 8.96 ms
An NEC header space is nominally         8 * 560 us = 4.48 ms
An NEC repeat header space is nominally  4 * 560 us = 2.24 ms

I think you need a more explicit name than {MIN,MAX}_START_TIME.


> +/* Pulse time: 560 us  */
> +#define MIN_PULSE_TIME	460000
> +#define MAX_PULSE_TIME	660000
> +
> +/* Bit 1 space time: 2.25ms-560 us */
> +#define MIN_BIT1_TIME	1490000
> +#define MAX_BIT1_TIME	1890000
> +
> +/* Bit 0 space time: 1.12ms-560 us */
> +#define MIN_BIT0_TIME	360000
> +#define MAX_BIT0_TIME	760000
> +

The fundamental unit of time in the NEC protocol is ideally:

	4192/197 cycles / 38 kHz = 559978.6 ns ~= 560 ns

All other time durations in the NEC protocol are multiples of this unit.
See:

	http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2#l1.96

If you define the your above constants in terms of that time unit, it
makes the tolerances you added in explicitly visible when reading the
source.


> +/** Decode NEC pulsecode. This code can take up to 76.5 ms to run.
> +	Unfortunately, using IRQ to decode pulse didn't work, since it uses
> +	a pulse train of 38KHz. This means one pulse on each 52 us
> +*/
> +
> +int ir_nec_decode(struct input_dev *input_dev,
> +		  struct ir_raw_event *evs,
> +		  int len)
> +{
> +	int i, count = -1;
> +	int ircode = 0, not_code = 0;
> +#if 0
> +	/* Needed only after porting the event code to the decoder */
> +	struct ir_input_dev *ir = input_get_drvdata(input_dev);
> +#endif
> +
> +	/* Be sure that the first event is an start one and is a pulse */
> +	for (i = 0; i < len; i++) {
> +		if (evs[i].type & (IR_START_EVENT | IR_PULSE))
> +			break;
> +	}
> +	i++;	/* First event doesn't contain data */
> +
> +	if (i >= len)
> +		return 0;
> +
> +	/* First space should have 4.5 ms otherwise is not NEC protocol */
> +	if ((evs[i].delta.tv_nsec < MIN_START_TIME) |
> +	    (evs[i].delta.tv_nsec > MAX_START_TIME) |
> +	    (evs[i].type != IR_SPACE))
> +		goto err;
> +
> +	/*
> +	 * FIXME: need to implement the repeat sequence
> +	 */

I have an NEC protocol decoder here:

	http://linuxtv.org/hg/~awalls/cx23885-ir2/rev/2cfef53b95a2

If you would find it useful, please feel free to borrow ideas or parts
of the code to implement any features you are missing.  (That code works
by converting a mark-space pair to an "nec_symbol", and then taking
action based on the symbol.)

I suspect you will want to implement the repeat sequence.  It is hard
not to get a repeat sequence from a remote.

NEC ideally sends a repeat at intervals of:

	4192 cycles * 38 kHz = 110.316 ms




> +	count = 0;
> +	for (i++; i < len; i++) {
> +		int bit;
> +
> +		if ((evs[i].delta.tv_nsec < MIN_PULSE_TIME) |
> +		    (evs[i].delta.tv_nsec > MAX_PULSE_TIME) |
> +		    (evs[i].type != IR_PULSE))
> +			goto err;
> +
> +		if (++i >= len)
> +			goto err;
> +		if (evs[i].type != IR_SPACE)
> +			goto err;
> +
> +		if ((evs[i].delta.tv_nsec > MIN_BIT1_TIME) &&
> +		    (evs[i].delta.tv_nsec < MAX_BIT1_TIME))
> +			bit = 1;
> +		else if ((evs[i].delta.tv_nsec > MIN_BIT0_TIME) &&
> +			 (evs[i].delta.tv_nsec < MAX_BIT0_TIME))
> +			bit = 0;
> +		else
> +			goto err;
> +
> +		if (bit) {
> +			int shift = count;
> +			/* Address first, then command */
> +			if (shift < 8) {
> +				shift += 8;
> +				ircode |= 1 << shift;
> +			} else if (shift < 16) {
> +				not_code |= 1 << shift;
> +			} else if (shift < 24) {
> +				shift -= 16;
> +				ircode |= 1 << shift;
> +			} else {
> +				shift -= 24;
> +				not_code |= 1 << shift;
> +			}
> +		}
> +		if (++count == 32)
> +			break;
> +	}
> +
> +	/*
> +	 * Fixme: may need to accept Extended NEC protocol?
> +	 */

Both of the NEC remotes that I own use the extended protocol, IIRC.



> +	if ((ircode & ~not_code) != ircode) {
> +		IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n",
> +			   ircode, not_code);
> +		return -EINVAL;
> +	}
> +
> +	IR_dprintk(1, "NEC scancode 0x%04x\n", ircode);
> +
> +	return ircode;
> +err:
> +	IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n",
> +		   count, (evs[i].delta.tv_nsec + 500) / 1000);
> +
> +	return -EINVAL;
> +}
> +EXPORT_SYMBOL_GPL(ir_nec_decode);
> diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
> new file mode 100644
> index 0000000..9c71ac8
> --- /dev/null
> +++ b/drivers/media/IR/ir-raw-event.c
> @@ -0,0 +1,117 @@
> +/* ir-raw-event.c - handle IR Pulse/Space event
> + *
> + * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@xxxxxxxxxx>
> + *
> + * 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 <media/ir-core.h>
> +
> +/* Define the max number of bit transitions per IR keycode */
> +#define MAX_IR_EVENT_SIZE	256
> +
> +int ir_raw_event_register(struct input_dev *input_dev)
> +{
> +	struct ir_input_dev *ir = input_get_drvdata(input_dev);
> +	int rc, size;
> +
> +	ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
> +
> +	size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2;
> +	size = roundup_pow_of_two(size);
> +
> +	rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL);
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(ir_raw_event_register);
> +
> +void ir_raw_event_unregister(struct input_dev *input_dev)
> +{
> +	struct ir_input_dev *ir = input_get_drvdata(input_dev);
> +
> +	if (!ir->raw)
> +		return;
> +
> +	kfifo_free(&ir->raw->kfifo);
> +	kfree(ir->raw);
> +	ir->raw = NULL;
> +}
> +EXPORT_SYMBOL_GPL(ir_raw_event_unregister);
> +
> +int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type)
> +{
> +	struct ir_input_dev	*ir = input_get_drvdata(input_dev);
> +	struct timespec		ts;
> +	struct ir_raw_event	event;
> +	int			rc;
> +
> +	if (!ir->raw)
> +		return -EINVAL;
> +
> +	event.type = type;
> +	event.delta.tv_sec = 0;
> +	event.delta.tv_nsec = 0;
> +
> +	ktime_get_ts(&ts);
> +
> +	if (timespec_equal(&ir->raw->last_event, &event.delta))
> +		event.type |= IR_START_EVENT;
> +	else
> +		event.delta = timespec_sub(ts, ir->raw->last_event);
> +
> +	memcpy(&ir->raw->last_event, &ts, sizeof(ts));
> +
> +	if (event.delta.tv_sec) {
> +		event.type |= IR_START_EVENT;
> +		event.delta.tv_sec = 0;
> +		event.delta.tv_nsec = 0;
> +	}
> +
> +	kfifo_in(&ir->raw->kfifo, &event, sizeof(event));
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(ir_raw_event_store);
> +
> +int ir_raw_event_handle(struct input_dev *input_dev)
> +{
> +	struct ir_input_dev		*ir = input_get_drvdata(input_dev);
> +	int				rc;
> +	struct ir_raw_event		*evs;
> +	int 				len, i;
> +
> +	/*
> +	 * Store the events into a temporary buffer. This allows calling more than
> +	 * one decoder to deal with the received data
> +	 */
> +	len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs);
> +	if (!len)
> +		return 0;
> +	evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC);
> +
> +	for (i = 0; i < len; i++) {
> +		rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs));
> +		if (rc != sizeof(*evs)) {
> +			IR_dprintk(1, "overflow error: received %d instead of %zd\n",
> +				   rc, sizeof(*evs));
> +			return -EINVAL;
> +		}
> +		IR_dprintk(2, "event type %d, time before event: %07luus\n",
> +			evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000);
> +	}
> +
> +	rc = ir_nec_decode(input_dev, evs, len);
> +
> +	kfree(evs);
> +
> +	return rc;
> +}
> +EXPORT_SYMBOL_GPL(ir_raw_event_handle);
> diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c
> index 8187928..7382995 100644
> --- a/drivers/media/video/saa7134/saa7134-input.c
> +++ b/drivers/media/video/saa7134/saa7134-input.c
> @@ -67,6 +67,7 @@ MODULE_PARM_DESC(disable_other_ir, "disable full codes of "
>  /* Helper functions for RC5 and NEC decoding at GPIO16 or GPIO18 */
>  static int saa7134_rc5_irq(struct saa7134_dev *dev);
>  static int saa7134_nec_irq(struct saa7134_dev *dev);
> +static int saa7134_raw_decode_irq(struct saa7134_dev *dev);
>  static void nec_task(unsigned long data);
>  static void saa7134_nec_timer(unsigned long data);
>  
> @@ -402,10 +403,12 @@ void saa7134_input_irq(struct saa7134_dev *dev)
>  
>  	if (ir->nec_gpio) {
>  		saa7134_nec_irq(dev);
> -	} else if (!ir->polling && !ir->rc5_gpio) {
> +	} else if (!ir->polling && !ir->rc5_gpio && !ir->raw_decode) {
>  		build_key(dev);
>  	} else if (ir->rc5_gpio) {
>  		saa7134_rc5_irq(dev);
> +	} else if (ir->raw_decode) {
> +		saa7134_raw_decode_irq(dev);
>  	}
>  }
>  
> @@ -418,6 +421,23 @@ static void saa7134_input_timer(unsigned long data)
>  	mod_timer(&ir->timer, jiffies + msecs_to_jiffies(ir->polling));
>  }
>  
> +void ir_raw_decode_timer_end(unsigned long data)
> +{
> +	struct saa7134_dev *dev = (struct saa7134_dev *)data;
> +	struct card_ir *ir = dev->remote;
> +	int rc;
> +
> +	/*
> +	 * FIXME: the IR key handling code should be called by the decoder,
> +	 * after implementing the repeat mode
> +	 */
> +	rc = ir_raw_event_handle(dev->remote->dev);
> +	if (rc >= 0) {
> +		ir_input_keydown(ir->dev, &ir->ir, rc);
> +		ir_input_nokey(ir->dev, &ir->ir);
> +	}
> +}
> +
>  void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
>  {
>  	if (ir->running)
> @@ -446,6 +466,11 @@ void saa7134_ir_start(struct saa7134_dev *dev, struct card_ir *ir)
>  		setup_timer(&ir->timer_keyup, saa7134_nec_timer,
>  			    (unsigned long)dev);
>  		tasklet_init(&ir->tlet, nec_task, (unsigned long)dev);
> +	} else if (ir->raw_decode) {
> +		/* set timer_end for code completion */
> +		init_timer(&ir->timer_end);
> +		ir->timer_end.function = ir_raw_decode_timer_end;
> +		ir->timer_end.data = (unsigned long)dev;
>  	}
>  }
>  
> @@ -461,6 +486,9 @@ void saa7134_ir_stop(struct saa7134_dev *dev)
>  		del_timer_sync(&ir->timer_end);
>  	else if (ir->nec_gpio)
>  		tasklet_kill(&ir->tlet);
> +	else if (ir->raw_decode)
> +		del_timer_sync(&ir->timer_end);
> +
>  	ir->running = 0;
>  }
>  
> @@ -508,6 +536,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
>  	int polling      = 0;
>  	int rc5_gpio	 = 0;
>  	int nec_gpio	 = 0;
> +	int raw_decode   = 0;
>  	u64 ir_type = IR_TYPE_OTHER;
>  	int err;
>  
> @@ -573,7 +602,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
>  		ir_codes     = &ir_codes_avermedia_m135a_rm_jx_table;
>  		mask_keydown = 0x0040000;
>  		mask_keycode = 0xffff;
> -		nec_gpio     = 1;
> +		raw_decode   = 1;
>  		break;
>  	case SAA7134_BOARD_AVERMEDIA_777:
>  	case SAA7134_BOARD_AVERMEDIA_A16AR:
> @@ -754,6 +783,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
>  	ir->polling      = polling;
>  	ir->rc5_gpio	 = rc5_gpio;
>  	ir->nec_gpio	 = nec_gpio;
> +	ir->raw_decode	 = raw_decode;
>  
>  	/* init input device */
>  	snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)",
> @@ -761,7 +791,7 @@ int saa7134_input_init1(struct saa7134_dev *dev)
>  	snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0",
>  		 pci_name(dev->pci));
>  
> -	if (ir_codes->ir_type != IR_TYPE_OTHER) {
> +	if (ir_codes->ir_type != IR_TYPE_OTHER && !raw_decode) {
>  		ir->props.allowed_protos = IR_TYPE_RC5 | IR_TYPE_NEC;
>  		ir->props.priv = dev;
>  		ir->props.change_protocol = saa7134_ir_change_protocol;
> @@ -789,6 +819,11 @@ int saa7134_input_init1(struct saa7134_dev *dev)
>  	err = ir_input_register(ir->dev, ir_codes, &ir->props, MODULE_NAME);
>  	if (err)
>  		goto err_out_stop;
> +	if (ir_codes->ir_type != IR_TYPE_OTHER) {
> +		err = ir_raw_event_register(ir->dev);
> +		if (err)
> +			goto err_out_stop;
> +	}
>  
>  	saa7134_ir_start(dev, ir);
>  
> @@ -812,6 +847,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
>  		return;
>  
>  	saa7134_ir_stop(dev);
> +	ir_raw_event_unregister(dev->remote->dev);
>  	ir_input_unregister(dev->remote->dev);
>  	kfree(dev->remote);
>  	dev->remote = NULL;
> @@ -918,6 +954,48 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev)
>  	i2c_new_device(&dev->i2c_adap, &info);
>  }
>  
> +static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
> +{
> +	struct card_ir	*ir = dev->remote;
> +	unsigned long 	timeout;
> +	int count, pulse, oldpulse;
> +
> +	/* Disable IR IRQ line */
> +	saa_clearl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
> +
> +	/* Generate initial event */
> +	saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
> +	saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
> +	pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown;
> +	ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE);
> +
> +#if 1
> +	/* Wait up to 10 ms for event change */
> +	oldpulse = pulse;
> +	for (count = 0; count < 1000; count++)  {
> +		udelay(10);
> +		/* rising SAA7134_GPIO_GPRESCAN reads the status */
> +		saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
> +		saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
> +		pulse = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)
> +			& ir->mask_keydown;
> +		if (pulse != oldpulse)
> +			break;
> +	}
> +
> +	/* Store final event */
> +	ir_raw_event_store(dev->remote->dev, pulse? IR_PULSE : IR_SPACE);
> +#endif
> +	/* Wait 15 ms before deciding to do something else */
> +	timeout = jiffies + jiffies_to_msecs(15);
> +	mod_timer(&ir->timer_end, timeout);
> +
> +	/* Enable IR IRQ line */
> +	saa_setl(SAA7134_IRQ2, SAA7134_IRQ2_INTE_GPIO18);
> +
> +	return 1;
> +}
> +
>  static int saa7134_rc5_irq(struct saa7134_dev *dev)
>  {
>  	struct card_ir *ir = dev->remote;
> @@ -960,7 +1038,6 @@ static int saa7134_rc5_irq(struct saa7134_dev *dev)
>  	return 1;
>  }
>  
> -
>  /* On NEC protocol, One has 2.25 ms, and zero has 1.125 ms
>     The first pulse (start) has 9 + 4.5 ms
>   */
> diff --git a/include/media/ir-common.h b/include/media/ir-common.h
> index 41469b7..87f2ec7 100644
> --- a/include/media/ir-common.h
> +++ b/include/media/ir-common.h
> @@ -82,6 +82,9 @@ struct card_ir {
>  	/* NEC decoding */
>  	u32			nec_gpio;
>  	struct tasklet_struct   tlet;
> +
> +	/* IR core raw decoding */
> +	u32			raw_decode;
>  };
>  
>  /* Routines from ir-functions.c */
> diff --git a/include/media/ir-core.h b/include/media/ir-core.h
> index 1eae72d..369969d 100644
> --- a/include/media/ir-core.h
> +++ b/include/media/ir-core.h
> @@ -16,6 +16,8 @@
>  
>  #include <linux/input.h>
>  #include <linux/spinlock.h>
> +#include <linux/kfifo.h>
> +#include <linux/time.h>
>  
>  extern int ir_core_debug;
>  #define IR_dprintk(level, fmt, arg...)	if (ir_core_debug >= level) \
> @@ -27,6 +29,13 @@ extern int ir_core_debug;
>  #define IR_TYPE_NEC	(1  << 2)
>  #define IR_TYPE_OTHER	(((u64)1) << 63l)
>  
> +enum raw_event_type {
> +	IR_SPACE	= (1 << 0),
> +	IR_PULSE	= (1 << 1),
> +	IR_START_EVENT	= (1 << 2),
> +	IR_STOP_EVENT	= (1 << 3),
> +};
> +

Why are these events encoded as bit flags?  Shouldn't they all be
orthogonal?

Regards,
Andy

>  struct ir_scancode {
>  	u16	scancode;
>  	u32	keycode;
> @@ -46,6 +55,15 @@ struct ir_dev_props {
>  	int (*change_protocol)(void *priv, u64 ir_type);
>  };
>  
> +struct ir_raw_event {
> +	struct timespec		delta;	/* Time spent before event */
> +	enum raw_event_type	type;	/* event type */
> +};
> +
> +struct ir_raw_event_ctrl {
> +	struct kfifo			kfifo;		/* fifo for the pulse/space events */
> +	struct timespec			last_event;	/* when last event occurred */
> +};
>  
>  struct ir_input_dev {
>  	struct device			dev;		/* device */
> @@ -53,7 +71,9 @@ struct ir_input_dev {
>  	struct ir_scancode_table	rc_tab;		/* scan/key table */
>  	unsigned long			devno;		/* device number */
>  	const struct ir_dev_props	*props;		/* Device properties */
> +	struct ir_raw_event_ctrl	*raw;		/* for raw pulse/space events */
>  };
> +
>  #define to_ir_input_dev(_attr) container_of(_attr, struct ir_input_dev, attr)
>  
>  /* Routines from ir-keytable.c */
> @@ -72,4 +92,16 @@ void ir_input_unregister(struct input_dev *input_dev);
>  int ir_register_class(struct input_dev *input_dev);
>  void ir_unregister_class(struct input_dev *input_dev);
>  
> +/* Routines from ir-raw-event.c */
> +int ir_raw_event_register(struct input_dev *input_dev);
> +void ir_raw_event_unregister(struct input_dev *input_dev);
> +int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type);
> +int ir_raw_event_handle(struct input_dev *input_dev);
> +
> +/* from ir-nec-decoder.c */
> +int ir_nec_decode(struct input_dev *input_dev,
> +		  struct ir_raw_event *evs,
> +		  int len);
> +
> +
>  #endif

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux