Beispiel #1
0
int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{
	int ret = -EINVAL;

	videobuf_queue_lock(q);
	if (unlikely(b->type != q->type)) {
		dprintk(1, "querybuf: Wrong type.\n");
		goto done;
	}
	if (unlikely(b->index >= VIDEO_MAX_FRAME)) {
		dprintk(1, "querybuf: index out of range.\n");
		goto done;
	}
	if (unlikely(NULL == q->bufs[b->index])) {
		dprintk(1, "querybuf: buffer is null.\n");
		goto done;
	}

	videobuf_status(q, b, q->bufs[b->index], q->type);

	ret = 0;
done:
	videobuf_queue_unlock(q);
	return ret;
}
static void videobuf_vm_close(struct vm_area_struct *vma)
{
	struct videobuf_mapping *map = vma->vm_private_data;
	struct videobuf_queue *q = map->q;
	struct videobuf_dma_sg_memory *mem;
	int i;

	dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map,
		map->count, vma->vm_start, vma->vm_end);

	map->count--;
	if (0 == map->count) {
		dprintk(1, "munmap %p q=%p\n", map, q);
		videobuf_queue_lock(q);
		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
			if (NULL == q->bufs[i])
				continue;
			mem = q->bufs[i]->priv;
			if (!mem)
				continue;

			MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);

			if (q->bufs[i]->map != map)
				continue;
			q->bufs[i]->map   = NULL;
			q->bufs[i]->baddr = 0;
			q->ops->buf_release(q, q->bufs[i]);
		}
		videobuf_queue_unlock(q);
		kfree(map);
	}
	return;
}
Beispiel #3
0
int videobuf_streamon(struct videobuf_queue *q)
{
	struct videobuf_buffer *buf;
	unsigned long flags = 0;
	int retval;

	videobuf_queue_lock(q);
	retval = -EBUSY;
	if (q->reading)
		goto done;
	retval = 0;
	if (q->streaming)
		goto done;
	q->streaming = 1;
	spin_lock_irqsave(q->irqlock, flags);
	list_for_each_entry(buf, &q->stream, stream)
		if (buf->state == VIDEOBUF_PREPARED)
			q->ops->buf_queue(q, buf);
	spin_unlock_irqrestore(q->irqlock, flags);

	wake_up_interruptible_sync(&q->wait);
done:
	videobuf_queue_unlock(q);
	return retval;
}
Beispiel #4
0
int videobuf_reqbufs(struct videobuf_queue *q,
		 struct v4l2_requestbuffers *req)
{
	unsigned int size, count;
	int retval;

	if (req->memory != V4L2_MEMORY_MMAP     &&
	    req->memory != V4L2_MEMORY_USERPTR  &&
	    req->memory != V4L2_MEMORY_OVERLAY) {
		dprintk(1, "reqbufs: memory type invalid\n");
		return -EINVAL;
	}

	videobuf_queue_lock(q);
	if (req->type != q->type) {
		dprintk(1, "reqbufs: queue type invalid\n");
		retval = -EINVAL;
		goto done;
	}

	if (q->streaming) {
		dprintk(1, "reqbufs: streaming already exists\n");
		retval = -EBUSY;
		goto done;
	}
	if (!list_empty(&q->stream)) {
		dprintk(1, "reqbufs: stream running\n");
		retval = -EBUSY;
		goto done;
	}

	if (req->count == 0) {
		dprintk(1, "reqbufs: count invalid (%d)\n", req->count);
		retval = __videobuf_free(q);
		goto done;
	}

