r5u870

Ricoh R5U870 Linux Driver
git clone https://logand.com/git/r5u870.git/
Log | Files | Refs | README | LICENSE

usbcam_buf.c (18729B)


      1 /*
      2  * USBCAM abstraction library for USB webcam drivers
      3  *
      4  * Copyright (c) 2007 Sam Revitch <samr7 cs washington edu>
      5  *
      6  * This program is free software; you can redistribute it and/or modify
      7  * it under the terms of the GNU General Public License as published by
      8  * the Free Software Foundation; either version 2, or (at your option)
      9  * any later version.
     10  *
     11  * This program is distributed in the hope that it will be useful,
     12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14  * GNU General Public License for more details.
     15  *
     16  * You should have received a copy of the GNU General Public License
     17  * along with this program; if not, write to the Free Software
     18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
     19  */
     20 
     21 #include "usbcam_priv.h"
     22 
     23 /*
     24  * This file contains videobuf frame buffer interface routines, and
     25  * current frame access functions.
     26  */
     27 
     28 /*
     29  * APPBUG: Some applications expect VIDIOCGMBUF to provide a buffer
     30  * large enough to accommodate whatever image format they choose in the
     31  * future.  We enable fixed size buffer mode from VIDIOCGMBUF, and
     32  * disable it from VIDIOC_REQBUFS.
     33  */
     34 static int fixed_fbsize = 1024 * 1024;
     35 module_param(fixed_fbsize, int, S_IRUGO|S_IWUSR);
     36 MODULE_PARM_DESC(fixed_fbsize, "Size in bytes of fixed-length framebuffers");
     37 
     38 /*
     39  * naresh <cyan_00391@yahoo.co.in>
     40  * Define the various codes to permit compilation of this on 
     41  * 2.6.25 and higher kernels, we use gcc preprocessors for backward
     42  * compatibility
     43  * CREDITS: Thanks to stefano.brivio for his patch.
     44  *          Refer bug @ http://bugs.mediati.org/r5u870/issue2
     45  */
     46 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
     47  #define STATE_ACTIVE      VIDEOBUF_ACTIVE
     48  #define STATE_DONE        VIDEOBUF_DONE
     49  #define STATE_ERROR       VIDEOBUF_ERROR
     50  #define STATE_NEEDS_INIT  VIDEOBUF_NEEDS_INIT
     51  #define STATE_PREPARED    VIDEOBUF_PREPARED
     52 #endif
     53 
     54 /*
     55  * Frame capture handling helpers follow
     56  */
     57 
     58 static inline struct usbcam_frame *
     59 usbcam_capture_curframe(struct usbcam_dev *udp)
     60 {
     61 	return list_empty(&udp->ud_frame_cap_queue)
     62 		? NULL
     63 		: list_entry(udp->ud_frame_cap_queue.next,
     64 			     struct usbcam_frame, cap_links);
     65 }
     66 
     67 static void usbcam_capture_abortall(struct usbcam_dev *udp)
     68 {
     69 	struct usbcam_frame *framep;
     70 
     71 	/* Abort all frames on the capture queue */
     72 	while (1) {
     73 		framep = usbcam_capture_curframe(udp);
     74 		if (!framep)
     75 			break;
     76 		usbcam_dbg(udp, VIDEOBUF, "completing frame %d STATE_ERROR",
     77 			   framep->vbb.i);
     78 		list_del_init(&framep->cap_links);
     79 		framep->vbb.state = STATE_ERROR;
     80 		wake_up_all(&framep->vbb.done);
     81 	}
     82 }
     83 
     84 static inline void usbcam_capture_complete_frame(struct usbcam_dev *udp,
     85 						 struct usbcam_frame *framep,
     86 						 int is_error)
     87 {
     88 	usbcam_chklock(udp);
     89 	usbcam_dbg(udp, VIDEOBUF, "completing frame %d/%p %s", framep->vbb.i,
     90 		   framep, is_error ? "STATE_ERROR" : "STATE_DONE");
     91 	list_del_init(&framep->cap_links);
     92 	framep->vbb.state = is_error ? STATE_ERROR : STATE_DONE;
     93 	wake_up_all(&framep->vbb.done);
     94 }
     95 
     96 static int usbcam_capture_start(struct usbcam_dev *udp)
     97 {
     98 	int res;
     99 
    100 	if (udp->ud_capturing) {
    101 		usbcam_warn(udp, "%s: already capturing", __FUNCTION__);
    102 		return 0;
    103 	}
    104 
    105 	if (list_empty(&udp->ud_frame_cap_queue)) {
    106 		usbcam_warn(udp, "%s: no frames queued to capture",
    107 			    __FUNCTION__);
    108 		return -ENOENT;
    109 	}
    110 
    111 	if (udp->ud_disconnected) {
    112 		/*
    113 		 * We can't let any frames through if the device has
    114 		 * been disconnected
    115 		 */
    116 		usbcam_capture_abortall(udp);
    117 		return -ENODEV;
    118 	}
    119 
    120 	usbcam_dbg(udp, CAPTURE, "invoking minidriver cap_start");
    121 
    122 	res = usbcam_minidrv_op(udp, cap_start);
    123 	if (res) {
    124 		usbcam_dbg(udp, CAPTURE,
    125 			   "%s: could not start capture for %s: %d",
    126 			   __FUNCTION__, usbcam_drvname(udp->ud_minidrv), res);
    127 
    128 		if (udp->ud_capturing) {
    129 			usbcam_warn(udp,
    130 				    "%s: minidriver left ud_capturing set\n",
    131 				    __FUNCTION__);
    132 		}
    133 
    134 		usbcam_capture_abortall(udp);
    135 		return res;
    136 	}
    137 
    138 	if (!udp->ud_capturing && usbcam_capture_curframe(udp)) {
    139 		usbcam_warn(udp, "%s: minidriver failed to set ud_capturing!",
    140 			    __FUNCTION__);
    141 	} else {
    142 		usbcam_dbg(udp, CAPTURE, "minidriver capture started");
    143 	}
    144 
    145 	return 0;
    146 }
    147 
    148 void usbcam_capture_stop(struct usbcam_dev *udp)
    149 {
    150 	if (udp->ud_capturing) {
    151 		usbcam_dbg(udp, CAPTURE, "invoking minidriver cap_stop");
    152 		usbcam_minidrv_op(udp, cap_stop);
    153 
    154 		if (udp->ud_capturing) {
    155 			usbcam_warn(udp, "%s: minidriver failed to clear "
    156 				    "ud_capturing!", __FUNCTION__);
    157 		} else {
    158 			usbcam_dbg(udp, CAPTURE, "minidriver capture stopped");
    159 		}
    160 	}
    161 }
    162 
    163 static inline struct videobuf_dmabuf* usbframe_get_dmabuf(struct videobuf_buffer *buf)
    164 {
    165 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    166     return &buf->dma;
    167 #else
    168     return videobuf_to_dma(buf);
    169 #endif
    170 }
    171 
    172 /*
    173  * External APIs for minidriver access to the frame queue
    174  */
    175 
    176 int usbcam_curframe_get(struct usbcam_dev *udp, struct usbcam_curframe *cf)
    177 {
    178 	struct usbcam_frame *framep = usbcam_capture_curframe(udp);
    179 	struct videobuf_dmabuf *dma;
    180 
    181 	usbcam_chklock(udp);
    182 
    183 	if (!framep)
    184 		return -ENOENT;
    185 		
    186 	dma = usbframe_get_dmabuf(&framep->vbb);
    187 
    188 	cf->uf_base = (u8 *) (framep->vmap_sof
    189 			      ? framep->vmap_sof
    190 			      : dma->vmalloc);
    191 	cf->uf_size = framep->vbb.size;
    192 	cf->uf_field = framep->vbb.field;
    193 	memset(&cf->uf_timestamp, 0, sizeof(cf->uf_timestamp));
    194 
    195 	return 0;
    196 }
    197 USBCAM_EXPORT_SYMBOL(usbcam_curframe_get);
    198 
    199 void usbcam_curframe_complete_detail(struct usbcam_dev *udp,
    200 				     struct usbcam_curframe *cf)
    201 {
    202 	struct usbcam_frame *framep;
    203 
    204 	usbcam_chklock(udp);
    205 
    206 	framep = usbcam_capture_curframe(udp);
    207 	if (!framep) {
    208 		usbcam_warn(udp, "%s: no current frame!", __FUNCTION__);
    209 		return;
    210 	}
    211 
    212 	if (framep->vbb.state != STATE_ACTIVE) {
    213 		usbcam_err(udp, "%s: current frame is in unexpected state %d",
    214 			   __FUNCTION__, framep->vbb.state);
    215 	}
    216 
    217 	if (cf) {
    218 		framep->vbb.size = cf->uf_size;
    219 		framep->vbb.field = cf->uf_field;
    220 		framep->vbb.ts = cf->uf_timestamp;
    221 
    222 		if (framep->vbb.bsize < cf->uf_size) {
    223 			usbcam_warn(udp, "%s: minidriver supplied "
    224 				    "excessive size %zu",
    225 				    __FUNCTION__, cf->uf_size);
    226 			framep->vbb.size = framep->vbb.bsize;
    227 		}
    228 	}
    229 
    230 	usbcam_capture_complete_frame(udp, framep, 0);
    231 }
    232 USBCAM_EXPORT_SYMBOL(usbcam_curframe_complete_detail);
    233 
    234 void usbcam_curframe_abortall(struct usbcam_dev *udp)
    235 {
    236 	usbcam_dbg(udp, CAPTURE, "minidriver aborting all frames");
    237 
    238 	usbcam_chklock(udp);
    239 
    240 	if (udp->ud_capturing) {
    241 		usbcam_warn(udp, "%s: minidriver left ud_capturing set",
    242 			    __FUNCTION__);
    243 	}
    244 	usbcam_capture_abortall(udp);
    245 }
    246 USBCAM_EXPORT_SYMBOL(usbcam_curframe_abortall);
    247 
    248 
    249 /*
    250  * Test pattern code
    251  */
    252 
    253 void usbcam_curframe_fill(struct usbcam_dev *udp, size_t offset,
    254 			  const void *pattern, int patlen, int nrecs)
    255 {
    256 	struct usbcam_curframe cf;
    257 	size_t end;
    258 
    259 	usbcam_chklock(udp);
    260 
    261 	if (usbcam_curframe_get(udp, &cf)) {
    262 		usbcam_warn(udp, "%s: no current frame", __FUNCTION__);
    263 		return;
    264 	}
    265 
    266 	end = offset + (patlen * nrecs);
    267 	if (end > cf.uf_size) {
    268 		usbcam_warn(udp, "%s(offs=%zu patlen=%d nrecs=%d) would "
    269 			    "write past end of %zu byte framebuffer",
    270 			    __FUNCTION__,
    271 			    offset, patlen, nrecs, cf.uf_size);
    272 		if (offset > cf.uf_size)
    273 			nrecs = 0;
    274 		else
    275 			nrecs = (cf.uf_size - offset) / patlen;
    276 	}
    277 	else if (end > udp->ud_format.sizeimage)
    278 		usbcam_warn(udp, "%s(offs=%zu patlen=%d nrecs=%d) writing "
    279 			    "beyond %u-byte sizeimage", __FUNCTION__,
    280 			    offset, patlen, nrecs, udp->ud_format.sizeimage);
    281 
    282 	if (!nrecs)
    283 		return;
    284 
    285 	if (patlen == 1) {
    286 		memset(cf.uf_base + offset, *(char *)pattern, nrecs);
    287 		return;
    288 	}
    289 
    290 	while (nrecs--) {
    291 		memcpy(cf.uf_base + offset, pattern, patlen);
    292 		offset += patlen;
    293 	}
    294 }
    295 USBCAM_EXPORT_SYMBOL(usbcam_curframe_fill);
    296 
    297 void usbcam_curframe_fill_lines(struct usbcam_dev *udp,
    298 				const char *pat, int patlen,
    299 				int pixperpat)
    300 {
    301 	int line, nrecperline, stride;
    302 	size_t offset = 0;
    303 
    304 	nrecperline = (udp->ud_format.width + pixperpat - 1) / pixperpat;
    305 	stride = udp->ud_format.bytesperline
    306 		? udp->ud_format.bytesperline
    307 		: (nrecperline * patlen);
    308 
    309 	if ((patlen * nrecperline) == stride) {
    310 		usbcam_curframe_fill(udp, 0, pat, patlen,
    311 				     nrecperline * udp->ud_format.height);
    312 		return;
    313 	}
    314 
    315 	for (line = 0; line < udp->ud_format.height; line++) {
    316 		usbcam_curframe_fill(udp, offset, pat, patlen, nrecperline);
    317 		offset += stride;
    318 	}
    319 }
    320 
    321 void usbcam_curframe_fill_interleaved(struct usbcam_dev *udp,
    322 				      const char *pat_even,
    323 				      const char *pat_odd,
    324 				      int patlen, int pixperpat)
    325 {
    326 	int line, nrecperline, stride;
    327 	size_t offset = 0;
    328 
    329 	nrecperline = (udp->ud_format.width + pixperpat - 1) / pixperpat;
    330 	stride = udp->ud_format.bytesperline
    331 		? udp->ud_format.bytesperline
    332 		: (nrecperline * patlen);
    333 
    334 	for (line = 0; line < udp->ud_format.height; line++) {
    335 		usbcam_curframe_fill(udp, offset,
    336 				     (line & 1) ? pat_odd : pat_even,
    337 				     patlen, nrecperline);
    338 		offset += stride;
    339 	}
    340 }
    341 
    342 void usbcam_curframe_fill_planar(struct usbcam_dev *udp,
    343 				 const char *pat0, int pat0len, int pixperpat0,
    344 				 const char *pat1, int pat1len, int pixperpat1,
    345 				 const char *pat2, int pat2len, int pixperpat2)
    346 {
    347 	int nrecperline;
    348 	size_t offset = 0;
    349 
    350 	if (pat0 && pat0len) {
    351 		nrecperline = ((udp->ud_format.width + pixperpat0 - 1) /
    352 			       pixperpat0);
    353 		usbcam_curframe_fill(udp, offset, pat0, pat0len,
    354 				     nrecperline * udp->ud_format.height);
    355 		offset += (nrecperline * udp->ud_format.height * pat0len);
    356 	}
    357 	if (pat1 && pat1len) {
    358 		nrecperline = ((udp->ud_format.width + pixperpat1 - 1) /
    359 			       pixperpat1);
    360 		usbcam_curframe_fill(udp, offset, pat1, pat1len,
    361 				     nrecperline * udp->ud_format.height);
    362 		offset += (nrecperline * udp->ud_format.height * pat1len);
    363 	}
    364 	if (pat2 && pat2len) {
    365 		nrecperline = ((udp->ud_format.width + pixperpat2 - 1) /
    366 			       pixperpat2);
    367 		usbcam_curframe_fill(udp, offset, pat2, pat2len,
    368 				     nrecperline * udp->ud_format.height);
    369 		offset += (nrecperline * udp->ud_format.height * pat2len);
    370 	}
    371 }
    372 
    373 /*
    374  * The goal is to be able to come up with a solid blue image in all
    375  * basic uncompressed formats.  No JPEG or compressed formats, at least
    376  * not yet.
    377  */
    378 int usbcam_curframe_testpattern(struct usbcam_dev *udp)
    379 {
    380 	usbcam_chklock(udp);
    381 
    382 #define DO_FILL(PIXPERPAT, TP...) {					\
    383 	const char tp[] = {TP};						\
    384 	usbcam_curframe_fill_lines(udp, tp, sizeof(tp),	PIXPERPAT);	\
    385 }
    386 	switch (udp->ud_format.pixelformat) {
    387 	case V4L2_PIX_FMT_RGB332:
    388 		DO_FILL(1, 0x03)
    389 		return 0;
    390 	case V4L2_PIX_FMT_RGB555:
    391 	case V4L2_PIX_FMT_RGB565:
    392 		DO_FILL(1, 0x1f, 0x00)
    393 		return 0;
    394 	case V4L2_PIX_FMT_RGB555X:
    395 	case V4L2_PIX_FMT_RGB565X:
    396 		DO_FILL(1, 0x00, 0x1f)
    397 		return 0;
    398 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
    399 	case V4L2_PIX_FMT_RGB444:
    400 		DO_FILL(1, 0x00, 0x0f)
    401 		return 0;
    402 #endif
    403 	case V4L2_PIX_FMT_BGR24:
    404 		DO_FILL(1, 0xff, 0x00, 0x00);
    405 		return 0;
    406 	case V4L2_PIX_FMT_RGB24:
    407 		DO_FILL(1, 0x00, 0x00, 0xff);
    408 		return 0;
    409 	case V4L2_PIX_FMT_BGR32:
    410 		DO_FILL(1, 0xff, 0x00, 0x00, 0x00);
    411 		return 0;
    412 	case V4L2_PIX_FMT_RGB32:
    413 		DO_FILL(1, 0x00, 0x00, 0xff, 0x00);
    414 		return 0;
    415 	case V4L2_PIX_FMT_GREY:
    416 		DO_FILL(1, 0x1f);
    417 		return 0;
    418 	case V4L2_PIX_FMT_YUYV:
    419 		DO_FILL(2, 0x29, 0xf0, 0x29, 0x6e);
    420 		return 0;
    421 	case V4L2_PIX_FMT_UYVY:
    422 		DO_FILL(2, 0xf0, 0x29, 0x6e, 0x29);
    423 		return 0;
    424 	case V4L2_PIX_FMT_YYUV:
    425 		DO_FILL(2, 0x29, 0x29, 0xf0, 0x6e);
    426 		return 0;
    427 	case V4L2_PIX_FMT_Y41P:
    428 		DO_FILL(8,
    429 			0xf0, 0x29, 0x6e, 0x29, 0xf0, 0x29, 0x6e, 0x29,
    430 			0x29, 0x29, 0x29, 0x29);
    431 		return 0;
    432 #undef DO_FILL
    433 
    434 	case V4L2_PIX_FMT_SBGGR8: {
    435 		const char tp0[] = { 0xff, 0x00 }, tp1[] = { 0x00, 0x00 };
    436 		usbcam_curframe_fill_interleaved(udp, tp0, tp1, 2, 2);
    437 		return 0;
    438 	}
    439 	case V4L2_PIX_FMT_YVU410: {
    440 		const char tp0[] = {0x29}, tp1[] = {0x6e}, tp2[] = {0xf0};
    441 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    442 					    tp1, sizeof(tp1), 16,
    443 					    tp2, sizeof(tp2), 16);
    444 		return 0;
    445 	}
    446 	case V4L2_PIX_FMT_YUV410: {
    447 		const char tp0[] = {0x29}, tp1[] = {0xf0}, tp2[] = {0x6e};
    448 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    449 					    tp1, sizeof(tp1), 16,
    450 					    tp2, sizeof(tp2), 16);
    451 		return 0;
    452 	}
    453 	case V4L2_PIX_FMT_YVU420: {
    454 		const char tp0[] = {0x29}, tp1[] = {0x6e}, tp2[] = {0xf0};
    455 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    456 					    tp1, sizeof(tp1), 4,
    457 					    tp2, sizeof(tp2), 4);
    458 		return 0;
    459 	}
    460 	case V4L2_PIX_FMT_YUV411P: 
    461 	case V4L2_PIX_FMT_YUV420: {
    462 		const char tp0[] = {0x29}, tp1[] = {0xf0}, tp2[] = {0x6e};
    463 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    464 					    tp1, sizeof(tp1), 4,
    465 					    tp2, sizeof(tp2), 4);
    466 		return 0;
    467 	}
    468 	case V4L2_PIX_FMT_YUV422P: {
    469 		const char tp0[] = {0x29}, tp1[] = {0xf0}, tp2[] = {0x6e};
    470 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    471 					    tp1, sizeof(tp1), 2,
    472 					    tp2, sizeof(tp2), 2);
    473 		return 0;
    474 	}
    475 	case V4L2_PIX_FMT_NV12: {
    476 		const char tp0[] = {0x29}, tp1[] = {0xf0, 0x6e};
    477 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    478 					    tp1, sizeof(tp1), 4,
    479 					    NULL, 0, 0);
    480 		return 0;
    481 	}
    482 	case V4L2_PIX_FMT_NV21: {
    483 		const char tp0[] = {0x29}, tp1[] = {0x6e, 0xf0};
    484 		usbcam_curframe_fill_planar(udp, tp0, sizeof(tp0), 1,
    485 					    tp1, sizeof(tp1), 4,
    486 					    NULL, 0, 0);
    487 		return 0;
    488 	}
    489 	}
    490 
    491 	return -EINVAL;
    492 }
    493 USBCAM_EXPORT_SYMBOL(usbcam_curframe_testpattern);
    494 
    495 
    496 /*
    497  * video-buf interfaces for managing frame buffers
    498  * The device mutex is not held on entry to _any_ of these functions.
    499  */
    500 
    501 static int usbcam_videobuf_setup(struct videobuf_queue *vq,
    502 				 unsigned int *count, unsigned int *size)
    503 {
    504 	struct usbcam_fh *ufp = container_of(vq, struct usbcam_fh, ufh_vbq);
    505 	struct usbcam_dev *udp = ufp->ufh_dev;
    506 
    507 	usbcam_lock(udp);
    508 
    509 	/* APPBUG: possibly request larger buffers than necessary */
    510 	if ((ufp->ufh_flags & USBCAM_FH_USE_FIXED_FB) &&
    511 	    (fixed_fbsize > udp->ud_format.sizeimage))
    512 		*size = fixed_fbsize;
    513 	else
    514 		*size = udp->ud_format.sizeimage;
    515 
    516 	if (!*count)
    517 		*count = 2;
    518 
    519 	usbcam_dbg(udp, VIDEOBUF, "videobuf setup: size=%u count=%u",
    520 		   *size, *count);
    521 
    522 	usbcam_unlock(udp);
    523 	return 0;
    524 }
    525 
    526 static void usbcam_videobuf_free(struct videobuf_queue *vq,
    527 				 struct usbcam_frame *framep)
    528 {
    529 	struct videobuf_dmabuf *dma = usbframe_get_dmabuf(&framep->vbb);
    530 	
    531 	videobuf_waiton(&framep->vbb, 0, 0);
    532 	videobuf_dma_unmap(vq, dma);
    533 	videobuf_dma_free(dma);
    534 	if (framep->vbb.state != STATE_NEEDS_INIT) {
    535 		if (framep->vmap_base) {
    536 			vunmap(framep->vmap_base);
    537 			framep->vmap_base = NULL;
    538 			framep->vmap_sof = NULL;
    539 		}
    540 		assert(list_empty(&framep->cap_links));
    541 		framep->vbb.state = STATE_NEEDS_INIT;
    542 	}
    543 }
    544 
    545 static int usbcam_videobuf_prepare(struct videobuf_queue *vq,
    546 				   struct videobuf_buffer *vb,
    547 				   enum v4l2_field field)
    548 {
    549 	struct usbcam_fh *ufp = container_of(vq, struct usbcam_fh, ufh_vbq);
    550 	struct usbcam_dev *udp = ufp->ufh_dev;
    551 	struct usbcam_frame *framep =
    552 		container_of(vb, struct usbcam_frame, vbb);
    553 	struct videobuf_dmabuf *dma = usbframe_get_dmabuf(&framep->vbb);
    554 	int res;
    555 
    556 	framep->vbb.size = udp->ud_format.sizeimage;
    557 	if (framep->vbb.baddr && (framep->vbb.bsize < framep->vbb.size)) {
    558 		usbcam_warn(udp, "process %s requested capture of a frame "
    559 			    "larger than its", current->comm);
    560 		usbcam_warn(udp, "allocated frame buffer, fix it!");
    561 		return -EINVAL;
    562 	}
    563 
    564 	if (framep->vbb.state == STATE_NEEDS_INIT) {
    565 		/*
    566 		 * This is the place where we initialize the rest of
    567 		 * the usbcam_frame structure.
    568 		 */
    569 		INIT_LIST_HEAD(&framep->cap_links);
    570 		framep->vmap_base = NULL;
    571 		framep->vmap_sof = NULL;
    572 
    573 		usbcam_dbg(udp, VIDEOBUF,
    574 			   "preparing frame %d/%p", framep->vbb.i, framep);
    575 
    576 		/* We also lock down the memory that was allocated for it */
    577 		res = videobuf_iolock(vq, &framep->vbb, NULL);
    578 		if (res)
    579 			goto fail;
    580 
    581 		/* If there's no kernel mapping, we must create one */
    582 		if (!dma->vmalloc) {
    583 			framep->vmap_base = vmap(dma->pages,
    584 						 dma->nr_pages,
    585 						 VM_MAP,
    586 						 PAGE_KERNEL);
    587 			if (!framep->vmap_base) {
    588 				res = -ENOMEM;
    589 				goto fail;
    590 			}
    591 
    592 			framep->vmap_sof =
    593 				((char *)framep->vmap_base) +
    594 				dma->offset;
    595 		}
    596 	}
    597 
    598 	framep->vbb.field = field;
    599 	framep->vbb.state = STATE_PREPARED;
    600 	return 0;
    601 
    602 fail:
    603 	usbcam_videobuf_free(vq, framep);
    604 	return res;
    605 }
    606 
    607 static void usbcam_videobuf_queue(struct videobuf_queue *vq,
    608 				  struct videobuf_buffer *vb)
    609 {
    610 	struct usbcam_fh *ufp = container_of(vq, struct usbcam_fh, ufh_vbq);
    611 	struct usbcam_dev *udp = ufp->ufh_dev;
    612 	struct usbcam_frame *framep =
    613 		container_of(vb, struct usbcam_frame, vbb);
    614 	int was_empty = 0;
    615 
    616 	assert(framep->vbb.state != STATE_NEEDS_INIT);
    617 
    618 	usbcam_lock(udp);
    619 
    620 	if (list_empty(&udp->ud_frame_cap_queue))
    621 		was_empty = 1;
    622 
    623 	usbcam_dbg(udp, VIDEOBUF, "queueing frame %d/%p",
    624 		   framep->vbb.i, framep);
    625 
    626 	/*
    627 	 * We always set buffers to STATE_ACTIVE to prevent them from
    628 	 * being manipulated / dequeued by the videobuf code.
    629 	 */
    630 	list_add_tail(&framep->cap_links, &udp->ud_frame_cap_queue);
    631 	framep->vbb.state = STATE_ACTIVE;
    632 
    633 	if (was_empty && !udp->ud_capturing)
    634 		(void) usbcam_capture_start(udp);
    635 
    636 	usbcam_unlock(udp);
    637 }
    638 
    639 static void usbcam_videobuf_release(struct videobuf_queue *vq,
    640 				    struct videobuf_buffer *vb)
    641 {
    642 	struct usbcam_fh *ufp = container_of(vq, struct usbcam_fh, ufh_vbq);
    643 	struct usbcam_dev *udp = ufp->ufh_dev;
    644 	struct usbcam_frame *framep =
    645 		container_of(vb, struct usbcam_frame, vbb);
    646 	int stopped_capture = 0;
    647 
    648 	usbcam_lock(udp);
    649 
    650 	if ((framep->vbb.state != STATE_NEEDS_INIT) &&
    651 	    !list_empty(&framep->cap_links)) {
    652 
    653 		usbcam_dbg(udp, VIDEOBUF,
    654 			   "aborting frame %d/%p", framep->vbb.i, framep);
    655 
    656 		/*
    657 		 * An active frame is being shot down here, most
    658 		 * likely by videobuf_queue_cancel.
    659 		 */
    660 		assert(framep->vbb.state == STATE_ACTIVE);
    661 
    662 		if (udp->ud_capturing &&
    663 		    !list_empty(&udp->ud_frame_cap_queue) &&
    664 		    (framep == usbcam_capture_curframe(udp))) {
    665 			/*
    666 			 * The current frame has been user-aborted.
    667 			 * We will stop capturing.  The minidriver may complete
    668 			 * it with an error, or may leave it alone, in which
    669 			 * case we will complete it with an error.
    670 			 */
    671 			usbcam_dbg(udp, VIDEOBUF,
    672 				   "current frame aborted, stopping capture");
    673 
    674 			usbcam_capture_stop(udp);
    675 			stopped_capture = 1;
    676 		}
    677 
    678 		if (!list_empty(&framep->cap_links))
    679 			usbcam_capture_complete_frame(udp, framep, 1);
    680 
    681 		/*
    682 		 * Ideally, if we stopped capturing, and there are frames
    683 		 * still in the queue, we would restart.
    684 		 *
    685 		 * In reality, we only take this code path if all frames
    686 		 * from the owning file handle are aborted, and restarting
    687 		 * would pointlessly slow down this process.
    688 		 */
    689 	}
    690 
    691 	usbcam_unlock(udp);
    692 	usbcam_videobuf_free(vq, framep);
    693 }
    694 
    695 struct videobuf_queue_ops usbcam_videobuf_qops = {
    696 	.buf_setup	= usbcam_videobuf_setup,
    697 	.buf_prepare	= usbcam_videobuf_prepare,
    698 	.buf_queue	= usbcam_videobuf_queue,
    699 	.buf_release	= usbcam_videobuf_release,
    700 };