aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-dev.c')
-rw-r--r--drivers/media/video/v4l2-dev.c365
1 files changed, 271 insertions, 94 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index ccd6566a515e..7ad6711ee327 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -9,7 +9,7 @@
9 * as published by the Free Software Foundation; either version 9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * Authors: Alan Cox, <alan@redhat.com> (version 1) 12 * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
13 * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2) 13 * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
14 * 14 *
15 * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com> 15 * Fixes: 20000516 Claudio Matsuoka <claudio@conectiva.com>
@@ -30,6 +30,7 @@
30#include <asm/system.h> 30#include <asm/system.h>
31 31
32#include <media/v4l2-common.h> 32#include <media/v4l2-common.h>
33#include <media/v4l2-device.h>
33 34
34#define VIDEO_NUM_DEVICES 256 35#define VIDEO_NUM_DEVICES 256
35#define VIDEO_NAME "video4linux" 36#define VIDEO_NAME "video4linux"
@@ -41,17 +42,17 @@
41static ssize_t show_index(struct device *cd, 42static ssize_t show_index(struct device *cd,
42 struct device_attribute *attr, char *buf) 43 struct device_attribute *attr, char *buf)
43{ 44{
44 struct video_device *vfd = container_of(cd, struct video_device, dev); 45 struct video_device *vdev = to_video_device(cd);
45 46
46 return sprintf(buf, "%i\n", vfd->index); 47 return sprintf(buf, "%i\n", vdev->index);
47} 48}
48 49
49static ssize_t show_name(struct device *cd, 50static ssize_t show_name(struct device *cd,
50 struct device_attribute *attr, char *buf) 51 struct device_attribute *attr, char *buf)
51{ 52{
52 struct video_device *vfd = container_of(cd, struct video_device, dev); 53 struct video_device *vdev = to_video_device(cd);
53 54
54 return sprintf(buf, "%.*s\n", (int)sizeof(vfd->name), vfd->name); 55 return sprintf(buf, "%.*s\n", (int)sizeof(vdev->name), vdev->name);
55} 56}
56 57
57static struct device_attribute video_device_attrs[] = { 58static struct device_attribute video_device_attrs[] = {
@@ -73,64 +74,64 @@ struct video_device *video_device_alloc(void)
73} 74}
74EXPORT_SYMBOL(video_device_alloc); 75EXPORT_SYMBOL(video_device_alloc);
75 76
76void video_device_release(struct video_device *vfd) 77void video_device_release(struct video_device *vdev)
77{ 78{
78 kfree(vfd); 79 kfree(vdev);
79} 80}
80EXPORT_SYMBOL(video_device_release); 81EXPORT_SYMBOL(video_device_release);
81 82
82void video_device_release_empty(struct video_device *vfd) 83void video_device_release_empty(struct video_device *vdev)
83{ 84{
84 /* Do nothing */ 85 /* Do nothing */
85 /* Only valid when the video_device struct is a static. */ 86 /* Only valid when the video_device struct is a static. */
86} 87}
87EXPORT_SYMBOL(video_device_release_empty); 88EXPORT_SYMBOL(video_device_release_empty);
88 89
89/* Called when the last user of the character device is gone. */ 90static inline void video_get(struct video_device *vdev)
90static void v4l2_chardev_release(struct kobject *kobj)
91{ 91{
92 struct video_device *vfd = container_of(kobj, struct video_device, cdev.kobj); 92 get_device(&vdev->dev);
93}
94
95static inline void video_put(struct video_device *vdev)
96{
97 put_device(&vdev->dev);
98}
99
100/* Called when the last user of the video device exits. */
101static void v4l2_device_release(struct device *cd)
102{
103 struct video_device *vdev = to_video_device(cd);
93 104
94 mutex_lock(&videodev_lock); 105 mutex_lock(&videodev_lock);
95 if (video_device[vfd->minor] != vfd) { 106 if (video_device[vdev->minor] != vdev) {
96 mutex_unlock(&videodev_lock); 107 mutex_unlock(&videodev_lock);
97 BUG(); 108 /* should not happen */
109 WARN_ON(1);
98 return; 110 return;
99 } 111 }
100 112
101 /* Free up this device for reuse */ 113 /* Free up this device for reuse */
102 video_device[vfd->minor] = NULL; 114 video_device[vdev->minor] = NULL;
103 clear_bit(vfd->num, video_nums[vfd->vfl_type]);
104 mutex_unlock(&videodev_lock);
105 115
106 /* Release the character device */ 116 /* Delete the cdev on this minor as well */
107 vfd->cdev_release(kobj); 117 cdev_del(vdev->cdev);
108 /* Release video_device and perform other 118 /* Just in case some driver tries to access this from
109 cleanups as needed. */ 119 the release() callback. */
110 if (vfd->release) 120 vdev->cdev = NULL;
111 vfd->release(vfd);
112}
113 121
114/* The new kobj_type for the character device */ 122 /* Mark minor as free */
115static struct kobj_type v4l2_ktype_cdev_default = { 123 clear_bit(vdev->num, video_nums[vdev->vfl_type]);
116 .release = v4l2_chardev_release,
117};
118 124
119static void video_release(struct device *cd) 125 mutex_unlock(&videodev_lock);
120{
121 struct video_device *vfd = container_of(cd, struct video_device, dev);
122 126
123 /* It's now safe to delete the char device. 127 /* Release video_device and perform other
124 This will either trigger the v4l2_chardev_release immediately (if 128 cleanups as needed. */
125 the refcount goes to 0) or later when the last user of the 129 vdev->release(vdev);
126 character device closes it. */
127 cdev_del(&vfd->cdev);
128} 130}
129 131
130static struct class video_class = { 132static struct class video_class = {
131 .name = VIDEO_NAME, 133 .name = VIDEO_NAME,
132 .dev_attrs = video_device_attrs, 134 .dev_attrs = video_device_attrs,
133 .dev_release = video_release,
134}; 135};
135 136
136struct video_device *video_devdata(struct file *file) 137struct video_device *video_devdata(struct file *file)
@@ -139,13 +140,163 @@ struct video_device *video_devdata(struct file *file)
139} 140}
140EXPORT_SYMBOL(video_devdata); 141EXPORT_SYMBOL(video_devdata);
141 142
143static ssize_t v4l2_read(struct file *filp, char __user *buf,
144 size_t sz, loff_t *off)
145{
146 struct video_device *vdev = video_devdata(filp);
147
148 if (!vdev->fops->read)
149 return -EINVAL;
150 if (video_is_unregistered(vdev))
151 return -EIO;
152 return vdev->fops->read(filp, buf, sz, off);
153}
154
155static ssize_t v4l2_write(struct file *filp, const char __user *buf,
156 size_t sz, loff_t *off)
157{
158 struct video_device *vdev = video_devdata(filp);
159
160 if (!vdev->fops->write)
161 return -EINVAL;
162 if (video_is_unregistered(vdev))
163 return -EIO;
164 return vdev->fops->write(filp, buf, sz, off);
165}
166
167static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
168{
169 struct video_device *vdev = video_devdata(filp);
170
171 if (!vdev->fops->poll || video_is_unregistered(vdev))
172 return DEFAULT_POLLMASK;
173 return vdev->fops->poll(filp, poll);
174}
175
176static int v4l2_ioctl(struct inode *inode, struct file *filp,
177 unsigned int cmd, unsigned long arg)
178{
179 struct video_device *vdev = video_devdata(filp);
180
181 if (!vdev->fops->ioctl)
182 return -ENOTTY;
183 /* Allow ioctl to continue even if the device was unregistered.
184 Things like dequeueing buffers might still be useful. */
185 return vdev->fops->ioctl(inode, filp, cmd, arg);
186}
187
188static long v4l2_unlocked_ioctl(struct file *filp,
189 unsigned int cmd, unsigned long arg)
190{
191 struct video_device *vdev = video_devdata(filp);
192
193 if (!vdev->fops->unlocked_ioctl)
194 return -ENOTTY;
195 /* Allow ioctl to continue even if the device was unregistered.
196 Things like dequeueing buffers might still be useful. */
197 return vdev->fops->unlocked_ioctl(filp, cmd, arg);
198}
199
200#ifdef CONFIG_COMPAT
201static long v4l2_compat_ioctl(struct file *filp,
202 unsigned int cmd, unsigned long arg)
203{
204 struct video_device *vdev = video_devdata(filp);
205
206 if (!vdev->fops->compat_ioctl)
207 return -ENOIOCTLCMD;
208 /* Allow ioctl to continue even if the device was unregistered.
209 Things like dequeueing buffers might still be useful. */
210 return vdev->fops->compat_ioctl(filp, cmd, arg);
211}
212#endif
213
214static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
215{
216 struct video_device *vdev = video_devdata(filp);
217
218 if (!vdev->fops->mmap ||
219 video_is_unregistered(vdev))
220 return -ENODEV;
221 return vdev->fops->mmap(filp, vm);
222}
223
224/* Override for the open function */
225static int v4l2_open(struct inode *inode, struct file *filp)
226{
227 struct video_device *vdev;
228 int ret;
229
230 /* Check if the video device is available */
231 mutex_lock(&videodev_lock);
232 vdev = video_devdata(filp);
233 /* return ENODEV if the video device has been removed
234 already or if it is not registered anymore. */
235 if (vdev == NULL || video_is_unregistered(vdev)) {
236 mutex_unlock(&videodev_lock);
237 return -ENODEV;
238 }
239 /* and increase the device refcount */
240 video_get(vdev);
241 mutex_unlock(&videodev_lock);
242 ret = vdev->fops->open(inode, filp);
243 /* decrease the refcount in case of an error */
244 if (ret)
245 video_put(vdev);
246 return ret;
247}
248
249/* Override for the release function */
250static int v4l2_release(struct inode *inode, struct file *filp)
251{
252 struct video_device *vdev = video_devdata(filp);
253 int ret = vdev->fops->release(inode, filp);
254
255 /* decrease the refcount unconditionally since the release()
256 return value is ignored. */
257 video_put(vdev);
258 return ret;
259}
260
261static const struct file_operations v4l2_unlocked_fops = {
262 .owner = THIS_MODULE,
263 .read = v4l2_read,
264 .write = v4l2_write,
265 .open = v4l2_open,
266 .mmap = v4l2_mmap,
267 .unlocked_ioctl = v4l2_unlocked_ioctl,
268#ifdef CONFIG_COMPAT
269 .compat_ioctl = v4l2_compat_ioctl,
270#endif
271 .release = v4l2_release,
272 .poll = v4l2_poll,
273 .llseek = no_llseek,
274};
275
276static const struct file_operations v4l2_fops = {
277 .owner = THIS_MODULE,
278 .read = v4l2_read,
279 .write = v4l2_write,
280 .open = v4l2_open,
281 .mmap = v4l2_mmap,
282 .ioctl = v4l2_ioctl,
283#ifdef CONFIG_COMPAT
284 .compat_ioctl = v4l2_compat_ioctl,
285#endif
286 .release = v4l2_release,
287 .poll = v4l2_poll,
288 .llseek = no_llseek,
289};
290
142/** 291/**
143 * get_index - assign stream number based on parent device 292 * get_index - assign stream number based on parent device
144 * @vdev: video_device to assign index number to, vdev->dev should be assigned 293 * @vdev: video_device to assign index number to, vdev->parent should be assigned
145 * @num: -1 if auto assign, requested number otherwise 294 * @num: -1 if auto assign, requested number otherwise
146 * 295 *
296 * Note that when this is called the new device has not yet been registered
297 * in the video_device array.
147 * 298 *
148 * returns -ENFILE if num is already in use, a free index number if 299 * Returns -ENFILE if num is already in use, a free index number if
149 * successful. 300 * successful.
150 */ 301 */
151static int get_index(struct video_device *vdev, int num) 302static int get_index(struct video_device *vdev, int num)
@@ -162,9 +313,12 @@ static int get_index(struct video_device *vdev, int num)
162 return -EINVAL; 313 return -EINVAL;
163 } 314 }
164 315
316 /* Some drivers do not set the parent. In that case always return 0. */
317 if (vdev->parent == NULL)
318 return 0;
319
165 for (i = 0; i < VIDEO_NUM_DEVICES; i++) { 320 for (i = 0; i < VIDEO_NUM_DEVICES; i++) {
166 if (video_device[i] != NULL && 321 if (video_device[i] != NULL &&
167 video_device[i] != vdev &&
168 video_device[i]->parent == vdev->parent) { 322 video_device[i]->parent == vdev->parent) {
169 used |= 1 << video_device[i]->index; 323 used |= 1 << video_device[i]->index;
170 } 324 }
@@ -180,17 +334,15 @@ static int get_index(struct video_device *vdev, int num)
180 return i > max_index ? -ENFILE : i; 334 return i > max_index ? -ENFILE : i;
181} 335}
182 336
183static const struct file_operations video_fops; 337int video_register_device(struct video_device *vdev, int type, int nr)
184
185int video_register_device(struct video_device *vfd, int type, int nr)
186{ 338{
187 return video_register_device_index(vfd, type, nr, -1); 339 return video_register_device_index(vdev, type, nr, -1);
188} 340}
189EXPORT_SYMBOL(video_register_device); 341EXPORT_SYMBOL(video_register_device);
190 342
191/** 343/**
192 * video_register_device_index - register video4linux devices 344 * video_register_device_index - register video4linux devices
193 * @vfd: video device structure we want to register 345 * @vdev: video device structure we want to register
194 * @type: type of device to register 346 * @type: type of device to register
195 * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ... 347 * @nr: which device number (0 == /dev/video0, 1 == /dev/video1, ...
196 * -1 == first free) 348 * -1 == first free)
@@ -214,8 +366,7 @@ EXPORT_SYMBOL(video_register_device);
214 * 366 *
215 * %VFL_TYPE_RADIO - A radio card 367 * %VFL_TYPE_RADIO - A radio card
216 */ 368 */
217 369int video_register_device_index(struct video_device *vdev, int type, int nr,
218int video_register_device_index(struct video_device *vfd, int type, int nr,
219 int index) 370 int index)
220{ 371{
221 int i = 0; 372 int i = 0;
@@ -223,14 +374,19 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
223 int minor_offset = 0; 374 int minor_offset = 0;
224 int minor_cnt = VIDEO_NUM_DEVICES; 375 int minor_cnt = VIDEO_NUM_DEVICES;
225 const char *name_base; 376 const char *name_base;
226 void *priv = video_get_drvdata(vfd); 377 void *priv = video_get_drvdata(vdev);
227 378
228 /* the release callback MUST be present */ 379 /* A minor value of -1 marks this video device as never
229 BUG_ON(!vfd->release); 380 having been registered */
381 if (vdev)
382 vdev->minor = -1;
230 383
231 if (vfd == NULL) 384 /* the release callback MUST be present */
385 WARN_ON(!vdev || !vdev->release);
386 if (!vdev || !vdev->release)
232 return -EINVAL; 387 return -EINVAL;
233 388
389 /* Part 1: check device type */
234 switch (type) { 390 switch (type) {
235 case VFL_TYPE_GRABBER: 391 case VFL_TYPE_GRABBER:
236 name_base = "video"; 392 name_base = "video";
@@ -250,8 +406,12 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
250 return -EINVAL; 406 return -EINVAL;
251 } 407 }
252 408
253 vfd->vfl_type = type; 409 vdev->vfl_type = type;
410 vdev->cdev = NULL;
411 if (vdev->v4l2_dev)
412 vdev->parent = vdev->v4l2_dev->dev;
254 413
414 /* Part 2: find a free minor, kernel number and device index. */
255#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES 415#ifdef CONFIG_VIDEO_FIXED_MINOR_RANGES
256 /* Keep the ranges for the first four types for historical 416 /* Keep the ranges for the first four types for historical
257 * reasons. 417 * reasons.
@@ -282,10 +442,7 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
282 } 442 }
283#endif 443#endif
284 444
285 /* Initialize the character device */ 445 /* Pick a minor number */
286 cdev_init(&vfd->cdev, vfd->fops);
287 vfd->cdev.owner = vfd->fops->owner;
288 /* pick a minor number */
289 mutex_lock(&videodev_lock); 446 mutex_lock(&videodev_lock);
290 nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr); 447 nr = find_next_zero_bit(video_nums[type], minor_cnt, nr == -1 ? 0 : nr);
291 if (nr == minor_cnt) 448 if (nr == minor_cnt)
@@ -309,72 +466,92 @@ int video_register_device_index(struct video_device *vfd, int type, int nr,
309 return -ENFILE; 466 return -ENFILE;
310 } 467 }
311#endif 468#endif
312 vfd->minor = i + minor_offset; 469 vdev->minor = i + minor_offset;
313 vfd->num = nr; 470 vdev->num = nr;
314 set_bit(nr, video_nums[type]); 471 set_bit(nr, video_nums[type]);
315 BUG_ON(video_device[vfd->minor]); 472 /* Should not happen since we thought this minor was free */
316 video_device[vfd->minor] = vfd; 473 WARN_ON(video_device[vdev->minor] != NULL);
317 474 ret = vdev->index = get_index(vdev, index);
318 ret = get_index(vfd, index);
319 vfd->index = ret;
320
321 mutex_unlock(&videodev_lock); 475 mutex_unlock(&videodev_lock);
322 476
323 if (ret < 0) { 477 if (ret < 0) {
324 printk(KERN_ERR "%s: get_index failed\n", __func__); 478 printk(KERN_ERR "%s: get_index failed\n", __func__);
325 goto fail_minor; 479 goto cleanup;
326 } 480 }
327 481
328 ret = cdev_add(&vfd->cdev, MKDEV(VIDEO_MAJOR, vfd->minor), 1); 482 /* Part 3: Initialize the character device */
483 vdev->cdev = cdev_alloc();
484 if (vdev->cdev == NULL) {
485 ret = -ENOMEM;
486 goto cleanup;
487 }
488 if (vdev->fops->unlocked_ioctl)
489 vdev->cdev->ops = &v4l2_unlocked_fops;
490 else
491 vdev->cdev->ops = &v4l2_fops;
492 vdev->cdev->owner = vdev->fops->owner;
493 ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
329 if (ret < 0) { 494 if (ret < 0) {
330 printk(KERN_ERR "%s: cdev_add failed\n", __func__); 495 printk(KERN_ERR "%s: cdev_add failed\n", __func__);
331 goto fail_minor; 496 kfree(vdev->cdev);
497 vdev->cdev = NULL;
498 goto cleanup;
332 } 499 }
333 /* sysfs class */ 500
334 memset(&vfd->dev, 0, sizeof(vfd->dev)); 501 /* Part 4: register the device with sysfs */
502 memset(&vdev->dev, 0, sizeof(vdev->dev));
335 /* The memset above cleared the device's drvdata, so 503 /* The memset above cleared the device's drvdata, so
336 put back the copy we made earlier. */ 504 put back the copy we made earlier. */
337 video_set_drvdata(vfd, priv); 505 video_set_drvdata(vdev, priv);
338 vfd->dev.class = &video_class; 506 vdev->dev.class = &video_class;
339 vfd->dev.devt = MKDEV(VIDEO_MAJOR, vfd->minor); 507 vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
340 if (vfd->parent) 508 if (vdev->parent)
341 vfd->dev.parent = vfd->parent; 509 vdev->dev.parent = vdev->parent;
342 sprintf(vfd->dev.bus_id, "%s%d", name_base, nr); 510 dev_set_name(&vdev->dev, "%s%d", name_base, nr);
343 ret = device_register(&vfd->dev); 511 ret = device_register(&vdev->dev);
344 if (ret < 0) { 512 if (ret < 0) {
345 printk(KERN_ERR "%s: device_register failed\n", __func__); 513 printk(KERN_ERR "%s: device_register failed\n", __func__);
346 goto del_cdev; 514 goto cleanup;
347 } 515 }
348 /* Remember the cdev's release function */ 516 /* Register the release callback that will be called when the last
349 vfd->cdev_release = vfd->cdev.kobj.ktype->release; 517 reference to the device goes away. */
350 /* Install our own */ 518 vdev->dev.release = v4l2_device_release;
351 vfd->cdev.kobj.ktype = &v4l2_ktype_cdev_default;
352 return 0;
353 519
354del_cdev: 520 /* Part 5: Activate this minor. The char device can now be used. */
355 cdev_del(&vfd->cdev); 521 mutex_lock(&videodev_lock);
522 video_device[vdev->minor] = vdev;
523 mutex_unlock(&videodev_lock);
524 return 0;
356 525
357fail_minor: 526cleanup:
358 mutex_lock(&videodev_lock); 527 mutex_lock(&videodev_lock);
359 video_device[vfd->minor] = NULL; 528 if (vdev->cdev)
360 clear_bit(vfd->num, video_nums[type]); 529 cdev_del(vdev->cdev);
530 clear_bit(vdev->num, video_nums[type]);
361 mutex_unlock(&videodev_lock); 531 mutex_unlock(&videodev_lock);
362 vfd->minor = -1; 532 /* Mark this video device as never having been registered. */
533 vdev->minor = -1;
363 return ret; 534 return ret;
364} 535}
365EXPORT_SYMBOL(video_register_device_index); 536EXPORT_SYMBOL(video_register_device_index);
366 537
367/** 538/**
368 * video_unregister_device - unregister a video4linux device 539 * video_unregister_device - unregister a video4linux device
369 * @vfd: the device to unregister 540 * @vdev: the device to unregister
370 * 541 *
371 * This unregisters the passed device and deassigns the minor 542 * This unregisters the passed device. Future open calls will
372 * number. Future open calls will be met with errors. 543 * be met with errors.
373 */ 544 */
374 545void video_unregister_device(struct video_device *vdev)
375void video_unregister_device(struct video_device *vfd)
376{ 546{
377 device_unregister(&vfd->dev); 547 /* Check if vdev was ever registered at all */
548 if (!vdev || vdev->minor < 0)
549 return;
550
551 mutex_lock(&videodev_lock);
552 set_bit(V4L2_FL_UNREGISTERED, &vdev->flags);
553 mutex_unlock(&videodev_lock);
554 device_unregister(&vdev->dev);
378} 555}
379EXPORT_SYMBOL(video_unregister_device); 556EXPORT_SYMBOL(video_unregister_device);
380 557