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 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