예제 #1
0
static int iguanair_get_features(struct iguanair *ir)
{
	int rc;

	/*
	 * On cold boot, the iguanair initializes on the first packet
	 * received but does not process that packet. Send an empty
	 * packet.
	 */
	ir->packet->header.start = 0;
	ir->packet->header.direction = DIR_OUT;
	ir->packet->header.cmd = CMD_NOP;
	iguanair_send(ir, sizeof(ir->packet->header));

	ir->packet->header.cmd = CMD_GET_VERSION;
	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc) {
		dev_info(ir->dev, "failed to get version\n");
		goto out;
	}

	if (ir->version < 0x205) {
		dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
		rc = -ENODEV;
		goto out;
	}

	ir->bufsize = 150;
	ir->cycle_overhead = 65;

	ir->packet->header.cmd = CMD_GET_BUFSIZE;

	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc) {
		dev_info(ir->dev, "failed to get buffer size\n");
		goto out;
	}

	if (ir->bufsize > BUF_SIZE) {
		dev_info(ir->dev, "buffer size %u larger than expected\n",
								ir->bufsize);
		ir->bufsize = BUF_SIZE;
	}

	ir->packet->header.cmd = CMD_GET_FEATURES;

	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc)
		dev_info(ir->dev, "failed to get features\n");
out:
	return rc;
}
예제 #2
0
static int iguanair_get_features(struct iguanair *ir)
{
	int rc;

	ir->packet->header.start = 0;
	ir->packet->header.direction = DIR_OUT;
	ir->packet->header.cmd = CMD_GET_VERSION;

	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc) {
		dev_info(ir->dev, "failed to get version\n");
		goto out;
	}

	if (ir->version < 0x205) {
		dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
		rc = -ENODEV;
		goto out;
	}

	ir->bufsize = 150;
	ir->cycle_overhead = 65;

	ir->packet->header.cmd = CMD_GET_BUFSIZE;

	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc) {
		dev_info(ir->dev, "failed to get buffer size\n");
		goto out;
	}

	if (ir->bufsize > BUF_SIZE) {
		dev_info(ir->dev, "buffer size %u larger than expected\n",
								ir->bufsize);
		ir->bufsize = BUF_SIZE;
	}

	ir->packet->header.cmd = CMD_GET_FEATURES;

	rc = iguanair_send(ir, sizeof(ir->packet->header));
	if (rc) {
		dev_info(ir->dev, "failed to get features\n");
		goto out;
	}

