Exemplo n.º 1
0
/**
 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
 * @input_dev:	the struct input_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) works
 * in similiar manner to ir_raw_event_store_edge.
 * This routine is intended for devices with limited internal buffer
 * It automerges samples of same type, and handles timeouts
 */
int ir_raw_event_store_with_filter(struct input_dev *input_dev,
						struct ir_raw_event *ev)
{
	struct ir_input_dev *ir = input_get_drvdata(input_dev);
	struct ir_raw_event_ctrl *raw = ir->raw;

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

	/* Ignore spaces in idle mode */
	if (ir->idle && !ev->pulse)
		return 0;
	else if (ir->idle)
		ir_raw_event_set_idle(input_dev, 0);

	if (!raw->this_ev.duration) {
		raw->this_ev = *ev;
	} else if (ev->pulse == raw->this_ev.pulse) {
		raw->this_ev.duration += ev->duration;
	} else {
		ir_raw_event_store(input_dev, &raw->this_ev);
		raw->this_ev = *ev;
	}

	/* Enter idle mode if nessesary */
	if (!ev->pulse && ir->props->timeout &&
		raw->this_ev.duration >= ir->props->timeout)
		ir_raw_event_set_idle(input_dev, 1);
	return 0;
}
Exemplo n.º 2
0
static void cx23885_input_process_measurements(struct cx23885_dev *dev,
					       bool overrun)
{
	struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir;

	ssize_t num;
	int count, i;
	bool handle = false;
	struct ir_raw_event ir_core_event[64];

	do {
		num = 0;
		v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event,
				 sizeof(ir_core_event), &num);

		count = num / sizeof(struct ir_raw_event);

		for (i = 0; i < count; i++) {
			ir_raw_event_store(kernel_ir->inp_dev,
					   &ir_core_event[i]);
			handle = true;
		}
	} while (num != 0);

	if (overrun)
		ir_raw_event_reset(kernel_ir->inp_dev);
	else if (handle)
		ir_raw_event_handle(kernel_ir->inp_dev);
}
Exemplo n.º 3
0
static int loop_set_wakeup_filter(struct rc_dev *dev,
				  struct rc_scancode_filter *sc)
{
	static const unsigned int max = 512;
	struct ir_raw_event *raw;
	int ret;
	int i;

	/* fine to disable filter */
	if (!sc->mask)
		return 0;

	/* encode the specified filter and loop it back */
	raw = kmalloc_array(max, sizeof(*raw), GFP_KERNEL);
	if (!raw)
		return -ENOMEM;

	ret = ir_raw_encode_scancode(dev->wakeup_protocol, sc->data, raw, max);
	/* still loop back the partial raw IR even if it's incomplete */
	if (ret == -ENOBUFS)
		ret = max;
	if (ret >= 0) {
		/* do the loopback */
		for (i = 0; i < ret; ++i)
			ir_raw_event_store(dev, &raw[i]);
		ir_raw_event_handle(dev);

		ret = 0;
	}

	kfree(raw);

	return ret;
}
Exemplo n.º 4
0
Arquivo: ir-raw.c Projeto: 7799/linux
/**
 * ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
 * @dev:	the struct rc_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) works
 * in similar manner to ir_raw_event_store_edge.
 * This routine is intended for devices with limited internal buffer
 * It automerges samples of same type, and handles timeouts. Returns non-zero
 * if the event was added, and zero if the event was ignored due to idle
 * processing.
 */
