Commit 2096a5dcf9704f5a86ecba37169eb813aaf0431c

Authored by Laurent Pinchart
Committed by Mauro Carvalho Chehab
1 parent 0070d91e5b

[media] v4l: subdev: Add device node support

Create a device node named subdevX for every registered subdev.

As the device node is registered before the subdev core::s_config
function is called, return -EGAIN on open until initialization
completes.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Vimarsh Zutshi <vimarsh.zutshi@gmail.com>
Acked-by: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

Showing 8 changed files with 158 additions and 22 deletions Side-by-side Diff

Documentation/video4linux/v4l2-framework.txt
... ... @@ -319,6 +319,22 @@
319 319 up the device, but once the subdev is registered it is completely transparent.
320 320  
321 321  
  322 +V4L2 sub-device userspace API
  323 +-----------------------------
  324 +
  325 +Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2
  326 +sub-devices can also be controlled directly by userspace applications.
  327 +
  328 +Device nodes named v4l-subdevX can be created in /dev to access sub-devices
  329 +directly. If a sub-device supports direct userspace configuration it must set
  330 +the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.
  331 +
  332 +After registering sub-devices, the v4l2_device driver can create device nodes
  333 +for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling
  334 +v4l2_device_register_subdev_nodes(). Those device nodes will be automatically
  335 +removed when sub-devices are unregistered.
  336 +
  337 +
322 338 I2C sub-device drivers
323 339 ----------------------
324 340  
drivers/media/video/Makefile
... ... @@ -11,7 +11,7 @@
11 11 omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
12 12  
13 13 videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
14   - v4l2-event.o v4l2-ctrls.o
  14 + v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
15 15  
16 16 # V4L2 core modules
17 17  
drivers/media/video/v4l2-dev.c
... ... @@ -408,13 +408,14 @@
408 408 }
409 409  
410 410 /**
411   - * video_register_device - register video4linux devices
  411 + * __video_register_device - register video4linux devices
412 412 * @vdev: video device structure we want to register
413 413 * @type: type of device to register
414 414 * @nr: which device node number (0 == /dev/video0, 1 == /dev/video1, ...
415 415 * -1 == first free)
416 416 * @warn_if_nr_in_use: warn if the desired device node number
417 417 * was already in use and another number was chosen instead.
  418 + * @owner: module that owns the video device node
418 419 *
419 420 * The registration code assigns minor numbers and device node numbers
420 421 * based on the requested type and registers the new device node with
421 422  
... ... @@ -435,9 +436,11 @@
435 436 * %VFL_TYPE_VBI - Vertical blank data (undecoded)
436 437 *
437 438 * %VFL_TYPE_RADIO - A radio card
  439 + *
  440 + * %VFL_TYPE_SUBDEV - A subdevice
438 441 */
439   -static int __video_register_device(struct video_device *vdev, int type, int nr,
440   - int warn_if_nr_in_use)
  442 +int __video_register_device(struct video_device *vdev, int type, int nr,
  443 + int warn_if_nr_in_use, struct module *owner)
441 444 {
442 445 int i = 0;
443 446 int ret;
... ... @@ -469,6 +472,9 @@
469 472 case VFL_TYPE_RADIO:
470 473 name_base = "radio";
471 474 break;
  475 + case VFL_TYPE_SUBDEV:
  476 + name_base = "v4l-subdev";
  477 + break;
472 478 default:
473 479 printk(KERN_ERR "%s called with unknown type: %d\n",
474 480 __func__, type);
... ... @@ -552,7 +558,7 @@
552 558 goto cleanup;
553 559 }
554 560 vdev->cdev->ops = &v4l2_fops;
555   - vdev->cdev->owner = vdev->fops->owner;
  561 + vdev->cdev->owner = owner;
556 562 ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
557 563 if (ret < 0) {
558 564 printk(KERN_ERR "%s: cdev_add failed\n", __func__);
... ... @@ -597,18 +603,7 @@
597 603 vdev->minor = -1;
598 604 return ret;
599 605 }
600   -
601   -int video_register_device(struct video_device *vdev, int type, int nr)
602   -{
603   - return __video_register_device(vdev, type, nr, 1);
604   -}
605   -EXPORT_SYMBOL(video_register_device);
606   -
607   -int video_register_device_no_warn(struct video_device *vdev, int type, int nr)
608   -{
609   - return __video_register_device(vdev, type, nr, 0);
610   -}
611   -EXPORT_SYMBOL(video_register_device_no_warn);
  606 +EXPORT_SYMBOL(__video_register_device);