out:
	return rc;
}
예제 #3
0
static int iguanair_receiver(struct iguanair *ir, bool enable)
{
	ir->packet->header.start = 0;
	ir->packet->header.direction = DIR_OUT;
	ir->packet->header.cmd = enable ? CMD_RECEIVER_ON : CMD_RECEIVER_OFF;

	if (enable)
		ir_raw_event_reset(ir->rc);

	return iguanair_send(ir, sizeof(ir->packet->header));
}
예제 #4
0
static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
{
	struct iguanair *ir = dev->priv;
	uint8_t space;
	unsigned i, size, periods, bytes;
	int rc;

	mutex_lock(&ir->lock);

	/* convert from us to carrier periods */
	for (i = space = size = 0; i < count; i++) {
		periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
		bytes = DIV_ROUND_UP(periods, 127);
		if (size + bytes > ir->bufsize) {
			count = i;
			break;
		}
		while (periods > 127) {
			ir->packet->payload[size++] = 127 | space;
			periods -= 127;
		}

		ir->packet->payload[size++] = periods | space;
		space ^= 0x80;
	}

	if (count == 0) {
		rc = -EINVAL;
		goto out;
	}

	ir->packet->header.start = 0;
	ir->packet->header.direction = DIR_OUT;
	ir->packet->header.cmd = CMD_SEND;
	ir->packet->length = size;

	ir->tx_overflow = false;

	rc = iguanair_send(ir, sizeof(*ir->packet) + size);

	if (rc == 0 && ir->tx_overflow)
		rc = -EOVERFLOW;

out:
	mutex_unlock(&ir->lock);

	return rc ? rc : count;
}
예제 #5
0
static int iguanair_receiver(struct iguanair *ir, bool enable)
{
	struct packet packet = { 0, DIR_OUT, enable ?
				CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
	int rc;

	INIT_COMPLETION(ir->completion);

	rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL);
	if (rc)
		return rc;

	wait_for_completion_timeout(&ir->completion, TIMEOUT);

	return 0;
}
예제 #6
0
static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
{
	struct iguanair *ir = dev->priv;
	uint8_t space, *payload;
	unsigned i, size, rc;
	struct send_packet *packet;

	mutex_lock(&ir->lock);

	/* convert from us to carrier periods */
	for (i = size = 0; i < count; i++) {
		txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
		size += (txbuf[i] + 126) / 127;
	}

	packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
	if (!packet) {
		rc = -ENOMEM;
		goto out;
	}

	if (size > ir->bufsize) {
		rc = -E2BIG;
		goto out;
	}

	packet->header.start = 0;
	packet->header.direction = DIR_OUT;
	packet->header.cmd = CMD_SEND;
	packet->length = size;
	packet->channels = ir->channels << 4;
	packet->busy7 = ir->busy7;
	packet->busy4 = ir->busy4;

	space = 0;
	payload = packet->payload;

	for (i = 0; i < count; i++) {
		unsigned periods = txbuf[i];

		while (periods > 127) {
			*payload++ = 127 | space;
			periods -= 127;
		}

		*payload++ = periods | space;
		space ^= 0x80;
	}

	if (ir->receiver_on) {
		rc = iguanair_receiver(ir, false);
		if (rc) {
			dev_warn(ir->dev, "disable receiver before transmit failed\n");
			goto out;
		}
	}

	ir->tx_overflow = false;

	INIT_COMPLETION(ir->completion);

	rc = iguanair_send(ir, packet, size + 8, NULL, NULL);

	if (rc == 0) {
		wait_for_completion_timeout(&ir->completion, TIMEOUT);
		if (ir->tx_overflow)
			rc = -EOVERFLOW;
	}

	ir->tx_overflow = false;

	if (ir->receiver_on) {
		if (iguanair_receiver(ir, true))
			dev_warn(ir->dev, "re-enable receiver after transmit failed\n");
	}

out:
	mutex_unlock(&ir->lock);
	kfree(packet);

	return rc;
}
예제 #7
0
static int iguanair_get_features(struct iguanair *ir)
{
	struct packet packet;
	struct response_packet response;
	int rc, len;

	packet.start = 0;
	packet.direction = DIR_OUT;
	packet.cmd = CMD_GET_VERSION;

	rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
	if (rc) {
		dev_info(ir->dev, "failed to get version\n");
		goto out;
	}

	if (len != 6) {
		dev_info(ir->dev, "failed to get version\n");
		rc = -EIO;
		goto out;
	}

	ir->version[0] = response.data[0];
	ir->version[1] = response.data[1];
	ir->bufsize = 150;
	ir->cycle_overhead = 65;

	packet.cmd = CMD_GET_BUFSIZE;

	rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
	if (rc) {
		dev_info(ir->dev, "failed to get buffer size\n");
		goto out;
	}

	if (len != 5) {
		dev_info(ir->dev, "failed to get buffer size\n");
		rc = -EIO;
		goto out;
	}

	ir->bufsize = response.data[0];

	if (ir->version[0] == 0 || ir->version[1] == 0)
		goto out;

	packet.cmd = CMD_GET_FEATURES;

	rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
	if (rc) {
		dev_info(ir->dev, "failed to get features\n");
		goto out;
	}

	if (len < 5) {
		dev_info(ir->dev, "failed to get features\n");
		rc = -EIO;
		goto out;
	}

	if (len > 5 && ir->version[0] >= 4)
		ir->cycle_overhead = response.data[1];

out:
	return rc;
}