int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
{
	if (!dev->raw)
		return -EINVAL;

	/* Ignore spaces in idle mode */
	if (dev->idle && !ev->pulse)
		return 0;
	else if (dev->idle)
		ir_raw_event_set_idle(dev, false);

	if (!dev->raw->this_ev.duration)
		dev->raw->this_ev = *ev;
	else if (ev->pulse == dev->raw->this_ev.pulse)
		dev->raw->this_ev.duration += ev->duration;
	else {
		ir_raw_event_store(dev, &dev->raw->this_ev);
		dev->raw->this_ev = *ev;
	}

	/* Enter idle mode if nessesary */
	if (!ev->pulse && dev->timeout &&
	    dev->raw->this_ev.duration >= dev->timeout)
		ir_raw_event_set_idle(dev, true);

	return 1;
}
Exemplo n.º 5
0
static void redrat3_process_ir_data(struct redrat3_dev *rr3)
{
	DEFINE_IR_RAW_EVENT(rawir);
	struct device *dev;
	unsigned int i, sig_size, single_len, offset, val;
	u32 mod_freq;

	dev = rr3->dev;

	mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
	dev_dbg(dev, "Got mod_freq of %u\n", mod_freq);
	if (mod_freq && rr3->wideband) {
		DEFINE_IR_RAW_EVENT(ev);

		ev.carrier_report = 1;
		ev.carrier = mod_freq;

		ir_raw_event_store(rr3->rc, &ev);
	}

	/* process each rr3 encoded byte into an int */
	sig_size = be16_to_cpu(rr3->irdata.sig_size);
	for (i = 0; i < sig_size; i++) {
		offset = rr3->irdata.sigdata[i];
		val = get_unaligned_be16(&rr3->irdata.lens[offset]);
		single_len = redrat3_len_to_us(val);

		/* we should always get pulse/space/pulse/space samples */
		if (i % 2)
			rawir.pulse = false;
		else
			rawir.pulse = true;

		rawir.duration = US_TO_NS(single_len);
		/* cap the value to IR_MAX_DURATION */
		rawir.duration = (rawir.duration > IR_MAX_DURATION) ?
				 IR_MAX_DURATION : rawir.duration;

		dev_dbg(dev, "storing %s with duration %d (i: %d)\n",
			rawir.pulse ? "pulse" : "space", rawir.duration, i);
		ir_raw_event_store_with_filter(rr3->rc, &rawir);
	}

	/* add a trailing space */
	rawir.pulse = false;
	rawir.timeout = true;
	rawir.duration = rr3->rc->timeout;
	dev_dbg(dev, "storing trailing timeout with duration %d\n",
							rawir.duration);
	ir_raw_event_store_with_filter(rr3->rc, &rawir);

	dev_dbg(dev, "calling ir_raw_event_handle\n");
	ir_raw_event_handle(rr3->rc);
}
Exemplo n.º 6
0
/**
 * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
 * @input_dev:	the struct input_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) is used to
 * store the beginning of an ir pulse or space (or the start/end of ir
 * reception) for the raw ir decoding state machines. This is used by
 * hardware which does not provide durations directly but only interrupts
 * (or similar events) on state change.
 */
int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type)
{
	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)
		return -EINVAL;

	now = ktime_get();
	delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));

	/* Check for a long duration since last event or if we're
	 * being called for the first time, note that delta can't
	 * possibly be negative.
	 */
	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) {
		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;
	ir->raw->last_type = type;
	return rc;
}
Exemplo n.º 7
0
Arquivo: ir-raw.c Projeto: 7799/linux
/**
 * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
 * @dev:	the struct rc_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) is used to
 * store the beginning of an ir pulse or space (or the start/end of ir
 * reception) for the raw ir decoding state machines. This is used by
 * hardware which does not provide durations directly but only interrupts
 * (or similar events) on state change.
 */
