Commit | Line | Data |
---|---|---|
8e080c2e MCC |
1 | <title>V4L2 Driver Programming</title> |
2 | ||
3 | <!-- This part defines the interface between the "videodev" | |
4 | module and individual drivers. --> | |
5 | ||
6 | <para>to do</para> | |
7 | <!-- | |
8 | <para>V4L2 is a two-layer driver system. The top layer is the "videodev" | |
9 | kernel module. When videodev initializes it registers as character device | |
10 | with major number 81, and it registers a set of file operations. All V4L2 | |
11 | drivers are really clients of videodev, which calls V4L2 drivers through | |
12 | driver method functions. V4L2 drivers are also written as kernel modules. | |
13 | After probing the hardware they register one or more devices with | |
14 | videodev.</para> | |
15 | ||
16 | <section id="driver-modules"> | |
17 | <title>Driver Modules</title> | |
18 | ||
19 | <para>V4L2 driver modules must have an initialization function which is | |
20 | called after the module was loaded into kernel, an exit function whis is | |
21 | called before the module is removed. When the driver is compiled into the | |
22 | kernel these functions called at system boot and shutdown time.</para> | |
23 | ||
24 | <informalexample> | |
25 | <programlisting> | |
26 | #include <linux/module.h> | |
27 | ||
28 | /* Export information about this module. For details and other useful | |
29 | macros see <filename>linux/module.h</filename>. */ | |
30 | MODULE_DESCRIPTION("my - driver for my hardware"); | |
31 | MODULE_AUTHOR("Your name here"); | |
32 | MODULE_LICENSE("GPL"); | |
33 | ||
34 | static void | |
35 | my_module_exit (void) | |
36 | { | |
37 | /* Free all resources allocated by my_module_init(). */ | |
38 | } | |
39 | ||
40 | static int | |
41 | my_module_init (void) | |
42 | { | |
43 | /* Bind the driver to the supported hardware, see | |
44 | <link linkend="driver-pci"> and | |
45 | <link linkend="driver-usb"> for examples. */ | |
46 | ||
47 | return 0; /* a negative value on error, 0 on success. */ | |
48 | } | |
49 | ||
50 | /* Export module functions. */ | |
51 | module_init (my_module_init); | |
52 | module_exit (my_module_exit); | |
53 | </programlisting> | |
54 | </informalexample> | |
55 | ||
56 | <para>Users can add parameters when kernel modules are inserted:</para> | |
57 | ||
58 | <informalexample> | |
59 | <programlisting> | |
60 | include <linux/moduleparam.h> | |
61 | ||
62 | static int my_option = 123; | |
63 | static int my_option_array[47]; | |
64 | ||
65 | /* Export the symbol, an int, with access permissions 0664. | |
66 | See <filename>linux/moduleparam.h</filename> for other types. */ | |
67 | module_param (my_option, int, 0644); | |
68 | module_param_array (my_option_array, int, NULL, 0644); | |
69 | ||
70 | MODULE_PARM_DESC (my_option, "Does magic things, default 123"); | |
71 | </programlisting> | |
72 | </informalexample> | |
73 | ||
74 | <para>One parameter should be supported by all V4L2 drivers, the minor | |
75 | number of the device it will register. Purpose is to predictably link V4L2 | |
76 | drivers to device nodes if more than one video device is installed. Use the | |
77 | name of the device node followed by a "_nr" suffix, for example "video_nr" | |
78 | for <filename>/dev/video</filename>.</para> | |
79 | ||
80 | <informalexample> | |
81 | <programlisting> | |
82 | /* Minor number of the device, -1 to allocate the first unused. */ | |
83 | static int video_nr = -1; | |
84 | ||
85 | module_param (video_nr, int, 0444); | |
86 | </programlisting> | |
87 | </informalexample> | |
88 | </section> | |
89 | ||
90 | <section id="driver-pci"> | |
91 | <title>PCI Devices</title> | |
92 | ||
93 | <para>PCI devices are initialized like this:</para> | |
94 | ||
95 | <informalexample> | |
96 | <programlisting> | |
97 | typedef struct { | |
98 | /* State of one physical device. */ | |
99 | } my_device; | |
100 | ||
101 | static int | |
102 | my_resume (struct pci_dev * pci_dev) | |
103 | { | |
104 | /* Restore the suspended device to working state. */ | |
105 | } | |
106 | ||
107 | static int | |
108 | my_suspend (struct pci_dev * pci_dev, | |
109 | pm_message_t state) | |
110 | { | |
111 | /* This function is called before the system goes to sleep. | |
112 | Stop all DMAs and disable interrupts, then put the device | |
113 | into a low power state. For details see the kernel | |
114 | sources under <filename>Documentation/power</filename>. */ | |
115 | ||
116 | return 0; /* a negative value on error, 0 on success. */ | |
117 | } | |
118 | ||
119 | static void __devexit | |
120 | my_remove (struct pci_dev * pci_dev) | |
121 | { | |
122 | my_device *my = pci_get_drvdata (pci_dev); | |
123 | ||
124 | /* Describe me. */ | |
125 | } | |
126 | ||
127 | static int __devinit | |
128 | my_probe (struct pci_dev * pci_dev, | |
129 | const struct pci_device_id * pci_id) | |
130 | { | |
131 | my_device *my; | |
132 | ||
133 | /* Describe me. */ | |
134 | ||
135 | /* You can allocate per-device data here and store a pointer | |
136 | to it in the pci_dev structure. */ | |
137 | my = ...; | |
138 | pci_set_drvdata (pci_dev, my); | |
139 | ||
140 | return 0; /* a negative value on error, 0 on success. */ | |
141 | } | |
142 | ||
143 | /* A list of supported PCI devices. */ | |
144 | static struct pci_device_id | |
145 | my_pci_device_ids [] = { | |
146 | { PCI_VENDOR_ID_FOO, PCI_DEVICE_ID_BAR, | |
147 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | |
148 | { 0 } /* end of list */ | |
149 | }; | |
150 | ||
151 | /* Load our module if supported PCI devices are installed. */ | |
152 | MODULE_DEVICE_TABLE (pci, my_pci_device_ids); | |
153 | ||
154 | static struct pci_driver | |
155 | my_pci_driver = { | |
156 | .name = "my", | |
157 | .id_table = my_pci_device_ids, | |
158 | ||
159 | .probe = my_probe, | |
160 | .remove = __devexit_p (my_remove), | |
161 | ||
162 | /* Power management functions. */ | |
163 | .suspend = my_suspend, | |
164 | .resume = my_resume, | |
165 | }; | |
166 | ||
167 | static void | |
168 | my_module_exit (void) | |
169 | { | |
170 | pci_unregister_driver (&my_pci_driver); | |
171 | } | |
172 | ||
173 | static int | |
174 | my_module_init (void) | |
175 | { | |
176 | return pci_register_driver (&my_pci_driver); | |
177 | } | |
178 | </programlisting> | |
179 | </informalexample> | |
180 | </section> | |
181 | ||
182 | <section id="driver-usb"> | |
183 | <title>USB Devices</title> | |
184 | <para>to do</para> | |
185 | </section> | |
186 | <section id="driver-registering"> | |
187 | <title>Registering V4L2 Drivers</title> | |
188 | ||
189 | <para>After a V4L2 driver probed the hardware it registers one or more | |
190 | devices with the videodev module.</para> | |
191 | </section> | |
192 | <section id="driver-file-ops"> | |
193 | <title>File Operations</title> | |
194 | <para>to do</para> | |
195 | </section> | |
196 | <section id="driver-internal-api"> | |
197 | <title>Internal API</title> | |
198 | <para>to do</para> | |
199 | </section> | |
200 | --> | |
201 | ||
202 | <!-- | |
203 | Local Variables: | |
204 | mode: sgml | |
205 | sgml-parent-document: "v4l2.sgml" | |
206 | indent-tabs-mode: nil | |
207 | End: | |
208 | --> |