Exemplo n.º 1
0
static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
{
	u32 *tmp;
	u32 timeout = MS_TO_US(150); /*                                      */
	int len, ret, pipe;

	len = sizeof(*tmp);
	tmp = kzalloc(len, GFP_KERNEL);
	if (!tmp) {
		dev_warn(rr3->dev, "Memory allocation faillure\n");
		return timeout;
	}

	pipe = usb_rcvctrlpipe(rr3->udev, 0);
	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
	if (ret != len) {
		dev_warn(rr3->dev, "Failed to read timeout from hardware\n");
		return timeout;
	}

	timeout = redrat3_len_to_us(be32_to_cpu(*tmp));

	rr3_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
	return timeout;
}
Exemplo n.º 2
0
static u32 redrat3_get_timeout(struct device *dev,
			       struct rc_dev *rc, struct usb_device *udev)
{
	u32 *tmp;
	u32 timeout = MS_TO_NS(150); /* a sane default, if things go haywire */
	int len, ret, pipe;

	len = sizeof(*tmp);
	tmp = kzalloc(len, GFP_KERNEL);
	if (!tmp) {
		dev_warn(dev, "Memory allocation faillure\n");
		return timeout;
	}

	pipe = usb_rcvctrlpipe(udev, 0);
	ret = usb_control_msg(udev, pipe, RR3_GET_IR_PARAM,
			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
	if (ret != len) {
		dev_warn(dev, "Failed to read timeout from hardware\n");
		return timeout;
	}

	timeout = US_TO_NS(redrat3_len_to_us(be32_to_cpu(*tmp)));
	if (timeout < rc->min_timeout)
		timeout = rc->min_timeout;
	else if (timeout > rc->max_timeout)
		timeout = rc->max_timeout;

	rr3_dbg(dev, "Got timeout of %d ms\n", timeout / (1000 * 1000));
	return timeout;
}
Exemplo n.º 3
0
static u32 redrat3_get_timeout(struct redrat3_dev *rr3)
{
	__be32 *tmp;
	u32 timeout = MS_TO_US(150); /* a sane default, if things go haywire */
	int len, ret, pipe;

	len = sizeof(*tmp);
	tmp = kzalloc(len, GFP_KERNEL);
	if (!tmp)
		return timeout;

	pipe = usb_rcvctrlpipe(rr3->udev, 0);
	ret = usb_control_msg(rr3->udev, pipe, RR3_GET_IR_PARAM,
			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
			      RR3_IR_IO_SIG_TIMEOUT, 0, tmp, len, HZ * 5);
	if (ret != len)
		dev_warn(rr3->dev, "Failed to read timeout from hardware\n");
	else {
		timeout = redrat3_len_to_us(be32_to_cpup(tmp));

		dev_dbg(rr3->dev, "Got timeout of %d ms\n", timeout / 1000);
	}

	kfree(tmp);

	return timeout;
}
Exemplo n.º 4
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.º 5
0
static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
				unsigned count)
{
	struct redrat3_dev *rr3 = rcdev->priv;
	struct device *dev = rr3->dev;
	struct redrat3_signal_header header;
	int i, j, ret, ret_len, offset;
	int lencheck, cur_sample_len, pipe;
	char *buffer = NULL, *sigdata = NULL;
	int *sample_lens = NULL;
	u32 tmpi;
	u16 tmps;
	u8 *datap;
	u8 curlencheck = 0;
	u16 *lengths_ptr;
	int sendbuf_len;

	rr3_ftr(dev, "Entering %s\n", __func__);

	if (rr3->transmitting) {
		dev_warn(dev, "%s: transmitter already in use\n", __func__);
		return -EAGAIN;
	}

	if (count > (RR3_DRIVER_MAXLENS * 2))
		return -EINVAL;

	/*                                          */
	rr3->det_enabled = false;
	rr3->transmitting = true;

	sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
	if (!sample_lens) {
		ret = -ENOMEM;
		goto out;
	}

	for (i = 0; i < count; i++) {
		for (lencheck = 0; lencheck < curlencheck; lencheck++) {
			cur_sample_len = redrat3_us_to_len(txbuf[i]);
			if (sample_lens[lencheck] == cur_sample_len)
				break;
		}
		if (lencheck == curlencheck) {
			cur_sample_len = redrat3_us_to_len(txbuf[i]);
			rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n",
				i, txbuf[i], curlencheck, cur_sample_len);
			if (curlencheck < 255) {
				/*                                  
                   */
				sample_lens[curlencheck] = cur_sample_len;
				curlencheck++;
			} else {
				dev_err(dev, "signal too long\n");
				ret = -EINVAL;
				goto out;
			}
		}
	}

	sigdata = kzalloc((count + RR3_TX_TRAILER_LEN), GFP_KERNEL);
	if (!sigdata) {
		ret = -ENOMEM;
		goto out;
	}

	sigdata[count] = RR3_END_OF_SIGNAL;
	sigdata[count + 1] = RR3_END_OF_SIGNAL;
	for (i = 0; i < count; i++) {
		for (j = 0; j < curlencheck; j++) {
			if (sample_lens[j] == redrat3_us_to_len(txbuf[i]))
				sigdata[i] = j;
		}
	}

	offset = RR3_TX_HEADER_OFFSET;
	sendbuf_len = RR3_HEADER_LENGTH + (sizeof(u16) * RR3_DRIVER_MAXLENS)
			+ count + RR3_TX_TRAILER_LEN + offset;

	buffer = kzalloc(sendbuf_len, GFP_KERNEL);
	if (!buffer) {
		ret = -ENOMEM;
		goto out;
	}

	/*                           */
	header.length = sendbuf_len - offset;
	header.transfer_type = RR3_MOD_SIGNAL_OUT;
	header.pause = redrat3_len_to_us(100);
	header.mod_freq_count = mod_freq_to_val(rr3->carrier);
	header.no_periods = 0; /*                 */
	header.max_lengths = RR3_DRIVER_MAXLENS;
	header.no_lengths = curlencheck;
	header.max_sig_size = RR3_MAX_SIG_SIZE;
	header.sig_size = count + RR3_TX_TRAILER_LEN;
	/*                                                                */
	header.no_repeats = 0;

	tmps = cpu_to_be16(header.length);
	memcpy(buffer, &tmps, 2);

	tmps = cpu_to_be16(header.transfer_type);
	memcpy(buffer + 2, &tmps, 2);

	tmpi = cpu_to_be32(header.pause);
	memcpy(buffer + offset, &tmpi, sizeof(tmpi));

	tmps = cpu_to_be16(header.mod_freq_count);
	memcpy(buffer + offset + RR3_FREQ_COUNT_OFFSET, &tmps, 2);

	buffer[offset + RR3_NUM_LENGTHS_OFFSET] = header.no_lengths;

	tmps = cpu_to_be16(header.sig_size);
	memcpy(buffer + offset + RR3_NUM_SIGS_OFFSET, &tmps, 2);

	buffer[offset + RR3_REPEATS_OFFSET] = header.no_repeats;

	lengths_ptr = (u16 *)(buffer + offset + RR3_HEADER_LENGTH);
	for (i = 0; i < curlencheck; ++i)
		lengths_ptr[i] = cpu_to_be16(sample_lens[i]);

	datap = (u8 *)(buffer + offset + RR3_HEADER_LENGTH +
			    (sizeof(u16) * RR3_DRIVER_MAXLENS));
	memcpy(datap, sigdata, (count + RR3_TX_TRAILER_LEN));

	if (debug) {
		redrat3_dump_signal_header(&header);
		redrat3_dump_signal_data(buffer, header.sig_size);
	}

	pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress);
	tmps = usb_bulk_msg(rr3->udev, pipe, buffer,
			    sendbuf_len, &ret_len, 10 * HZ);
	rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, tmps);

	/*                                                   */
	pipe = usb_rcvctrlpipe(rr3->udev, 0);
	ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL,
			      USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
			      0, 0, buffer, 2, HZ * 10);

	if (ret < 0)
		dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
	else
		ret = count;

