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