diff options
Diffstat (limited to 'drivers/media/video/videobuf-core.c')
-rw-r--r-- | drivers/media/video/videobuf-core.c | 1204 |
1 files changed, 1204 insertions, 0 deletions
diff --git a/drivers/media/video/videobuf-core.c b/drivers/media/video/videobuf-core.c new file mode 100644 index 00000000000..de4fa4eb884 --- /dev/null +++ b/drivers/media/video/videobuf-core.c | |||
@@ -0,0 +1,1204 @@ | |||
1 | /* | ||
2 | * generic helper functions for handling video4linux capture buffers | ||
3 | * | ||
4 | * (c) 2007 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
5 | * | ||
6 | * Highly based on video-buf written originally by: | ||
7 | * (c) 2001,02 Gerd Knorr <kraxel@bytesex.org> | ||
8 | * (c) 2006 Mauro Carvalho Chehab, <mchehab@infradead.org> | ||
9 | * (c) 2006 Ted Walther and John Sokol | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 | ||
14 | */ | ||
15 | |||
16 | #include <linux/init.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/mm.h> | ||
20 | #include <linux/sched.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | |||
24 | #include <media/videobuf-core.h> | ||
25 | |||
26 | #define MAGIC_BUFFER 0x20070728 | ||
27 | #define MAGIC_CHECK(is, should) \ | ||
28 | do { \ | ||
29 | if (unlikely((is) != (should))) { \ | ||
30 | printk(KERN_ERR \ | ||
31 | "magic mismatch: %x (expected %x)\n", \ | ||
32 | is, should); \ | ||
33 | BUG(); \ | ||
34 | } \ | ||
35 | } while (0) | ||
36 | |||
37 | static int debug; | ||
38 | module_param(debug, int, 0644); | ||
39 | |||
40 | MODULE_DESCRIPTION("helper module to manage video4linux buffers"); | ||
41 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | ||
42 | MODULE_LICENSE("GPL"); | ||
43 | |||
44 | #define dprintk(level, fmt, arg...) \ | ||
45 | do { \ | ||
46 | if (debug >= level) \ | ||
47 | printk(KERN_DEBUG "vbuf: " fmt, ## arg); \ | ||
48 | } while (0) | ||
49 | |||
50 | /* --------------------------------------------------------------------- */ | ||
51 | |||
52 | #define CALL(q, f, arg...) \ | ||
53 | ((q->int_ops->f) ? q->int_ops->f(arg) : 0) | ||
54 | |||
55 | struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q) | ||
56 | { | ||
57 | struct videobuf_buffer *vb; | ||
58 | |||
59 | BUG_ON(q->msize < sizeof(*vb)); | ||
60 | |||
61 | if (!q->int_ops || !q->int_ops->alloc_vb) { | ||
62 | printk(KERN_ERR "No specific ops defined!\n"); | ||
63 | BUG(); | ||
64 | } | ||
65 | |||
66 | vb = q->int_ops->alloc_vb(q->msize); | ||
67 | if (NULL != vb) { | ||
68 | init_waitqueue_head(&vb->done); | ||
69 | vb->magic = MAGIC_BUFFER; | ||
70 | } | ||
71 | |||
72 | return vb; | ||
73 | } | ||
74 | EXPORT_SYMBOL_GPL(videobuf_alloc_vb); | ||
75 | |||
76 | static int is_state_active_or_queued(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
77 | { | ||
78 | unsigned long flags; | ||
79 | bool rc; | ||
80 | |||
81 | spin_lock_irqsave(q->irqlock, flags); | ||
82 | rc = vb->state != VIDEOBUF_ACTIVE && vb->state != VIDEOBUF_QUEUED; | ||
83 | spin_unlock_irqrestore(q->irqlock, flags); | ||
84 | return rc; | ||
85 | }; | ||
86 | |||
87 | int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
88 | int non_blocking, int intr) | ||
89 | { | ||
90 | bool is_ext_locked; | ||
91 | int ret = 0; | ||
92 | |||
93 | MAGIC_CHECK(vb->magic, MAGIC_BUFFER); | ||
94 | |||
95 | if (non_blocking) { | ||
96 | if (is_state_active_or_queued(q, vb)) | ||
97 | return 0; | ||
98 | return -EAGAIN; | ||
99 | } | ||
100 | |||
101 | is_ext_locked = q->ext_lock && mutex_is_locked(q->ext_lock); | ||
102 | |||
103 | /* Release vdev lock to prevent this wait from blocking outside access to | ||
104 | the device. */ | ||
105 | if (is_ext_locked) | ||
106 | mutex_unlock(q->ext_lock); | ||
107 | if (intr) | ||
108 | ret = wait_event_interruptible(vb->done, is_state_active_or_queued(q, vb)); | ||
109 | else | ||
110 | wait_event(vb->done, is_state_active_or_queued(q, vb)); | ||
111 | /* Relock */ | ||
112 | if (is_ext_locked) | ||
113 | mutex_lock(q->ext_lock); | ||
114 | |||
115 | return ret; | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(videobuf_waiton); | ||
118 | |||
119 | int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
120 | struct v4l2_framebuffer *fbuf) | ||
121 | { | ||
122 | MAGIC_CHECK(vb->magic, MAGIC_BUFFER); | ||
123 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
124 | |||
125 | return CALL(q, iolock, q, vb, fbuf); | ||
126 | } | ||
127 | EXPORT_SYMBOL_GPL(videobuf_iolock); | ||
128 | |||
129 | void *videobuf_queue_to_vaddr(struct videobuf_queue *q, | ||
130 | struct videobuf_buffer *buf) | ||
131 | { | ||
132 | if (q->int_ops->vaddr) | ||
133 | return q->int_ops->vaddr(buf); | ||
134 | return NULL; | ||
135 | } | ||
136 | EXPORT_SYMBOL_GPL(videobuf_queue_to_vaddr); | ||
137 | |||
138 | /* --------------------------------------------------------------------- */ | ||
139 | |||
140 | |||
141 | void videobuf_queue_core_init(struct videobuf_queue *q, | ||
142 | const struct videobuf_queue_ops *ops, | ||
143 | struct device *dev, | ||
144 | spinlock_t *irqlock, | ||
145 | enum v4l2_buf_type type, | ||
146 | enum v4l2_field field, | ||
147 | unsigned int msize, | ||
148 | void *priv, | ||
149 | struct videobuf_qtype_ops *int_ops, | ||
150 | struct mutex *ext_lock) | ||
151 | { | ||
152 | BUG_ON(!q); | ||
153 | memset(q, 0, sizeof(*q)); | ||
154 | q->irqlock = irqlock; | ||
155 | q->ext_lock = ext_lock; | ||
156 | q->dev = dev; | ||
157 | q->type = type; | ||
158 | q->field = field; | ||
159 | q->msize = msize; | ||
160 | q->ops = ops; | ||
161 | q->priv_data = priv; | ||
162 | q->int_ops = int_ops; | ||
163 | |||
164 | /* All buffer operations are mandatory */ | ||
165 | BUG_ON(!q->ops->buf_setup); | ||
166 | BUG_ON(!q->ops->buf_prepare); | ||
167 | BUG_ON(!q->ops->buf_queue); | ||
168 | BUG_ON(!q->ops->buf_release); | ||
169 | |||
170 | /* Lock is mandatory for queue_cancel to work */ | ||
171 | BUG_ON(!irqlock); | ||
172 | |||
173 | /* Having implementations for abstract methods are mandatory */ | ||
174 | BUG_ON(!q->int_ops); | ||
175 | |||
176 | mutex_init(&q->vb_lock); | ||
177 | init_waitqueue_head(&q->wait); | ||
178 | INIT_LIST_HEAD(&q->stream); | ||
179 | } | ||
180 | EXPORT_SYMBOL_GPL(videobuf_queue_core_init); | ||
181 | |||
182 | /* Locking: Only usage in bttv unsafe find way to remove */ | ||
183 | int videobuf_queue_is_busy(struct videobuf_queue *q) | ||
184 | { | ||
185 | int i; | ||
186 | |||
187 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
188 | |||
189 | if (q->streaming) { | ||
190 | dprintk(1, "busy: streaming active\n"); | ||
191 | return 1; | ||
192 | } | ||
193 | if (q->reading) { | ||
194 | dprintk(1, "busy: pending read #1\n"); | ||
195 | return 1; | ||
196 | } | ||
197 | if (q->read_buf) { | ||
198 | dprintk(1, "busy: pending read #2\n"); | ||
199 | return 1; | ||
200 | } | ||
201 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
202 | if (NULL == q->bufs[i]) | ||
203 | continue; | ||
204 | if (q->bufs[i]->map) { | ||
205 | dprintk(1, "busy: buffer #%d mapped\n", i); | ||
206 | return 1; | ||
207 | } | ||
208 | if (q->bufs[i]->state == VIDEOBUF_QUEUED) { | ||
209 | dprintk(1, "busy: buffer #%d queued\n", i); | ||
210 | return 1; | ||
211 | } | ||
212 | if (q->bufs[i]->state == VIDEOBUF_ACTIVE) { | ||
213 | dprintk(1, "busy: buffer #%d avtive\n", i); | ||
214 | return 1; | ||
215 | } | ||
216 | } | ||
217 | return 0; | ||
218 | } | ||
219 | EXPORT_SYMBOL_GPL(videobuf_queue_is_busy); | ||
220 | |||
221 | /** | ||
222 | * __videobuf_free() - free all the buffers and their control structures | ||
223 | * | ||
224 | * This function can only be called if streaming/reading is off, i.e. no buffers | ||
225 | * are under control of the driver. | ||
226 | */ | ||
227 | /* Locking: Caller holds q->vb_lock */ | ||
228 | static int __videobuf_free(struct videobuf_queue *q) | ||
229 | { | ||
230 | int i; | ||
231 | |||
232 | dprintk(1, "%s\n", __func__); | ||
233 | if (!q) | ||
234 | return 0; | ||
235 | |||
236 | if (q->streaming || q->reading) { | ||
237 | dprintk(1, "Cannot free buffers when streaming or reading\n"); | ||
238 | return -EBUSY; | ||
239 | } | ||
240 | |||
241 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
242 | |||
243 | for (i = 0; i < VIDEO_MAX_FRAME; i++) | ||
244 | if (q->bufs[i] && q->bufs[i]->map) { | ||
245 | dprintk(1, "Cannot free mmapped buffers\n"); | ||
246 | return -EBUSY; | ||
247 | } | ||
248 | |||
249 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
250 | if (NULL == q->bufs[i]) | ||
251 | continue; | ||
252 | q->ops->buf_release(q, q->bufs[i]); | ||
253 | kfree(q->bufs[i]); | ||
254 | q->bufs[i] = NULL; | ||
255 | } | ||
256 | |||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /* Locking: Caller holds q->vb_lock */ | ||
261 | void videobuf_queue_cancel(struct videobuf_queue *q) | ||
262 | { | ||
263 | unsigned long flags = 0; | ||
264 | int i; | ||
265 | |||
266 | q->streaming = 0; | ||
267 | q->reading = 0; | ||
268 | wake_up_interruptible_sync(&q->wait); | ||
269 | |||
270 | /* remove queued buffers from list */ | ||
271 | spin_lock_irqsave(q->irqlock, flags); | ||
272 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
273 | if (NULL == q->bufs[i]) | ||
274 | continue; | ||
275 | if (q->bufs[i]->state == VIDEOBUF_QUEUED) { | ||
276 | list_del(&q->bufs[i]->queue); | ||
277 | q->bufs[i]->state = VIDEOBUF_ERROR; | ||
278 | wake_up_all(&q->bufs[i]->done); | ||
279 | } | ||
280 | } | ||
281 | spin_unlock_irqrestore(q->irqlock, flags); | ||
282 | |||
283 | /* free all buffers + clear queue */ | ||
284 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
285 | if (NULL == q->bufs[i]) | ||
286 | continue; | ||
287 | q->ops->buf_release(q, q->bufs[i]); | ||
288 | } | ||
289 | INIT_LIST_HEAD(&q->stream); | ||
290 | } | ||
291 | EXPORT_SYMBOL_GPL(videobuf_queue_cancel); | ||
292 | |||
293 | /* --------------------------------------------------------------------- */ | ||
294 | |||
295 | /* Locking: Caller holds q->vb_lock */ | ||
296 | enum v4l2_field videobuf_next_field(struct videobuf_queue *q) | ||
297 | { | ||
298 | enum v4l2_field field = q->field; | ||
299 | |||
300 | BUG_ON(V4L2_FIELD_ANY == field); | ||
301 | |||
302 | if (V4L2_FIELD_ALTERNATE == field) { | ||
303 | if (V4L2_FIELD_TOP == q->last) { | ||
304 | field = V4L2_FIELD_BOTTOM; | ||
305 | q->last = V4L2_FIELD_BOTTOM; | ||
306 | } else { | ||
307 | field = V4L2_FIELD_TOP; | ||
308 | q->last = V4L2_FIELD_TOP; | ||
309 | } | ||
310 | } | ||
311 | return field; | ||
312 | } | ||
313 | EXPORT_SYMBOL_GPL(videobuf_next_field); | ||
314 | |||
315 | /* Locking: Caller holds q->vb_lock */ | ||
316 | static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, | ||
317 | struct videobuf_buffer *vb, enum v4l2_buf_type type) | ||
318 | { | ||
319 | MAGIC_CHECK(vb->magic, MAGIC_BUFFER); | ||
320 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
321 | |||
322 | b->index = vb->i; | ||
323 | b->type = type; | ||
324 | |||
325 | b->memory = vb->memory; | ||
326 | switch (b->memory) { | ||
327 | case V4L2_MEMORY_MMAP: | ||
328 | b->m.offset = vb->boff; | ||
329 | b->length = vb->bsize; | ||
330 | break; | ||
331 | case V4L2_MEMORY_USERPTR: | ||
332 | b->m.userptr = vb->baddr; | ||
333 | b->length = vb->bsize; | ||
334 | break; | ||
335 | case V4L2_MEMORY_OVERLAY: | ||
336 | b->m.offset = vb->boff; | ||
337 | break; | ||
338 | } | ||
339 | |||
340 | b->flags = 0; | ||
341 | if (vb->map) | ||
342 | b->flags |= V4L2_BUF_FLAG_MAPPED; | ||
343 | |||
344 | switch (vb->state) { | ||
345 | case VIDEOBUF_PREPARED: | ||
346 | case VIDEOBUF_QUEUED: | ||
347 | case VIDEOBUF_ACTIVE: | ||
348 | b->flags |= V4L2_BUF_FLAG_QUEUED; | ||
349 | break; | ||
350 | case VIDEOBUF_ERROR: | ||
351 | b->flags |= V4L2_BUF_FLAG_ERROR; | ||
352 | /* fall through */ | ||
353 | case VIDEOBUF_DONE: | ||
354 | b->flags |= V4L2_BUF_FLAG_DONE; | ||
355 | break; | ||
356 | case VIDEOBUF_NEEDS_INIT: | ||
357 | case VIDEOBUF_IDLE: | ||
358 | /* nothing */ | ||
359 | break; | ||
360 | } | ||
361 | |||
362 | if (vb->input != UNSET) { | ||
363 | b->flags |= V4L2_BUF_FLAG_INPUT; | ||
364 | b->input = vb->input; | ||
365 | } | ||
366 | |||
367 | b->field = vb->field; | ||
368 | b->timestamp = vb->ts; | ||
369 | b->bytesused = vb->size; | ||
370 | b->sequence = vb->field_count >> 1; | ||
371 | } | ||
372 | |||
373 | int videobuf_mmap_free(struct videobuf_queue *q) | ||
374 | { | ||
375 | int ret; | ||
376 | videobuf_queue_lock(q); | ||
377 | ret = __videobuf_free(q); | ||
378 | videobuf_queue_unlock(q); | ||
379 | return ret; | ||
380 | } | ||
381 | EXPORT_SYMBOL_GPL(videobuf_mmap_free); | ||
382 | |||
383 | /* Locking: Caller holds q->vb_lock */ | ||
384 | int __videobuf_mmap_setup(struct videobuf_queue *q, | ||
385 | unsigned int bcount, unsigned int bsize, | ||
386 | enum v4l2_memory memory) | ||
387 | { | ||
388 | unsigned int i; | ||
389 | int err; | ||
390 | |||
391 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
392 | |||
393 | err = __videobuf_free(q); | ||
394 | if (0 != err) | ||
395 | return err; | ||
396 | |||
397 | /* Allocate and initialize buffers */ | ||
398 | for (i = 0; i < bcount; i++) { | ||
399 | q->bufs[i] = videobuf_alloc_vb(q); | ||
400 | |||
401 | if (NULL == q->bufs[i]) | ||
402 | break; | ||
403 | |||
404 | q->bufs[i]->i = i; | ||
405 | q->bufs[i]->input = UNSET; | ||
406 | q->bufs[i]->memory = memory; | ||
407 | q->bufs[i]->bsize = bsize; | ||
408 | switch (memory) { | ||
409 | case V4L2_MEMORY_MMAP: | ||
410 | q->bufs[i]->boff = PAGE_ALIGN(bsize) * i; | ||
411 | break; | ||
412 | case V4L2_MEMORY_USERPTR: | ||
413 | case V4L2_MEMORY_OVERLAY: | ||
414 | /* nothing */ | ||
415 | break; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | if (!i) | ||
420 | return -ENOMEM; | ||
421 | |||
422 | dprintk(1, "mmap setup: %d buffers, %d bytes each\n", i, bsize); | ||
423 | |||
424 | return i; | ||
425 | } | ||
426 | EXPORT_SYMBOL_GPL(__videobuf_mmap_setup); | ||
427 | |||
428 | int videobuf_mmap_setup(struct videobuf_queue *q, | ||
429 | unsigned int bcount, unsigned int bsize, | ||
430 | enum v4l2_memory memory) | ||
431 | { | ||
432 | int ret; | ||
433 | videobuf_queue_lock(q); | ||
434 | ret = __videobuf_mmap_setup(q, bcount, bsize, memory); | ||
435 | videobuf_queue_unlock(q); | ||
436 | return ret; | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(videobuf_mmap_setup); | ||
439 | |||
440 | int videobuf_reqbufs(struct videobuf_queue *q, | ||
441 | struct v4l2_requestbuffers *req) | ||
442 | { | ||
443 | unsigned int size, count; | ||
444 | int retval; | ||
445 | |||
446 | if (req->count < 1) { | ||
447 | dprintk(1, "reqbufs: count invalid (%d)\n", req->count); | ||
448 | return -EINVAL; | ||
449 | } | ||
450 | |||
451 | if (req->memory != V4L2_MEMORY_MMAP && | ||
452 | req->memory != V4L2_MEMORY_USERPTR && | ||
453 | req->memory != V4L2_MEMORY_OVERLAY) { | ||
454 | dprintk(1, "reqbufs: memory type invalid\n"); | ||
455 | return -EINVAL; | ||
456 | } | ||
457 | |||
458 | videobuf_queue_lock(q); | ||
459 | if (req->type != q->type) { | ||
460 | dprintk(1, "reqbufs: queue type invalid\n"); | ||
461 | retval = -EINVAL; | ||
462 | goto done; | ||
463 | } | ||
464 | |||
465 | if (q->streaming) { | ||
466 | dprintk(1, "reqbufs: streaming already exists\n"); | ||
467 | retval = -EBUSY; | ||
468 | goto done; | ||
469 | } | ||
470 | if (!list_empty(&q->stream)) { | ||
471 | dprintk(1, "reqbufs: stream running\n"); | ||
472 | retval = -EBUSY; | ||
473 | goto done; | ||
474 | } | ||
475 | |||
476 | count = req->count; | ||
477 | if (count > VIDEO_MAX_FRAME) | ||
478 | count = VIDEO_MAX_FRAME; | ||
479 | size = 0; | ||
480 | q->ops->buf_setup(q, &count, &size); | ||
481 | dprintk(1, "reqbufs: bufs=%d, size=0x%x [%u pages total]\n", | ||
482 | count, size, | ||
483 | (unsigned int)((count * PAGE_ALIGN(size)) >> PAGE_SHIFT)); | ||
484 | |||
485 | retval = __videobuf_mmap_setup(q, count, size, req->memory); | ||
486 | if (retval < 0) { | ||
487 | dprintk(1, "reqbufs: mmap setup returned %d\n", retval); | ||
488 | goto done; | ||
489 | } | ||
490 | |||
491 | req->count = retval; | ||
492 | retval = 0; | ||
493 | |||
494 | done: | ||
495 | videobuf_queue_unlock(q); | ||
496 | return retval; | ||
497 | } | ||
498 | EXPORT_SYMBOL_GPL(videobuf_reqbufs); | ||
499 | |||
500 | int videobuf_querybuf(struct videobuf_queue *q, struct v4l2_buffer *b) | ||
501 | { | ||
502 | int ret = -EINVAL; | ||
503 | |||
504 | videobuf_queue_lock(q); | ||
505 | if (unlikely(b->type != q->type)) { | ||
506 | dprintk(1, "querybuf: Wrong type.\n"); | ||
507 | goto done; | ||
508 | } | ||
509 | if (unlikely(b->index >= VIDEO_MAX_FRAME)) { | ||
510 | dprintk(1, "querybuf: index out of range.\n"); | ||
511 | goto done; | ||
512 | } | ||
513 | if (unlikely(NULL == q->bufs[b->index])) { | ||
514 | dprintk(1, "querybuf: buffer is null.\n"); | ||
515 | goto done; | ||
516 | } | ||
517 | |||
518 | videobuf_status(q, b, q->bufs[b->index], q->type); | ||
519 | |||
520 | ret = 0; | ||
521 | done: | ||
522 | videobuf_queue_unlock(q); | ||
523 | return ret; | ||
524 | } | ||
525 | EXPORT_SYMBOL_GPL(videobuf_querybuf); | ||
526 | |||
527 | int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b) | ||
528 | { | ||
529 | struct videobuf_buffer *buf; | ||
530 | enum v4l2_field field; | ||
531 | unsigned long flags = 0; | ||
532 | int retval; | ||
533 | |||
534 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
535 | |||
536 | if (b->memory == V4L2_MEMORY_MMAP) | ||
537 | down_read(¤t->mm->mmap_sem); | ||
538 | |||
539 | videobuf_queue_lock(q); | ||
540 | retval = -EBUSY; | ||
541 | if (q->reading) { | ||
542 | dprintk(1, "qbuf: Reading running...\n"); | ||
543 | goto done; | ||
544 | } | ||
545 | retval = -EINVAL; | ||
546 | if (b->type != q->type) { | ||
547 | dprintk(1, "qbuf: Wrong type.\n"); | ||
548 | goto done; | ||
549 | } | ||
550 | if (b->index >= VIDEO_MAX_FRAME) { | ||
551 | dprintk(1, "qbuf: index out of range.\n"); | ||
552 | goto done; | ||
553 | } | ||
554 | buf = q->bufs[b->index]; | ||
555 | if (NULL == buf) { | ||
556 | dprintk(1, "qbuf: buffer is null.\n"); | ||
557 | goto done; | ||
558 | } | ||
559 | MAGIC_CHECK(buf->magic, MAGIC_BUFFER); | ||
560 | if (buf->memory != b->memory) { | ||
561 | dprintk(1, "qbuf: memory type is wrong.\n"); | ||
562 | goto done; | ||
563 | } | ||
564 | if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) { | ||
565 | dprintk(1, "qbuf: buffer is already queued or active.\n"); | ||
566 | goto done; | ||
567 | } | ||
568 | |||
569 | if (b->flags & V4L2_BUF_FLAG_INPUT) { | ||
570 | if (b->input >= q->inputs) { | ||
571 | dprintk(1, "qbuf: wrong input.\n"); | ||
572 | goto done; | ||
573 | } | ||
574 | buf->input = b->input; | ||
575 | } else { | ||
576 | buf->input = UNSET; | ||
577 | } | ||
578 | |||
579 | switch (b->memory) { | ||
580 | case V4L2_MEMORY_MMAP: | ||
581 | if (0 == buf->baddr) { | ||
582 | dprintk(1, "qbuf: mmap requested " | ||
583 | "but buffer addr is zero!\n"); | ||
584 | goto done; | ||
585 | } | ||
586 | if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT | ||
587 | || q->type == V4L2_BUF_TYPE_VBI_OUTPUT | ||
588 | || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT) { | ||
589 | buf->size = b->bytesused; | ||
590 | buf->field = b->field; | ||
591 | buf->ts = b->timestamp; | ||
592 | } | ||
593 | break; | ||
594 | case V4L2_MEMORY_USERPTR: | ||
595 | if (b->length < buf->bsize) { | ||
596 | dprintk(1, "qbuf: buffer length is not enough\n"); | ||
597 | goto done; | ||
598 | } | ||
599 | if (VIDEOBUF_NEEDS_INIT != buf->state && | ||
600 | buf->baddr != b->m.userptr) | ||
601 | q->ops->buf_release(q, buf); | ||
602 | buf->baddr = b->m.userptr; | ||
603 | break; | ||
604 | case V4L2_MEMORY_OVERLAY: | ||
605 | buf->boff = b->m.offset; | ||
606 | break; | ||
607 | default: | ||
608 | dprintk(1, "qbuf: wrong memory type\n"); | ||
609 | goto done; | ||
610 | } | ||
611 | |||
612 | dprintk(1, "qbuf: requesting next field\n"); | ||
613 | field = videobuf_next_field(q); | ||
614 | retval = q->ops->buf_prepare(q, buf, field); | ||
615 | if (0 != retval) { | ||
616 | dprintk(1, "qbuf: buffer_prepare returned %d\n", retval); | ||
617 | goto done; | ||
618 | } | ||
619 | |||
620 | list_add_tail(&buf->stream, &q->stream); | ||
621 | if (q->streaming) { | ||
622 | spin_lock_irqsave(q->irqlock, flags); | ||
623 | q->ops->buf_queue(q, buf); | ||
624 | spin_unlock_irqrestore(q->irqlock, flags); | ||
625 | } | ||
626 | dprintk(1, "qbuf: succeeded\n"); | ||
627 | retval = 0; | ||
628 | wake_up_interruptible_sync(&q->wait); | ||
629 | |||
630 | done: | ||
631 | videobuf_queue_unlock(q); | ||
632 | |||
633 | if (b->memory == V4L2_MEMORY_MMAP) | ||
634 | up_read(¤t->mm->mmap_sem); | ||
635 | |||
636 | return retval; | ||
637 | } | ||
638 | EXPORT_SYMBOL_GPL(videobuf_qbuf); | ||
639 | |||
640 | /* Locking: Caller holds q->vb_lock */ | ||
641 | static int stream_next_buffer_check_queue(struct videobuf_queue *q, int noblock) | ||
642 | { | ||
643 | int retval; | ||
644 | |||
645 | checks: | ||
646 | if (!q->streaming) { | ||
647 | dprintk(1, "next_buffer: Not streaming\n"); | ||
648 | retval = -EINVAL; | ||
649 | goto done; | ||
650 | } | ||
651 | |||
652 | if (list_empty(&q->stream)) { | ||
653 | if (noblock) { | ||
654 | retval = -EAGAIN; | ||
655 | dprintk(2, "next_buffer: no buffers to dequeue\n"); | ||
656 | goto done; | ||
657 | } else { | ||
658 | dprintk(2, "next_buffer: waiting on buffer\n"); | ||
659 | |||
660 | /* Drop lock to avoid deadlock with qbuf */ | ||
661 | videobuf_queue_unlock(q); | ||
662 | |||
663 | /* Checking list_empty and streaming is safe without | ||
664 | * locks because we goto checks to validate while | ||
665 | * holding locks before proceeding */ | ||
666 | retval = wait_event_interruptible(q->wait, | ||
667 | !list_empty(&q->stream) || !q->streaming); | ||
668 | videobuf_queue_lock(q); | ||
669 | |||
670 | if (retval) | ||
671 | goto done; | ||
672 | |||
673 | goto checks; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | retval = 0; | ||
678 | |||
679 | done: | ||
680 | return retval; | ||
681 | } | ||
682 | |||
683 | /* Locking: Caller holds q->vb_lock */ | ||
684 | static int stream_next_buffer(struct videobuf_queue *q, | ||
685 | struct videobuf_buffer **vb, int nonblocking) | ||
686 | { | ||
687 | int retval; | ||
688 | struct videobuf_buffer *buf = NULL; | ||
689 | |||
690 | retval = stream_next_buffer_check_queue(q, nonblocking); | ||
691 | if (retval) | ||
692 | goto done; | ||
693 | |||
694 | buf = list_entry(q->stream.next, struct videobuf_buffer, stream); | ||
695 | retval = videobuf_waiton(q, buf, nonblocking, 1); | ||
696 | if (retval < 0) | ||
697 | goto done; | ||
698 | |||
699 | *vb = buf; | ||
700 | done: | ||
701 | return retval; | ||
702 | } | ||
703 | |||
704 | int videobuf_dqbuf(struct videobuf_queue *q, | ||
705 | struct v4l2_buffer *b, int nonblocking) | ||
706 | { | ||
707 | struct videobuf_buffer *buf = NULL; | ||
708 | int retval; | ||
709 | |||
710 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
711 | |||
712 | memset(b, 0, sizeof(*b)); | ||
713 | videobuf_queue_lock(q); | ||
714 | |||
715 | retval = stream_next_buffer(q, &buf, nonblocking); | ||
716 | if (retval < 0) { | ||
717 | dprintk(1, "dqbuf: next_buffer error: %i\n", retval); | ||
718 | goto done; | ||
719 | } | ||
720 | |||
721 | switch (buf->state) { | ||
722 | case VIDEOBUF_ERROR: | ||
723 | dprintk(1, "dqbuf: state is error\n"); | ||
724 | break; | ||
725 | case VIDEOBUF_DONE: | ||
726 | dprintk(1, "dqbuf: state is done\n"); | ||
727 | break; | ||
728 | default: | ||
729 | dprintk(1, "dqbuf: state invalid\n"); | ||
730 | retval = -EINVAL; | ||
731 | goto done; | ||
732 | } | ||
733 | CALL(q, sync, q, buf); | ||
734 | videobuf_status(q, b, buf, q->type); | ||
735 | list_del(&buf->stream); | ||
736 | buf->state = VIDEOBUF_IDLE; | ||
737 | b->flags &= ~V4L2_BUF_FLAG_DONE; | ||
738 | done: | ||
739 | videobuf_queue_unlock(q); | ||
740 | return retval; | ||
741 | } | ||
742 | EXPORT_SYMBOL_GPL(videobuf_dqbuf); | ||
743 | |||
744 | int videobuf_streamon(struct videobuf_queue *q) | ||
745 | { | ||
746 | struct videobuf_buffer *buf; | ||
747 | unsigned long flags = 0; | ||
748 | int retval; | ||
749 | |||
750 | videobuf_queue_lock(q); | ||
751 | retval = -EBUSY; | ||
752 | if (q->reading) | ||
753 | goto done; | ||
754 | retval = 0; | ||
755 | if (q->streaming) | ||
756 | goto done; | ||
757 | q->streaming = 1; | ||
758 | spin_lock_irqsave(q->irqlock, flags); | ||
759 | list_for_each_entry(buf, &q->stream, stream) | ||
760 | if (buf->state == VIDEOBUF_PREPARED) | ||
761 | q->ops->buf_queue(q, buf); | ||
762 | spin_unlock_irqrestore(q->irqlock, flags); | ||
763 | |||
764 | wake_up_interruptible_sync(&q->wait); | ||
765 | done: | ||
766 | videobuf_queue_unlock(q); | ||
767 | return retval; | ||
768 | } | ||
769 | EXPORT_SYMBOL_GPL(videobuf_streamon); | ||
770 | |||
771 | /* Locking: Caller holds q->vb_lock */ | ||
772 | static int __videobuf_streamoff(struct videobuf_queue *q) | ||
773 | { | ||
774 | if (!q->streaming) | ||
775 | return -EINVAL; | ||
776 | |||
777 | videobuf_queue_cancel(q); | ||
778 | |||
779 | return 0; | ||
780 | } | ||
781 | |||
782 | int videobuf_streamoff(struct videobuf_queue *q) | ||
783 | { | ||
784 | int retval; | ||
785 | |||
786 | videobuf_queue_lock(q); | ||
787 | retval = __videobuf_streamoff(q); | ||
788 | videobuf_queue_unlock(q); | ||
789 | |||
790 | return retval; | ||
791 | } | ||
792 | EXPORT_SYMBOL_GPL(videobuf_streamoff); | ||
793 | |||
794 | /* Locking: Caller holds q->vb_lock */ | ||
795 | static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, | ||
796 | char __user *data, | ||
797 | size_t count, loff_t *ppos) | ||
798 | { | ||
799 | enum v4l2_field field; | ||
800 | unsigned long flags = 0; | ||
801 | int retval; | ||
802 | |||
803 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
804 | |||
805 | /* setup stuff */ | ||
806 | q->read_buf = videobuf_alloc_vb(q); | ||
807 | if (NULL == q->read_buf) | ||
808 | return -ENOMEM; | ||
809 | |||
810 | q->read_buf->memory = V4L2_MEMORY_USERPTR; | ||
811 | q->read_buf->baddr = (unsigned long)data; | ||
812 | q->read_buf->bsize = count; | ||
813 | |||
814 | field = videobuf_next_field(q); | ||
815 | retval = q->ops->buf_prepare(q, q->read_buf, field); | ||
816 | if (0 != retval) | ||
817 | goto done; | ||
818 | |||
819 | /* start capture & wait */ | ||
820 | spin_lock_irqsave(q->irqlock, flags); | ||
821 | q->ops->buf_queue(q, q->read_buf); | ||
822 | spin_unlock_irqrestore(q->irqlock, flags); | ||
823 | retval = videobuf_waiton(q, q->read_buf, 0, 0); | ||
824 | if (0 == retval) { | ||
825 | CALL(q, sync, q, q->read_buf); | ||
826 | if (VIDEOBUF_ERROR == q->read_buf->state) | ||
827 | retval = -EIO; | ||
828 | else | ||
829 | retval = q->read_buf->size; | ||
830 | } | ||
831 | |||
832 | done: | ||
833 | /* cleanup */ | ||
834 | q->ops->buf_release(q, q->read_buf); | ||
835 | kfree(q->read_buf); | ||
836 | q->read_buf = NULL; | ||
837 | return retval; | ||
838 | } | ||
839 | |||
840 | static int __videobuf_copy_to_user(struct videobuf_queue *q, | ||
841 | struct videobuf_buffer *buf, | ||
842 | char __user *data, size_t count, | ||
843 | int nonblocking) | ||
844 | { | ||
845 | void *vaddr = CALL(q, vaddr, buf); | ||
846 | |||
847 | /* copy to userspace */ | ||
848 | if (count > buf->size - q->read_off) | ||
849 | count = buf->size - q->read_off; | ||
850 | |||
851 | if (copy_to_user(data, vaddr + q->read_off, count)) | ||
852 | return -EFAULT; | ||
853 | |||
854 | return count; | ||
855 | } | ||
856 | |||
857 | static int __videobuf_copy_stream(struct videobuf_queue *q, | ||
858 | struct videobuf_buffer *buf, | ||
859 | char __user *data, size_t count, size_t pos, | ||
860 | int vbihack, int nonblocking) | ||
861 | { | ||
862 | unsigned int *fc = CALL(q, vaddr, buf); | ||
863 | |||
864 | if (vbihack) { | ||
865 | /* dirty, undocumented hack -- pass the frame counter | ||
866 | * within the last four bytes of each vbi data block. | ||
867 | * We need that one to maintain backward compatibility | ||
868 | * to all vbi decoding software out there ... */ | ||
869 | fc += (buf->size >> 2) - 1; | ||
870 | *fc = buf->field_count >> 1; | ||
871 | dprintk(1, "vbihack: %d\n", *fc); | ||
872 | } | ||
873 | |||
874 | /* copy stuff using the common method */ | ||
875 | count = __videobuf_copy_to_user(q, buf, data, count, nonblocking); | ||
876 | |||
877 | if ((count == -EFAULT) && (pos == 0)) | ||
878 | return -EFAULT; | ||
879 | |||
880 | return count; | ||
881 | } | ||
882 | |||
883 | ssize_t videobuf_read_one(struct videobuf_queue *q, | ||
884 | char __user *data, size_t count, loff_t *ppos, | ||
885 | int nonblocking) | ||
886 | { | ||
887 | enum v4l2_field field; | ||
888 | unsigned long flags = 0; | ||
889 | unsigned size = 0, nbufs = 1; | ||
890 | int retval; | ||
891 | |||
892 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
893 | |||
894 | videobuf_queue_lock(q); | ||
895 | |||
896 | q->ops->buf_setup(q, &nbufs, &size); | ||
897 | |||
898 | if (NULL == q->read_buf && | ||
899 | count >= size && | ||
900 | !nonblocking) { | ||
901 | retval = videobuf_read_zerocopy(q, data, count, ppos); | ||
902 | if (retval >= 0 || retval == -EIO) | ||
903 | /* ok, all done */ | ||
904 | goto done; | ||
905 | /* fallback to kernel bounce buffer on failures */ | ||
906 | } | ||
907 | |||
908 | if (NULL == q->read_buf) { | ||
909 | /* need to capture a new frame */ | ||
910 | retval = -ENOMEM; | ||
911 | q->read_buf = videobuf_alloc_vb(q); | ||
912 | |||
913 | dprintk(1, "video alloc=0x%p\n", q->read_buf); | ||
914 | if (NULL == q->read_buf) | ||
915 | goto done; | ||
916 | q->read_buf->memory = V4L2_MEMORY_USERPTR; | ||
917 | q->read_buf->bsize = count; /* preferred size */ | ||
918 | field = videobuf_next_field(q); | ||
919 | retval = q->ops->buf_prepare(q, q->read_buf, field); | ||
920 | |||
921 | if (0 != retval) { | ||
922 | kfree(q->read_buf); | ||
923 | q->read_buf = NULL; | ||
924 | goto done; | ||
925 | } | ||
926 | |||
927 | spin_lock_irqsave(q->irqlock, flags); | ||
928 | q->ops->buf_queue(q, q->read_buf); | ||
929 | spin_unlock_irqrestore(q->irqlock, flags); | ||
930 | |||
931 | q->read_off = 0; | ||
932 | } | ||
933 | |||
934 | /* wait until capture is done */ | ||
935 | retval = videobuf_waiton(q, q->read_buf, nonblocking, 1); | ||
936 | if (0 != retval) | ||
937 | goto done; | ||
938 | |||
939 | CALL(q, sync, q, q->read_buf); | ||
940 | |||
941 | if (VIDEOBUF_ERROR == q->read_buf->state) { | ||
942 | /* catch I/O errors */ | ||
943 | q->ops->buf_release(q, q->read_buf); | ||
944 | kfree(q->read_buf); | ||
945 | q->read_buf = NULL; | ||
946 | retval = -EIO; | ||
947 | goto done; | ||
948 | } | ||
949 | |||
950 | /* Copy to userspace */ | ||
951 | retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking); | ||
952 | if (retval < 0) | ||
953 | goto done; | ||
954 | |||
955 | q->read_off += retval; | ||
956 | if (q->read_off == q->read_buf->size) { | ||
957 | /* all data copied, cleanup */ | ||
958 | q->ops->buf_release(q, q->read_buf); | ||
959 | kfree(q->read_buf); | ||
960 | q->read_buf = NULL; | ||
961 | } | ||
962 | |||
963 | done: | ||
964 | videobuf_queue_unlock(q); | ||
965 | return retval; | ||
966 | } | ||
967 | EXPORT_SYMBOL_GPL(videobuf_read_one); | ||
968 | |||
969 | /* Locking: Caller holds q->vb_lock */ | ||
970 | static int __videobuf_read_start(struct videobuf_queue *q) | ||
971 | { | ||
972 | enum v4l2_field field; | ||
973 | unsigned long flags = 0; | ||
974 | unsigned int count = 0, size = 0; | ||
975 | int err, i; | ||
976 | |||
977 | q->ops->buf_setup(q, &count, &size); | ||
978 | if (count < 2) | ||
979 | count = 2; | ||
980 | if (count > VIDEO_MAX_FRAME) | ||
981 | count = VIDEO_MAX_FRAME; | ||
982 | size = PAGE_ALIGN(size); | ||
983 | |||
984 | err = __videobuf_mmap_setup(q, count, size, V4L2_MEMORY_USERPTR); | ||
985 | if (err < 0) | ||
986 | return err; | ||
987 | |||
988 | count = err; | ||
989 | |||
990 | for (i = 0; i < count; i++) { | ||
991 | field = videobuf_next_field(q); | ||
992 | err = q->ops->buf_prepare(q, q->bufs[i], field); | ||
993 | if (err) | ||
994 | return err; | ||
995 | list_add_tail(&q->bufs[i]->stream, &q->stream); | ||
996 | } | ||
997 | spin_lock_irqsave(q->irqlock, flags); | ||
998 | for (i = 0; i < count; i++) | ||
999 | q->ops->buf_queue(q, q->bufs[i]); | ||
1000 | spin_unlock_irqrestore(q->irqlock, flags); | ||
1001 | q->reading = 1; | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | static void __videobuf_read_stop(struct videobuf_queue *q) | ||
1006 | { | ||
1007 | int i; | ||
1008 | |||
1009 | videobuf_queue_cancel(q); | ||
1010 | __videobuf_free(q); | ||
1011 | INIT_LIST_HEAD(&q->stream); | ||
1012 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
1013 | if (NULL == q->bufs[i]) | ||
1014 | continue; | ||
1015 | kfree(q->bufs[i]); | ||
1016 | q->bufs[i] = NULL; | ||
1017 | } | ||
1018 | q->read_buf = NULL; | ||
1019 | } | ||
1020 | |||
1021 | int videobuf_read_start(struct videobuf_queue *q) | ||
1022 | { | ||
1023 | int rc; | ||
1024 | |||
1025 | videobuf_queue_lock(q); | ||
1026 | rc = __videobuf_read_start(q); | ||
1027 | videobuf_queue_unlock(q); | ||
1028 | |||
1029 | return rc; | ||
1030 | } | ||
1031 | EXPORT_SYMBOL_GPL(videobuf_read_start); | ||
1032 | |||
1033 | void videobuf_read_stop(struct videobuf_queue *q) | ||
1034 | { | ||
1035 | videobuf_queue_lock(q); | ||
1036 | __videobuf_read_stop(q); | ||
1037 | videobuf_queue_unlock(q); | ||
1038 | } | ||
1039 | EXPORT_SYMBOL_GPL(videobuf_read_stop); | ||
1040 | |||
1041 | void videobuf_stop(struct videobuf_queue *q) | ||
1042 | { | ||
1043 | videobuf_queue_lock(q); | ||
1044 | |||
1045 | if (q->streaming) | ||
1046 | __videobuf_streamoff(q); | ||
1047 | |||
1048 | if (q->reading) | ||
1049 | __videobuf_read_stop(q); | ||
1050 | |||
1051 | videobuf_queue_unlock(q); | ||
1052 | } | ||
1053 | EXPORT_SYMBOL_GPL(videobuf_stop); | ||
1054 | |||
1055 | ssize_t videobuf_read_stream(struct videobuf_queue *q, | ||
1056 | char __user *data, size_t count, loff_t *ppos, | ||
1057 | int vbihack, int nonblocking) | ||
1058 | { | ||
1059 | int rc, retval; | ||
1060 | unsigned long flags = 0; | ||
1061 | |||
1062 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
1063 | |||
1064 | dprintk(2, "%s\n", __func__); | ||
1065 | videobuf_queue_lock(q); | ||
1066 | retval = -EBUSY; | ||
1067 | if (q->streaming) | ||
1068 | goto done; | ||
1069 | if (!q->reading) { | ||
1070 | retval = __videobuf_read_start(q); | ||
1071 | if (retval < 0) | ||
1072 | goto done; | ||
1073 | } | ||
1074 | |||
1075 | retval = 0; | ||
1076 | while (count > 0) { | ||
1077 | /* get / wait for data */ | ||
1078 | if (NULL == q->read_buf) { | ||
1079 | q->read_buf = list_entry(q->stream.next, | ||
1080 | struct videobuf_buffer, | ||
1081 | stream); | ||
1082 | list_del(&q->read_buf->stream); | ||
1083 | q->read_off = 0; | ||
1084 | } | ||
1085 | rc = videobuf_waiton(q, q->read_buf, nonblocking, 1); | ||
1086 | if (rc < 0) { | ||
1087 | if (0 == retval) | ||
1088 | retval = rc; | ||
1089 | break; | ||
1090 | } | ||
1091 | |||
1092 | if (q->read_buf->state == VIDEOBUF_DONE) { | ||
1093 | rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count, | ||
1094 | retval, vbihack, nonblocking); | ||
1095 | if (rc < 0) { | ||
1096 | retval = rc; | ||
1097 | break; | ||
1098 | } | ||
1099 | retval += rc; | ||
1100 | count -= rc; | ||
1101 | q->read_off += rc; | ||
1102 | } else { | ||
1103 | /* some error */ | ||
1104 | q->read_off = q->read_buf->size; | ||
1105 | if (0 == retval) | ||
1106 | retval = -EIO; | ||
1107 | } | ||
1108 | |||
1109 | /* requeue buffer when done with copying */ | ||
1110 | if (q->read_off == q->read_buf->size) { | ||
1111 | list_add_tail(&q->read_buf->stream, | ||
1112 | &q->stream); | ||
1113 | spin_lock_irqsave(q->irqlock, flags); | ||
1114 | q->ops->buf_queue(q, q->read_buf); | ||
1115 | spin_unlock_irqrestore(q->irqlock, flags); | ||
1116 | q->read_buf = NULL; | ||
1117 | } | ||
1118 | if (retval < 0) | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | done: | ||
1123 | videobuf_queue_unlock(q); | ||
1124 | return retval; | ||
1125 | } | ||
1126 | EXPORT_SYMBOL_GPL(videobuf_read_stream); | ||
1127 | |||
1128 | unsigned int videobuf_poll_stream(struct file *file, | ||
1129 | struct videobuf_queue *q, | ||
1130 | poll_table *wait) | ||
1131 | { | ||
1132 | struct videobuf_buffer *buf = NULL; | ||
1133 | unsigned int rc = 0; | ||
1134 | |||
1135 | videobuf_queue_lock(q); | ||
1136 | if (q->streaming) { | ||
1137 | if (!list_empty(&q->stream)) | ||
1138 | buf = list_entry(q->stream.next, | ||
1139 | struct videobuf_buffer, stream); | ||
1140 | } else { | ||
1141 | if (!q->reading) | ||
1142 | __videobuf_read_start(q); | ||
1143 | if (!q->reading) { | ||
1144 | rc = POLLERR; | ||
1145 | } else if (NULL == q->read_buf) { | ||
1146 | q->read_buf = list_entry(q->stream.next, | ||
1147 | struct videobuf_buffer, | ||
1148 | stream); | ||
1149 | list_del(&q->read_buf->stream); | ||
1150 | q->read_off = 0; | ||
1151 | } | ||
1152 | buf = q->read_buf; | ||
1153 | } | ||
1154 | if (!buf) | ||
1155 | rc = POLLERR; | ||
1156 | |||
1157 | if (0 == rc) { | ||
1158 | poll_wait(file, &buf->done, wait); | ||
1159 | if (buf->state == VIDEOBUF_DONE || | ||
1160 | buf->state == VIDEOBUF_ERROR) { | ||
1161 | switch (q->type) { | ||
1162 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
1163 | case V4L2_BUF_TYPE_VBI_OUTPUT: | ||
1164 | case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: | ||
1165 | rc = POLLOUT | POLLWRNORM; | ||
1166 | break; | ||
1167 | default: | ||
1168 | rc = POLLIN | POLLRDNORM; | ||
1169 | break; | ||
1170 | } | ||
1171 | } | ||
1172 | } | ||
1173 | videobuf_queue_unlock(q); | ||
1174 | return rc; | ||
1175 | } | ||
1176 | EXPORT_SYMBOL_GPL(videobuf_poll_stream); | ||
1177 | |||
1178 | int videobuf_mmap_mapper(struct videobuf_queue *q, struct vm_area_struct *vma) | ||
1179 | { | ||
1180 | int rc = -EINVAL; | ||
1181 | int i; | ||
1182 | |||
1183 | MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS); | ||
1184 | |||
1185 | if (!(vma->vm_flags & VM_WRITE) || !(vma->vm_flags & VM_SHARED)) { | ||
1186 | dprintk(1, "mmap appl bug: PROT_WRITE and MAP_SHARED are required\n"); | ||
1187 | return -EINVAL; | ||
1188 | } | ||
1189 | |||
1190 | videobuf_queue_lock(q); | ||
1191 | for (i = 0; i < VIDEO_MAX_FRAME; i++) { | ||
1192 | struct videobuf_buffer *buf = q->bufs[i]; | ||
1193 | |||
1194 | if (buf && buf->memory == V4L2_MEMORY_MMAP && | ||
1195 | buf->boff == (vma->vm_pgoff << PAGE_SHIFT)) { | ||
1196 | rc = CALL(q, mmap_mapper, q, buf, vma); | ||
1197 | break; | ||
1198 | } | ||
1199 | } | ||
1200 | videobuf_queue_unlock(q); | ||
1201 | |||
1202 | return rc; | ||
1203 | } | ||
1204 | EXPORT_SYMBOL_GPL(videobuf_mmap_mapper); | ||