diff options
-rw-r--r-- | drivers/media/video/videobuf2-core.c | 257 | ||||
-rw-r--r-- | include/media/videobuf2-core.h | 41 |
2 files changed, 298 insertions, 0 deletions
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index ed38eb748357..4e0290ab5071 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c | |||
@@ -2125,6 +2125,263 @@ size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count, | |||
2125 | } | 2125 | } |
2126 | EXPORT_SYMBOL_GPL(vb2_write); | 2126 | EXPORT_SYMBOL_GPL(vb2_write); |
2127 | 2127 | ||
2128 | |||
2129 | /* | ||
2130 | * The following functions are not part of the vb2 core API, but are helper | ||
2131 | * functions that plug into struct v4l2_ioctl_ops, struct v4l2_file_operations | ||
2132 | * and struct vb2_ops. | ||
2133 | * They contain boilerplate code that most if not all drivers have to do | ||
2134 | * and so they simplify the driver code. | ||
2135 | */ | ||
2136 | |||
2137 | /* The queue is busy if there is a owner and you are not that owner. */ | ||
2138 | static inline bool vb2_queue_is_busy(struct video_device *vdev, struct file *file) | ||
2139 | { | ||
2140 | return vdev->queue->owner && vdev->queue->owner != file->private_data; | ||
2141 | } | ||
2142 | |||
2143 | /* vb2 ioctl helpers */ | ||
2144 | |||
2145 | int vb2_ioctl_reqbufs(struct file *file, void *priv, | ||
2146 | struct v4l2_requestbuffers *p) | ||
2147 | { | ||
2148 | struct video_device *vdev = video_devdata(file); | ||
2149 | int res = __verify_memory_type(vdev->queue, p->memory, p->type); | ||
2150 | |||
2151 | if (res) | ||
2152 | return res; | ||
2153 | if (vb2_queue_is_busy(vdev, file)) | ||
2154 | return -EBUSY; | ||
2155 | res = __reqbufs(vdev->queue, p); | ||
2156 | /* If count == 0, then the owner has released all buffers and he | ||
2157 | is no longer owner of the queue. Otherwise we have a new owner. */ | ||
2158 | if (res == 0) | ||
2159 | vdev->queue->owner = p->count ? file->private_data : NULL; | ||
2160 | return res; | ||
2161 | } | ||
2162 | EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs); | ||
2163 | |||
2164 | int vb2_ioctl_create_bufs(struct file *file, void *priv, | ||
2165 | struct v4l2_create_buffers *p) | ||
2166 | { | ||
2167 | struct video_device *vdev = video_devdata(file); | ||
2168 | int res = __verify_memory_type(vdev->queue, p->memory, p->format.type); | ||
2169 | |||
2170 | p->index = vdev->queue->num_buffers; | ||
2171 | /* If count == 0, then just check if memory and type are valid. | ||
2172 | Any -EBUSY result from __verify_memory_type can be mapped to 0. */ | ||
2173 | if (p->count == 0) | ||
2174 | return res != -EBUSY ? res : 0; | ||
2175 | if (res) | ||
2176 | return res; | ||
2177 | if (vb2_queue_is_busy(vdev, file)) | ||
2178 | return -EBUSY; | ||
2179 | res = __create_bufs(vdev->queue, p); | ||
2180 | if (res == 0) | ||
2181 | vdev->queue->owner = file->private_data; | ||
2182 | return res; | ||
2183 | } | ||
2184 | EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs); | ||
2185 | |||
2186 | int vb2_ioctl_prepare_buf(struct file *file, void *priv, | ||
2187 | struct v4l2_buffer *p) | ||
2188 | { | ||
2189 | struct video_device *vdev = video_devdata(file); | ||
2190 | |||
2191 | if (vb2_queue_is_busy(vdev, file)) | ||
2192 | return -EBUSY; | ||
2193 | return vb2_prepare_buf(vdev->queue, p); | ||
2194 | } | ||
2195 | EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf); | ||
2196 | |||
2197 | int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
2198 | { | ||
2199 | struct video_device *vdev = video_devdata(file); | ||
2200 | |||
2201 | /* No need to call vb2_queue_is_busy(), anyone can query buffers. */ | ||
2202 | return vb2_querybuf(vdev->queue, p); | ||
2203 | } | ||
2204 | EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf); | ||
2205 | |||
2206 | int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
2207 | { | ||
2208 | struct video_device *vdev = video_devdata(file); | ||
2209 | |||
2210 | if (vb2_queue_is_busy(vdev, file)) | ||
2211 | return -EBUSY; | ||
2212 | return vb2_qbuf(vdev->queue, p); | ||
2213 | } | ||
2214 | EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf); | ||
2215 | |||
2216 | int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | ||
2217 | { | ||
2218 | struct video_device *vdev = video_devdata(file); | ||
2219 | |||
2220 | if (vb2_queue_is_busy(vdev, file)) | ||
2221 | return -EBUSY; | ||
2222 | return vb2_dqbuf(vdev->queue, p, file->f_flags & O_NONBLOCK); | ||
2223 | } | ||
2224 | EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf); | ||
2225 | |||
2226 | int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
2227 | { | ||
2228 | struct video_device *vdev = video_devdata(file); | ||
2229 | |||
2230 | if (vb2_queue_is_busy(vdev, file)) | ||
2231 | return -EBUSY; | ||
2232 | return vb2_streamon(vdev->queue, i); | ||
2233 | } | ||
2234 | EXPORT_SYMBOL_GPL(vb2_ioctl_streamon); | ||
2235 | |||
2236 | int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
2237 | { | ||
2238 | struct video_device *vdev = video_devdata(file); | ||
2239 | |||
2240 | if (vb2_queue_is_busy(vdev, file)) | ||
2241 | return -EBUSY; | ||
2242 | return vb2_streamoff(vdev->queue, i); | ||
2243 | } | ||
2244 | EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff); | ||
2245 | |||
2246 | /* v4l2_file_operations helpers */ | ||
2247 | |||
2248 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma) | ||
2249 | { | ||
2250 | struct video_device *vdev = video_devdata(file); | ||
2251 | |||
2252 | return vb2_mmap(vdev->queue, vma); | ||
2253 | } | ||
2254 | EXPORT_SYMBOL_GPL(vb2_fop_mmap); | ||
2255 | |||
2256 | int vb2_fop_release(struct file *file) | ||
2257 | { | ||
2258 | struct video_device *vdev = video_devdata(file); | ||
2259 | |||
2260 | if (file->private_data == vdev->queue->owner) { | ||
2261 | vb2_queue_release(vdev->queue); | ||
2262 | vdev->queue->owner = NULL; | ||
2263 | } | ||
2264 | return v4l2_fh_release(file); | ||
2265 | } | ||
2266 | EXPORT_SYMBOL_GPL(vb2_fop_release); | ||
2267 | |||
2268 | ssize_t vb2_fop_write(struct file *file, char __user *buf, | ||
2269 | size_t count, loff_t *ppos) | ||
2270 | { | ||
2271 | struct video_device *vdev = video_devdata(file); | ||
2272 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
2273 | bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && lock; | ||
2274 | int err = -EBUSY; | ||
2275 | |||
2276 | if (must_lock && mutex_lock_interruptible(lock)) | ||
2277 | return -ERESTARTSYS; | ||
2278 | if (vb2_queue_is_busy(vdev, file)) | ||
2279 | goto exit; | ||
2280 | err = vb2_write(vdev->queue, buf, count, ppos, | ||
2281 | file->f_flags & O_NONBLOCK); | ||
2282 | if (err >= 0) | ||
2283 | vdev->queue->owner = file->private_data; | ||
2284 | exit: | ||
2285 | if (must_lock) | ||
2286 | mutex_unlock(lock); | ||
2287 | return err; | ||
2288 | } | ||
2289 | EXPORT_SYMBOL_GPL(vb2_fop_write); | ||
2290 | |||
2291 | ssize_t vb2_fop_read(struct file *file, char __user *buf, | ||
2292 | size_t count, loff_t *ppos) | ||
2293 | { | ||
2294 | struct video_device *vdev = video_devdata(file); | ||
2295 | struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock; | ||
2296 | bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && vdev->lock; | ||
2297 | int err = -EBUSY; | ||
2298 | |||
2299 | if (must_lock && mutex_lock_interruptible(lock)) | ||
2300 | return -ERESTARTSYS; | ||
2301 | if (vb2_queue_is_busy(vdev, file)) | ||
2302 | goto exit; | ||
2303 | err = vb2_read(vdev->queue, buf, count, ppos, | ||
2304 | file->f_flags & O_NONBLOCK); | ||
2305 | if (err >= 0) | ||
2306 | vdev->queue->owner = file->private_data; | ||
2307 | exit: | ||
2308 | if (must_lock) | ||
2309 | mutex_unlock(lock); | ||
2310 | return err; | ||
2311 | } | ||
2312 | EXPORT_SYMBOL_GPL(vb2_fop_read); | ||
2313 | |||
2314 | unsigned int vb2_fop_poll(struct file *file, poll_table *wait) | ||
2315 | { | ||
2316 | struct video_device *vdev = video_devdata(file); | ||
2317 | struct vb2_queue *q = vdev->queue; | ||
2318 | struct mutex *lock = q->lock ? q->lock : vdev->lock; | ||
2319 | unsigned long req_events = poll_requested_events(wait); | ||
2320 | unsigned res; | ||
2321 | void *fileio; | ||
2322 | /* Yuck. We really need to get rid of this flag asap. If it is | ||
2323 | set, then the core took the serialization lock before calling | ||
2324 | poll(). This is being phased out, but for now we have to handle | ||
2325 | this case. */ | ||
2326 | bool locked = test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags); | ||
2327 | bool must_lock = false; | ||
2328 | |||
2329 | /* Try to be smart: only lock if polling might start fileio, | ||
2330 | otherwise locking will only introduce unwanted delays. */ | ||
2331 | if (q->num_buffers == 0 && q->fileio == NULL) { | ||
2332 | if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) && | ||
2333 | (req_events & (POLLIN | POLLRDNORM))) | ||
2334 | must_lock = true; | ||
2335 | else if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) && | ||
2336 | (req_events & (POLLOUT | POLLWRNORM))) | ||
2337 | must_lock = true; | ||
2338 | } | ||
2339 | |||
2340 | /* If locking is needed, but this helper doesn't know how, then you | ||
2341 | shouldn't be using this helper but you should write your own. */ | ||
2342 | WARN_ON(must_lock && !locked && !lock); | ||
2343 | |||
2344 | if (must_lock && !locked && lock && mutex_lock_interruptible(lock)) | ||
2345 | return POLLERR; | ||
2346 | |||
2347 | fileio = q->fileio; | ||
2348 | |||
2349 | res = vb2_poll(vdev->queue, file, wait); | ||
2350 | |||
2351 | /* If fileio was started, then we have a new queue owner. */ | ||
2352 | if (must_lock && !fileio && q->fileio) | ||
2353 | q->owner = file->private_data; | ||
2354 | if (must_lock && !locked && lock) | ||
2355 | mutex_unlock(lock); | ||
2356 | return res; | ||
2357 | } | ||
2358 | EXPORT_SYMBOL_GPL(vb2_fop_poll); | ||
2359 | |||
2360 | #ifndef CONFIG_MMU | ||
2361 | unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, | ||
2362 | unsigned long len, unsigned long pgoff, unsigned long flags) | ||
2363 | { | ||
2364 | struct video_device *vdev = video_devdata(file); | ||
2365 | |||
2366 | return vb2_get_unmapped_area(vdev->queue, addr, len, pgoff, flags); | ||
2367 | } | ||
2368 | EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area); | ||
2369 | #endif | ||
2370 | |||
2371 | /* vb2_ops helpers. Only use if vq->lock is non-NULL. */ | ||
2372 | |||
2373 | void vb2_ops_wait_prepare(struct vb2_queue *vq) | ||
2374 | { | ||
2375 | mutex_unlock(vq->lock); | ||
2376 | } | ||
2377 | EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare); | ||
2378 | |||
2379 | void vb2_ops_wait_finish(struct vb2_queue *vq) | ||
2380 | { | ||
2381 | mutex_lock(vq->lock); | ||
2382 | } | ||
2383 | EXPORT_SYMBOL_GPL(vb2_ops_wait_finish); | ||
2384 | |||
2128 | MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); | 2385 | MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); |
2129 | MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); | 2386 | MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); |
2130 | MODULE_LICENSE("GPL"); | 2387 | MODULE_LICENSE("GPL"); |
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h index 924e95e0a0a6..8dd9b6cc296b 100644 --- a/include/media/videobuf2-core.h +++ b/include/media/videobuf2-core.h | |||
@@ -417,4 +417,45 @@ vb2_plane_size(struct vb2_buffer *vb, unsigned int plane_no) | |||
417 | return 0; | 417 | return 0; |
418 | } | 418 | } |
419 | 419 | ||
420 | /* | ||
421 | * The following functions are not part of the vb2 core API, but are simple | ||
422 | * helper functions that you can use in your struct v4l2_file_operations, | ||
423 | * struct v4l2_ioctl_ops and struct vb2_ops. They will serialize if vb2_queue->lock | ||
424 | * or video_device->lock is set, and they will set and test vb2_queue->owner | ||
425 | * to check if the calling filehandle is permitted to do the queuing operation. | ||
426 | */ | ||
427 | |||
428 | /* struct v4l2_ioctl_ops helpers */ | ||
429 | |||
430 | int vb2_ioctl_reqbufs(struct file *file, void *priv, | ||
431 | struct v4l2_requestbuffers *p); | ||
432 | int vb2_ioctl_create_bufs(struct file *file, void *priv, | ||
433 | struct v4l2_create_buffers *p); | ||
434 | int vb2_ioctl_prepare_buf(struct file *file, void *priv, | ||
435 | struct v4l2_buffer *p); | ||
436 | int vb2_ioctl_querybuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
437 | int vb2_ioctl_qbuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
438 | int vb2_ioctl_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p); | ||
439 | int vb2_ioctl_streamon(struct file *file, void *priv, enum v4l2_buf_type i); | ||
440 | int vb2_ioctl_streamoff(struct file *file, void *priv, enum v4l2_buf_type i); | ||
441 | |||
442 | /* struct v4l2_file_operations helpers */ | ||
443 | |||
444 | int vb2_fop_mmap(struct file *file, struct vm_area_struct *vma); | ||
445 | int vb2_fop_release(struct file *file); | ||
446 | ssize_t vb2_fop_write(struct file *file, char __user *buf, | ||
447 | size_t count, loff_t *ppos); | ||
448 | ssize_t vb2_fop_read(struct file *file, char __user *buf, | ||
449 | size_t count, loff_t *ppos); | ||
450 | unsigned int vb2_fop_poll(struct file *file, poll_table *wait); | ||
451 | #ifndef CONFIG_MMU | ||
452 | unsigned long vb2_fop_get_unmapped_area(struct file *file, unsigned long addr, | ||
453 | unsigned long len, unsigned long pgoff, unsigned long flags); | ||
454 | #endif | ||
455 | |||
456 | /* struct vb2_ops helpers, only use if vq->lock is non-NULL. */ | ||
457 | |||
458 | void vb2_ops_wait_prepare(struct vb2_queue *vq); | ||
459 | void vb2_ops_wait_finish(struct vb2_queue *vq); | ||
460 | |||
420 | #endif /* _MEDIA_VIDEOBUF2_CORE_H */ | 461 | #endif /* _MEDIA_VIDEOBUF2_CORE_H */ |