612 607  
613 608 /**
614 609 * video_unregister_device - unregister a video4linux device
drivers/media/video/v4l2-device.c
... ... @@ -124,16 +124,20 @@
124 124 /* Check for valid input */
125 125 if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
126 126 return -EINVAL;
  127 +
127 128 /* Warn if we apparently re-register a subdev */
128 129 WARN_ON(sd->v4l2_dev != NULL);
  130 +
129 131 if (!try_module_get(sd->owner))
130 132 return -ENODEV;
  133 +
131 134 sd->v4l2_dev = v4l2_dev;
132 135 if (sd->internal_ops && sd->internal_ops->registered) {
133 136 err = sd->internal_ops->registered(sd);
134 137 if (err)
135 138 return err;
136 139 }
  140 +
137 141 /* This just returns 0 if either of the two args is NULL */
138 142 err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
139 143 if (err) {
140 144  
141 145  
142 146  
143 147  
... ... @@ -141,24 +145,57 @@
141 145 sd->internal_ops->unregistered(sd);
142 146 return err;
143 147 }
  148 +
144 149 spin_lock(&v4l2_dev->lock);
145 150 list_add_tail(&sd->list, &v4l2_dev->subdevs);
146 151 spin_unlock(&v4l2_dev->lock);
  152 +
147 153 return 0;
148 154 }
149 155 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
150 156  
  157 +int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
  158 +{
  159 + struct video_device *vdev;
  160 + struct v4l2_subdev *sd;
  161 + int err;
  162 +
  163 + /* Register a device node for every subdev marked with the
  164 + * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
  165 + */
  166 + list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
  167 + if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
  168 + continue;
  169 +
  170 + vdev = &sd->devnode;
  171 + strlcpy(vdev->name, sd->name, sizeof(vdev->name));
  172 + vdev->v4l2_dev = v4l2_dev;
  173 + vdev->fops = &v4l2_subdev_fops;
  174 + vdev->release = video_device_release_empty;
  175 + err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
  176 + sd->owner);
  177 + if (err < 0)
  178 + return err;
  179 + }
  180 +
  181 + return 0;
  182 +}
  183 +EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
  184 +
151 185 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
152 186 {
153 187 /* return if it isn't registered */
154 188 if (sd == NULL || sd->v4l2_dev == NULL)
155 189 return;
  190 +
156 191 spin_lock(&sd->v4l2_dev->lock);
157 192 list_del(&sd->list);
158 193 spin_unlock(&sd->v4l2_dev->lock);
159 194 if (sd->internal_ops && sd->internal_ops->unregistered)
160 195 sd->internal_ops->unregistered(sd);
161 196 sd->v4l2_dev = NULL;
  197 +
  198 + video_unregister_device(&sd->devnode);
162 199 module_put(sd->owner);
163 200 }
164 201 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
drivers/media/video/v4l2-subdev.c
  1 +/*
  2 + * V4L2 subdevice support.
  3 + *
  4 + * Copyright (C) 2010 Nokia Corporation
  5 + *
  6 + * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License as published by
  10 + * the Free Software Foundation.
  11 + *
  12 + * This program is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15 + * GNU General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU General Public License
  18 + * along with this program; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +
  22 +#include <linux/types.h>
  23 +#include <linux/ioctl.h>
  24 +#include <linux/videodev2.h>
  25 +
  26 +#include <media/v4l2-device.h>
  27 +#include <media/v4l2-ioctl.h>
  28 +
  29 +static int subdev_open(struct file *file)
  30 +{
  31 + return 0;
  32 +}
  33 +
  34 +static int subdev_close(struct file *file)
  35 +{
  36 + return 0;
  37 +}
  38 +
  39 +static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
  40 +{
  41 + switch (cmd) {
  42 + default:
  43 + return -ENOIOCTLCMD;
  44 + }
  45 +
  46 + return 0;
  47 +}
  48 +
  49 +static long subdev_ioctl(struct file *file, unsigned int cmd,
  50 + unsigned long arg)
  51 +{
  52 + return video_usercopy(file, cmd, arg, subdev_do_ioctl);
  53 +}
  54 +
  55 +const struct v4l2_file_operations v4l2_subdev_fops = {
  56 + .owner = THIS_MODULE,
  57 + .open = subdev_open,
  58 + .unlocked_ioctl = subdev_ioctl,
  59 + .release = subdev_close,
  60 +};
include/media/v4l2-dev.h
... ... @@ -21,7 +21,8 @@
21 21 #define VFL_TYPE_GRABBER 0
22 22 #define VFL_TYPE_VBI 1
23 23 #define VFL_TYPE_RADIO 2
24   -#define VFL_TYPE_MAX 3
  24 +#define VFL_TYPE_SUBDEV 3
  25 +#define VFL_TYPE_MAX 4
25 26  
26 27 struct v4l2_ioctl_callbacks;
27 28 struct video_device;
28 29  
29 30  
... ... @@ -102,15 +103,26 @@
102 103 /* dev to video-device */
103 104 #define to_video_device(cd) container_of(cd, struct video_device, dev)
104 105  
  106 +int __must_check __video_register_device(struct video_device *vdev, int type,
  107 + int nr, int warn_if_nr_in_use, struct module *owner);
  108 +