out:
	kfree(sample_lens);
	kfree(buffer);
	kfree(sigdata);

	rr3->transmitting = false;
	/*                                                          */
	rr3->det_enabled = true;

	return ret;
}
Exemplo n.º 6
0
static void redrat3_process_ir_data(struct redrat3_dev *rr3)
{
	DEFINE_IR_RAW_EVENT(rawir);
	struct redrat3_signal_header header;
	struct device *dev;
	int i, trailer = 0;
	unsigned long delay;
	u32 mod_freq, single_len;
	u16 *len_vals;
	u8 *data_vals;
	u32 tmp32;
	u16 tmp16;
	char *sig_data;

	if (!rr3) {
		pr_err("%s called with no context!\n", __func__);
		return;
	}

	rr3_ftr(rr3->dev, "Entered %s\n", __func__);

	dev = rr3->dev;
	sig_data = rr3->pbuf;

	header.length = rr3->pktlen;
	header.transfer_type = rr3->pkttype;

	/*              */
	if (!(header.length >= RR3_HEADER_LENGTH))
		dev_warn(dev, "read returned less than rr3 header len\n");

	/*                                                           */
	delay = usecs_to_jiffies(rr3->hw_timeout);
	mod_timer(&rr3->rx_timeout, jiffies + delay);

	memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32));
	header.pause = be32_to_cpu(tmp32);

	memcpy(&tmp16, sig_data + RR3_FREQ_COUNT_OFFSET, sizeof(tmp16));
	header.mod_freq_count = be16_to_cpu(tmp16);

	memcpy(&tmp16, sig_data + RR3_NUM_PERIOD_OFFSET, sizeof(tmp16));
	header.no_periods = be16_to_cpu(tmp16);

	header.max_lengths = sig_data[RR3_MAX_LENGTHS_OFFSET];
	header.no_lengths = sig_data[RR3_NUM_LENGTHS_OFFSET];

	memcpy(&tmp16, sig_data + RR3_MAX_SIGS_OFFSET, sizeof(tmp16));
	header.max_sig_size = be16_to_cpu(tmp16);

	memcpy(&tmp16, sig_data + RR3_NUM_SIGS_OFFSET, sizeof(tmp16));
	header.sig_size = be16_to_cpu(tmp16);

	header.no_repeats= sig_data[RR3_REPEATS_OFFSET];

	if (debug) {
		redrat3_dump_signal_header(&header);
		redrat3_dump_signal_data(sig_data, header.sig_size);
	}

	mod_freq = redrat3_val_to_mod_freq(&header);
	rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq);

	/*                                                      */
	len_vals = (u16 *)(sig_data + RR3_HEADER_LENGTH);

	data_vals = sig_data + RR3_HEADER_LENGTH +
		    (header.max_lengths * sizeof(u16));

	/*                                           */
	for (i = 0; i < header.sig_size; i++) {
		u16 val = len_vals[data_vals[i]];
		single_len = redrat3_len_to_us((u32)be16_to_cpu(val));

		/*                                                      */
		if (i % 2)
			rawir.pulse = false;
		else
			rawir.pulse = true;

		rawir.duration = US_TO_NS(single_len);
		/*                                            */
		if (i == 0)
			trailer = rawir.duration;
		/*                                  */
		rawir.duration &= IR_MAX_DURATION;

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

	/*                                  */
	if (i % 2) {
		rawir.pulse = false;
		/*                                                   */
		if (trailer < US_TO_NS(1000))
			rawir.duration = US_TO_NS(2800);
		else
			rawir.duration = trailer;
		rr3_dbg(dev, "storing trailing space with duration %d\n",
			rawir.duration);
		ir_raw_event_store_with_filter(rr3->rc, &rawir);
	}

	rr3_dbg(dev, "calling ir_raw_event_handle\n");
	ir_raw_event_handle(rr3->rc);

	return;
}
static int redrat3_transmit_ir(struct rc_dev *rcdev, unsigned *txbuf,
                               unsigned count)
{
    struct redrat3_dev *rr3 = rcdev->priv;
    struct device *dev = rr3->dev;
    struct redrat3_irdata *irdata = NULL;
    int ret, ret_len;
    int lencheck, cur_sample_len, pipe;
    int *sample_lens = NULL;
    u8 curlencheck = 0;
    unsigned i, sendbuf_len;

    rr3_ftr(dev, "Entering %s\n", __func__);

    if (rr3->transmitting) {
        dev_warn(dev, "%s: transmitter already in use\n", __func__);
        return -EAGAIN;
    }

    if (count > RR3_MAX_SIG_SIZE - RR3_TX_TRAILER_LEN)
        return -EINVAL;

    /* rr3 will disable rc detector on transmit */
    rr3->transmitting = true;

    sample_lens = kzalloc(sizeof(int) * RR3_DRIVER_MAXLENS, GFP_KERNEL);
    if (!sample_lens) {
        ret = -ENOMEM;
        goto out;
    }

    irdata = kzalloc(sizeof(*irdata), GFP_KERNEL);
    if (!irdata) {
        ret = -ENOMEM;
        goto out;
    }

    for (i = 0; i < count; i++) {
        cur_sample_len = redrat3_us_to_len(txbuf[i]);
        if (cur_sample_len > 0xffff) {
            dev_warn(dev, "transmit period of %uus truncated to %uus\n",
                     txbuf[i], redrat3_len_to_us(0xffff));
            cur_sample_len = 0xffff;
        }
        for (lencheck = 0; lencheck < curlencheck; lencheck++) {
            if (sample_lens[lencheck] == cur_sample_len)
                break;
        }
        if (lencheck == curlencheck) {
            rr3_dbg(dev, "txbuf[%d]=%u, pos %d, enc %u\n",
                    i, txbuf[i], curlencheck, cur_sample_len);
            if (curlencheck < RR3_DRIVER_MAXLENS) {
                /* now convert the value to a proper
                 * rr3 value.. */
                sample_lens[curlencheck] = cur_sample_len;
                put_unaligned_be16(cur_sample_len,
                                   &irdata->lens[curlencheck]);
                curlencheck++;
            } else {
                ret = -EINVAL;
                goto out;
            }
        }
        irdata->sigdata[i] = lencheck;
    }

    irdata->sigdata[count] = RR3_END_OF_SIGNAL;
    irdata->sigdata[count + 1] = RR3_END_OF_SIGNAL;

    sendbuf_len = offsetof(struct redrat3_irdata,
                           sigdata[count + RR3_TX_TRAILER_LEN]);
    /* fill in our packet header */
    irdata->header.length = cpu_to_be16(sendbuf_len -
                                        sizeof(struct redrat3_header));
    irdata->header.transfer_type = cpu_to_be16(RR3_MOD_SIGNAL_OUT);
    irdata->pause = cpu_to_be32(redrat3_len_to_us(100));
    irdata->mod_freq_count = cpu_to_be16(mod_freq_to_val(rr3->carrier));
    irdata->no_lengths = curlencheck;
    irdata->sig_size = cpu_to_be16(count + RR3_TX_TRAILER_LEN);

    pipe = usb_sndbulkpipe(rr3->udev, rr3->ep_out->bEndpointAddress);
    ret = usb_bulk_msg(rr3->udev, pipe, irdata,
                       sendbuf_len, &ret_len, 10 * HZ);
    rr3_dbg(dev, "sent %d bytes, (ret %d)\n", ret_len, ret);

    /* now tell the hardware to transmit what we sent it */
    pipe = usb_rcvctrlpipe(rr3->udev, 0);
    ret = usb_control_msg(rr3->udev, pipe, RR3_TX_SEND_SIGNAL,
                          USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                          0, 0, irdata, 2, HZ * 10);

    if (ret < 0)
        dev_err(dev, "Error: control msg send failed, rc %d\n", ret);
    else
        ret = count;

out:
    kfree(sample_lens);
    kfree(irdata);

    rr3->transmitting = false;
    /* rr3 re-enables rc detector because it was enabled before */

    return ret;
}
static void redrat3_process_ir_data(struct redrat3_dev *rr3)
{
    DEFINE_IR_RAW_EVENT(rawir);
    struct device *dev;
    unsigned i, trailer = 0;
    unsigned sig_size, single_len, offset, val;
    unsigned long delay;
    u32 mod_freq;

    if (!rr3) {
        pr_err("%s called with no context!\n", __func__);
        return;
    }

    rr3_ftr(rr3->dev, "Entered %s\n", __func__);

    dev = rr3->dev;

    /* Make sure we reset the IR kfifo after a bit of inactivity */
    delay = usecs_to_jiffies(rr3->hw_timeout);
    mod_timer(&rr3->rx_timeout, jiffies + delay);

    mod_freq = redrat3_val_to_mod_freq(&rr3->irdata);
    rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq);

    /* 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);
        /* Save initial pulse length to fudge trailer */
        if (i == 0)
            trailer = rawir.duration;
        /* cap the value to IR_MAX_DURATION */
        rawir.duration &= IR_MAX_DURATION;

        rr3_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, if need be */
    if (i % 2) {
        rawir.pulse = false;
        /* this duration is made up, and may not be ideal... */
        if (trailer < US_TO_NS(1000))
            rawir.duration = US_TO_NS(2800);
        else
            rawir.duration = trailer;
        rr3_dbg(dev, "storing trailing space with duration %d\n",
                rawir.duration);
        ir_raw_event_store_with_filter(rr3->rc, &rawir);
    }

    rr3_dbg(dev, "calling ir_raw_event_handle\n");
    ir_raw_event_handle(rr3->rc);
}
Exemplo n.º 9
0
static void redrat3_process_ir_data(struct redrat3_dev *rr3)
{
	DEFINE_IR_RAW_EVENT(rawir);
	struct redrat3_signal_header header;
	struct device *dev;
	int i;
	unsigned long delay;
	u32 mod_freq, single_len;
	u16 *len_vals;
	u8 *data_vals;
	u32 tmp32;
	u16 tmp16;
	char *sig_data;

	if (!rr3) {
		pr_err("%s called with no context!\n", __func__);
		return;
	}

	rr3_ftr(rr3->dev, "Entered %s\n", __func__);

	dev = rr3->dev;
	sig_data = rr3->pbuf;

	header.length = rr3->pktlen;
	header.transfer_type = rr3->pkttype;

	/* Sanity check */
	if (!(header.length >= RR3_HEADER_LENGTH))
		dev_warn(dev, "read returned less than rr3 header len\n");

	delay = usecs_to_jiffies(rr3->rc->timeout / 1000);
	mod_timer(&rr3->rx_timeout, jiffies + delay);

	memcpy(&tmp32, sig_data + RR3_PAUSE_OFFSET, sizeof(tmp32));
	header.pause = be32_to_cpu(tmp32);

	memcpy(&tmp16, sig_data + RR3_FREQ_COUNT_OFFSET, sizeof(tmp16));
	header.mod_freq_count = be16_to_cpu(tmp16);

	memcpy(&tmp16, sig_data + RR3_NUM_PERIOD_OFFSET, sizeof(tmp16));
	header.no_periods = be16_to_cpu(tmp16);

	header.max_lengths = sig_data[RR3_MAX_LENGTHS_OFFSET];
	header.no_lengths = sig_data[RR3_NUM_LENGTHS_OFFSET];

	memcpy(&tmp16, sig_data + RR3_MAX_SIGS_OFFSET, sizeof(tmp16));
	header.max_sig_size = be16_to_cpu(tmp16);

	memcpy(&tmp16, sig_data + RR3_NUM_SIGS_OFFSET, sizeof(tmp16));
	header.sig_size = be16_to_cpu(tmp16);

	header.no_repeats= sig_data[RR3_REPEATS_OFFSET];

	if (debug) {
		redrat3_dump_signal_header(&header);
		redrat3_dump_signal_data(sig_data, header.sig_size);
	}

	mod_freq = redrat3_val_to_mod_freq(&header);
	rr3_dbg(dev, "Got mod_freq of %u\n", mod_freq);

	/* Here we pull out the 'length' values from the signal */
	len_vals = (u16 *)(sig_data + RR3_HEADER_LENGTH);

	data_vals = sig_data + RR3_HEADER_LENGTH +
		    (header.max_lengths * sizeof(u16));

	/* process each rr3 encoded byte into an int */
	for (i = 0; i < header.sig_size; i++) {
		u16 val = len_vals[data_vals[i]];
		single_len = redrat3_len_to_us((u32)be16_to_cpu(val));

		/* cap the value to IR_MAX_DURATION */
		single_len &= IR_MAX_DURATION;

		/* 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);
		rr3_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, if need be */
	if (i % 2) {
		rawir.pulse = false;
		/* this duration is made up, and may not be ideal... */
		rawir.duration = rr3->rc->timeout / 2;
		rr3_dbg(dev, "storing trailing space with duration %d\n",
			rawir.duration);
		ir_raw_event_store_with_filter(rr3->rc, &rawir);
	}

	rr3_dbg(dev, "calling ir_raw_event_handle\n");
	ir_raw_event_handle(rr3->rc);

	return;
}