int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
{
	ktime_t			now;
	s64			delta; /* ns */
	DEFINE_IR_RAW_EVENT(ev);
	int			rc = 0;
	int			delay;

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

	now = ktime_get();
	delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
	delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);

	/* Check for a long duration since last event or if we're
	 * being called for the first time, note that delta can't
	 * possibly be negative.
	 */
	if (delta > delay || !dev->raw->last_type)
		type |= IR_START_EVENT;
	else
		ev.duration = delta;

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

	dev->raw->last_event = now;
	dev->raw->last_type = type;
	return rc;
}
Exemplo n.º 8
0
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
{
	int i;
	const s32 *samples = (const void *)buf;

	for (i = 0; i < len >> 2; i++) {
		struct ir_raw_event ev;

		ev.duration = abs(samples[i]) * 1000; /* Convert to ns */
		ev.pulse = (samples[i] > 0) ? false : true;

		ir_raw_event_store(coredev->ir.input_dev, &ev);
	}
	ir_raw_event_handle(coredev->ir.input_dev);
}
Exemplo n.º 9
0
void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len)
{
	int i;
	const s32 *samples = (const void *)buf;

	for (i = 0; i < len >> 2; i++) {
		DEFINE_IR_RAW_EVENT(ev);

		ev.duration = abs(samples[i]) * 1000; 
		ev.pulse = (samples[i] > 0) ? false : true;

		ir_raw_event_store(coredev->ir.dev, &ev);
	}
	ir_raw_event_handle(coredev->ir.dev);
}
Exemplo n.º 10
0
Arquivo: ir-raw.c Projeto: 7799/linux
/**
 * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not
 * @dev:	the struct rc_dev device descriptor
 * @idle:	whether the device is idle or not
 */
void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
{
	if (!dev->raw)
		return;

	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");

	if (idle) {
		dev->raw->this_ev.timeout = true;
		ir_raw_event_store(dev, &dev->raw->this_ev);
		init_ir_raw_event(&dev->raw->this_ev);
	}

	if (dev->s_idle)
		dev->s_idle(dev, idle);

	dev->idle = idle;
}
Exemplo n.º 11
0
int picolcd_raw_cir(struct picolcd_data *data,
		struct hid_report *report, u8 *raw_data, int size)
{
	unsigned long flags;
	int i, w, sz;
	DEFINE_IR_RAW_EVENT(rawir);

	/* ignore if rc_dev is NULL or status is shunned */
	spin_lock_irqsave(&data->lock, flags);
	if (!data->rc_dev || (data->status & PICOLCD_CIR_SHUN)) {
		spin_unlock_irqrestore(&data->lock, flags);
		return 1;
	}
	spin_unlock_irqrestore(&data->lock, flags);

	/* PicoLCD USB packets contain 16-bit intervals in network order,
	 * with value negated for pulse. Intervals are in microseconds.
	 *
	 * Note: some userspace LIRC code for PicoLCD says negated values
	 * for space - is it a matter of IR chip? (pulse for my TSOP2236)
	 *
	 * In addition, the first interval seems to be around 15000 + base
	 * interval for non-first report of IR data - thus the quirk below
	 * to get RC_CODE to understand Sony and JVC remotes I have at hand
	 */
	sz = size > 0 ? min((int)raw_data[0], size-1) : 0;
	for (i = 0; i+1 < sz; i += 2) {
		init_ir_raw_event(&rawir);
		w = (raw_data[i] << 8) | (raw_data[i+1]);
		rawir.pulse = !!(w & 0x8000);
		rawir.duration = US_TO_NS(rawir.pulse ? (65536 - w) : w);
		/* Quirk!! - see above */
		if (i == 0 && rawir.duration > 15000000)
			rawir.duration -= 15000000;
		ir_raw_event_store(data->rc_dev, &rawir);
	}
	ir_raw_event_handle(data->rc_dev);

	return 1;
}
Exemplo n.º 12
0
void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
{
	struct ir_input_dev *ir = input_get_drvdata(input_dev);
	struct ir_raw_event_ctrl *raw = ir->raw;
	ktime_t now;
	u64 delta;

	if (!ir->props)
		return;

	if (!ir->raw)
		goto out;

	if (idle) {
		IR_dprintk(2, "enter idle mode\n");
		raw->last_event = ktime_get();
	} else {
		IR_dprintk(2, "exit idle mode\n");

		now = ktime_get();
		delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));

		WARN_ON(raw->this_ev.pulse);

		raw->this_ev.duration =
			min(raw->this_ev.duration + delta,
						(u64)IR_MAX_DURATION);

		ir_raw_event_store(input_dev, &raw->this_ev);

		if (raw->this_ev.duration == IR_MAX_DURATION)
			ir_raw_event_reset(input_dev);

		raw->this_ev.duration = 0;
	}
