diff options
Diffstat (limited to 'drivers/usb/gadget/function')
-rw-r--r-- | drivers/usb/gadget/function/f_uvc.c | 40 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc.h | 3 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_queue.c | 79 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_queue.h | 4 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_v4l2.c | 8 | ||||
-rw-r--r-- | drivers/usb/gadget/function/uvc_video.c | 3 |
6 files changed, 41 insertions, 96 deletions
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 76891adfba7a..cf0df8fbba89 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -222,7 +222,7 @@ uvc_function_ep0_complete(struct usb_ep *ep, struct usb_request *req) v4l2_event.type = UVC_EVENT_DATA; uvc_event->data.length = req->actual; memcpy(&uvc_event->data.data, req->buf, req->actual); - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); } } @@ -256,7 +256,7 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_SETUP; memcpy(&uvc_event->req, ctrl, sizeof(uvc_event->req)); - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); return 0; } @@ -315,7 +315,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_CONNECT; uvc_event->speed = cdev->gadget->speed; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; } @@ -343,7 +343,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMOFF; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_CONNECTED; return 0; @@ -370,7 +370,7 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMON; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); return USB_GADGET_DELAYED_STATUS; default: @@ -388,7 +388,7 @@ uvc_function_disable(struct usb_function *f) memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_DISCONNECT; - v4l2_event_queue(uvc->vdev, &v4l2_event); + v4l2_event_queue(&uvc->vdev, &v4l2_event); uvc->state = UVC_STATE_DISCONNECTED; @@ -435,24 +435,19 @@ static int uvc_register_video(struct uvc_device *uvc) { struct usb_composite_dev *cdev = uvc->func.config->cdev; - struct video_device *video; /* TODO reference counting. */ - video = video_device_alloc(); - if (video == NULL) - return -ENOMEM; + uvc->vdev.v4l2_dev = &uvc->v4l2_dev; + uvc->vdev.fops = &uvc_v4l2_fops; + uvc->vdev.ioctl_ops = &uvc_v4l2_ioctl_ops; + uvc->vdev.release = video_device_release_empty; + uvc->vdev.vfl_dir = VFL_DIR_TX; + uvc->vdev.lock = &uvc->video.mutex; + strlcpy(uvc->vdev.name, cdev->gadget->name, sizeof(uvc->vdev.name)); - video->v4l2_dev = &uvc->v4l2_dev; - video->fops = &uvc_v4l2_fops; - video->ioctl_ops = &uvc_v4l2_ioctl_ops; - video->release = video_device_release; - video->vfl_dir = VFL_DIR_TX; - strlcpy(video->name, cdev->gadget->name, sizeof(video->name)); + video_set_drvdata(&uvc->vdev, uvc); - uvc->vdev = video; - video_set_drvdata(video, uvc); - - return video_register_device(video, VFL_TYPE_GRABBER, -1); + return video_register_device(&uvc->vdev, VFL_TYPE_GRABBER, -1); } #define UVC_COPY_DESCRIPTOR(mem, dst, desc) \ @@ -765,8 +760,6 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) error: v4l2_device_unregister(&uvc->v4l2_dev); - if (uvc->vdev) - video_device_release(uvc->vdev); if (uvc->control_ep) uvc->control_ep->driver_data = NULL; @@ -897,7 +890,7 @@ static void uvc_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "%s\n", __func__); - video_unregister_device(uvc->vdev); + video_unregister_device(&uvc->vdev); v4l2_device_unregister(&uvc->v4l2_dev); uvc->control_ep->driver_data = NULL; uvc->video.ep->driver_data = NULL; @@ -918,6 +911,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi) if (uvc == NULL) return ERR_PTR(-ENOMEM); + mutex_init(&uvc->video.mutex); uvc->state = UVC_STATE_DISCONNECTED; opts = fi_to_f_uvc_opts(fi); diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index f67695cb28f8..ebe409b9e419 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -115,6 +115,7 @@ struct uvc_video unsigned int width; unsigned int height; unsigned int imagesize; + struct mutex mutex; /* protects frame parameters */ /* Requests */ unsigned int req_size; @@ -143,7 +144,7 @@ enum uvc_state struct uvc_device { - struct video_device *vdev; + struct video_device vdev; struct v4l2_device v4l2_dev; enum uvc_state state; struct usb_function func; diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 8ea8b3b227b4..d617c39a0052 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -104,29 +104,16 @@ static void uvc_buffer_queue(struct vb2_buffer *vb) spin_unlock_irqrestore(&queue->irqlock, flags); } -static void uvc_wait_prepare(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_unlock(&queue->mutex); -} - -static void uvc_wait_finish(struct vb2_queue *vq) -{ - struct uvc_video_queue *queue = vb2_get_drv_priv(vq); - - mutex_lock(&queue->mutex); -} - static struct vb2_ops uvc_queue_qops = { .queue_setup = uvc_queue_setup, .buf_prepare = uvc_buffer_prepare, .buf_queue = uvc_buffer_queue, - .wait_prepare = uvc_wait_prepare, - .wait_finish = uvc_wait_finish, + .wait_prepare = vb2_ops_wait_prepare, + .wait_finish = vb2_ops_wait_finish, }; -int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) +int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, + struct mutex *lock) { int ret; @@ -135,6 +122,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) queue->queue.drv_priv = queue; queue->queue.buf_struct_size = sizeof(struct uvc_buffer); queue->queue.ops = &uvc_queue_qops; + queue->queue.lock = lock; queue->queue.mem_ops = &vb2_vmalloc_memops; queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC | V4L2_BUF_FLAG_TSTAMP_SRC_EOF; @@ -142,7 +130,6 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) if (ret) return ret; - mutex_init(&queue->mutex); spin_lock_init(&queue->irqlock); INIT_LIST_HEAD(&queue->irqqueue); queue->flags = 0; @@ -155,9 +142,7 @@ int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) */ void uvcg_free_buffers(struct uvc_video_queue *queue) { - mutex_lock(&queue->mutex); vb2_queue_release(&queue->queue); - mutex_unlock(&queue->mutex); } /* @@ -168,22 +153,14 @@ int uvcg_alloc_buffers(struct uvc_video_queue *queue, { int ret; - mutex_lock(&queue->mutex); ret = vb2_reqbufs(&queue->queue, rb); - mutex_unlock(&queue->mutex); return ret ? ret : rb->count; } int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_querybuf(&queue->queue, buf); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_querybuf(&queue->queue, buf); } int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) @@ -191,18 +168,14 @@ int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) unsigned long flags; int ret; - mutex_lock(&queue->mutex); ret = vb2_qbuf(&queue->queue, buf); if (ret < 0) - goto done; + return ret; spin_lock_irqsave(&queue->irqlock, flags); ret = (queue->flags & UVC_QUEUE_PAUSED) != 0; queue->flags &= ~UVC_QUEUE_PAUSED; spin_unlock_irqrestore(&queue->irqlock, flags); - -done: - mutex_unlock(&queue->mutex); return ret; } @@ -213,13 +186,7 @@ done: int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, int nonblocking) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_dqbuf(&queue->queue, buf, nonblocking); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_dqbuf(&queue->queue, buf, nonblocking); } /* @@ -231,24 +198,12 @@ int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, unsigned int uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait) { - unsigned int ret; - - mutex_lock(&queue->mutex); - ret = vb2_poll(&queue->queue, file, wait); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_poll(&queue->queue, file, wait); } int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) { - int ret; - - mutex_lock(&queue->mutex); - ret = vb2_mmap(&queue->queue, vma); - mutex_unlock(&queue->mutex); - - return ret; + return vb2_mmap(&queue->queue, vma); } #ifndef CONFIG_MMU @@ -260,12 +215,7 @@ int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue, unsigned long pgoff) { - unsigned long ret; - - mutex_lock(&queue->mutex); - ret = vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); - mutex_unlock(&queue->mutex); - return ret; + return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0); } #endif @@ -327,18 +277,17 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) unsigned long flags; int ret = 0; - mutex_lock(&queue->mutex); if (enable) { ret = vb2_streamon(&queue->queue, queue->queue.type); if (ret < 0) - goto done; + return ret; queue->sequence = 0; queue->buf_used = 0; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) - goto done; + return ret; spin_lock_irqsave(&queue->irqlock, flags); INIT_LIST_HEAD(&queue->irqqueue); @@ -353,8 +302,6 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) spin_unlock_irqrestore(&queue->irqlock, flags); } -done: - mutex_unlock(&queue->mutex); return ret; } diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h index 03919c724961..01ca9eab3481 100644 --- a/drivers/usb/gadget/function/uvc_queue.h +++ b/drivers/usb/gadget/function/uvc_queue.h @@ -41,7 +41,6 @@ struct uvc_buffer { struct uvc_video_queue { struct vb2_queue queue; - struct mutex mutex; /* Protects queue */ unsigned int flags; __u32 sequence; @@ -57,7 +56,8 @@ static inline int uvc_queue_streaming(struct uvc_video_queue *queue) return vb2_is_streaming(&queue->queue); } -int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type); +int uvcg_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, + struct mutex *lock); void uvcg_free_buffers(struct uvc_video_queue *queue); diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 8b818fd027b3..f4ccbd56f4d2 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -14,7 +14,6 @@ #include <linux/device.h> #include <linux/errno.h> #include <linux/list.h> -#include <linux/mutex.h> #include <linux/videodev2.h> #include <linux/vmalloc.h> #include <linux/wait.h> @@ -77,7 +76,8 @@ uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap) strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev), sizeof(cap->bus_info)); - cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING; + cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; return 0; } @@ -312,8 +312,10 @@ uvc_v4l2_release(struct file *file) uvc_function_disconnect(uvc); + mutex_lock(&video->mutex); uvcg_video_enable(video, 0); uvcg_free_buffers(&video->queue); + mutex_unlock(&video->mutex); file->private_data = NULL; v4l2_fh_del(&handle->vfh); @@ -357,7 +359,7 @@ struct v4l2_file_operations uvc_v4l2_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, .release = uvc_v4l2_release, - .ioctl = video_ioctl2, + .unlocked_ioctl = video_ioctl2, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, #ifndef CONFIG_MMU diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 50a5e637ca35..3d0d5d94a62f 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -391,7 +391,8 @@ int uvcg_video_init(struct uvc_video *video) video->imagesize = 320 * 240 * 2; /* Initialize the video buffers queue. */ - uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT); + uvcg_queue_init(&video->queue, V4L2_BUF_TYPE_VIDEO_OUTPUT, + &video->mutex); return 0; } |