aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-07-02 04:59:18 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-07-06 16:32:06 -0400
commit4c1ffcaad5070ea5bca9b8057bdd7b4925237bc0 (patch)
treecf8b068a37f23d7ca5ee30870ee8bd670c54c53f /drivers/media
parent5a5adf6b669cf1a3dd2af419cd68a4c491f384a3 (diff)
[media] videobuf2-core: add helper functions
Add helper functions to make it easier to adapt drivers to vb2. These helpers take care of core locking and check if the filehandle is the owner of the queue. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/videobuf2-core.c257
1 files changed, 257 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}
2126EXPORT_SYMBOL_GPL(vb2_write); 2126EXPORT_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. */
2138static 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
2145int 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}
2162EXPORT_SYMBOL_GPL(vb2_ioctl_reqbufs);
2163
2164int 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}
2184EXPORT_SYMBOL_GPL(vb2_ioctl_create_bufs);
2185
2186int 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}
2195EXPORT_SYMBOL_GPL(vb2_ioctl_prepare_buf);
2196
2197int 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}
2204EXPORT_SYMBOL_GPL(vb2_ioctl_querybuf);
2205
2206int 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}
2214EXPORT_SYMBOL_GPL(vb2_ioctl_qbuf);
2215
2216int 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}
2224EXPORT_SYMBOL_GPL(vb2_ioctl_dqbuf);
2225
2226int 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}
2234EXPORT_SYMBOL_GPL(vb2_ioctl_streamon);
2235
2236int 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}
2244EXPORT_SYMBOL_GPL(vb2_ioctl_streamoff);
2245
2246/* v4l2_file_operations helpers */
2247
2248int 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}
2254EXPORT_SYMBOL_GPL(vb2_fop_mmap);
2255
2256int 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}
2266EXPORT_SYMBOL_GPL(vb2_fop_release);
2267
2268ssize_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;
2284exit:
2285 if (must_lock)
2286 mutex_unlock(lock);
2287 return err;
2288}
2289EXPORT_SYMBOL_GPL(vb2_fop_write);
2290
2291ssize_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;
2307exit:
2308 if (must_lock)
2309 mutex_unlock(lock);
2310 return err;
2311}
2312EXPORT_SYMBOL_GPL(vb2_fop_read);
2313
2314unsigned 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}
2358EXPORT_SYMBOL_GPL(vb2_fop_poll);
2359
2360#ifndef CONFIG_MMU
2361unsigned 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}
2368EXPORT_SYMBOL_GPL(vb2_fop_get_unmapped_area);
2369#endif
2370
2371/* vb2_ops helpers. Only use if vq->lock is non-NULL. */
2372
2373void vb2_ops_wait_prepare(struct vb2_queue *vq)
2374{
2375 mutex_unlock(vq->lock);
2376}
2377EXPORT_SYMBOL_GPL(vb2_ops_wait_prepare);
2378
2379void vb2_ops_wait_finish(struct vb2_queue *vq)
2380{
2381 mutex_lock(vq->lock);
2382}
2383EXPORT_SYMBOL_GPL(vb2_ops_wait_finish);
2384
2128MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2"); 2385MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
2129MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski"); 2386MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
2130MODULE_LICENSE("GPL"); 2387MODULE_LICENSE("GPL");