linux/drivers/usb/gadget/function/uvc_v4l2.c
<<
>>
Prefs
   1/*
   2 *      uvc_v4l2.c  --  USB Video Class Gadget driver
   3 *
   4 *      Copyright (C) 2009-2010
   5 *          Laurent Pinchart (laurent.pinchart@ideasonboard.com)
   6 *
   7 *      This program is free software; you can redistribute it and/or modify
   8 *      it under the terms of the GNU General Public License as published by
   9 *      the Free Software Foundation; either version 2 of the License, or
  10 *      (at your option) any later version.
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/device.h>
  15#include <linux/errno.h>
  16#include <linux/list.h>
  17#include <linux/videodev2.h>
  18#include <linux/vmalloc.h>
  19#include <linux/wait.h>
  20
  21#include <media/v4l2-dev.h>
  22#include <media/v4l2-event.h>
  23#include <media/v4l2-ioctl.h>
  24
  25#include "f_uvc.h"
  26#include "uvc.h"
  27#include "uvc_queue.h"
  28#include "uvc_video.h"
  29#include "uvc_v4l2.h"
  30
  31/* --------------------------------------------------------------------------
  32 * Requests handling
  33 */
  34
  35static int
  36uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
  37{
  38        struct usb_composite_dev *cdev = uvc->func.config->cdev;
  39        struct usb_request *req = uvc->control_req;
  40
  41        if (data->length < 0)
  42                return usb_ep_set_halt(cdev->gadget->ep0);
  43
  44        req->length = min_t(unsigned int, uvc->event_length, data->length);
  45        req->zero = data->length < uvc->event_length;
  46
  47        memcpy(req->buf, data->data, req->length);
  48
  49        return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
  50}
  51
  52/* --------------------------------------------------------------------------
  53 * V4L2 ioctls
  54 */
  55
  56struct uvc_format
  57{
  58        u8 bpp;
  59        u32 fcc;
  60};
  61
  62static struct uvc_format uvc_formats[] = {
  63        { 16, V4L2_PIX_FMT_YUYV  },
  64        { 0,  V4L2_PIX_FMT_MJPEG },
  65};
  66
  67static int
  68uvc_v4l2_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
  69{
  70        struct video_device *vdev = video_devdata(file);
  71        struct uvc_device *uvc = video_get_drvdata(vdev);
  72        struct usb_composite_dev *cdev = uvc->func.config->cdev;
  73
  74        strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
  75        strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
  76        strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
  77                sizeof(cap->bus_info));
  78
  79        cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
  80        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
  81
  82        return 0;
  83}
  84
  85static int
  86uvc_v4l2_get_format(struct file *file, void *fh, struct v4l2_format *fmt)
  87{
  88        struct video_device *vdev = video_devdata(file);
  89        struct uvc_device *uvc = video_get_drvdata(vdev);
  90        struct uvc_video *video = &uvc->video;
  91
  92        fmt->fmt.pix.pixelformat = video->fcc;
  93        fmt->fmt.pix.width = video->width;
  94        fmt->fmt.pix.height = video->height;
  95        fmt->fmt.pix.field = V4L2_FIELD_NONE;
  96        fmt->fmt.pix.bytesperline = video->bpp * video->width / 8;
  97        fmt->fmt.pix.sizeimage = video->imagesize;
  98        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  99        fmt->fmt.pix.priv = 0;
 100
 101        return 0;
 102}
 103
 104static int
 105uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt)
 106{
 107        struct video_device *vdev = video_devdata(file);
 108        struct uvc_device *uvc = video_get_drvdata(vdev);
 109        struct uvc_video *video = &uvc->video;
 110        struct uvc_format *format;
 111        unsigned int imagesize;
 112        unsigned int bpl;
 113        unsigned int i;
 114
 115        for (i = 0; i < ARRAY_SIZE(uvc_formats); ++i) {
 116                format = &uvc_formats[i];
 117                if (format->fcc == fmt->fmt.pix.pixelformat)
 118                        break;
 119        }
 120
 121        if (i == ARRAY_SIZE(uvc_formats)) {
 122                printk(KERN_INFO "Unsupported format 0x%08x.\n",
 123                        fmt->fmt.pix.pixelformat);
 124                return -EINVAL;
 125        }
 126
 127        bpl = format->bpp * fmt->fmt.pix.width / 8;
 128        imagesize = bpl ? bpl * fmt->fmt.pix.height : fmt->fmt.pix.sizeimage;
 129
 130        video->fcc = format->fcc;
 131        video->bpp = format->bpp;
 132        video->width = fmt->fmt.pix.width;
 133        video->height = fmt->fmt.pix.height;
 134        video->imagesize = imagesize;
 135
 136        fmt->fmt.pix.field = V4L2_FIELD_NONE;
 137        fmt->fmt.pix.bytesperline = bpl;
 138        fmt->fmt.pix.sizeimage = imagesize;
 139        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 140        fmt->fmt.pix.priv = 0;
 141
 142        return 0;
 143}
 144
 145static int
 146uvc_v4l2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *b)
 147{
 148        struct video_device *vdev = video_devdata(file);
 149        struct uvc_device *uvc = video_get_drvdata(vdev);
 150        struct uvc_video *video = &uvc->video;
 151
 152        if (b->type != video->queue.queue.type)
 153                return -EINVAL;
 154
 155        return uvcg_alloc_buffers(&video->queue, b);
 156}
 157
 158static int
 159uvc_v4l2_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
 160{
 161        struct video_device *vdev = video_devdata(file);
 162        struct uvc_device *uvc = video_get_drvdata(vdev);
 163        struct uvc_video *video = &uvc->video;
 164
 165        return uvcg_query_buffer(&video->queue, b);
 166}
 167
 168static int
 169uvc_v4l2_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 170{
 171        struct video_device *vdev = video_devdata(file);
 172        struct uvc_device *uvc = video_get_drvdata(vdev);
 173        struct uvc_video *video = &uvc->video;
 174        int ret;
 175
 176        ret = uvcg_queue_buffer(&video->queue, b);
 177        if (ret < 0)
 178                return ret;
 179
 180        return uvcg_video_pump(video);
 181}
 182
 183static int
 184uvc_v4l2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
 185{
 186        struct video_device *vdev = video_devdata(file);
 187        struct uvc_device *uvc = video_get_drvdata(vdev);
 188        struct uvc_video *video = &uvc->video;
 189
 190        return uvcg_dequeue_buffer(&video->queue, b, file->f_flags & O_NONBLOCK);
 191}
 192
 193static int
 194uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
 195{
 196        struct video_device *vdev = video_devdata(file);
 197        struct uvc_device *uvc = video_get_drvdata(vdev);
 198        struct uvc_video *video = &uvc->video;
 199        int ret;
 200
 201        if (type != video->queue.queue.type)
 202                return -EINVAL;
 203
 204        /* Enable UVC video. */
 205        ret = uvcg_video_enable(video, 1);
 206        if (ret < 0)
 207                return ret;
 208
 209        /*
 210         * Complete the alternate setting selection setup phase now that
 211         * userspace is ready to provide video frames.
 212         */
 213        uvc_function_setup_continue(uvc);
 214        uvc->state = UVC_STATE_STREAMING;
 215
 216        return 0;
 217}
 218
 219static int
 220uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 221{
 222        struct video_device *vdev = video_devdata(file);
 223        struct uvc_device *uvc = video_get_drvdata(vdev);
 224        struct uvc_video *video = &uvc->video;
 225
 226        if (type != video->queue.queue.type)
 227                return -EINVAL;
 228
 229        return uvcg_video_enable(video, 0);
 230}
 231
 232static int
 233uvc_v4l2_subscribe_event(struct v4l2_fh *fh,
 234                         const struct v4l2_event_subscription *sub)
 235{
 236        if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
 237                return -EINVAL;
 238
 239        return v4l2_event_subscribe(fh, sub, 2, NULL);
 240}
 241
 242static int
 243uvc_v4l2_unsubscribe_event(struct v4l2_fh *fh,
 244                           const struct v4l2_event_subscription *sub)
 245{
 246        return v4l2_event_unsubscribe(fh, sub);
 247}
 248
 249static long
 250uvc_v4l2_ioctl_default(struct file *file, void *fh, bool valid_prio,
 251                       unsigned int cmd, void *arg)
 252{
 253        struct video_device *vdev = video_devdata(file);
 254        struct uvc_device *uvc = video_get_drvdata(vdev);
 255
 256        switch (cmd) {
 257        case UVCIOC_SEND_RESPONSE:
 258                return uvc_send_response(uvc, arg);
 259
 260        default:
 261                return -ENOIOCTLCMD;
 262        }
 263}
 264
 265const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
 266        .vidioc_querycap = uvc_v4l2_querycap,
 267        .vidioc_g_fmt_vid_out = uvc_v4l2_get_format,
 268        .vidioc_s_fmt_vid_out = uvc_v4l2_set_format,
 269        .vidioc_reqbufs = uvc_v4l2_reqbufs,
 270        .vidioc_querybuf = uvc_v4l2_querybuf,
 271        .vidioc_qbuf = uvc_v4l2_qbuf,
 272        .vidioc_dqbuf = uvc_v4l2_dqbuf,
 273        .vidioc_streamon = uvc_v4l2_streamon,
 274        .vidioc_streamoff = uvc_v4l2_streamoff,
 275        .vidioc_subscribe_event = uvc_v4l2_subscribe_event,
 276        .vidioc_unsubscribe_event = uvc_v4l2_unsubscribe_event,
 277        .vidioc_default = uvc_v4l2_ioctl_default,
 278};
 279
 280/* --------------------------------------------------------------------------
 281 * V4L2
 282 */
 283
 284static int
 285uvc_v4l2_open(struct file *file)
 286{
 287        struct video_device *vdev = video_devdata(file);
 288        struct uvc_device *uvc = video_get_drvdata(vdev);
 289        struct uvc_file_handle *handle;
 290
 291        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
 292        if (handle == NULL)
 293                return -ENOMEM;
 294
 295        v4l2_fh_init(&handle->vfh, vdev);
 296        v4l2_fh_add(&handle->vfh);
 297
 298        handle->device = &uvc->video;
 299        file->private_data = &handle->vfh;
 300
 301        uvc_function_connect(uvc);
 302        return 0;
 303}
 304
 305static int
 306uvc_v4l2_release(struct file *file)
 307{
 308        struct video_device *vdev = video_devdata(file);
 309        struct uvc_device *uvc = video_get_drvdata(vdev);
 310        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 311        struct uvc_video *video = handle->device;
 312
 313        uvc_function_disconnect(uvc);
 314
 315        mutex_lock(&video->mutex);
 316        uvcg_video_enable(video, 0);
 317        uvcg_free_buffers(&video->queue);
 318        mutex_unlock(&video->mutex);
 319
 320        file->private_data = NULL;
 321        v4l2_fh_del(&handle->vfh);
 322        v4l2_fh_exit(&handle->vfh);
 323        kfree(handle);
 324
 325        return 0;
 326}
 327
 328static int
 329uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 330{
 331        struct video_device *vdev = video_devdata(file);
 332        struct uvc_device *uvc = video_get_drvdata(vdev);
 333
 334        return uvcg_queue_mmap(&uvc->video.queue, vma);
 335}
 336
 337static unsigned int
 338uvc_v4l2_poll(struct file *file, poll_table *wait)
 339{
 340        struct video_device *vdev = video_devdata(file);
 341        struct uvc_device *uvc = video_get_drvdata(vdev);
 342
 343        return uvcg_queue_poll(&uvc->video.queue, file, wait);
 344}
 345
 346#ifndef CONFIG_MMU
 347static unsigned long uvcg_v4l2_get_unmapped_area(struct file *file,
 348                unsigned long addr, unsigned long len, unsigned long pgoff,
 349                unsigned long flags)
 350{
 351        struct video_device *vdev = video_devdata(file);
 352        struct uvc_device *uvc = video_get_drvdata(vdev);
 353
 354        return uvcg_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 355}
 356#endif
 357
 358struct v4l2_file_operations uvc_v4l2_fops = {
 359        .owner          = THIS_MODULE,
 360        .open           = uvc_v4l2_open,
 361        .release        = uvc_v4l2_release,
 362        .unlocked_ioctl = video_ioctl2,
 363        .mmap           = uvc_v4l2_mmap,
 364        .poll           = uvc_v4l2_poll,
 365#ifndef CONFIG_MMU
 366        .get_unmapped_area = uvcg_v4l2_get_unmapped_area,
 367#endif
 368};
 369
 370