105 109 /* Register video devices. Note that if video_register_device fails,
106 110 the release() callback of the video_device structure is *not* called, so
107 111 the caller is responsible for freeing any data. Usually that means that
108 112 you call video_device_release() on failure. */
109   -int __must_check video_register_device(struct video_device *vdev, int type, int nr);
  113 +static inline int __must_check video_register_device(struct video_device *vdev,
  114 + int type, int nr)
  115 +{
  116 + return __video_register_device(vdev, type, nr, 1, vdev->fops->owner);
  117 +}
110 118  
111 119 /* Same as video_register_device, but no warning is issued if the desired
112 120 device node number was already in use. */
113   -int __must_check video_register_device_no_warn(struct video_device *vdev, int type, int nr);
  121 +static inline int __must_check video_register_device_no_warn(
  122 + struct video_device *vdev, int type, int nr)
  123 +{
  124 + return __video_register_device(vdev, type, nr, 0, vdev->fops->owner);
  125 +}
114 126  
115 127 /* Unregister video devices. Will do nothing if vdev == NULL or
116 128 video_is_registered() returns false. */
include/media/v4l2-device.h
... ... @@ -96,6 +96,12 @@
96 96 wasn't registered. In that case it will do nothing. */
97 97 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd);
98 98  
  99 +/* Register device nodes for all subdev of the v4l2 device that are marked with
  100 + * the V4L2_SUBDEV_FL_HAS_DEVNODE flag.
  101 + */
  102 +int __must_check
  103 +v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
  104 +
99 105 /* Iterate over all subdevs. */
100 106 #define v4l2_device_for_each_subdev(sd, v4l2_dev) \
101 107 list_for_each_entry(sd, &(v4l2_dev)->subdevs, list)
include/media/v4l2-subdev.h
... ... @@ -22,6 +22,7 @@
22 22 #define _V4L2_SUBDEV_H
23 23  
24 24 #include <media/v4l2-common.h>
  25 +#include <media/v4l2-dev.h>
25 26 #include <media/v4l2-mediabus.h>
26 27  
27 28 /* generic v4l2_device notify callback notification values */
28 29  
... ... @@ -431,9 +432,11 @@
431 432 #define V4L2_SUBDEV_NAME_SIZE 32
432 433  
433 434 /* Set this flag if this subdev is a i2c device. */
434   -#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
  435 +#define V4L2_SUBDEV_FL_IS_I2C (1U << 0)
435 436 /* Set this flag if this subdev is a spi device. */
436   -#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
  437 +#define V4L2_SUBDEV_FL_IS_SPI (1U << 1)
  438 +/* Set this flag if this subdev needs a device node. */
  439 +#define V4L2_SUBDEV_FL_HAS_DEVNODE (1U << 2)
437 440  
438 441 /* Each instance of a subdev driver should create this struct, either
439 442 stand-alone or embedded in a larger struct.
440 443  
... ... @@ -455,7 +458,14 @@
455 458 /* pointer to private data */
456 459 void *dev_priv;
457 460 void *host_priv;
  461 + /* subdev device node */
  462 + struct video_device devnode;
458 463 };
  464 +
  465 +#define vdev_to_v4l2_subdev(vdev) \
  466 + container_of(vdev, struct v4l2_subdev, devnode)
  467 +
  468 +extern const struct v4l2_file_operations v4l2_subdev_fops;
459 469  
460 470 static inline void v4l2_set_subdevdata(struct v4l2_subdev *sd, void *p)
461 471 {