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