/**
 * @brief Dequeue a video buffer.
 *
 * @param queue
 * @param v4l2_buf
 * @param nonblocking
 *
 * @return 0 or negative error code
 *
 * If nonblocking is false, block until a buffer is
 * available.
 */
int microdia_dequeue_buffer(struct microdia_video_queue *queue,
	struct v4l2_buffer *v4l2_buf, int nonblocking)
{
	struct microdia_buffer *buf;
	int ret = 0;

	if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
		UDIA_ERROR("[E] Invalid buffer type (%u) "
			"and/or memory (%u).\n", v4l2_buf->type,
			v4l2_buf->memory);
		return -EINVAL;
	}

	mutex_lock(&queue->mutex);
	if (list_empty(&queue->mainqueue)) {
		UDIA_ERROR("[E] Empty buffer queue.\n");
		ret = -EINVAL;
		goto done;
	}

	buf = list_first_entry(&queue->mainqueue, struct microdia_buffer,
			       stream);

	ret = microdia_queue_waiton(buf, nonblocking);
	if (ret < 0)
		goto done;

	UDIA_DEBUG("Dequeuing buffer %u (%u, %u bytes).\n",
		buf->buf.index, buf->state, buf->buf.bytesused);

	switch (buf->state) {
	case MICRODIA_BUF_STATE_ERROR:
		UDIA_WARNING("[W] Corrupted data (transmission error).\n");
		ret = -EIO;
	case MICRODIA_BUF_STATE_DONE:
		buf->state = MICRODIA_BUF_STATE_IDLE;
		break;

	case MICRODIA_BUF_STATE_IDLE:
	case MICRODIA_BUF_STATE_QUEUED:
	case MICRODIA_BUF_STATE_ACTIVE:
	default:
		UDIA_ERROR("[E] Invalid buffer state %u "
			"(driver bug?).\n", buf->state);
		ret = -EINVAL;
		goto done;
	}

	list_del(&buf->stream);
	__microdia_query_buffer(buf, v4l2_buf);

done:
	mutex_unlock(&queue->mutex);
	return ret;
}
示例#2
0
文件: micron.c 项目: benatto/microdia
int mt9v111_select_address_space(struct usb_sn9c20x *dev, __u8 address_space)
{
	__u8 buf[2];
	int retI2C;
	int k;

	/* check if selection is valid: */
	if ((address_space != MT9V111_ADDRESSSPACE_IFP) &&
		(address_space != MT9V111_ADDRESSSPACE_SENSOR)) {
			UDIA_WARNING("invalid register address space "
				"selection for sensor MT9V111/MI0360SOC !\n");
			return -1;
	}
	/* read address space slection register: */
	k = 0;
	retI2C = -1;
	while ((k < 3) && (retI2C != 0)) {
		retI2C = sn9c20x_read_i2c_data(dev, 2, 0x01, buf);
		if (retI2C != 0 && k < 2)
			udelay(1000);
		k++;
	}
	if (retI2C != 0) {
		UDIA_ERROR("MT9V111/MI0360SOC (I2C-slave 0x5c): "
			"read of reg0x01 (address space selection) failed !\n");
		return -1;
	}
	/* check current address space: */
	if ((buf[0] != 0x00) || (buf[1] != address_space)) {
		k = 0;
		retI2C = -1;
		while ((k < 3) && (retI2C != 0)) {
			/* switch address space: */
			buf[0] = 0x00; buf[1] = address_space;
			retI2C = sn9c20x_write_i2c_data(dev, 2, 0x01, buf);
			if (retI2C != 0 && k < 2)
				udelay(1000);
			k++;
		}
		if (retI2C != 0) {
			if (address_space == MT9V111_ADDRESSSPACE_IFP)
				UDIA_ERROR("MT9V111/MI0360SOC "
					"(I2C-slave 0x5c): switch to IFP "
					"address space failed !\n");
			else
				UDIA_ERROR("MT9V111/MI0360SOC "
					"(I2C-slave 0x5c): switch to sensor "
					"core address space failed !\n");
			return -1;
		}
	}
	return 0;
}