out:
	if (ir->props->s_idle)
		ir->props->s_idle(ir->props->priv, idle);
	ir->idle = idle;
}
Exemplo n.º 13
0
/**
 * ir_raw_event_set_idle() - provide hint to rc-core when the device is idle or not
 * @dev:	the struct rc_dev device descriptor
 * @idle:	whether the device is idle or not
 */
void ir_raw_event_set_idle(struct rc_dev *dev, bool idle)
{
	if (!dev->raw)
		return;

#ifdef CONFIG_DEBUG_PRINTK
	IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave");
#else
	IR_d;
#endif

	if (idle) {
		dev->raw->this_ev.timeout = true;
		ir_raw_event_store(dev, &dev->raw->this_ev);
		init_ir_raw_event(&dev->raw->this_ev);
	}

	if (dev->s_idle)
		dev->s_idle(dev, idle);

	dev->idle = idle;
}
Exemplo n.º 14
0
static void
wbcir_carrier_report(struct wbcir_data *data)
{
	unsigned counter = inb(data->ebase + WBCIR_REG_ECEIR_CNT_LO) |
			inb(data->ebase + WBCIR_REG_ECEIR_CNT_HI) << 8;

	if (counter > 0 && counter < 0xffff) {
		DEFINE_IR_RAW_EVENT(ev);

		ev.carrier_report = 1;
		ev.carrier = DIV_ROUND_CLOSEST(counter * 1000000u,
						data->pulse_duration);

		ir_raw_event_store(data->dev, &ev);
	}

	/* reset and restart the counter */
	data->pulse_duration = 0;
	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_R,
						WBCIR_CNTR_EN | WBCIR_CNTR_R);
	wbcir_set_bits(data->ebase + WBCIR_REG_ECEIR_CCTL, WBCIR_CNTR_EN,
						WBCIR_CNTR_EN | WBCIR_CNTR_R);
}
Exemplo n.º 15
0
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);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
    while (kfifo_get(raw->kfifo, (void *)&ev, sizeof(ev)) == sizeof(ev)) {
#else
    while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
#endif
        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;
    }
}

/**
 * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
 * @input_dev:	the struct input_dev device descriptor
 * @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, struct ir_raw_event *ev)
{
    struct ir_input_dev *ir = input_get_drvdata(input_dev);

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

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
    if (kfifo_put(ir->raw->kfifo, (void *)ev, sizeof(*ev)) != sizeof(*ev))
        return -ENOMEM;
#else
    if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
        return -ENOMEM;
#endif

    return 0;
}
EXPORT_SYMBOL_GPL(ir_raw_event_store);

/**
 * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space
 * @input_dev:	the struct input_dev device descriptor
 * @type:	the type of the event that has occurred
 *
 * This routine (which may be called from an interrupt context) is used to
 * store the beginning of an ir pulse or space (or the start/end of ir
 * reception) for the raw ir decoding state machines. This is used by
 * hardware which does not provide durations directly but only interrupts
 * (or similar events) on state change.
 */
int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type)
{
    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)
        return -EINVAL;

    now = ktime_get();
    delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));

    /* Check for a long duration since last event or if we're
     * being called for the first time, note that delta can't
     * possibly be negative.
     */
    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) {
        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;
    ir->raw->last_type = type;
    return rc;
}
EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);

/**
 * ir_raw_event_handle() - schedules the decoding of stored ir data
 * @input_dev:	the struct input_dev device descriptor
 *
 * This routine will signal the workqueue to start decoding stored ir data.
 */
