diff options
-rw-r--r-- | Documentation/video4linux/v4l2-framework.txt | 10 | ||||
-rw-r--r-- | drivers/media/video/v4l2-device.c | 37 | ||||
-rw-r--r-- | include/media/v4l2-device.h | 31 |
3 files changed, 48 insertions, 30 deletions
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt index 48cdf86248cb..e1620e2a38ff 100644 --- a/Documentation/video4linux/v4l2-framework.txt +++ b/Documentation/video4linux/v4l2-framework.txt | |||
@@ -84,12 +84,14 @@ You must register the device instance: | |||
84 | v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); | 84 | v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); |
85 | 85 | ||
86 | Registration will initialize the v4l2_device struct and link dev->driver_data | 86 | Registration will initialize the v4l2_device struct and link dev->driver_data |
87 | to v4l2_dev. Registration will also set v4l2_dev->name to a value derived from | 87 | to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived |
88 | dev (driver name followed by the bus_id, to be precise). You may change the | 88 | from dev (driver name followed by the bus_id, to be precise). If you set it |
89 | name after registration if you want. | 89 | up before calling v4l2_device_register then it will be untouched. If dev is |
90 | NULL, then you *must* setup v4l2_dev->name before calling v4l2_device_register. | ||
90 | 91 | ||
91 | The first 'dev' argument is normally the struct device pointer of a pci_dev, | 92 | The first 'dev' argument is normally the struct device pointer of a pci_dev, |
92 | usb_device or platform_device. | 93 | usb_device or platform_device. It is rare for dev to be NULL, but it happens |
94 | with ISA devices, for example. | ||
93 | 95 | ||
94 | You unregister with: | 96 | You unregister with: |
95 | 97 | ||
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 8a4b74f3129f..3330ffb7d010 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c | |||
@@ -26,15 +26,24 @@ | |||
26 | 26 | ||
27 | int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) | 27 | int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) |
28 | { | 28 | { |
29 | if (dev == NULL || v4l2_dev == NULL) | 29 | if (v4l2_dev == NULL) |
30 | return -EINVAL; | 30 | return -EINVAL; |
31 | /* Warn if we apparently re-register a device */ | 31 | |
32 | WARN_ON(dev_get_drvdata(dev) != NULL); | ||
33 | INIT_LIST_HEAD(&v4l2_dev->subdevs); | 32 | INIT_LIST_HEAD(&v4l2_dev->subdevs); |
34 | spin_lock_init(&v4l2_dev->lock); | 33 | spin_lock_init(&v4l2_dev->lock); |
35 | v4l2_dev->dev = dev; | 34 | v4l2_dev->dev = dev; |
36 | snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", | 35 | if (dev == NULL) { |
36 | /* If dev == NULL, then name must be filled in by the caller */ | ||
37 | WARN_ON(!v4l2_dev->name[0]); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
41 | /* Set name to driver name + device name if it is empty. */ | ||
42 | if (!v4l2_dev->name[0]) | ||
43 | snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", | ||
37 | dev->driver->name, dev_name(dev)); | 44 | dev->driver->name, dev_name(dev)); |
45 | if (dev_get_drvdata(dev)) | ||
46 | v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n"); | ||
38 | dev_set_drvdata(dev, v4l2_dev); | 47 | dev_set_drvdata(dev, v4l2_dev); |
39 | return 0; | 48 | return 0; |
40 | } | 49 | } |
@@ -44,10 +53,11 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) | |||
44 | { | 53 | { |
45 | struct v4l2_subdev *sd, *next; | 54 | struct v4l2_subdev *sd, *next; |
46 | 55 | ||
47 | if (v4l2_dev == NULL || v4l2_dev->dev == NULL) | 56 | if (v4l2_dev == NULL) |
48 | return; | 57 | return; |
49 | dev_set_drvdata(v4l2_dev->dev, NULL); | 58 | if (v4l2_dev->dev) |
50 | /* unregister subdevs */ | 59 | dev_set_drvdata(v4l2_dev->dev, NULL); |
60 | /* Unregister subdevs */ | ||
51 | list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) | 61 | list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) |
52 | v4l2_device_unregister_subdev(sd); | 62 | v4l2_device_unregister_subdev(sd); |
53 | 63 | ||
@@ -55,19 +65,20 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev) | |||
55 | } | 65 | } |
56 | EXPORT_SYMBOL_GPL(v4l2_device_unregister); | 66 | EXPORT_SYMBOL_GPL(v4l2_device_unregister); |
57 | 67 | ||
58 | int v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd) | 68 | int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, |
69 | struct v4l2_subdev *sd) | ||
59 | { | 70 | { |
60 | /* Check for valid input */ | 71 | /* Check for valid input */ |
61 | if (dev == NULL || sd == NULL || !sd->name[0]) | 72 | if (v4l2_dev == NULL || sd == NULL || !sd->name[0]) |
62 | return -EINVAL; | 73 | return -EINVAL; |
63 | /* Warn if we apparently re-register a subdev */ | 74 | /* Warn if we apparently re-register a subdev */ |
64 | WARN_ON(sd->dev != NULL); | 75 | WARN_ON(sd->dev != NULL); |
65 | if (!try_module_get(sd->owner)) | 76 | if (!try_module_get(sd->owner)) |
66 | return -ENODEV; | 77 | return -ENODEV; |
67 | sd->dev = dev; | 78 | sd->dev = v4l2_dev; |
68 | spin_lock(&dev->lock); | 79 | spin_lock(&v4l2_dev->lock); |
69 | list_add_tail(&sd->list, &dev->subdevs); | 80 | list_add_tail(&sd->list, &v4l2_dev->subdevs); |
70 | spin_unlock(&dev->lock); | 81 | spin_unlock(&v4l2_dev->lock); |
71 | return 0; | 82 | return 0; |
72 | } | 83 | } |
73 | EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); | 84 | EXPORT_SYMBOL_GPL(v4l2_device_register_subdev); |
diff --git a/include/media/v4l2-device.h b/include/media/v4l2-device.h index 55e41afd95ef..5d7146dc2913 100644 --- a/include/media/v4l2-device.h +++ b/include/media/v4l2-device.h | |||
@@ -33,7 +33,9 @@ | |||
33 | #define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16) | 33 | #define V4L2_DEVICE_NAME_SIZE (BUS_ID_SIZE + 16) |
34 | 34 | ||
35 | struct v4l2_device { | 35 | struct v4l2_device { |
36 | /* dev->driver_data points to this struct */ | 36 | /* dev->driver_data points to this struct. |
37 | Note: dev might be NULL if there is no parent device | ||
38 | as is the case with e.g. ISA devices. */ | ||
37 | struct device *dev; | 39 | struct device *dev; |
38 | /* used to keep track of the registered subdevs */ | 40 | /* used to keep track of the registered subdevs */ |
39 | struct list_head subdevs; | 41 | struct list_head subdevs; |
@@ -44,7 +46,9 @@ struct v4l2_device { | |||
44 | char name[V4L2_DEVICE_NAME_SIZE]; | 46 | char name[V4L2_DEVICE_NAME_SIZE]; |
45 | }; | 47 | }; |
46 | 48 | ||
47 | /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev */ | 49 | /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev. |
50 | dev may be NULL in rare cases (ISA devices). In that case you | ||
51 | must fill in the v4l2_dev->name field before calling this function. */ | ||
48 | int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); | 52 | int __must_check v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev); |
49 | /* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */ | 53 | /* Set v4l2_dev->dev->driver_data to NULL and unregister all sub-devices */ |
50 | void v4l2_device_unregister(struct v4l2_device *v4l2_dev); | 54 | void v4l2_device_unregister(struct v4l2_device *v4l2_dev); |
@@ -52,23 +56,24 @@ void v4l2_device_unregister(struct v4l2_device *v4l2_dev); | |||
52 | /* Register a subdev with a v4l2 device. While registered the subdev module | 56 | /* Register a subdev with a v4l2 device. While registered the subdev module |
53 | is marked as in-use. An error is returned if the module is no longer | 57 | is marked as in-use. An error is returned if the module is no longer |
54 | loaded when you attempt to register it. */ | 58 | loaded when you attempt to register it. */ |
55 | int __must_check v4l2_device_register_subdev(struct v4l2_device *dev, struct v4l2_subdev *sd); | 59 | int __must_check v4l2_device_register_subdev(struct v4l2_device *v4l2_dev, |
60 | struct v4l2_subdev *sd); | ||
56 | /* Unregister a subdev with a v4l2 device. Can also be called if the subdev | 61 | /* Unregister a subdev with a v4l2 device. Can also be called if the subdev |
57 | wasn't registered. In that case it will do nothing. */ | 62 | wasn't registered. In that case it will do nothing. */ |
58 | void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); | 63 | void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); |
59 | 64 | ||
60 | /* Iterate over all subdevs. */ | 65 | /* Iterate over all subdevs. */ |
61 | #define v4l2_device_for_each_subdev(sd, dev) \ | 66 | #define v4l2_device_for_each_subdev(sd, v4l2_dev) \ |
62 | list_for_each_entry(sd, &(dev)->subdevs, list) | 67 | list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) |
63 | 68 | ||
64 | /* Call the specified callback for all subdevs matching the condition. | 69 | /* Call the specified callback for all subdevs matching the condition. |
65 | Ignore any errors. Note that you cannot add or delete a subdev | 70 | Ignore any errors. Note that you cannot add or delete a subdev |
66 | while walking the subdevs list. */ | 71 | while walking the subdevs list. */ |
67 | #define __v4l2_device_call_subdevs(dev, cond, o, f, args...) \ | 72 | #define __v4l2_device_call_subdevs(v4l2_dev, cond, o, f, args...) \ |
68 | do { \ | 73 | do { \ |
69 | struct v4l2_subdev *sd; \ | 74 | struct v4l2_subdev *sd; \ |
70 | \ | 75 | \ |
71 | list_for_each_entry(sd, &(dev)->subdevs, list) \ | 76 | list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) \ |
72 | if ((cond) && sd->ops->o && sd->ops->o->f) \ | 77 | if ((cond) && sd->ops->o && sd->ops->o->f) \ |
73 | sd->ops->o->f(sd , ##args); \ | 78 | sd->ops->o->f(sd , ##args); \ |
74 | } while (0) | 79 | } while (0) |
@@ -77,12 +82,12 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); | |||
77 | If the callback returns an error other than 0 or -ENOIOCTLCMD, then | 82 | If the callback returns an error other than 0 or -ENOIOCTLCMD, then |
78 | return with that error code. Note that you cannot add or delete a | 83 | return with that error code. Note that you cannot add or delete a |
79 | subdev while walking the subdevs list. */ | 84 | subdev while walking the subdevs list. */ |
80 | #define __v4l2_device_call_subdevs_until_err(dev, cond, o, f, args...) \ | 85 | #define __v4l2_device_call_subdevs_until_err(v4l2_dev, cond, o, f, args...) \ |
81 | ({ \ | 86 | ({ \ |
82 | struct v4l2_subdev *sd; \ | 87 | struct v4l2_subdev *sd; \ |
83 | long err = 0; \ | 88 | long err = 0; \ |
84 | \ | 89 | \ |
85 | list_for_each_entry(sd, &(dev)->subdevs, list) { \ | 90 | list_for_each_entry(sd, &(v4l2_dev)->subdevs, list) { \ |
86 | if ((cond) && sd->ops->o && sd->ops->o->f) \ | 91 | if ((cond) && sd->ops->o && sd->ops->o->f) \ |
87 | err = sd->ops->o->f(sd , ##args); \ | 92 | err = sd->ops->o->f(sd , ##args); \ |
88 | if (err && err != -ENOIOCTLCMD) \ | 93 | if (err && err != -ENOIOCTLCMD) \ |
@@ -94,16 +99,16 @@ void v4l2_device_unregister_subdev(struct v4l2_subdev *sd); | |||
94 | /* Call the specified callback for all subdevs matching grp_id (if 0, then | 99 | /* Call the specified callback for all subdevs matching grp_id (if 0, then |
95 | match them all). Ignore any errors. Note that you cannot add or delete | 100 | match them all). Ignore any errors. Note that you cannot add or delete |
96 | a subdev while walking the subdevs list. */ | 101 | a subdev while walking the subdevs list. */ |
97 | #define v4l2_device_call_all(dev, grpid, o, f, args...) \ | 102 | #define v4l2_device_call_all(v4l2_dev, grpid, o, f, args...) \ |
98 | __v4l2_device_call_subdevs(dev, \ | 103 | __v4l2_device_call_subdevs(v4l2_dev, \ |
99 | !(grpid) || sd->grp_id == (grpid), o, f , ##args) | 104 | !(grpid) || sd->grp_id == (grpid), o, f , ##args) |
100 | 105 | ||
101 | /* Call the specified callback for all subdevs matching grp_id (if 0, then | 106 | /* Call the specified callback for all subdevs matching grp_id (if 0, then |
102 | match them all). If the callback returns an error other than 0 or | 107 | match them all). If the callback returns an error other than 0 or |
103 | -ENOIOCTLCMD, then return with that error code. Note that you cannot | 108 | -ENOIOCTLCMD, then return with that error code. Note that you cannot |
104 | add or delete a subdev while walking the subdevs list. */ | 109 | add or delete a subdev while walking the subdevs list. */ |
105 | #define v4l2_device_call_until_err(dev, grpid, o, f, args...) \ | 110 | #define v4l2_device_call_until_err(v4l2_dev, grpid, o, f, args...) \ |
106 | __v4l2_device_call_subdevs_until_err(dev, \ | 111 | __v4l2_device_call_subdevs_until_err(v4l2_dev, \ |
107 | !(grpid) || sd->grp_id == (grpid), o, f , ##args) | 112 | !(grpid) || sd->grp_id == (grpid), o, f , ##args) |
108 | 113 | ||
109 | #endif | 114 | #endif |