Index: uvc_queue.c =================================================================== --- uvc_queue.c (revision 139) +++ uvc_queue.c (working copy) @@ -81,241 +81,119 @@ void uvc_queue_init(struct uvc_video_queue *queue) { mutex_init(&queue->mutex); - spin_lock_init(&queue->irqlock); - INIT_LIST_HEAD(&queue->mainqueue); INIT_LIST_HEAD(&queue->irqqueue); } -/* - * Allocate the video buffers. - * - * Pages are reserved to make sure they will not be swaped, as they will be - * filled in URB completion handler. - * - * Buffers will be individually mapped, so they must all be page aligned. - */ -int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, - unsigned int buflength) +static int buffer_setup(struct videobuf_queue *q, unsigned int *count, + unsigned int *size) { - unsigned int bufsize = PAGE_ALIGN(buflength); - unsigned int i; - void *mem = NULL; - int ret; + struct uvc_fh *fh = q->priv_data; + struct uvc_video_device *dev = fh->device; - if (nbuffers > UVC_MAX_VIDEO_BUFFERS) - nbuffers = UVC_MAX_VIDEO_BUFFERS; + if (*count > UVC_MAX_VIDEO_BUFFERS) + *count = UVC_MAX_VIDEO_BUFFERS; - mutex_lock(&queue->mutex); + *size = dev->streaming->ctrl.dwMaxVideoFrameSize; - if ((ret = uvc_free_buffers(queue)) < 0) - goto done; + return 0; +} - /* Decrement the number of buffers until allocation succeeds. */ - for (; nbuffers > 0; --nbuffers) { - mem = vmalloc_32(nbuffers * bufsize); - if (mem != NULL) - break; - } - if (mem == NULL) { - ret = -ENOMEM; - goto done; - } +static void free_buffer(struct videobuf_queue *vq, struct uvc_buffer *buf) +{ + if (in_interrupt()) + BUG(); - for (i = 0; i < nbuffers; ++i) { - memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); - queue->buffer[i].size = bufsize; - queue->buffer[i].buf.index = i; - queue->buffer[i].buf.m.offset = i * bufsize; - queue->buffer[i].buf.length = buflength; - queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - queue->buffer[i].buf.sequence = 0; - queue->buffer[i].buf.field = V4L2_FIELD_NONE; - queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; - queue->buffer[i].buf.flags = 0; - init_waitqueue_head(&queue->buffer[i].wait); - } - - queue->mem = mem; - queue->count = nbuffers; - ret = nbuffers; - -done: - mutex_unlock(&queue->mutex); - return ret; + videobuf_waiton(&buf->vb, 0, 0); + videobuf_vmalloc_free(&buf->vb); + buf->vb.state = STATE_NEEDS_INIT; } /* - * Free the video buffers. - * - * This function must be called with the queue lock held. + * Queue a video buffer. Attempting to queue a buffer that has already been + * queued will return -EINVAL. */ -int uvc_free_buffers(struct uvc_video_queue *queue) +static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) { - unsigned int i; + struct uvc_fh *fh = q->priv_data; + struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, vb); + struct uvc_video_device *vdev = fh->device; + //struct uvc_device *dev = vdev->dev; + struct uvc_video_queue *queue = &vdev->queue; - for (i = 0; i < queue->count; ++i) { - if (queue->buffer[i].vma_use_count != 0) - return -EBUSY; - } + uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %p.\n", &buf->vb); + printk("Queuing buffer %p.\n", &buf->vb); - if (queue->count) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - unsigned long addr = (unsigned long)queue->mem; - size_t size = queue->count * queue->buffer[0].size; - while (size > 0) { - ClearPageReserved(vmalloc_to_page((void*)addr)); - addr += PAGE_SIZE; - size -= PAGE_SIZE; - } -#endif - vfree(queue->mem); - queue->count = 0; +/* + if (vb->state != UVC_BUF_STATE_IDLE) { + uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " + "(%u).\n", buf->vb.state); + return -EINVAL; } +*/ - return 0; + buf->vb.state = UVC_BUF_STATE_QUEUED; + buf->vb.size = 0; + list_add_tail(&buf->vb.queue, &queue->irqqueue); } -void uvc_query_buffer(struct uvc_buffer *buf, - struct v4l2_buffer *v4l2_buf) +static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, + enum v4l2_field field) { - memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); + struct uvc_fh *fh = q->priv_data; + struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, vb); + struct uvc_video_device *dev = fh->device; + int ret = 0; - if(buf->vma_use_count) - v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; + vb->size = dev->streaming->ctrl.dwMaxVideoFrameSize; + if (buf->vb.baddr != 0 && buf->vb.bsize < buf->vb.size) + return -EINVAL; - switch (buf->state) { - case UVC_BUF_STATE_ERROR: - case UVC_BUF_STATE_DONE: - v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; - break; - case UVC_BUF_STATE_QUEUED: - case UVC_BUF_STATE_ACTIVE: - v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; - break; - case UVC_BUF_STATE_IDLE: - default: - break; + if (buf->format != dev->streaming->cur_format) { + buf->format = dev->streaming->cur_format; + buf->vb.state = STATE_NEEDS_INIT; } -} + + if (buf->vb.state == STATE_NEEDS_INIT) { + ret = videobuf_iolock(q, &buf->vb, NULL); + if (ret != 0) + goto fail; + } -/* - * Queue a video buffer. Attempting to queue a buffer that has already been - * queued will return -EINVAL. - */ -int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf) -{ - struct uvc_buffer *buf; - unsigned long flags; - int ret = 0; + /* TODO: WTF. Size is used as bytesused and the buffer allocation + * size, this needs to be cleaned up */ - uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); + vb->size = 0; - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - v4l2_buf->memory != V4L2_MEMORY_MMAP) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " - "and/or memory (%u).\n", v4l2_buf->type, - v4l2_buf->memory); - return -EINVAL; - } + /* TODO: Only needs to happen once */ + //uvc_video_enable(dev, 1); - mutex_lock(&queue->mutex); - if (v4l2_buf->index >= queue->count) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); - ret = -EINVAL; - goto done; - } + buf->vb.state = STATE_PREPARED; + buffer_queue(q, vb); - buf = &queue->buffer[v4l2_buf->index]; - if (buf->state != UVC_BUF_STATE_IDLE) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " - "(%u).\n", buf->state); - ret = -EINVAL; - goto done; - } + return 0; - buf->state = UVC_BUF_STATE_QUEUED; - buf->buf.bytesused = 0; - list_add_tail(&buf->stream, &queue->mainqueue); - spin_lock_irqsave(&queue->irqlock, flags); - list_add_tail(&buf->queue, &queue->irqqueue); - spin_unlock_irqrestore(&queue->irqlock, flags); - -done: - mutex_unlock(&queue->mutex); +fail: + free_buffer(q, buf); return ret; } -static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) -{ - if (nonblocking) { - return (buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE) - ? 0 : -EAGAIN; - } - return wait_event_interruptible(buf->wait, - buf->state != UVC_BUF_STATE_QUEUED && - buf->state != UVC_BUF_STATE_ACTIVE); -} -/* - * Dequeue a video buffer. If nonblocking is false, block until a buffer is - * available. - */ -int uvc_dequeue_buffer(struct uvc_video_queue *queue, - struct v4l2_buffer *v4l2_buf, int nonblocking) +static void buffer_release(struct videobuf_queue *vq, struct videobuf_buffer *vb) { - struct uvc_buffer *buf; - int ret = 0; + struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, vb); + free_buffer(vq, buf); +} - if (v4l2_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - v4l2_buf->memory != V4L2_MEMORY_MMAP) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " - "and/or memory (%u).\n", v4l2_buf->type, - v4l2_buf->memory); - return -EINVAL; - } +struct videobuf_queue_ops uvc_video_qops = { + .buf_setup = buffer_setup, + .buf_prepare = buffer_prepare, + .buf_queue = buffer_queue, + .buf_release = buffer_release, +}; - mutex_lock(&queue->mutex); - if (list_empty(&queue->mainqueue)) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); - ret = -EINVAL; - goto done; - } - buf = list_entry(queue->mainqueue.next, struct uvc_buffer, stream); - uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u.\n", buf->buf.index); - if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) - goto done; - - switch (buf->state) { - case UVC_BUF_STATE_ERROR: - uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " - "(transmission error).\n"); - ret = -EIO; - case UVC_BUF_STATE_DONE: - buf->state = UVC_BUF_STATE_IDLE; - break; - - case UVC_BUF_STATE_IDLE: - case UVC_BUF_STATE_QUEUED: - case UVC_BUF_STATE_ACTIVE: - default: - uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " - "(driver bug?).\n", buf->state); - ret = -EINVAL; - goto done; - } - - list_del(&buf->stream); - uvc_query_buffer(buf, v4l2_buf); - -done: - mutex_unlock(&queue->mutex); - return ret; -} - /* * Enable or disable the video buffers queue. * @@ -353,10 +231,9 @@ } else { uvc_queue_cancel(queue); - INIT_LIST_HEAD(&queue->mainqueue); for (i = 0; i < queue->count; ++i) - queue->buffer[i].state = UVC_BUF_STATE_IDLE; + queue->buffer[i].vb.state = UVC_BUF_STATE_IDLE; queue->streaming = 0; } @@ -378,37 +255,37 @@ void uvc_queue_cancel(struct uvc_video_queue *queue) { struct uvc_buffer *buf; + struct uvc_video_device *dev = container_of(queue, struct uvc_video_device, queue); unsigned long flags; - spin_lock_irqsave(&queue->irqlock, flags); + // TODO: Check locking on this + //spin_lock_irqsave(&dev->irqlock, flags); while (!list_empty(&queue->irqqueue)) { - buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue); - list_del(&buf->queue); - buf->state = UVC_BUF_STATE_ERROR; - wake_up(&buf->wait); + buf = list_entry(queue->irqqueue.next, struct uvc_buffer, vb.queue); + list_del(&buf->vb.queue); + buf->vb.state = UVC_BUF_STATE_ERROR; + wake_up(&buf->vb.done); } - spin_unlock_irqrestore(&queue->irqlock, flags); + //spin_unlock_irqrestore(&dev->irqlock, flags); } struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { struct uvc_buffer *nextbuf; - unsigned long flags; - spin_lock_irqsave(&queue->irqlock, flags); - list_del(&buf->queue); + list_del(&buf->vb.queue); if (!list_empty(&queue->irqqueue)) nextbuf = list_entry(queue->irqqueue.next, struct uvc_buffer, - queue); + vb.queue); else nextbuf = NULL; - spin_unlock_irqrestore(&queue->irqlock, flags); - buf->buf.sequence = queue->sequence++; - do_gettimeofday(&buf->buf.timestamp); + //buf->buf.sequence = queue->sequence++; + do_gettimeofday(&buf->vb.ts); - wake_up(&buf->wait); + printk("waking up with buf %p, state %i\n", buf, buf->vb.state); + wake_up(&buf->vb.done); return nextbuf; } Index: uvc_video.c =================================================================== --- uvc_video.c (revision 139) +++ uvc_video.c (working copy) @@ -299,7 +299,7 @@ * queue->last_fid is initialized to -1, so the first isochronous * frame will always be in sync. */ - if (buf->state != UVC_BUF_STATE_ACTIVE) { + if (buf->vb.state != UVC_BUF_STATE_ACTIVE) { if (fid == queue->last_fid) { uvc_trace(UVC_TRACE_FRAME, "Dropping payload (out of " "sync).\n"); @@ -307,7 +307,7 @@ } /* TODO: Handle PTS and SCR. */ - buf->state = UVC_BUF_STATE_ACTIVE; + buf->vb.state = UVC_BUF_STATE_ACTIVE; } /* Mark the buffer as done if we're at the beginning of a new frame. @@ -325,10 +325,10 @@ * avoids detecting and of frame conditions at FID toggling if the * previous payload had the EOF bit set. */ - if (fid != queue->last_fid && buf->buf.bytesused != 0) { + if (fid != queue->last_fid && buf->vb.size != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " "toggled).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->vb.state = UVC_BUF_STATE_DONE; return -EAGAIN; } @@ -347,16 +347,16 @@ return; /* Copy the video data to the buffer. */ - maxlen = buf->buf.length - buf->buf.bytesused; - mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; + maxlen = buf->vb.bsize - buf->vb.size; + mem = videobuf_to_vmalloc(&buf->vb) + buf->vb.size; nbytes = min((unsigned int)len, maxlen); memcpy(mem, data, nbytes); - buf->buf.bytesused += nbytes; + buf->vb.size += nbytes; /* Complete the current frame if the buffer size was exceeded. */ if (len > maxlen) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (overflow).\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->vb.state = UVC_BUF_STATE_DONE; } } @@ -364,11 +364,11 @@ struct uvc_buffer *buf, const __u8 *data, int len) { /* Mark the buffer as done if the EOF marker is set. */ - if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) { + if (data[1] & UVC_STREAM_EOF && buf->vb.size != 0) { uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); if (data[0] == len) uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); - buf->state = UVC_BUF_STATE_DONE; + buf->vb.state = UVC_BUF_STATE_DONE; } } @@ -484,8 +484,8 @@ /* Process the header again. */ uvc_video_decode_end(queue, buf, mem, ret); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->vb.state == UVC_BUF_STATE_DONE || + buf->vb.state == UVC_BUF_STATE_ERROR) buf = uvc_queue_next_buffer(queue, buf); } } @@ -540,8 +540,8 @@ if (!queue->bulk.skip_payload && buf != NULL) { uvc_video_decode_end(queue, buf, queue->bulk.header, queue->bulk.header_size); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) + if (buf->vb.state == UVC_BUF_STATE_DONE || + buf->vb.state == UVC_BUF_STATE_ERROR) buf = uvc_queue_next_buffer(queue, buf); } @@ -558,6 +558,7 @@ #endif { struct uvc_video_queue *queue = urb->context; + struct uvc_video_device *dev = container_of(queue, struct uvc_video_device, queue); struct uvc_buffer *buf = NULL; unsigned long flags; int ret; @@ -580,10 +581,10 @@ return; } - spin_lock_irqsave(&queue->irqlock, flags); + spin_lock_irqsave(&dev->irqlock, flags); if (!list_empty(&queue->irqqueue)) - buf = list_entry(queue->irqqueue.next, struct uvc_buffer, queue); - spin_unlock_irqrestore(&queue->irqlock, flags); + buf = list_entry(queue->irqqueue.next, struct uvc_buffer, vb.queue); + spin_unlock_irqrestore(&dev->irqlock, flags); if (urb->number_of_packets) uvc_video_complete_isoc(urb, queue, buf); Index: uvc_v4l2.c =================================================================== --- uvc_v4l2.c (revision 139) +++ uvc_v4l2.c (working copy) @@ -426,6 +426,13 @@ kref_get(&video->dev->kref); + spin_lock_init(&video->irqlock); + + videobuf_queue_vmalloc_init(&handle->device->dev->vidq, &uvc_video_qops, + NULL, &video->irqlock, V4L2_BUF_TYPE_VIDEO_CAPTURE, + V4L2_FIELD_NONE, + sizeof(struct uvc_buffer), handle); + done: mutex_unlock(&uvc_driver.open_mutex); return ret; @@ -442,12 +449,7 @@ /* Only free resources if this is a privileged handle. */ if (uvc_has_privileges(handle)) { uvc_video_enable(video, 0); - - mutex_lock(&video->queue.mutex); - if (uvc_free_buffers(&video->queue) < 0) - uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " - "free buffers.\n"); - mutex_unlock(&video->queue.mutex); + videobuf_mmap_free(&video->dev->vidq); } /* Release the file handle. */ @@ -813,7 +815,6 @@ case VIDIOC_REQBUFS: { struct v4l2_requestbuffers *rb = arg; - unsigned int bufsize = video->streaming->ctrl.dwMaxVideoFrameSize; if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || rb->memory != V4L2_MEMORY_MMAP) @@ -822,28 +823,18 @@ if ((ret = uvc_acquire_privileges(handle)) < 0) return ret; - if ((ret = uvc_alloc_buffers(&video->queue, rb->count, bufsize)) < 0) - return ret; - - rb->count = ret; - ret = 0; + return videobuf_reqbufs(&video->dev->vidq, arg); } break; case VIDIOC_QUERYBUF: { - struct v4l2_buffer *buf = arg; - struct uvc_buffer *ubuf; + //struct v4l2_buffer *buf = arg; - if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - buf->index >= video->queue.count) - return -EINVAL; - if (!uvc_has_privileges(handle)) return -EBUSY; - ubuf = &video->queue.buffer[buf->index]; - uvc_query_buffer(ubuf, buf); + return (videobuf_querybuf(&video->dev->vidq, arg)); } break; @@ -851,15 +842,14 @@ if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_queue_buffer(&video->queue, - (struct v4l2_buffer*)arg); + return (videobuf_qbuf(&video->dev->vidq, arg)); case VIDIOC_DQBUF: if (!uvc_has_privileges(handle)) return -EBUSY; - return uvc_dequeue_buffer(&video->queue, - (struct v4l2_buffer*)arg, file->f_flags & O_NONBLOCK); + return (videobuf_dqbuf(&video->dev->vidq, arg, + file->f_flags & O_NONBLOCK)); case VIDIOC_STREAMON: { @@ -873,6 +863,8 @@ if ((ret = uvc_video_enable(video, 1)) < 0) return ret; + + return (videobuf_streamon(&video->dev->vidq)); } break; @@ -979,109 +971,33 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data, size_t count, loff_t *ppos) { + struct video_device *vdev = video_devdata(file); + struct uvc_video_device *video = video_get_drvdata(vdev); + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_read: not implemented.\n"); - return -ENODEV; -} -/* - * VMA operations. - */ -static void uvc_vm_open(struct vm_area_struct *vma) -{ - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count++; + return videobuf_read_stream(&video->dev->vidq, data, count, ppos, 0, + file->f_flags & O_NONBLOCK); } -static void uvc_vm_close(struct vm_area_struct *vma) -{ - struct uvc_buffer *buffer = vma->vm_private_data; - buffer->vma_use_count--; -} - -static struct vm_operations_struct uvc_vm_ops = { - .open = uvc_vm_open, - .close = uvc_vm_close, -}; - static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) { struct video_device *vdev = video_devdata(file); struct uvc_video_device *video = video_get_drvdata(vdev); - struct uvc_buffer *buffer = NULL; - struct page *page; - unsigned long addr, start, size; - unsigned int i; - int ret = 0; - uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); - - start = vma->vm_start; - size = vma->vm_end - vma->vm_start; - - mutex_lock(&video->queue.mutex); - - for (i = 0; i < video->queue.count; ++i) { - if ((video->queue.buffer[i].buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) { - buffer = &video->queue.buffer[i]; - break; - } - } - - if (buffer == NULL || size != buffer->size) { - ret = -EINVAL; - goto done; - } - - /* - * VM_IO marks the area as being an mmaped region for I/O to a - * device. It also prevents the region from being core dumped. - */ - vma->vm_flags |= VM_IO; - - addr = (unsigned long)video->queue.mem + buffer->buf.m.offset; - while (size > 0) { - page = vmalloc_to_page((void*)addr); - if ((ret = vm_insert_page(vma, start, page)) < 0) - goto done; - - start += PAGE_SIZE; - addr += PAGE_SIZE; - size -= PAGE_SIZE; - } - - vma->vm_ops = &uvc_vm_ops; - vma->vm_private_data = buffer; - uvc_vm_open(vma); - -done: - mutex_unlock(&video->queue.mutex); - return ret; + return videobuf_mmap_mapper(&video->dev->vidq, vma); } static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) { struct video_device *vdev = video_devdata(file); struct uvc_video_device *video = video_get_drvdata(vdev); - struct uvc_buffer *buf; - unsigned int mask = 0; + //struct uvc_buffer *buf; + //unsigned int mask = 0; uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_poll\n"); - mutex_lock(&video->queue.mutex); - if (list_empty(&video->queue.mainqueue)) { - mask |= POLLERR; - goto done; - } - buf = list_entry(video->queue.mainqueue.next, struct uvc_buffer, stream); - - poll_wait(file, &buf->wait, wait); - if (buf->state == UVC_BUF_STATE_DONE || - buf->state == UVC_BUF_STATE_ERROR) - mask |= POLLIN | POLLRDNORM; - -done: - mutex_unlock(&video->queue.mutex); - return mask; + return videobuf_poll_stream(file, &video->dev->vidq, wait); } struct file_operations uvc_fops = { Index: uvc_driver.c =================================================================== --- uvc_driver.c (revision 139) +++ uvc_driver.c (working copy) @@ -700,6 +700,7 @@ for (i = 0; i < intf->num_altsetting; ++i) { struct usb_host_endpoint *ep; alts = &intf->altsetting[i]; + printk("streaming: %p\n", streaming); ep = uvc_find_endpoint(alts, streaming->input.bEndpointAddress); if (ep == NULL) @@ -1433,7 +1434,6 @@ vdev->dev = &dev->udev->dev; vdev->type = 0; vdev->type2 = 0; - vdev->hardware = 0; vdev->minor = -1; vdev->fops = &uvc_fops; vdev->release = video_device_release; Index: uvcvideo.h =================================================================== --- uvcvideo.h (revision 139) +++ uvcvideo.h (working copy) @@ -2,7 +2,9 @@ #define _USB_VIDEO_H_ #include +#include #include +#include /* Compatibility */ #include "uvc_compat.h" @@ -533,6 +535,7 @@ struct mutex mutex; }; +/* enum uvc_buffer_state { UVC_BUF_STATE_IDLE = 0, UVC_BUF_STATE_QUEUED = 1, @@ -540,17 +543,33 @@ UVC_BUF_STATE_DONE = 3, UVC_BUF_STATE_ERROR = 4, }; +*/ +enum uvc_buffer_state { + UVC_BUF_STATE_NEEDS_INIT = 0, + UVC_BUF_STATE_PREPARED = 1, + UVC_BUF_STATE_QUEUED = 2, + UVC_BUF_STATE_ACTIVE = 3, + UVC_BUF_STATE_DONE = 4, + UVC_BUF_STATE_ERROR = 5, + UVC_BUF_STATE_IDLE = 6, +}; + + struct uvc_buffer { - unsigned int size; - unsigned long vma_use_count; - struct list_head stream; + struct videobuf_buffer vb; + struct uvc_format *format; + +// unsigned int size; +// unsigned long vma_use_count; +// struct list_head stream; + /* Touched by interrupt handler. */ - struct v4l2_buffer buf; - struct list_head queue; - wait_queue_head_t wait; - enum uvc_buffer_state state; +// struct v4l2_buffer buf; +// struct list_head queue; +// wait_queue_head_t wait; /* &buf->vb.done */ +// enum uvc_buffer_state state; }; struct uvc_video_queue { @@ -572,9 +591,7 @@ unsigned int count; struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; struct mutex mutex; - spinlock_t irqlock; - struct list_head mainqueue; struct list_head irqqueue; }; @@ -597,6 +614,7 @@ struct urb *urb[UVC_URBS]; char *urb_buffer[UVC_URBS]; + spinlock_t irqlock; }; enum uvc_device_state { @@ -628,6 +646,7 @@ /* Video Streaming interfaces */ struct list_head streaming; + struct videobuf_queue vidq; }; enum uvc_handle_state { @@ -665,6 +684,7 @@ #define UVC_TRACE_SUSPEND (1 << 8) extern unsigned int uvc_trace_param; +extern struct videobuf_queue_ops uvc_video_qops; #define uvc_trace(flag, msg...) \ do { \