void ir_raw_event_handle(struct input_dev *input_dev)
{
    struct ir_input_dev *ir = input_get_drvdata(input_dev);

    if (!ir->raw)
        return;

    schedule_work(&ir->raw->rx_work);
}
EXPORT_SYMBOL_GPL(ir_raw_event_handle);

/* used internally by the sysfs interface */
u64
ir_raw_get_allowed_protocols()
{
    u64 protocols;
    spin_lock(&ir_raw_handler_lock);
    protocols = available_protocols;
    spin_unlock(&ir_raw_handler_lock);
    return protocols;
}

/*
 * Used to (un)register raw event clients
 */
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;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
    spinlock_t ir_raw_lock;
#endif

    ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
    if (!ir->raw)
        return -ENOMEM;

    ir->raw->input_dev = input_dev;
    INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
    ir->raw->enabled_protocols = ~0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
    spin_lock_init(&ir_raw_lock);
    ir->raw->kfifo = kfifo_alloc(sizeof(s64) * MAX_IR_EVENT_SIZE, GFP_KERNEL, &ir_raw_lock);
#else
    rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
                     GFP_KERNEL);
#endif
    if (rc < 0) {
        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 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);

    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);

#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)
    kfifo_free(ir->raw->kfifo);
#else
    kfifo_free(&ir->raw->kfifo);
#endif
    kfree(ir->raw);
    ir->raw = NULL;
}

/*
 * Extension interface - used to register the IR decoders
 */

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);

    return 0;
}
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);
}
EXPORT_SYMBOL(ir_raw_handler_unregister);

#ifdef MODULE
static void init_decoders(struct work_struct *work)
{
    /* Load the decoder modules */

    load_nec_decode();
    load_rc5_decode();
    load_rc6_decode();
    load_jvc_decode();
    load_sony_decode();
    load_lirc_codec();

    /* 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
     */
}
Exemplo n.º 16
0
static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
{
	DEFINE_IR_RAW_EVENT(ev);
	ev.timeout = true;
	ir_raw_event_store(rdev, &ev);
}
Exemplo n.º 17
0
static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
{
	unsigned int symbol, mark = 0;
	struct st_rc_device *dev = data;
	int last_symbol = 0;
	u32 status;
	DEFINE_IR_RAW_EVENT(ev);

	if (dev->irq_wake)
		pm_wakeup_event(dev->dev, 0);

	status  = readl(dev->rx_base + IRB_RX_STATUS);

	while (status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)) {
		u32 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
		if (unlikely(int_status & IRB_RX_OVERRUN_INT)) {
			/* discard the entire collection in case of errors!  */
			ir_raw_event_reset(dev->rdev);
			dev_info(dev->dev, "IR RX overrun\n");
			writel(IRB_RX_OVERRUN_INT,
					dev->rx_base + IRB_RX_INT_CLEAR);
			continue;
		}

		symbol = readl(dev->rx_base + IRB_RX_SYS);
		mark = readl(dev->rx_base + IRB_RX_ON);

		if (symbol == IRB_TIMEOUT)
			last_symbol = 1;

		 /* Ignore any noise */
		if ((mark > 2) && (symbol > 1)) {
			symbol -= mark;
			if (dev->overclocking) { /* adjustments to timings */
				symbol *= dev->sample_mult;
				symbol /= dev->sample_div;
				mark *= dev->sample_mult;
				mark /= dev->sample_div;
			}

			ev.duration = US_TO_NS(mark);
			ev.pulse = true;
			ir_raw_event_store(dev->rdev, &ev);

			if (!last_symbol) {
				ev.duration = US_TO_NS(symbol);
				ev.pulse = false;
				ir_raw_event_store(dev->rdev, &ev);
			} else  {
				st_rc_send_lirc_timeout(dev->rdev);
			}

		}
		last_symbol = 0;
		status  = readl(dev->rx_base + IRB_RX_STATUS);
	}

	writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR);

	/* Empty software fifo */
	ir_raw_event_handle(dev->rdev);
	return IRQ_HANDLED;
}