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_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;
}
Exemple #3
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;
}