linux/drivers/usb/gadget/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/mutex.h>
  18#include <linux/videodev2.h>
  19#include <linux/vmalloc.h>
  20#include <linux/wait.h>
  21
  22#include <media/v4l2-dev.h>
  23#include <media/v4l2-event.h>
  24#include <media/v4l2-ioctl.h>
  25
  26#include "uvc.h"
  27#include "uvc_queue.h"
  28
  29/* --------------------------------------------------------------------------
  30 * Requests handling
  31 */
  32
  33static int
  34uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
  35{
  36        struct usb_composite_dev *cdev = uvc->func.config->cdev;
  37        struct usb_request *req = uvc->control_req;
  38
  39        if (data->length < 0)
  40                return usb_ep_set_halt(cdev->gadget->ep0);
  41
  42        req->length = min_t(unsigned int, uvc->event_length, data->length);
  43        req->zero = data->length < uvc->event_length;
  44
  45        memcpy(req->buf, data->data, req->length);
  46
  47        return usb_ep_queue(cdev->gadget->ep0, req, GFP_KERNEL);
  48}
  49
  50/* --------------------------------------------------------------------------
  51 * V4L2
  52 */
  53
  54struct uvc_format
  55{
  56        u8 bpp;
  57        u32 fcc;
  58};
  59
  60static struct uvc_format uvc_formats[] = {
  61        { 16, V4L2_PIX_FMT_YUYV  },
  62        { 0,  V4L2_PIX_FMT_MJPEG },
  63};
  64
  65static int
  66uvc_v4l2_get_format(struct uvc_video *video, struct v4l2_format *fmt)
  67{
  68        fmt->fmt.pix.pixelformat = video->fcc;
  69        fmt->fmt.pix.width = video->width;
  70        fmt->fmt.pix.height = video->height;
  71        fmt->fmt.pix.field = V4L2_FIELD_NONE;
  72        fmt->fmt.pix.bytesperline = video->bpp * video->width / 8;
  73        fmt->fmt.pix.sizeimage = video->imagesize;
  74        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
  75        fmt->fmt.pix.priv = 0;
  76
  77        return 0;
  78}
  79
  80static int
  81uvc_v4l2_set_format(struct uvc_video *video, struct v4l2_format *fmt)
  82{
  83        struct uvc_format *format;
  84        unsigned int imagesize;
  85        unsigned int bpl;
  86        unsigned int i;
  87
  88        for (i = 0; i < ARRAY_SIZE(uvc_formats); ++i) {
  89                format = &uvc_formats[i];
  90                if (format->fcc == fmt->fmt.pix.pixelformat)
  91                        break;
  92        }
  93
  94        if (i == ARRAY_SIZE(uvc_formats)) {
  95                printk(KERN_INFO "Unsupported format 0x%08x.\n",
  96                        fmt->fmt.pix.pixelformat);
  97                return -EINVAL;
  98        }
  99
 100        bpl = format->bpp * fmt->fmt.pix.width / 8;
 101        imagesize = bpl ? bpl * fmt->fmt.pix.height : fmt->fmt.pix.sizeimage;
 102
 103        video->fcc = format->fcc;
 104        video->bpp = format->bpp;
 105        video->width = fmt->fmt.pix.width;
 106        video->height = fmt->fmt.pix.height;
 107        video->imagesize = imagesize;
 108
 109        fmt->fmt.pix.field = V4L2_FIELD_NONE;
 110        fmt->fmt.pix.bytesperline = bpl;
 111        fmt->fmt.pix.sizeimage = imagesize;
 112        fmt->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
 113        fmt->fmt.pix.priv = 0;
 114
 115        return 0;
 116}
 117
 118static int
 119uvc_v4l2_open(struct file *file)
 120{
 121        struct video_device *vdev = video_devdata(file);
 122        struct uvc_device *uvc = video_get_drvdata(vdev);
 123        struct uvc_file_handle *handle;
 124
 125        handle = kzalloc(sizeof(*handle), GFP_KERNEL);
 126        if (handle == NULL)
 127                return -ENOMEM;
 128
 129        v4l2_fh_init(&handle->vfh, vdev);
 130        v4l2_fh_add(&handle->vfh);
 131
 132        handle->device = &uvc->video;
 133        file->private_data = &handle->vfh;
 134
 135        uvc_function_connect(uvc);
 136        return 0;
 137}
 138
 139static int
 140uvc_v4l2_release(struct file *file)
 141{
 142        struct video_device *vdev = video_devdata(file);
 143        struct uvc_device *uvc = video_get_drvdata(vdev);
 144        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 145        struct uvc_video *video = handle->device;
 146
 147        uvc_function_disconnect(uvc);
 148
 149        uvc_video_enable(video, 0);
 150        uvc_free_buffers(&video->queue);
 151
 152        file->private_data = NULL;
 153        v4l2_fh_del(&handle->vfh);
 154        v4l2_fh_exit(&handle->vfh);
 155        kfree(handle);
 156
 157        return 0;
 158}
 159
 160static long
 161uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
 162{
 163        struct video_device *vdev = video_devdata(file);
 164        struct uvc_device *uvc = video_get_drvdata(vdev);
 165        struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data);
 166        struct usb_composite_dev *cdev = uvc->func.config->cdev;
 167        struct uvc_video *video = &uvc->video;
 168        int ret = 0;
 169
 170        switch (cmd) {
 171        /* Query capabilities */
 172        case VIDIOC_QUERYCAP:
 173        {
 174                struct v4l2_capability *cap = arg;
 175
 176                memset(cap, 0, sizeof *cap);
 177                strlcpy(cap->driver, "g_uvc", sizeof(cap->driver));
 178                strlcpy(cap->card, cdev->gadget->name, sizeof(cap->card));
 179                strlcpy(cap->bus_info, dev_name(&cdev->gadget->dev),
 180                        sizeof cap->bus_info);
 181                cap->version = DRIVER_VERSION_NUMBER;
 182                cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
 183                break;
 184        }
 185
 186        /* Get & Set format */
 187        case VIDIOC_G_FMT:
 188        {
 189                struct v4l2_format *fmt = arg;
 190
 191                if (fmt->type != video->queue.queue.type)
 192                        return -EINVAL;
 193
 194                return uvc_v4l2_get_format(video, fmt);
 195        }
 196
 197        case VIDIOC_S_FMT:
 198        {
 199                struct v4l2_format *fmt = arg;
 200
 201                if (fmt->type != video->queue.queue.type)
 202                        return -EINVAL;
 203
 204                return uvc_v4l2_set_format(video, fmt);
 205        }
 206
 207        /* Buffers & streaming */
 208        case VIDIOC_REQBUFS:
 209        {
 210                struct v4l2_requestbuffers *rb = arg;
 211
 212                if (rb->type != video->queue.queue.type)
 213                        return -EINVAL;
 214
 215                ret = uvc_alloc_buffers(&video->queue, rb);
 216                if (ret < 0)
 217                        return ret;
 218
 219                ret = 0;
 220                break;
 221        }
 222
 223        case VIDIOC_QUERYBUF:
 224        {
 225                struct v4l2_buffer *buf = arg;
 226
 227                return uvc_query_buffer(&video->queue, buf);
 228        }
 229
 230        case VIDIOC_QBUF:
 231                if ((ret = uvc_queue_buffer(&video->queue, arg)) < 0)
 232                        return ret;
 233
 234                return uvc_video_pump(video);
 235
 236        case VIDIOC_DQBUF:
 237                return uvc_dequeue_buffer(&video->queue, arg,
 238                        file->f_flags & O_NONBLOCK);
 239
 240        case VIDIOC_STREAMON:
 241        {
 242                int *type = arg;
 243
 244                if (*type != video->queue.queue.type)
 245                        return -EINVAL;
 246
 247                /* Enable UVC video. */
 248                ret = uvc_video_enable(video, 1);
 249                if (ret < 0)
 250                        return ret;
 251
 252                /*
 253                 * Complete the alternate setting selection setup phase now that
 254                 * userspace is ready to provide video frames.
 255                 */
 256                uvc_function_setup_continue(uvc);
 257                uvc->state = UVC_STATE_STREAMING;
 258
 259                return 0;
 260        }
 261
 262        case VIDIOC_STREAMOFF:
 263        {
 264                int *type = arg;
 265
 266                if (*type != video->queue.queue.type)
 267                        return -EINVAL;
 268
 269                return uvc_video_enable(video, 0);
 270        }
 271
 272        /* Events */
 273        case VIDIOC_DQEVENT:
 274        {
 275                struct v4l2_event *event = arg;
 276
 277                ret = v4l2_event_dequeue(&handle->vfh, event,
 278                                         file->f_flags & O_NONBLOCK);
 279                if (ret == 0 && event->type == UVC_EVENT_SETUP) {
 280                        struct uvc_event *uvc_event = (void *)&event->u.data;
 281
 282                        /* Tell the complete callback to generate an event for
 283                         * the next request that will be enqueued by
 284                         * uvc_event_write.
 285                         */
 286                        uvc->event_setup_out =
 287                                !(uvc_event->req.bRequestType & USB_DIR_IN);
 288                        uvc->event_length = uvc_event->req.wLength;
 289                }
 290
 291                return ret;
 292        }
 293
 294        case VIDIOC_SUBSCRIBE_EVENT:
 295        {
 296                struct v4l2_event_subscription *sub = arg;
 297
 298                if (sub->type < UVC_EVENT_FIRST || sub->type > UVC_EVENT_LAST)
 299                        return -EINVAL;
 300
 301                return v4l2_event_subscribe(&handle->vfh, arg, 2, NULL);
 302        }
 303
 304        case VIDIOC_UNSUBSCRIBE_EVENT:
 305                return v4l2_event_unsubscribe(&handle->vfh, arg);
 306
 307        case UVCIOC_SEND_RESPONSE:
 308                ret = uvc_send_response(uvc, arg);
 309                break;
 310
 311        default:
 312                return -ENOIOCTLCMD;
 313        }
 314
 315        return ret;
 316}
 317
 318static long
 319uvc_v4l2_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 320{
 321        return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
 322}
 323
 324static int
 325uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 326{
 327        struct video_device *vdev = video_devdata(file);
 328        struct uvc_device *uvc = video_get_drvdata(vdev);
 329
 330        return uvc_queue_mmap(&uvc->video.queue, vma);
 331}
 332
 333static unsigned int
 334uvc_v4l2_poll(struct file *file, poll_table *wait)
 335{
 336        struct video_device *vdev = video_devdata(file);
 337        struct uvc_device *uvc = video_get_drvdata(vdev);
 338
 339        return uvc_queue_poll(&uvc->video.queue, file, wait);
 340}
 341
 342#ifndef CONFIG_MMU
 343static unsigned long uvc_v4l2_get_unmapped_area(struct file *file,
 344                unsigned long addr, unsigned long len, unsigned long pgoff,
 345                unsigned long flags)
 346{
 347        struct video_device *vdev = video_devdata(file);
 348        struct uvc_device *uvc = video_get_drvdata(vdev);
 349
 350        return uvc_queue_get_unmapped_area(&uvc->video.queue, pgoff);
 351}
 352#endif
 353
 354static struct v4l2_file_operations uvc_v4l2_fops = {
 355        .owner          = THIS_MODULE,
 356        .open           = uvc_v4l2_open,
 357        .release        = uvc_v4l2_release,
 358        .ioctl          = uvc_v4l2_ioctl,
 359        .mmap           = uvc_v4l2_mmap,
 360        .poll           = uvc_v4l2_poll,
 361#ifndef CONFIG_MMU
 362        .get_unmapped_area = uvc_v4l2_get_unmapped_area,
 363#endif
 364};
 365
 366