| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | .. SPDX-License-Identifier: GPL-2.0 | 
|  | 2 |  | 
|  | 3 | V4L2 device instance | 
|  | 4 | -------------------- | 
|  | 5 |  | 
|  | 6 | Each device instance is represented by a struct :c:type:`v4l2_device`. | 
|  | 7 | Very simple devices can just allocate this struct, but most of the time you | 
|  | 8 | would embed this struct inside a larger struct. | 
|  | 9 |  | 
|  | 10 | You must register the device instance by calling: | 
|  | 11 |  | 
|  | 12 | :c:func:`v4l2_device_register <v4l2_device_register>` | 
|  | 13 | (dev, :c:type:`v4l2_dev <v4l2_device>`). | 
|  | 14 |  | 
|  | 15 | Registration will initialize the :c:type:`v4l2_device` struct. If the | 
|  | 16 | dev->driver_data field is ``NULL``, it will be linked to | 
|  | 17 | :c:type:`v4l2_dev <v4l2_device>` argument. | 
|  | 18 |  | 
|  | 19 | Drivers that want integration with the media device framework need to set | 
|  | 20 | dev->driver_data manually to point to the driver-specific device structure | 
|  | 21 | that embed the struct :c:type:`v4l2_device` instance. This is achieved by a | 
|  | 22 | ``dev_set_drvdata()`` call before registering the V4L2 device instance. | 
|  | 23 | They must also set the struct :c:type:`v4l2_device` mdev field to point to a | 
|  | 24 | properly initialized and registered :c:type:`media_device` instance. | 
|  | 25 |  | 
|  | 26 | If :c:type:`v4l2_dev <v4l2_device>`\ ->name is empty then it will be set to a | 
|  | 27 | value derived from dev (driver name followed by the bus_id, to be precise). | 
|  | 28 | If you set it up before  calling :c:func:`v4l2_device_register` then it will | 
|  | 29 | be untouched. If dev is ``NULL``, then you **must** setup | 
|  | 30 | :c:type:`v4l2_dev <v4l2_device>`\ ->name before calling | 
|  | 31 | :c:func:`v4l2_device_register`. | 
|  | 32 |  | 
|  | 33 | You can use :c:func:`v4l2_device_set_name` to set the name based on a driver | 
|  | 34 | name and a driver-global atomic_t instance. This will generate names like | 
|  | 35 | ``ivtv0``, ``ivtv1``, etc. If the name ends with a digit, then it will insert | 
|  | 36 | a dash: ``cx18-0``, ``cx18-1``, etc. This function returns the instance number. | 
|  | 37 |  | 
|  | 38 | The first ``dev`` argument is normally the ``struct device`` pointer of a | 
|  | 39 | ``pci_dev``, ``usb_interface`` or ``platform_device``. It is rare for dev to | 
|  | 40 | be ``NULL``, but it happens with ISA devices or when one device creates | 
|  | 41 | multiple PCI devices, thus making it impossible to associate | 
|  | 42 | :c:type:`v4l2_dev <v4l2_device>` with a particular parent. | 
|  | 43 |  | 
|  | 44 | You can also supply a ``notify()`` callback that can be called by sub-devices | 
|  | 45 | to notify you of events. Whether you need to set this depends on the | 
|  | 46 | sub-device. Any notifications a sub-device supports must be defined in a header | 
|  | 47 | in ``include/media/subdevice.h``. | 
|  | 48 |  | 
|  | 49 | V4L2 devices are unregistered by calling: | 
|  | 50 |  | 
|  | 51 | :c:func:`v4l2_device_unregister` | 
|  | 52 | (:c:type:`v4l2_dev <v4l2_device>`). | 
|  | 53 |  | 
|  | 54 | If the dev->driver_data field points to :c:type:`v4l2_dev <v4l2_device>`, | 
|  | 55 | it will be reset to ``NULL``. Unregistering will also automatically unregister | 
|  | 56 | all subdevs from the device. | 
|  | 57 |  | 
|  | 58 | If you have a hotpluggable device (e.g. a USB device), then when a disconnect | 
|  | 59 | happens the parent device becomes invalid. Since :c:type:`v4l2_device` has a | 
|  | 60 | pointer to that parent device it has to be cleared as well to mark that the | 
|  | 61 | parent is gone. To do this call: | 
|  | 62 |  | 
|  | 63 | :c:func:`v4l2_device_disconnect` | 
|  | 64 | (:c:type:`v4l2_dev <v4l2_device>`). | 
|  | 65 |  | 
|  | 66 | This does *not* unregister the subdevs, so you still need to call the | 
|  | 67 | :c:func:`v4l2_device_unregister` function for that. If your driver is not | 
|  | 68 | hotpluggable, then there is no need to call :c:func:`v4l2_device_disconnect`. | 
|  | 69 |  | 
|  | 70 | Sometimes you need to iterate over all devices registered by a specific | 
|  | 71 | driver. This is usually the case if multiple device drivers use the same | 
|  | 72 | hardware. E.g. the ivtvfb driver is a framebuffer driver that uses the ivtv | 
|  | 73 | hardware. The same is true for alsa drivers for example. | 
|  | 74 |  | 
|  | 75 | You can iterate over all registered devices as follows: | 
|  | 76 |  | 
|  | 77 | .. code-block:: c | 
|  | 78 |  | 
|  | 79 | static int callback(struct device *dev, void *p) | 
|  | 80 | { | 
|  | 81 | struct v4l2_device *v4l2_dev = dev_get_drvdata(dev); | 
|  | 82 |  | 
|  | 83 | /* test if this device was inited */ | 
|  | 84 | if (v4l2_dev == NULL) | 
|  | 85 | return 0; | 
|  | 86 | ... | 
|  | 87 | return 0; | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | int iterate(void *p) | 
|  | 91 | { | 
|  | 92 | struct device_driver *drv; | 
|  | 93 | int err; | 
|  | 94 |  | 
|  | 95 | /* Find driver 'ivtv' on the PCI bus. | 
|  | 96 | pci_bus_type is a global. For USB buses use usb_bus_type. */ | 
|  | 97 | drv = driver_find("ivtv", &pci_bus_type); | 
|  | 98 | /* iterate over all ivtv device instances */ | 
|  | 99 | err = driver_for_each_device(drv, NULL, p, callback); | 
|  | 100 | put_driver(drv); | 
|  | 101 | return err; | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | Sometimes you need to keep a running counter of the device instance. This is | 
|  | 105 | commonly used to map a device instance to an index of a module option array. | 
|  | 106 |  | 
|  | 107 | The recommended approach is as follows: | 
|  | 108 |  | 
|  | 109 | .. code-block:: c | 
|  | 110 |  | 
|  | 111 | static atomic_t drv_instance = ATOMIC_INIT(0); | 
|  | 112 |  | 
|  | 113 | static int drv_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) | 
|  | 114 | { | 
|  | 115 | ... | 
|  | 116 | state->instance = atomic_inc_return(&drv_instance) - 1; | 
|  | 117 | } | 
|  | 118 |  | 
|  | 119 | If you have multiple device nodes then it can be difficult to know when it is | 
|  | 120 | safe to unregister :c:type:`v4l2_device` for hotpluggable devices. For this | 
|  | 121 | purpose :c:type:`v4l2_device` has refcounting support. The refcount is | 
|  | 122 | increased whenever :c:func:`video_register_device` is called and it is | 
|  | 123 | decreased whenever that device node is released. When the refcount reaches | 
|  | 124 | zero, then the :c:type:`v4l2_device` release() callback is called. You can | 
|  | 125 | do your final cleanup there. | 
|  | 126 |  | 
|  | 127 | If other device nodes (e.g. ALSA) are created, then you can increase and | 
|  | 128 | decrease the refcount manually as well by calling: | 
|  | 129 |  | 
|  | 130 | :c:func:`v4l2_device_get` | 
|  | 131 | (:c:type:`v4l2_dev <v4l2_device>`). | 
|  | 132 |  | 
|  | 133 | or: | 
|  | 134 |  | 
|  | 135 | :c:func:`v4l2_device_put` | 
|  | 136 | (:c:type:`v4l2_dev <v4l2_device>`). | 
|  | 137 |  | 
|  | 138 | Since the initial refcount is 1 you also need to call | 
|  | 139 | :c:func:`v4l2_device_put` in the ``disconnect()`` callback (for USB devices) | 
|  | 140 | or in the ``remove()`` callback (for e.g. PCI devices), otherwise the refcount | 
|  | 141 | will never reach 0. | 
|  | 142 |  | 
|  | 143 | v4l2_device functions and data structures | 
|  | 144 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 
|  | 145 |  | 
|  | 146 | .. kernel-doc:: include/media/v4l2-device.h |