	count = req->count;
	if (count > VIDEO_MAX_FRAME)
		count = VIDEO_MAX_FRAME;
	size = 0;
	q->ops->buf_setup(q, &count, &size);
	dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n",
		count, size,
		(unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT));

	retval = __videobuf_mmap_setup(q, count, size, req->memory);
	if (retval < 0) {
		dprintk(1, "reqbufs: mmap setup returned %d\n", retval);
		goto done;
	}

	req->count = retval;
	retval = 0;

 done:
	videobuf_queue_unlock(q);
	return retval;
}
Beispiel #5
0
int videobuf_mmap_free(struct videobuf_queue *q)
{
	int ret;
	videobuf_queue_lock(q);
	ret = __videobuf_free(q);
	videobuf_queue_unlock(q);
	return ret;
}
static void videobuf_vm_close(struct vm_area_struct *vma)
{
	struct videobuf_mapping *map = vma->vm_private_data;
	struct videobuf_queue *q = map->q;
	int i;

	dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
		map->count, vma->vm_start, vma->vm_end);

	map->count--;
	if (0 == map->count) {
		struct videobuf_vmalloc_memory *mem;

		dprintk(1, "munmap %p q=%p\n", map, q);
		videobuf_queue_lock(q);

		/*                                                   */
		if (q->streaming)
			videobuf_queue_cancel(q);

		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
			if (NULL == q->bufs[i])
				continue;

			if (q->bufs[i]->map != map)
				continue;

			mem = q->bufs[i]->priv;
			if (mem) {
				/*                                           
                                                   
                                            
                                   
     */

				MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);

				/*                               
                                 
     */
				dprintk(1, "%s: buf[%d] freeing (%p)\n",
					__func__, i, mem->vaddr);

				vfree(mem->vaddr);
				mem->vaddr = NULL;
			}

			q->bufs[i]->map   = NULL;
			q->bufs[i]->baddr = 0;
		}

		kfree(map);

		videobuf_queue_unlock(q);
	}

	return;
}
Beispiel #7
0
static void videobuf_vm_close(struct vm_area_struct *vma)
{
	struct videobuf_mapping *map = vma->vm_private_data;
	struct videobuf_queue *q = map->q;
	int i;

	dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
		map->count, vma->vm_start, vma->vm_end);

	map->count--;
	if (0 == map->count) {
		struct videobuf_vmalloc_memory *mem;

		dprintk(1, "munmap %p q=%p\n", map, q);
		videobuf_queue_lock(q);

		/* We need first to cancel streams, before unmapping */
		if (q->streaming)
			videobuf_queue_cancel(q);

		for (i = 0; i < VIDEO_MAX_FRAME; i++) {
			if (NULL == q->bufs[i])
				continue;

			if (q->bufs[i]->map != map)
				continue;

			mem = q->bufs[i]->priv;
			if (mem) {
				/* This callback is called only if kernel has
				   allocated memory and this memory is mmapped.
				   In this case, memory should be freed,
				   in order to do memory unmap.
				 */

				MAGIC_CHECK(mem->magic, MAGIC_VMAL_MEM);

				/* vfree is not atomic - can't be
				   called with IRQ's disabled
				 */
				dprintk(1, "%s: buf[%d] freeing (%p)\n",
					__func__, i, mem->vaddr);

				vfree(mem->vaddr);
				mem->vaddr = NULL;
			}

			q->bufs[i]->map   = NULL;
			q->bufs[i]->baddr = 0;
		}

		kfree(map);

		videobuf_queue_unlock(q);
	}

	return;
}
Beispiel #8
0
int videobuf_streamoff(struct videobuf_queue *q)
{
	int retval;

	videobuf_queue_lock(q);
	retval = __videobuf_streamoff(q);
	videobuf_queue_unlock(q);

	return retval;
}
Beispiel #9
0
int videobuf_mmap_setup(struct videobuf_queue *q,
			unsigned int bcount, unsigned int bsize,
			enum v4l2_memory memory)
{
	int ret;
	videobuf_queue_lock(q);
	ret = __videobuf_mmap_setup(q, bcount, bsize, memory);
	videobuf_queue_unlock(q);
	return ret;
}
Beispiel #10
0
int videobuf_read_start(struct videobuf_queue *q)
{
	int rc;

	videobuf_queue_lock(q);
	rc = __videobuf_read_start(q);
	videobuf_queue_unlock(q);

	return rc;
}
/* Locking: Caller holds q->vb_lock */
static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
{
	int retval;
    bool is_ext_locked;

checks:
	if (!q->streaming) {
		dprintk(1, "next_buffer: Not streaming\n");
		retval = -EINVAL;
		goto done;
	}

	if (list_empty(&q->stream)) {
		if (noblock) {
			retval = -EAGAIN;
			dprintk(2, "next_buffer: no buffers to dequeue\n");
			goto done;
		} else {
			dprintk(2, "next_buffer: waiting on buffer\n");

			/* Drop lock to avoid deadlock with qbuf */            
            videobuf_queue_unlock(q);
            /*[email protected] */
            is_ext_locked = q->ext_lock && mutex_is_locked(q->ext_lock);

        	/* Release vdev lock to prevent this wait from blocking outside access to
        	   the device. */
        	if (is_ext_locked)
        		mutex_unlock(q->ext_lock);
            
            
			/* Checking list_empty and streaming is safe without
			 * locks because we goto checks to validate while
			 * holding locks before proceeding */
			retval = wait_event_interruptible(q->wait,
				!list_empty(&q->stream) || !q->streaming);

            videobuf_queue_lock(q);
            /*[email protected] */
            if (is_ext_locked)
        		mutex_lock(q->ext_lock);
            
			if (retval)
				goto done;

			goto checks;
		}
	}

	retval = 0;

done:
	return retval;
}
Beispiel #12
0
void videobuf_stop(struct videobuf_queue *q)
{
	videobuf_queue_lock(q);

	if (q->streaming)
		__videobuf_streamoff(q);

	if (q->reading)
		__videobuf_read_stop(q);

	videobuf_queue_unlock(q);
}
Beispiel #13
0
/* Locking: Caller holds q->vb_lock */
static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock)
{
	int retval;

checks:
	if (!q->streaming) {
		dprintk(1, "next_buffer: Not streaming\n");
		retval = -EINVAL;
		goto done;
	}

	if (list_empty(&q->stream)) {
		if (noblock) {
			retval = -EAGAIN;
			dprintk(2, "next_buffer: no buffers to dequeue\n");
			goto done;
		} else {
			dprintk(2, "next_buffer: waiting on buffer\n");

			/* Drop lock to avoid deadlock with qbuf */
			videobuf_queue_unlock(q);

			/* Checking list_empty and streaming is safe without
			 * locks because we goto checks to validate while
			 * holding locks before proceeding */
			retval = wait_event_interruptible(q->wait,
				!list_empty(&q->stream) || !q->streaming);
			videobuf_queue_lock(q);

			if (retval)
				goto done;

			goto checks;
		}
	}

	retval = 0;

done:
	return retval;
}
Beispiel #14
0
int videobuf_dqbuf(struct videobuf_queue *q,
		   struct v4l2_buffer *b, int nonblocking)
{
	struct videobuf_buffer *buf = NULL;
	int retval;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	memset(b, 0, sizeof(*b));
	videobuf_queue_lock(q);

