Blame view
drivers/media/video/v4l2-dev.c
21.4 KB
27a5e6d3f V4L/DVB (8427): v... |
1 2 3 4 5 6 7 8 9 10 11 |
/* * Video capture interface for Linux version 2 * * A generic video device interface for the LINUX operating system * using a set of device structures/vectors for low level operations. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * |
d9b01449e V4L/DVB (9491): r... |
12 |
* Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1) |
27a5e6d3f V4L/DVB (8427): v... |
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
* Mauro Carvalho Chehab <mchehab@infradead.org> (version 2) * * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com> * - Added procfs support */ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/kmod.h> #include <linux/slab.h> |
27a5e6d3f V4L/DVB (8427): v... |
28 29 30 31 |
#include <asm/uaccess.h> #include <asm/system.h> #include <media/v4l2-common.h> |
9bea3514d V4L/DVB (9974): v... |
32 |
#include <media/v4l2-device.h> |
bec43661b V4L/DVB (10135): ... |
33 |
#include <media/v4l2-ioctl.h> |
27a5e6d3f V4L/DVB (8427): v... |
34 35 36 37 38 39 40 41 42 43 44 |
#define VIDEO_NUM_DEVICES 256 #define VIDEO_NAME "video4linux" /* * sysfs stuff */ static ssize_t show_index(struct device *cd, struct device_attribute *attr, char *buf) { |
dc93a70cc V4L/DVB (9973): v... |
45 |
struct video_device *vdev = to_video_device(cd); |
bfa8a273b V4L/DVB (8787): v... |
46 |
|
dc93a70cc V4L/DVB (9973): v... |
47 48 |
return sprintf(buf, "%i ", vdev->index); |
27a5e6d3f V4L/DVB (8427): v... |
49 50 51 52 53 |
} static ssize_t show_name(struct device *cd, struct device_attribute *attr, char *buf) { |
dc93a70cc V4L/DVB (9973): v... |
54 |
struct video_device *vdev = to_video_device(cd); |
bfa8a273b V4L/DVB (8787): v... |
55 |
|
dc93a70cc V4L/DVB (9973): v... |
56 57 |
return sprintf(buf, "%.*s ", (int)sizeof(vdev->name), vdev->name); |
27a5e6d3f V4L/DVB (8427): v... |
58 59 60 61 62 63 64 |
} static struct device_attribute video_device_attrs[] = { __ATTR(name, S_IRUGO, show_name, NULL), __ATTR(index, S_IRUGO, show_index, NULL), __ATTR_NULL }; |
7f8ecfab7 V4L/DVB (8852): v... |
65 66 67 68 69 |
/* * Active devices */ static struct video_device *video_device[VIDEO_NUM_DEVICES]; static DEFINE_MUTEX(videodev_lock); |
22e221258 V4L/DVB (12722): ... |
70 |
static DECLARE_BITMAP(devnode_nums[VFL_TYPE_MAX], VIDEO_NUM_DEVICES); |
7f8ecfab7 V4L/DVB (8852): v... |
71 |
|
5062cb70c V4L/DVB (12724): ... |
72 73 74 75 76 77 78 79 80 81 82 83 |
/* Device node utility functions */ /* Note: these utility functions all assume that vfl_type is in the range [0, VFL_TYPE_MAX-1]. */ #ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* Return the bitmap corresponding to vfl_type. */ static inline unsigned long *devnode_bits(int vfl_type) { /* Any types not assigned to fixed minor ranges must be mapped to one single bitmap for the purposes of finding a free node number since all those unassigned types use the same minor range. */ |
226c0eeae V4L/DVB: videotex... |
84 |
int idx = (vfl_type > VFL_TYPE_RADIO) ? VFL_TYPE_MAX - 1 : vfl_type; |
5062cb70c V4L/DVB (12724): ... |
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
return devnode_nums[idx]; } #else /* Return the bitmap corresponding to vfl_type. */ static inline unsigned long *devnode_bits(int vfl_type) { return devnode_nums[vfl_type]; } #endif /* Mark device node number vdev->num as used */ static inline void devnode_set(struct video_device *vdev) { set_bit(vdev->num, devnode_bits(vdev->vfl_type)); } /* Mark device node number vdev->num as unused */ static inline void devnode_clear(struct video_device *vdev) { clear_bit(vdev->num, devnode_bits(vdev->vfl_type)); } /* Try to find a free device node number in the range [from, to> */ static inline int devnode_find(struct video_device *vdev, int from, int to) { return find_next_zero_bit(devnode_bits(vdev->vfl_type), to, from); } |
27a5e6d3f V4L/DVB (8427): v... |
113 114 |
struct video_device *video_device_alloc(void) { |
bfa8a273b V4L/DVB (8787): v... |
115 |
return kzalloc(sizeof(struct video_device), GFP_KERNEL); |
27a5e6d3f V4L/DVB (8427): v... |
116 117 |
} EXPORT_SYMBOL(video_device_alloc); |
dc93a70cc V4L/DVB (9973): v... |
118 |
void video_device_release(struct video_device *vdev) |
27a5e6d3f V4L/DVB (8427): v... |
119 |
{ |
dc93a70cc V4L/DVB (9973): v... |
120 |
kfree(vdev); |
27a5e6d3f V4L/DVB (8427): v... |
121 122 |
} EXPORT_SYMBOL(video_device_release); |
dc93a70cc V4L/DVB (9973): v... |
123 |
void video_device_release_empty(struct video_device *vdev) |
f9e86b5e9 V4L/DVB (8782): v... |
124 125 126 127 128 |
{ /* Do nothing */ /* Only valid when the video_device struct is a static. */ } EXPORT_SYMBOL(video_device_release_empty); |
dc93a70cc V4L/DVB (9973): v... |
129 |
static inline void video_get(struct video_device *vdev) |
7f8ecfab7 V4L/DVB (8852): v... |
130 |
{ |
dc93a70cc V4L/DVB (9973): v... |
131 132 133 134 135 136 137 138 139 140 141 142 |
get_device(&vdev->dev); } static inline void video_put(struct video_device *vdev) { put_device(&vdev->dev); } /* Called when the last user of the video device exits. */ static void v4l2_device_release(struct device *cd) { struct video_device *vdev = to_video_device(cd); |
bedf8bcf6 [media] v4l2-devi... |
143 |
struct v4l2_device *v4l2_dev = vdev->v4l2_dev; |
7f8ecfab7 V4L/DVB (8852): v... |
144 145 |
mutex_lock(&videodev_lock); |
1fc2b5f7f [media] V4L: cosm... |
146 |
if (WARN_ON(video_device[vdev->minor] != vdev)) { |
dc93a70cc V4L/DVB (9973): v... |
147 |
/* should not happen */ |
1fc2b5f7f [media] V4L: cosm... |
148 |
mutex_unlock(&videodev_lock); |
6ea9a1829 V4L/DVB (8857): v... |
149 150 |
return; } |
7f8ecfab7 V4L/DVB (8852): v... |
151 152 |
/* Free up this device for reuse */ |
dc93a70cc V4L/DVB (9973): v... |
153 |
video_device[vdev->minor] = NULL; |
7f8ecfab7 V4L/DVB (8852): v... |
154 |
|
dc93a70cc V4L/DVB (9973): v... |
155 156 157 158 159 |
/* Delete the cdev on this minor as well */ cdev_del(vdev->cdev); /* Just in case some driver tries to access this from the release() callback. */ vdev->cdev = NULL; |
7f8ecfab7 V4L/DVB (8852): v... |
160 |
|
22e221258 V4L/DVB (12722): ... |
161 |
/* Mark device node number as free */ |
5062cb70c V4L/DVB (12724): ... |
162 |
devnode_clear(vdev); |
7f8ecfab7 V4L/DVB (8852): v... |
163 |
|
dc93a70cc V4L/DVB (9973): v... |
164 |
mutex_unlock(&videodev_lock); |
27a5e6d3f V4L/DVB (8427): v... |
165 |
|
c064b8eac [media] v4l: Don'... |
166 |
#if defined(CONFIG_MEDIA_CONTROLLER) |
1fc2b5f7f [media] V4L: cosm... |
167 |
if (v4l2_dev && v4l2_dev->mdev && |
c064b8eac [media] v4l: Don'... |
168 169 170 |
vdev->vfl_type != VFL_TYPE_SUBDEV) media_device_unregister_entity(&vdev->entity); #endif |
8280b662d [media] v4l: Fix ... |
171 172 173 174 175 176 177 178 |
/* Do not call v4l2_device_put if there is no release callback set. * Drivers that have no v4l2_device release callback might free the * v4l2_dev instance in the video_device release callback below, so we * must perform this check here. * * TODO: In the long run all drivers that use v4l2_device should use the * v4l2_device release callback. This check will then be unnecessary. */ |
e58fced20 [media] videodev:... |
179 |
if (v4l2_dev && v4l2_dev->release == NULL) |
8280b662d [media] v4l: Fix ... |
180 |
v4l2_dev = NULL; |
dc93a70cc V4L/DVB (9973): v... |
181 182 183 |
/* Release video_device and perform other cleanups as needed. */ vdev->release(vdev); |
bedf8bcf6 [media] v4l2-devi... |
184 185 186 187 |
/* Decrease v4l2_device refcount */ if (v4l2_dev) v4l2_device_put(v4l2_dev); |
27a5e6d3f V4L/DVB (8427): v... |
188 189 190 191 192 |
} static struct class video_class = { .name = VIDEO_NAME, .dev_attrs = video_device_attrs, |
27a5e6d3f V4L/DVB (8427): v... |
193 |
}; |
27a5e6d3f V4L/DVB (8427): v... |
194 195 196 197 198 |
struct video_device *video_devdata(struct file *file) { return video_device[iminor(file->f_path.dentry->d_inode)]; } EXPORT_SYMBOL(video_devdata); |
022654930 [media] v4l2_prio... |
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
/* Priority handling */ static inline bool prio_is_valid(enum v4l2_priority prio) { return prio == V4L2_PRIORITY_BACKGROUND || prio == V4L2_PRIORITY_INTERACTIVE || prio == V4L2_PRIORITY_RECORD; } void v4l2_prio_init(struct v4l2_prio_state *global) { memset(global, 0, sizeof(*global)); } EXPORT_SYMBOL(v4l2_prio_init); int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, enum v4l2_priority new) { if (!prio_is_valid(new)) return -EINVAL; if (*local == new) return 0; atomic_inc(&global->prios[new]); if (prio_is_valid(*local)) atomic_dec(&global->prios[*local]); *local = new; return 0; } EXPORT_SYMBOL(v4l2_prio_change); void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) { v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT); } EXPORT_SYMBOL(v4l2_prio_open); void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local) { if (prio_is_valid(local)) atomic_dec(&global->prios[local]); } EXPORT_SYMBOL(v4l2_prio_close); enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) { if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0) return V4L2_PRIORITY_RECORD; if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0) return V4L2_PRIORITY_INTERACTIVE; if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0) return V4L2_PRIORITY_BACKGROUND; return V4L2_PRIORITY_UNSET; } EXPORT_SYMBOL(v4l2_prio_max); int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local) { return (local < v4l2_prio_max(global)) ? -EBUSY : 0; } EXPORT_SYMBOL(v4l2_prio_check); |
dc93a70cc V4L/DVB (9973): v... |
261 262 263 264 |
static ssize_t v4l2_read(struct file *filp, char __user *buf, size_t sz, loff_t *off) { struct video_device *vdev = video_devdata(filp); |
2877842de [media] v4l2-dev:... |
265 |
int ret = -ENODEV; |
dc93a70cc V4L/DVB (9973): v... |
266 267 268 |
if (!vdev->fops->read) return -EINVAL; |
2877842de [media] v4l2-dev:... |
269 270 |
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; |
ee6869afc V4L/DVB: v4l2: ad... |
271 272 273 274 275 |
if (video_is_registered(vdev)) ret = vdev->fops->read(filp, buf, sz, off); if (vdev->lock) mutex_unlock(vdev->lock); return ret; |
dc93a70cc V4L/DVB (9973): v... |
276 277 278 279 280 281 |
} static ssize_t v4l2_write(struct file *filp, const char __user *buf, size_t sz, loff_t *off) { struct video_device *vdev = video_devdata(filp); |
2877842de [media] v4l2-dev:... |
282 |
int ret = -ENODEV; |
dc93a70cc V4L/DVB (9973): v... |
283 284 285 |
if (!vdev->fops->write) return -EINVAL; |
2877842de [media] v4l2-dev:... |
286 287 |
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; |
ee6869afc V4L/DVB: v4l2: ad... |
288 289 290 291 292 |
if (video_is_registered(vdev)) ret = vdev->fops->write(filp, buf, sz, off); if (vdev->lock) mutex_unlock(vdev->lock); return ret; |
dc93a70cc V4L/DVB (9973): v... |
293 294 295 296 297 |
} static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll) { struct video_device *vdev = video_devdata(filp); |
2877842de [media] v4l2-dev:... |
298 |
int ret = POLLERR | POLLHUP; |
ee6869afc V4L/DVB: v4l2: ad... |
299 300 |
if (!vdev->fops->poll) |
2877842de [media] v4l2-dev:... |
301 |
return DEFAULT_POLLMASK; |
ee6869afc V4L/DVB: v4l2: ad... |
302 303 304 305 306 307 308 |
if (vdev->lock) mutex_lock(vdev->lock); if (video_is_registered(vdev)) ret = vdev->fops->poll(filp, poll); if (vdev->lock) mutex_unlock(vdev->lock); return ret; |
dc93a70cc V4L/DVB (9973): v... |
309 |
} |
86a5ef7d7 v4l: Convert v4l2... |
310 |
static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
dc93a70cc V4L/DVB (9973): v... |
311 312 |
{ struct video_device *vdev = video_devdata(filp); |
724206301 V4L/DVB: Fix a me... |
313 |
int ret = -ENODEV; |
dc93a70cc V4L/DVB (9973): v... |
314 |
|
86a5ef7d7 v4l: Convert v4l2... |
315 |
if (vdev->fops->unlocked_ioctl) { |
2877842de [media] v4l2-dev:... |
316 317 |
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; |
724206301 V4L/DVB: Fix a me... |
318 319 |
if (video_is_registered(vdev)) ret = vdev->fops->unlocked_ioctl(filp, cmd, arg); |
ee6869afc V4L/DVB: v4l2: ad... |
320 321 |
if (vdev->lock) mutex_unlock(vdev->lock); |
86a5ef7d7 v4l: Convert v4l2... |
322 |
} else if (vdev->fops->ioctl) { |
879aa24d6 [media] V4L: impr... |
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 |
/* This code path is a replacement for the BKL. It is a major * hack but it will have to do for those drivers that are not * yet converted to use unlocked_ioctl. * * There are two options: if the driver implements struct * v4l2_device, then the lock defined there is used to * serialize the ioctls. Otherwise the v4l2 core lock defined * below is used. This lock is really bad since it serializes * completely independent devices. * * Both variants suffer from the same problem: if the driver * sleeps, then it blocks all ioctls since the lock is still * held. This is very common for VIDIOC_DQBUF since that * normally waits for a frame to arrive. As a result any other * ioctl calls will proceed very, very slowly since each call * will have to wait for the VIDIOC_QBUF to finish. Things that * should take 0.01s may now take 10-20 seconds. * * The workaround is to *not* take the lock for VIDIOC_DQBUF. * This actually works OK for videobuf-based drivers, since * videobuf will take its own internal lock. */ |
0edf2e5e2 [media] v4l: kill... |
345 |
static DEFINE_MUTEX(v4l2_ioctl_mutex); |
879aa24d6 [media] V4L: impr... |
346 347 |
struct mutex *m = vdev->v4l2_dev ? &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex; |
0edf2e5e2 [media] v4l: kill... |
348 |
|
879aa24d6 [media] V4L: impr... |
349 350 |
if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m)) return -ERESTARTSYS; |
724206301 V4L/DVB: Fix a me... |
351 352 |
if (video_is_registered(vdev)) ret = vdev->fops->ioctl(filp, cmd, arg); |
879aa24d6 [media] V4L: impr... |
353 354 |
if (cmd != VIDIOC_DQBUF) mutex_unlock(m); |
86a5ef7d7 v4l: Convert v4l2... |
355 356 |
} else ret = -ENOTTY; |
dc93a70cc V4L/DVB (9973): v... |
357 |
|
86a5ef7d7 v4l: Convert v4l2... |
358 |
return ret; |
dc93a70cc V4L/DVB (9973): v... |
359 |
} |
ecc6517d9 [media] Revert "V... |
360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
#ifdef CONFIG_MMU #define v4l2_get_unmapped_area NULL #else static unsigned long v4l2_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { struct video_device *vdev = video_devdata(filp); if (!vdev->fops->get_unmapped_area) return -ENOSYS; if (!video_is_registered(vdev)) return -ENODEV; return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); } #endif |
dc93a70cc V4L/DVB (9973): v... |
376 377 378 |
static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); |
ee6869afc V4L/DVB: v4l2: ad... |
379 380 381 382 |
int ret = -ENODEV; if (!vdev->fops->mmap) return ret; |
2877842de [media] v4l2-dev:... |
383 384 |
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) return -ERESTARTSYS; |
ee6869afc V4L/DVB: v4l2: ad... |
385 386 387 388 389 |
if (video_is_registered(vdev)) ret = vdev->fops->mmap(filp, vm); if (vdev->lock) mutex_unlock(vdev->lock); return ret; |
dc93a70cc V4L/DVB (9973): v... |
390 391 392 393 394 395 |
} /* Override for the open function */ static int v4l2_open(struct inode *inode, struct file *filp) { struct video_device *vdev; |
65d9ff9c8 V4L/DVB (11390): ... |
396 |
int ret = 0; |
dc93a70cc V4L/DVB (9973): v... |
397 398 399 400 |
/* Check if the video device is available */ mutex_lock(&videodev_lock); vdev = video_devdata(filp); |
ee6869afc V4L/DVB: v4l2: ad... |
401 |
/* return ENODEV if the video device has already been removed. */ |
ca9afe6f8 [media] v4l2-dev:... |
402 |
if (vdev == NULL || !video_is_registered(vdev)) { |
dc93a70cc V4L/DVB (9973): v... |
403 404 405 406 407 408 |
mutex_unlock(&videodev_lock); return -ENODEV; } /* and increase the device refcount */ video_get(vdev); mutex_unlock(&videodev_lock); |
ee6869afc V4L/DVB: v4l2: ad... |
409 |
if (vdev->fops->open) { |
2877842de [media] v4l2-dev:... |
410 411 412 413 |
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) { ret = -ERESTARTSYS; goto err; } |
ee6869afc V4L/DVB: v4l2: ad... |
414 415 416 417 418 419 420 |
if (video_is_registered(vdev)) ret = vdev->fops->open(filp); else ret = -ENODEV; if (vdev->lock) mutex_unlock(vdev->lock); } |
65d9ff9c8 V4L/DVB (11390): ... |
421 |
|
2877842de [media] v4l2-dev:... |
422 |
err: |
dc93a70cc V4L/DVB (9973): v... |
423 |
/* decrease the refcount in case of an error */ |
c064b8eac [media] v4l: Don'... |
424 |
if (ret) |
dc93a70cc V4L/DVB (9973): v... |
425 426 427 428 429 430 431 432 |
video_put(vdev); return ret; } /* Override for the release function */ static int v4l2_release(struct inode *inode, struct file *filp) { struct video_device *vdev = video_devdata(filp); |
65d9ff9c8 V4L/DVB (11390): ... |
433 |
int ret = 0; |
ee6869afc V4L/DVB: v4l2: ad... |
434 435 436 |
if (vdev->fops->release) { if (vdev->lock) mutex_lock(vdev->lock); |
65d9ff9c8 V4L/DVB (11390): ... |
437 |
vdev->fops->release(filp); |
ee6869afc V4L/DVB: v4l2: ad... |
438 439 440 |
if (vdev->lock) mutex_unlock(vdev->lock); } |
dc93a70cc V4L/DVB (9973): v... |
441 442 443 444 445 |
/* decrease the refcount unconditionally since the release() return value is ignored. */ video_put(vdev); return ret; } |
dc93a70cc V4L/DVB (9973): v... |
446 447 448 449 450 |
static const struct file_operations v4l2_fops = { .owner = THIS_MODULE, .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, |
ecc6517d9 [media] Revert "V... |
451 |
.get_unmapped_area = v4l2_get_unmapped_area, |
dc93a70cc V4L/DVB (9973): v... |
452 |
.mmap = v4l2_mmap, |
86a5ef7d7 v4l: Convert v4l2... |
453 |
.unlocked_ioctl = v4l2_ioctl, |
dc93a70cc V4L/DVB (9973): v... |
454 |
#ifdef CONFIG_COMPAT |
9bb7cde79 V4L/DVB (10139): ... |
455 |
.compat_ioctl = v4l2_compat_ioctl32, |
dc93a70cc V4L/DVB (9973): v... |
456 457 458 459 460 |
#endif .release = v4l2_release, .poll = v4l2_poll, .llseek = no_llseek, }; |
27a5e6d3f V4L/DVB (8427): v... |
461 |
/** |
7ae0cd9bc V4L/DVB (12541): ... |
462 |
* get_index - assign stream index number based on parent device |
dc93a70cc V4L/DVB (9973): v... |
463 |
* @vdev: video_device to assign index number to, vdev->parent should be assigned |
27a5e6d3f V4L/DVB (8427): v... |
464 |
* |
dc93a70cc V4L/DVB (9973): v... |
465 |
* Note that when this is called the new device has not yet been registered |
7ae0cd9bc V4L/DVB (12541): ... |
466 |
* in the video_device array, but it was able to obtain a minor number. |
27a5e6d3f V4L/DVB (8427): v... |
467 |
* |
7ae0cd9bc V4L/DVB (12541): ... |
468 469 470 471 472 |
* This means that we can always obtain a free stream index number since * the worst case scenario is that there are VIDEO_NUM_DEVICES - 1 slots in * use of the video_device array. * * Returns a free index number. |
27a5e6d3f V4L/DVB (8427): v... |
473 |
*/ |
7ae0cd9bc V4L/DVB (12541): ... |
474 |
static int get_index(struct video_device *vdev) |
27a5e6d3f V4L/DVB (8427): v... |
475 |
{ |
775a05dd5 V4L/DVB (10641): ... |
476 477 478 |
/* This can be static since this function is called with the global videodev_lock held. */ static DECLARE_BITMAP(used, VIDEO_NUM_DEVICES); |
27a5e6d3f V4L/DVB (8427): v... |
479 |
int i; |
7ae0cd9bc V4L/DVB (12541): ... |
480 |
/* Some drivers do not set the parent. In that case always return 0. */ |
806e5b7cf V4L/DVB (9942): v... |
481 |
if (vdev->parent == NULL) |
7ae0cd9bc V4L/DVB (12541): ... |
482 |
return 0; |
775a05dd5 V4L/DVB (10641): ... |
483 484 |
bitmap_zero(used, VIDEO_NUM_DEVICES); |
806e5b7cf V4L/DVB (9942): v... |
485 |
|
27a5e6d3f V4L/DVB (8427): v... |
486 487 |
for (i = 0; i < VIDEO_NUM_DEVICES; i++) { if (video_device[i] != NULL && |
5e85e732f V4L/DVB (8428): v... |
488 |
video_device[i]->parent == vdev->parent) { |
775a05dd5 V4L/DVB (10641): ... |
489 |
set_bit(video_device[i]->index, used); |
27a5e6d3f V4L/DVB (8427): v... |
490 491 |
} } |
7ae0cd9bc V4L/DVB (12541): ... |
492 |
return find_first_zero_bit(used, VIDEO_NUM_DEVICES); |
27a5e6d3f V4L/DVB (8427): v... |
493 |
} |
27a5e6d3f V4L/DVB (8427): v... |
494 |
/** |
2096a5dcf [media] v4l: subd... |
495 |
* __video_register_device - register video4linux devices |
dc93a70cc V4L/DVB (9973): v... |
496 |
* @vdev: video device structure we want to register |
27a5e6d3f V4L/DVB (8427): v... |
497 |
* @type: type of device to register |
22e221258 V4L/DVB (12722): ... |
498 |
* @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ... |
27a5e6d3f V4L/DVB (8427): v... |
499 |
* -1 == first free) |
6b5270d21 V4L/DVB (12725): ... |
500 501 |
* @warn_if_nr_in_use: warn if the desired device node number * was already in use and another number was chosen instead. |
2096a5dcf [media] v4l: subd... |
502 |
* @owner: module that owns the video device node |
27a5e6d3f V4L/DVB (8427): v... |
503 |
* |
22e221258 V4L/DVB (12722): ... |
504 505 506 |
* The registration code assigns minor numbers and device node numbers * based on the requested type and registers the new device node with * the kernel. |
46b633779 [media] v4l2-dev:... |
507 508 509 510 |
* * This function assumes that struct video_device was zeroed when it * was allocated and does not contain any stale date. * |
22e221258 V4L/DVB (12722): ... |
511 512 |
* An error is returned if no free minor or device node number could be * found, or if the registration of the device node failed. |
27a5e6d3f V4L/DVB (8427): v... |
513 514 515 516 517 518 519 |
* * Zero is returned on success. * * Valid types are * * %VFL_TYPE_GRABBER - A frame grabber * |
27a5e6d3f V4L/DVB (8427): v... |
520 521 522 |
* %VFL_TYPE_VBI - Vertical blank data (undecoded) * * %VFL_TYPE_RADIO - A radio card |
2096a5dcf [media] v4l: subd... |
523 524 |
* * %VFL_TYPE_SUBDEV - A subdevice |
27a5e6d3f V4L/DVB (8427): v... |
525 |
*/ |
2096a5dcf [media] v4l: subd... |
526 527 |
int __video_register_device(struct video_device *vdev, int type, int nr, int warn_if_nr_in_use, struct module *owner) |
27a5e6d3f V4L/DVB (8427): v... |
528 529 |
{ int i = 0; |
27a5e6d3f V4L/DVB (8427): v... |
530 |
int ret; |
dd89601d4 V4L/DVB (9133): v... |
531 532 533 |
int minor_offset = 0; int minor_cnt = VIDEO_NUM_DEVICES; const char *name_base; |
27a5e6d3f V4L/DVB (8427): v... |
534 |
|
dc93a70cc V4L/DVB (9973): v... |
535 536 |
/* A minor value of -1 marks this video device as never having been registered */ |
428c8d191 V4L/DVB (10791): ... |
537 |
vdev->minor = -1; |
f3b9f50ef V4L/DVB (8750): V... |
538 |
|
dc93a70cc V4L/DVB (9973): v... |
539 |
/* the release callback MUST be present */ |
1fc2b5f7f [media] V4L: cosm... |
540 |
if (WARN_ON(!vdev->release)) |
ee7aa9f82 V4L/DVB (8750): V... |
541 |
return -EINVAL; |
1babcb460 V4L/DVB: V4L: Fil... |
542 543 544 |
/* v4l2_fh support */ spin_lock_init(&vdev->fh_lock); INIT_LIST_HEAD(&vdev->fh_list); |
dc93a70cc V4L/DVB (9973): v... |
545 |
/* Part 1: check device type */ |
27a5e6d3f V4L/DVB (8427): v... |
546 547 |
switch (type) { case VFL_TYPE_GRABBER: |
27a5e6d3f V4L/DVB (8427): v... |
548 549 |
name_base = "video"; break; |
27a5e6d3f V4L/DVB (8427): v... |
550 |
case VFL_TYPE_VBI: |
27a5e6d3f V4L/DVB (8427): v... |
551 552 553 |
name_base = "vbi"; break; case VFL_TYPE_RADIO: |
27a5e6d3f V4L/DVB (8427): v... |
554 555 |
name_base = "radio"; break; |
2096a5dcf [media] v4l: subd... |
556 557 558 |
case VFL_TYPE_SUBDEV: name_base = "v4l-subdev"; break; |
27a5e6d3f V4L/DVB (8427): v... |
559 560 561 562 |
default: printk(KERN_ERR "%s called with unknown type: %d ", __func__, type); |
46f2c21cf V4L/DVB (8682): V... |
563 |
return -EINVAL; |
27a5e6d3f V4L/DVB (8427): v... |
564 |
} |
dc93a70cc V4L/DVB (9973): v... |
565 566 |
vdev->vfl_type = type; vdev->cdev = NULL; |
11bbc1cad V4L/DVB: v4l2: ho... |
567 568 569 570 571 |
if (vdev->v4l2_dev) { if (vdev->v4l2_dev->dev) vdev->parent = vdev->v4l2_dev->dev; if (vdev->ctrl_handler == NULL) vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler; |
b1a873a37 [media] v4l2: use... |
572 573 574 |
/* If the prio state pointer is NULL, then use the v4l2_device prio state. */ if (vdev->prio == NULL) |
0f62fd6a2 [media] v4l2: add... |
575 |
vdev->prio = &vdev->v4l2_dev->prio; |
11bbc1cad V4L/DVB: v4l2: ho... |
576 |
} |
dd89601d4 V4L/DVB (9133): v... |
577 |
|
22e221258 V4L/DVB (12722): ... |
578 |
/* Part 2: find a free minor, device node number and device index. */ |
dd89601d4 V4L/DVB (9133): v... |
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 |
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES /* Keep the ranges for the first four types for historical * reasons. * Newer devices (not yet in place) should use the range * of 128-191 and just pick the first free minor there * (new style). */ switch (type) { case VFL_TYPE_GRABBER: minor_offset = 0; minor_cnt = 64; break; case VFL_TYPE_RADIO: minor_offset = 64; minor_cnt = 64; break; |
dd89601d4 V4L/DVB (9133): v... |
594 595 596 597 598 599 600 601 602 603 |
case VFL_TYPE_VBI: minor_offset = 224; minor_cnt = 32; break; default: minor_offset = 128; minor_cnt = 64; break; } #endif |
22e221258 V4L/DVB (12722): ... |
604 |
/* Pick a device node number */ |
27a5e6d3f V4L/DVB (8427): v... |
605 |
mutex_lock(&videodev_lock); |
5062cb70c V4L/DVB (12724): ... |
606 |
nr = devnode_find(vdev, nr == -1 ? 0 : nr, minor_cnt); |
dd89601d4 V4L/DVB (9133): v... |
607 |
if (nr == minor_cnt) |
5062cb70c V4L/DVB (12724): ... |
608 |
nr = devnode_find(vdev, 0, minor_cnt); |
dd89601d4 V4L/DVB (9133): v... |
609 |
if (nr == minor_cnt) { |
22e221258 V4L/DVB (12722): ... |
610 611 |
printk(KERN_ERR "could not get a free device node number "); |
dd89601d4 V4L/DVB (9133): v... |
612 613 |
mutex_unlock(&videodev_lock); return -ENFILE; |
27a5e6d3f V4L/DVB (8427): v... |
614 |
} |
dd89601d4 V4L/DVB (9133): v... |
615 |
#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES |
22e221258 V4L/DVB (12722): ... |
616 |
/* 1-on-1 mapping of device node number to minor number */ |
dd89601d4 V4L/DVB (9133): v... |
617 618 |
i = nr; #else |
22e221258 V4L/DVB (12722): ... |
619 620 |
/* The device node number and minor numbers are independent, so we just find the first free minor number. */ |
dd89601d4 V4L/DVB (9133): v... |
621 622 623 624 625 626 627 628 629 630 |
for (i = 0; i < VIDEO_NUM_DEVICES; i++) if (video_device[i] == NULL) break; if (i == VIDEO_NUM_DEVICES) { mutex_unlock(&videodev_lock); printk(KERN_ERR "could not get a free minor "); return -ENFILE; } #endif |
dc93a70cc V4L/DVB (9973): v... |
631 632 |
vdev->minor = i + minor_offset; vdev->num = nr; |
5062cb70c V4L/DVB (12724): ... |
633 |
devnode_set(vdev); |
dc93a70cc V4L/DVB (9973): v... |
634 635 |
/* Should not happen since we thought this minor was free */ WARN_ON(video_device[vdev->minor] != NULL); |
7ae0cd9bc V4L/DVB (12541): ... |
636 |
vdev->index = get_index(vdev); |
27a5e6d3f V4L/DVB (8427): v... |
637 |
mutex_unlock(&videodev_lock); |
dc93a70cc V4L/DVB (9973): v... |
638 639 640 641 642 643 |
/* Part 3: Initialize the character device */ vdev->cdev = cdev_alloc(); if (vdev->cdev == NULL) { ret = -ENOMEM; goto cleanup; } |
86a5ef7d7 v4l: Convert v4l2... |
644 |
vdev->cdev->ops = &v4l2_fops; |
2096a5dcf [media] v4l: subd... |
645 |
vdev->cdev->owner = owner; |
dc93a70cc V4L/DVB (9973): v... |
646 |
ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); |
7f8ecfab7 V4L/DVB (8852): v... |
647 648 649 |
if (ret < 0) { printk(KERN_ERR "%s: cdev_add failed ", __func__); |
dc93a70cc V4L/DVB (9973): v... |
650 651 652 |
kfree(vdev->cdev); vdev->cdev = NULL; goto cleanup; |
7f8ecfab7 V4L/DVB (8852): v... |
653 |
} |
dc93a70cc V4L/DVB (9973): v... |
654 655 |
/* Part 4: register the device with sysfs */ |
dc93a70cc V4L/DVB (9973): v... |
656 657 658 659 |
vdev->dev.class = &video_class; vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor); if (vdev->parent) vdev->dev.parent = vdev->parent; |
22e221258 V4L/DVB (12722): ... |
660 |
dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num); |
dc93a70cc V4L/DVB (9973): v... |
661 |
ret = device_register(&vdev->dev); |
27a5e6d3f V4L/DVB (8427): v... |
662 663 664 |
if (ret < 0) { printk(KERN_ERR "%s: device_register failed ", __func__); |
dc93a70cc V4L/DVB (9973): v... |
665 |
goto cleanup; |
27a5e6d3f V4L/DVB (8427): v... |
666 |
} |
dc93a70cc V4L/DVB (9973): v... |
667 668 669 |
/* Register the release callback that will be called when the last reference to the device goes away. */ vdev->dev.release = v4l2_device_release; |
27a5e6d3f V4L/DVB (8427): v... |
670 |
|
6b5270d21 V4L/DVB (12725): ... |
671 |
if (nr != -1 && nr != vdev->num && warn_if_nr_in_use) |
eac8ea536 V4L/DVB (13549): ... |
672 673 674 |
printk(KERN_WARNING "%s: requested %s%d, got %s ", __func__, name_base, nr, video_device_node_name(vdev)); |
bedf8bcf6 [media] v4l2-devi... |
675 676 677 678 |
/* Increase v4l2_device refcount */ if (vdev->v4l2_dev) v4l2_device_get(vdev->v4l2_dev); |
2c0ab67be [media] v4l: Make... |
679 680 |
#if defined(CONFIG_MEDIA_CONTROLLER) /* Part 5: Register the entity. */ |
c4f0b78ad [media] v4l: Don'... |
681 682 |
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && vdev->vfl_type != VFL_TYPE_SUBDEV) { |
2c0ab67be [media] v4l: Make... |
683 684 |
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; vdev->entity.name = vdev->name; |
fa5034c66 [media] media: fi... |
685 686 |
vdev->entity.info.v4l.major = VIDEO_MAJOR; vdev->entity.info.v4l.minor = vdev->minor; |
2c0ab67be [media] v4l: Make... |
687 688 689 690 691 692 693 694 695 696 |
ret = media_device_register_entity(vdev->v4l2_dev->mdev, &vdev->entity); if (ret < 0) printk(KERN_WARNING "%s: media_device_register_entity failed ", __func__); } #endif /* Part 6: Activate this minor. The char device can now be used. */ |
957b4aa9f V4L/DVB (13552): ... |
697 |
set_bit(V4L2_FL_REGISTERED, &vdev->flags); |
dc93a70cc V4L/DVB (9973): v... |
698 699 700 |
mutex_lock(&videodev_lock); video_device[vdev->minor] = vdev; mutex_unlock(&videodev_lock); |
2c0ab67be [media] v4l: Make... |
701 |
|
dc93a70cc V4L/DVB (9973): v... |
702 |
return 0; |
7f8ecfab7 V4L/DVB (8852): v... |
703 |
|
dc93a70cc V4L/DVB (9973): v... |
704 |
cleanup: |
27a5e6d3f V4L/DVB (8427): v... |
705 |
mutex_lock(&videodev_lock); |
dc93a70cc V4L/DVB (9973): v... |
706 707 |
if (vdev->cdev) cdev_del(vdev->cdev); |
5062cb70c V4L/DVB (12724): ... |
708 |
devnode_clear(vdev); |
27a5e6d3f V4L/DVB (8427): v... |
709 |
mutex_unlock(&videodev_lock); |
dc93a70cc V4L/DVB (9973): v... |
710 711 |
/* Mark this video device as never having been registered. */ vdev->minor = -1; |
27a5e6d3f V4L/DVB (8427): v... |
712 713 |
return ret; } |
2096a5dcf [media] v4l: subd... |
714 |
EXPORT_SYMBOL(__video_register_device); |
6b5270d21 V4L/DVB (12725): ... |
715 |
|
27a5e6d3f V4L/DVB (8427): v... |
716 717 |
/** * video_unregister_device - unregister a video4linux device |
dc93a70cc V4L/DVB (9973): v... |
718 |
* @vdev: the device to unregister |
27a5e6d3f V4L/DVB (8427): v... |
719 |
* |
dc93a70cc V4L/DVB (9973): v... |
720 721 |
* This unregisters the passed device. Future open calls will * be met with errors. |
27a5e6d3f V4L/DVB (8427): v... |
722 |
*/ |
dc93a70cc V4L/DVB (9973): v... |
723 |
void video_unregister_device(struct video_device *vdev) |
27a5e6d3f V4L/DVB (8427): v... |
724 |
{ |
dc93a70cc V4L/DVB (9973): v... |
725 |
/* Check if vdev was ever registered at all */ |
957b4aa9f V4L/DVB (13552): ... |
726 |
if (!vdev || !video_is_registered(vdev)) |
dc93a70cc V4L/DVB (9973): v... |
727 |
return; |
ca9afe6f8 [media] v4l2-dev:... |
728 729 730 731 |
mutex_lock(&videodev_lock); /* This must be in a critical section to prevent a race with v4l2_open. * Once this bit has been cleared video_get may never be called again. */ |
957b4aa9f V4L/DVB (13552): ... |
732 |
clear_bit(V4L2_FL_REGISTERED, &vdev->flags); |
ca9afe6f8 [media] v4l2-dev:... |
733 |
mutex_unlock(&videodev_lock); |
dc93a70cc V4L/DVB (9973): v... |
734 |
device_unregister(&vdev->dev); |
27a5e6d3f V4L/DVB (8427): v... |
735 736 737 738 |
} EXPORT_SYMBOL(video_unregister_device); /* |
27a5e6d3f V4L/DVB (8427): v... |
739 740 |
* Initialise video for linux */ |
27a5e6d3f V4L/DVB (8427): v... |
741 742 |
static int __init videodev_init(void) { |
7f8ecfab7 V4L/DVB (8852): v... |
743 |
dev_t dev = MKDEV(VIDEO_MAJOR, 0); |
27a5e6d3f V4L/DVB (8427): v... |
744 745 746 747 |
int ret; printk(KERN_INFO "Linux video capture interface: v2.00 "); |
7f8ecfab7 V4L/DVB (8852): v... |
748 749 750 751 752 753 |
ret = register_chrdev_region(dev, VIDEO_NUM_DEVICES, VIDEO_NAME); if (ret < 0) { printk(KERN_WARNING "videodev: unable to get major %d ", VIDEO_MAJOR); return ret; |
27a5e6d3f V4L/DVB (8427): v... |
754 755 756 757 |
} ret = class_register(&video_class); if (ret < 0) { |
7f8ecfab7 V4L/DVB (8852): v... |
758 |
unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
27a5e6d3f V4L/DVB (8427): v... |
759 760 761 762 763 764 765 766 767 768 |
printk(KERN_WARNING "video_dev: class_register failed "); return -EIO; } return 0; } static void __exit videodev_exit(void) { |
7f8ecfab7 V4L/DVB (8852): v... |
769 |
dev_t dev = MKDEV(VIDEO_MAJOR, 0); |
27a5e6d3f V4L/DVB (8427): v... |
770 |
class_unregister(&video_class); |
7f8ecfab7 V4L/DVB (8852): v... |
771 |
unregister_chrdev_region(dev, VIDEO_NUM_DEVICES); |
27a5e6d3f V4L/DVB (8427): v... |
772 773 774 775 776 777 778 779 |
} module_init(videodev_init) module_exit(videodev_exit) MODULE_AUTHOR("Alan Cox, Mauro Carvalho Chehab <mchehab@infradead.org>"); MODULE_DESCRIPTION("Device registrar for Video4Linux drivers v2"); MODULE_LICENSE("GPL"); |
cbb72b0f6 V4L/DVB (10947): ... |
780 |
MODULE_ALIAS_CHARDEV_MAJOR(VIDEO_MAJOR); |
27a5e6d3f V4L/DVB (8427): v... |
781 782 783 784 785 786 787 |
/* * Local variables: * c-basic-offset: 8 * End: */ |