	retval = stream_next_buffer(q, &buf, nonblocking);
	if (retval < 0) {
		dprintk(1, "dqbuf: next_buffer error: %i\n", retval);
		goto done;
	}

	switch (buf->state) {
	case VIDEOBUF_ERROR:
		dprintk(1, "dqbuf: state is error\n");
		break;
	case VIDEOBUF_DONE:
		dprintk(1, "dqbuf: state is done\n");
		break;
	default:
		dprintk(1, "dqbuf: state invalid\n");
		retval = -EINVAL;
		goto done;
	}
	CALL(q, sync, q, buf);
	videobuf_status(q, b, buf, q->type);
	list_del(&buf->stream);
	buf->state = VIDEOBUF_IDLE;
	b->flags &= ~V4L2_BUF_FLAG_DONE;
done:
	videobuf_queue_unlock(q);
	return retval;
}
Beispiel #15
0
ssize_t videobuf_read_one(struct videobuf_queue *q,
			  char __user *data, size_t count, loff_t *ppos,
			  int nonblocking)
{
	enum v4l2_field field;
	unsigned long flags = 0;
	unsigned size = 0, nbufs = 1;
	int retval;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	videobuf_queue_lock(q);

	q->ops->buf_setup(q, &nbufs, &size);

	if (NULL == q->read_buf  &&
	    count >= size        &&
	    !nonblocking) {
		retval = videobuf_read_zerocopy(q, data, count, ppos);
		if (retval >= 0  ||  retval == -EIO)
			/* ok, all done */
			goto done;
		/* fallback to kernel bounce buffer on failures */
	}

	if (NULL == q->read_buf) {
		/* need to capture a new frame */
		retval = -ENOMEM;
		q->read_buf = videobuf_alloc_vb(q);

		dprintk(1, "video alloc=0x%p\n", q->read_buf);
		if (NULL == q->read_buf)
			goto done;
		q->read_buf->memory = V4L2_MEMORY_USERPTR;
		q->read_buf->bsize = count; /* preferred size */
		field = videobuf_next_field(q);
		retval = q->ops->buf_prepare(q, q->read_buf, field);

		if (0 != retval) {
			kfree(q->read_buf);
			q->read_buf = NULL;
			goto done;
		}

		spin_lock_irqsave(q->irqlock, flags);
		q->ops->buf_queue(q, q->read_buf);
		spin_unlock_irqrestore(q->irqlock, flags);

		q->read_off = 0;
	}

	/* wait until capture is done */
	retval = videobuf_waiton(q, q->read_buf, nonblocking, 1);
	if (0 != retval)
		goto done;

	CALL(q, sync, q, q->read_buf);

	if (VIDEOBUF_ERROR == q->read_buf->state) {
		/* catch I/O errors */
		q->ops->buf_release(q, q->read_buf);
		kfree(q->read_buf);
		q->read_buf = NULL;
		retval = -EIO;
		goto done;
	}

	/* Copy to userspace */
	retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking);
	if (retval < 0)
		goto done;

	q->read_off += retval;
	if (q->read_off == q->read_buf->size) {
		/* all data copied, cleanup */
		q->ops->buf_release(q, q->read_buf);
		kfree(q->read_buf);
		q->read_buf = NULL;
	}

done:
	videobuf_queue_unlock(q);
	return retval;
}
Beispiel #16
0
int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{
	struct videobuf_buffer *buf;
	enum v4l2_field field;
	unsigned long flags = 0;
	int retval;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	if (b->memory == V4L2_MEMORY_MMAP)
		down_read(&current->mm->mmap_sem);

	videobuf_queue_lock(q);
	retval = -EBUSY;
	if (q->reading) {
		dprintk(1, "qbuf: Reading running...\n");
		goto done;
	}
	retval = -EINVAL;
	if (b->type != q->type) {
		dprintk(1, "qbuf: Wrong type.\n");
		goto done;
	}
	if (b->index >= VIDEO_MAX_FRAME) {
		dprintk(1, "qbuf: index out of range.\n");
		goto done;
	}
	buf = q->bufs[b->index];
	if (NULL == buf) {
		dprintk(1, "qbuf: buffer is null.\n");
		goto done;
	}
	MAGIC_CHECK(buf->magic, MAGIC_BUFFER);
	if (buf->memory != b->memory) {
		dprintk(1, "qbuf: memory type is wrong.\n");
		goto done;
	}
	if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) {
		dprintk(1, "qbuf: buffer is already queued or active.\n");
		goto done;
	}

	switch (b->memory) {
	case V4L2_MEMORY_MMAP:
		if (0 == buf->baddr) {
			dprintk(1, "qbuf: mmap requested but buffer addr is zero!\n");
			goto done;
		}
		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
		    || q->type == V4L2_BUF_TYPE_VBI_OUTPUT
		    || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
		    || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) {
			buf->size = b->bytesused;
			buf->field = b->field;
			buf->ts = v4l2_timeval_to_ns(&b->timestamp);
		}
		break;
	case V4L2_MEMORY_USERPTR:
		if (b->length < buf->bsize) {
			dprintk(1, "qbuf: buffer length is not enough\n");
			goto done;
		}
		if (VIDEOBUF_NEEDS_INIT != buf->state &&
		    buf->baddr != b->m.userptr)
			q->ops->buf_release(q, buf);
		buf->baddr = b->m.userptr;
		break;
	case V4L2_MEMORY_OVERLAY:
		buf->boff = b->m.offset;
		break;
	default:
		dprintk(1, "qbuf: wrong memory type\n");
		goto done;
	}

	dprintk(1, "qbuf: requesting next field\n");
	field = videobuf_next_field(q);
	retval = q->ops->buf_prepare(q, buf, field);
	if (0 != retval) {
		dprintk(1, "qbuf: buffer_prepare returned %d\n", retval);
		goto done;
	}

	list_add_tail(&buf->stream, &q->stream);
	if (q->streaming) {
		spin_lock_irqsave(q->irqlock, flags);
		q->ops->buf_queue(q, buf);
		spin_unlock_irqrestore(q->irqlock, flags);
	}
	dprintk(1, "qbuf: succeeded\n");
	retval = 0;
	wake_up_interruptible_sync(&q->wait);

done:
	videobuf_queue_unlock(q);

	if (b->memory == V4L2_MEMORY_MMAP)
		up_read(&current->mm->mmap_sem);

	return retval;
}
Beispiel #17
0
void videobuf_read_stop(struct videobuf_queue *q)
{
	videobuf_queue_lock(q);
	__videobuf_read_stop(q);
	videobuf_queue_unlock(q);
}