blob: 583f9c158e63fdacef5324c6147aa51a897bf4e7 [file] [log] [blame]
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001/*
2 * Video capture interface for Linux version 2
3 *
4 * A generic framework to process V4L2 ioctl commands.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Alan Coxd9b01442008-10-27 15:13:47 -030011 * Authors: Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
Hans Verkuil35ea11f2008-07-20 08:12:02 -030012 * Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
13 */
14
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/kernel.h>
18
19#define __OLD_VIDIOC_ /* To allow fixing old calls */
Mauro Carvalho Chehab7e0a16f2009-03-10 05:31:34 -030020#include <linux/videodev.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030021#include <linux/videodev2.h>
22
23#ifdef CONFIG_VIDEO_V4L1
24#include <linux/videodev.h>
25#endif
26#include <media/v4l2-common.h>
27#include <media/v4l2-ioctl.h>
Hans Verkuil80b36e02009-02-07 11:00:02 -030028#include <media/v4l2-chip-ident.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030029
30#define dbgarg(cmd, fmt, arg...) \
31 do { \
32 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
33 printk(KERN_DEBUG "%s: ", vfd->name); \
34 v4l_printk_ioctl(cmd); \
35 printk(" " fmt, ## arg); \
36 } \
37 } while (0)
38
39#define dbgarg2(fmt, arg...) \
40 do { \
41 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
42 printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
43 } while (0)
44
45struct std_descr {
46 v4l2_std_id std;
47 const char *descr;
48};
49
50static const struct std_descr standards[] = {
51 { V4L2_STD_NTSC, "NTSC" },
52 { V4L2_STD_NTSC_M, "NTSC-M" },
53 { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" },
54 { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" },
55 { V4L2_STD_NTSC_443, "NTSC-443" },
56 { V4L2_STD_PAL, "PAL" },
57 { V4L2_STD_PAL_BG, "PAL-BG" },
58 { V4L2_STD_PAL_B, "PAL-B" },
59 { V4L2_STD_PAL_B1, "PAL-B1" },
60 { V4L2_STD_PAL_G, "PAL-G" },
61 { V4L2_STD_PAL_H, "PAL-H" },
62 { V4L2_STD_PAL_I, "PAL-I" },
63 { V4L2_STD_PAL_DK, "PAL-DK" },
64 { V4L2_STD_PAL_D, "PAL-D" },
65 { V4L2_STD_PAL_D1, "PAL-D1" },
66 { V4L2_STD_PAL_K, "PAL-K" },
67 { V4L2_STD_PAL_M, "PAL-M" },
68 { V4L2_STD_PAL_N, "PAL-N" },
69 { V4L2_STD_PAL_Nc, "PAL-Nc" },
70 { V4L2_STD_PAL_60, "PAL-60" },
71 { V4L2_STD_SECAM, "SECAM" },
72 { V4L2_STD_SECAM_B, "SECAM-B" },
73 { V4L2_STD_SECAM_G, "SECAM-G" },
74 { V4L2_STD_SECAM_H, "SECAM-H" },
75 { V4L2_STD_SECAM_DK, "SECAM-DK" },
76 { V4L2_STD_SECAM_D, "SECAM-D" },
77 { V4L2_STD_SECAM_K, "SECAM-K" },
78 { V4L2_STD_SECAM_K1, "SECAM-K1" },
79 { V4L2_STD_SECAM_L, "SECAM-L" },
80 { V4L2_STD_SECAM_LC, "SECAM-Lc" },
81 { 0, "Unknown" }
82};
83
84/* video4linux standard ID conversion to standard name
85 */
86const char *v4l2_norm_to_name(v4l2_std_id id)
87{
88 u32 myid = id;
89 int i;
90
91 /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
92 64 bit comparations. So, on that architecture, with some gcc
93 variants, compilation fails. Currently, the max value is 30bit wide.
94 */
95 BUG_ON(myid != id);
96
97 for (i = 0; standards[i].std; i++)
98 if (myid == standards[i].std)
99 break;
100 return standards[i].descr;
101}
102EXPORT_SYMBOL(v4l2_norm_to_name);
103
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300104/* Returns frame period for the given standard */
105void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
106{
107 if (id & V4L2_STD_525_60) {
108 frameperiod->numerator = 1001;
109 frameperiod->denominator = 30000;
110 } else {
111 frameperiod->numerator = 1;
112 frameperiod->denominator = 25;
113 }
114}
115EXPORT_SYMBOL(v4l2_video_std_frame_period);
116
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300117/* Fill in the fields of a v4l2_standard structure according to the
118 'id' and 'transmission' parameters. Returns negative on error. */
119int v4l2_video_std_construct(struct v4l2_standard *vs,
120 int id, const char *name)
121{
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300122 vs->id = id;
123 v4l2_video_std_frame_period(id, &vs->frameperiod);
124 vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300125 strlcpy(vs->name, name, sizeof(vs->name));
126 return 0;
127}
128EXPORT_SYMBOL(v4l2_video_std_construct);
129
130/* ----------------------------------------------------------------- */
131/* some arrays for pretty-printing debug messages of enum types */
132
133const char *v4l2_field_names[] = {
134 [V4L2_FIELD_ANY] = "any",
135 [V4L2_FIELD_NONE] = "none",
136 [V4L2_FIELD_TOP] = "top",
137 [V4L2_FIELD_BOTTOM] = "bottom",
138 [V4L2_FIELD_INTERLACED] = "interlaced",
139 [V4L2_FIELD_SEQ_TB] = "seq-tb",
140 [V4L2_FIELD_SEQ_BT] = "seq-bt",
141 [V4L2_FIELD_ALTERNATE] = "alternate",
142 [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
143 [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
144};
145EXPORT_SYMBOL(v4l2_field_names);
146
147const char *v4l2_type_names[] = {
148 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "vid-cap",
149 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "vid-overlay",
150 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "vid-out",
151 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
152 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
153 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
154 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
155 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
156};
157EXPORT_SYMBOL(v4l2_type_names);
158
159static const char *v4l2_memory_names[] = {
160 [V4L2_MEMORY_MMAP] = "mmap",
161 [V4L2_MEMORY_USERPTR] = "userptr",
162 [V4L2_MEMORY_OVERLAY] = "overlay",
163};
164
165#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
166 arr[a] : "unknown")
167
168/* ------------------------------------------------------------------ */
169/* debug help functions */
170
171#ifdef CONFIG_VIDEO_V4L1_COMPAT
172static const char *v4l1_ioctls[] = {
173 [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
174 [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
175 [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
176 [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
177 [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
178 [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
179 [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
180 [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
181 [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
182 [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
183 [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
184 [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
185 [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
186 [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
187 [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
188 [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
189 [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
190 [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
191 [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
192 [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
193 [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
194 [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
195 [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
196 [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
197 [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
198 [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
199 [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
200 [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
201 [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
202};
203#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
204#endif
205
206static const char *v4l2_ioctls[] = {
207 [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
208 [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
209 [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
210 [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
211 [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
212 [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
213 [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
214 [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
215 [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
216 [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
217 [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
218 [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
219 [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
220 [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
221 [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
222 [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
223 [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
224 [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
225 [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
226 [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
227 [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
228 [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
229 [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
230 [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
231 [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
232 [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
233 [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
234 [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
235 [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
236 [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
237 [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
238 [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
239 [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
240 [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
241 [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
242 [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
243 [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
244 [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
245 [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
246 [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
247 [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
248 [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
249 [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
250 [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
251 [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
252 [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
253 [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
254 [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
255 [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
256 [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
257 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
258 [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
259 [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
260 [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
261 [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
262#if 1
263 [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
264 [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
265 [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
266 [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
267 [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
268
269 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
270 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
271
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300272 [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300273 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
274#endif
275};
276#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
277
278static const char *v4l2_int_ioctls[] = {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300279 [_IOC_NR(AUDC_SET_RADIO)] = "AUDC_SET_RADIO",
280
281 [_IOC_NR(TUNER_SET_TYPE_ADDR)] = "TUNER_SET_TYPE_ADDR",
282 [_IOC_NR(TUNER_SET_STANDBY)] = "TUNER_SET_STANDBY",
283 [_IOC_NR(TUNER_SET_CONFIG)] = "TUNER_SET_CONFIG",
284
285 [_IOC_NR(VIDIOC_INT_S_TUNER_MODE)] = "VIDIOC_INT_S_TUNER_MODE",
286 [_IOC_NR(VIDIOC_INT_RESET)] = "VIDIOC_INT_RESET",
287 [_IOC_NR(VIDIOC_INT_AUDIO_CLOCK_FREQ)] = "VIDIOC_INT_AUDIO_CLOCK_FREQ",
288 [_IOC_NR(VIDIOC_INT_DECODE_VBI_LINE)] = "VIDIOC_INT_DECODE_VBI_LINE",
289 [_IOC_NR(VIDIOC_INT_S_VBI_DATA)] = "VIDIOC_INT_S_VBI_DATA",
290 [_IOC_NR(VIDIOC_INT_G_VBI_DATA)] = "VIDIOC_INT_G_VBI_DATA",
291 [_IOC_NR(VIDIOC_INT_I2S_CLOCK_FREQ)] = "VIDIOC_INT_I2S_CLOCK_FREQ",
292 [_IOC_NR(VIDIOC_INT_S_STANDBY)] = "VIDIOC_INT_S_STANDBY",
293 [_IOC_NR(VIDIOC_INT_S_AUDIO_ROUTING)] = "VIDIOC_INT_S_AUDIO_ROUTING",
294 [_IOC_NR(VIDIOC_INT_G_AUDIO_ROUTING)] = "VIDIOC_INT_G_AUDIO_ROUTING",
295 [_IOC_NR(VIDIOC_INT_S_VIDEO_ROUTING)] = "VIDIOC_INT_S_VIDEO_ROUTING",
296 [_IOC_NR(VIDIOC_INT_G_VIDEO_ROUTING)] = "VIDIOC_INT_G_VIDEO_ROUTING",
297 [_IOC_NR(VIDIOC_INT_S_CRYSTAL_FREQ)] = "VIDIOC_INT_S_CRYSTAL_FREQ",
298 [_IOC_NR(VIDIOC_INT_INIT)] = "VIDIOC_INT_INIT",
299 [_IOC_NR(VIDIOC_INT_G_STD_OUTPUT)] = "VIDIOC_INT_G_STD_OUTPUT",
300 [_IOC_NR(VIDIOC_INT_S_STD_OUTPUT)] = "VIDIOC_INT_S_STD_OUTPUT",
301};
302#define V4L2_INT_IOCTLS ARRAY_SIZE(v4l2_int_ioctls)
303
304/* Common ioctl debug function. This function can be used by
305 external ioctl messages as well as internal V4L ioctl */
306void v4l_printk_ioctl(unsigned int cmd)
307{
308 char *dir, *type;
309
310 switch (_IOC_TYPE(cmd)) {
311 case 'd':
312 if (_IOC_NR(cmd) >= V4L2_INT_IOCTLS) {
313 type = "v4l2_int";
314 break;
315 }
316 printk("%s", v4l2_int_ioctls[_IOC_NR(cmd)]);
317 return;
318#ifdef CONFIG_VIDEO_V4L1_COMPAT
319 case 'v':
320 if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
321 type = "v4l1";
322 break;
323 }
324 printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
325 return;
326#endif
327 case 'V':
328 if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
329 type = "v4l2";
330 break;
331 }
332 printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
333 return;
334 default:
335 type = "unknown";
336 }
337
338 switch (_IOC_DIR(cmd)) {
339 case _IOC_NONE: dir = "--"; break;
340 case _IOC_READ: dir = "r-"; break;
341 case _IOC_WRITE: dir = "-w"; break;
342 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
343 default: dir = "*ERR*"; break;
344 }
345 printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
346 type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
347}
348EXPORT_SYMBOL(v4l_printk_ioctl);
349
350/*
351 * helper function -- handles userspace copying for ioctl arguments
352 */
353
354#ifdef __OLD_VIDIOC_
355static unsigned int
356video_fix_command(unsigned int cmd)
357{
358 switch (cmd) {
359 case VIDIOC_OVERLAY_OLD:
360 cmd = VIDIOC_OVERLAY;
361 break;
362 case VIDIOC_S_PARM_OLD:
363 cmd = VIDIOC_S_PARM;
364 break;
365 case VIDIOC_S_CTRL_OLD:
366 cmd = VIDIOC_S_CTRL;
367 break;
368 case VIDIOC_G_AUDIO_OLD:
369 cmd = VIDIOC_G_AUDIO;
370 break;
371 case VIDIOC_G_AUDOUT_OLD:
372 cmd = VIDIOC_G_AUDOUT;
373 break;
374 case VIDIOC_CROPCAP_OLD:
375 cmd = VIDIOC_CROPCAP;
376 break;
377 }
378 return cmd;
379}
380#endif
381
382/*
383 * Obsolete usercopy function - Should be removed soon
384 */
Hans Verkuil069b7472008-12-30 07:04:34 -0300385long
Hans Verkuilf473bf72008-11-01 08:25:11 -0300386video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
387 v4l2_kioctl func)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300388{
389 char sbuf[128];
390 void *mbuf = NULL;
391 void *parg = NULL;
Hans Verkuil069b7472008-12-30 07:04:34 -0300392 long err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300393 int is_ext_ctrl;
394 size_t ctrls_size = 0;
395 void __user *user_ptr = NULL;
396
397#ifdef __OLD_VIDIOC_
398 cmd = video_fix_command(cmd);
399#endif
400 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
401 cmd == VIDIOC_TRY_EXT_CTRLS);
402
403 /* Copy arguments into temp kernel buffer */
404 switch (_IOC_DIR(cmd)) {
405 case _IOC_NONE:
406 parg = NULL;
407 break;
408 case _IOC_READ:
409 case _IOC_WRITE:
410 case (_IOC_WRITE | _IOC_READ):
411 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
412 parg = sbuf;
413 } else {
414 /* too big to allocate from stack */
415 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
416 if (NULL == mbuf)
417 return -ENOMEM;
418 parg = mbuf;
419 }
420
421 err = -EFAULT;
422 if (_IOC_DIR(cmd) & _IOC_WRITE)
423 if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
424 goto out;
425 break;
426 }
427 if (is_ext_ctrl) {
428 struct v4l2_ext_controls *p = parg;
429
430 /* In case of an error, tell the caller that it wasn't
431 a specific control that caused it. */
432 p->error_idx = p->count;
433 user_ptr = (void __user *)p->controls;
434 if (p->count) {
435 ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
436 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
437 mbuf = kmalloc(ctrls_size, GFP_KERNEL);
438 err = -ENOMEM;
439 if (NULL == mbuf)
440 goto out_ext_ctrl;
441 err = -EFAULT;
442 if (copy_from_user(mbuf, user_ptr, ctrls_size))
443 goto out_ext_ctrl;
444 p->controls = mbuf;
445 }
446 }
447
448 /* call driver */
Hans Verkuilf473bf72008-11-01 08:25:11 -0300449 err = func(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300450 if (err == -ENOIOCTLCMD)
451 err = -EINVAL;
452 if (is_ext_ctrl) {
453 struct v4l2_ext_controls *p = parg;
454
455 p->controls = (void *)user_ptr;
456 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
457 err = -EFAULT;
458 goto out_ext_ctrl;
459 }
460 if (err < 0)
461 goto out;
462
463out_ext_ctrl:
464 /* Copy results into user buffer */
465 switch (_IOC_DIR(cmd)) {
466 case _IOC_READ:
467 case (_IOC_WRITE | _IOC_READ):
468 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
469 err = -EFAULT;
470 break;
471 }
472
473out:
474 kfree(mbuf);
475 return err;
476}
477EXPORT_SYMBOL(video_usercopy);
478
479static void dbgbuf(unsigned int cmd, struct video_device *vfd,
480 struct v4l2_buffer *p)
481{
482 struct v4l2_timecode *tc = &p->timecode;
483
484 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
485 "bytesused=%d, flags=0x%08d, "
486 "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
487 p->timestamp.tv_sec / 3600,
488 (int)(p->timestamp.tv_sec / 60) % 60,
489 (int)(p->timestamp.tv_sec % 60),
Alexander Beregalovb0459792008-09-03 16:47:38 -0300490 (long)p->timestamp.tv_usec,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300491 p->index,
492 prt_names(p->type, v4l2_type_names),
493 p->bytesused, p->flags,
494 p->field, p->sequence,
495 prt_names(p->memory, v4l2_memory_names),
496 p->m.userptr, p->length);
497 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
498 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
499 tc->hours, tc->minutes, tc->seconds,
500 tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
501}
502
503static inline void dbgrect(struct video_device *vfd, char *s,
504 struct v4l2_rect *r)
505{
506 dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
507 r->width, r->height);
508};
509
510static inline void v4l_print_pix_fmt(struct video_device *vfd,
511 struct v4l2_pix_format *fmt)
512{
513 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
514 "bytesperline=%d sizeimage=%d, colorspace=%d\n",
515 fmt->width, fmt->height,
516 (fmt->pixelformat & 0xff),
517 (fmt->pixelformat >> 8) & 0xff,
518 (fmt->pixelformat >> 16) & 0xff,
519 (fmt->pixelformat >> 24) & 0xff,
520 prt_names(fmt->field, v4l2_field_names),
521 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
522};
523
524static inline void v4l_print_ext_ctrls(unsigned int cmd,
525 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
526{
527 __u32 i;
528
529 if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
530 return;
531 dbgarg(cmd, "");
532 printk(KERN_CONT "class=0x%x", c->ctrl_class);
533 for (i = 0; i < c->count; i++) {
534 if (show_vals)
535 printk(KERN_CONT " id/val=0x%x/0x%x",
536 c->controls[i].id, c->controls[i].value);
537 else
538 printk(KERN_CONT " id=0x%x", c->controls[i].id);
539 }
540 printk(KERN_CONT "\n");
541};
542
543static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
544{
545 __u32 i;
546
547 /* zero the reserved fields */
548 c->reserved[0] = c->reserved[1] = 0;
549 for (i = 0; i < c->count; i++) {
550 c->controls[i].reserved2[0] = 0;
551 c->controls[i].reserved2[1] = 0;
552 }
553 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
554 when using extended controls.
555 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
556 is it allowed for backwards compatibility.
557 */
558 if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
559 return 0;
560 /* Check that all controls are from the same control class. */
561 for (i = 0; i < c->count; i++) {
562 if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
563 c->error_idx = i;
564 return 0;
565 }
566 }
567 return 1;
568}
569
Hans Verkuila3998102008-07-21 02:57:38 -0300570static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300571{
Hans Verkuila3998102008-07-21 02:57:38 -0300572 if (ops == NULL)
573 return -EINVAL;
574
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300575 switch (type) {
576 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300577 if (ops->vidioc_try_fmt_vid_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300578 return 0;
579 break;
580 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300581 if (ops->vidioc_try_fmt_vid_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300582 return 0;
583 break;
584 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300585 if (ops->vidioc_try_fmt_vid_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300586 return 0;
587 break;
588 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300589 if (ops->vidioc_try_fmt_vid_out_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300590 return 0;
591 break;
592 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300593 if (ops->vidioc_try_fmt_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300594 return 0;
595 break;
596 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300597 if (ops->vidioc_try_fmt_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300598 return 0;
599 break;
600 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300601 if (ops->vidioc_try_fmt_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300602 return 0;
603 break;
604 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300605 if (ops->vidioc_try_fmt_sliced_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300606 return 0;
607 break;
608 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300609 if (ops->vidioc_try_fmt_type_private)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300610 return 0;
611 break;
612 }
613 return -EINVAL;
614}
615
Hans Verkuil069b7472008-12-30 07:04:34 -0300616static long __video_do_ioctl(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300617 unsigned int cmd, void *arg)
618{
619 struct video_device *vfd = video_devdata(file);
Hans Verkuila3998102008-07-21 02:57:38 -0300620 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
Hans Verkuild5fbf322008-10-18 13:39:53 -0300621 void *fh = file->private_data;
Hans Verkuil069b7472008-12-30 07:04:34 -0300622 long ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300623
624 if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
625 !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
626 v4l_print_ioctl(vfd->name, cmd);
627 printk(KERN_CONT "\n");
628 }
629
Hans Verkuila3998102008-07-21 02:57:38 -0300630 if (ops == NULL) {
631 printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
632 vfd->name);
633 return -EINVAL;
634 }
635
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300636#ifdef CONFIG_VIDEO_V4L1_COMPAT
637 /***********************************************************
638 Handles calls to the obsoleted V4L1 API
639 Due to the nature of VIDIOCGMBUF, each driver that supports
640 V4L1 should implement its own handler for this ioctl.
641 ***********************************************************/
642
643 /* --- streaming capture ------------------------------------- */
644 if (cmd == VIDIOCGMBUF) {
645 struct video_mbuf *p = arg;
646
Hans Verkuila3998102008-07-21 02:57:38 -0300647 if (!ops->vidiocgmbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300648 return ret;
Hans Verkuila3998102008-07-21 02:57:38 -0300649 ret = ops->vidiocgmbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300650 if (!ret)
651 dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
652 p->size, p->frames,
653 (unsigned long)p->offsets);
654 return ret;
655 }
656
657 /********************************************************
658 All other V4L1 calls are handled by v4l1_compat module.
659 Those calls will be translated into V4L2 calls, and
660 __video_do_ioctl will be called again, with one or more
661 V4L2 ioctls.
662 ********************************************************/
Hans Verkuil888fe742008-09-03 16:46:50 -0300663 if (_IOC_TYPE(cmd) == 'v' && _IOC_NR(cmd) < BASE_VIDIOCPRIVATE)
Mauro Carvalho Chehabb1f88402008-10-21 11:27:20 -0300664 return v4l_compat_translate_ioctl(file, cmd, arg,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300665 __video_do_ioctl);
666#endif
667
668 switch (cmd) {
669 /* --- capabilities ------------------------------------------ */
670 case VIDIOC_QUERYCAP:
671 {
672 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300673
Hans Verkuila3998102008-07-21 02:57:38 -0300674 if (!ops->vidioc_querycap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300675 break;
676
Hans Verkuila3998102008-07-21 02:57:38 -0300677 ret = ops->vidioc_querycap(file, fh, cap);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300678 if (!ret)
679 dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
680 "version=0x%08x, "
681 "capabilities=0x%08x\n",
682 cap->driver, cap->card, cap->bus_info,
683 cap->version,
684 cap->capabilities);
685 break;
686 }
687
688 /* --- priority ------------------------------------------ */
689 case VIDIOC_G_PRIORITY:
690 {
691 enum v4l2_priority *p = arg;
692
Hans Verkuila3998102008-07-21 02:57:38 -0300693 if (!ops->vidioc_g_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300694 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300695 ret = ops->vidioc_g_priority(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300696 if (!ret)
697 dbgarg(cmd, "priority is %d\n", *p);
698 break;
699 }
700 case VIDIOC_S_PRIORITY:
701 {
702 enum v4l2_priority *p = arg;
703
Hans Verkuila3998102008-07-21 02:57:38 -0300704 if (!ops->vidioc_s_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300705 break;
706 dbgarg(cmd, "setting priority to %d\n", *p);
Hans Verkuila3998102008-07-21 02:57:38 -0300707 ret = ops->vidioc_s_priority(file, fh, *p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300708 break;
709 }
710
711 /* --- capture ioctls ---------------------------------------- */
712 case VIDIOC_ENUM_FMT:
713 {
714 struct v4l2_fmtdesc *f = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300715
Trent Piepho19c96e42009-03-04 01:21:02 -0300716 switch (f->type) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300717 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300718 if (ops->vidioc_enum_fmt_vid_cap)
719 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300720 break;
721 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300722 if (ops->vidioc_enum_fmt_vid_overlay)
723 ret = ops->vidioc_enum_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300724 fh, f);
725 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300726 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300727 if (ops->vidioc_enum_fmt_vid_out)
728 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300729 break;
730 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300731 if (ops->vidioc_enum_fmt_type_private)
732 ret = ops->vidioc_enum_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300733 fh, f);
734 break;
735 default:
736 break;
737 }
738 if (!ret)
739 dbgarg(cmd, "index=%d, type=%d, flags=%d, "
740 "pixelformat=%c%c%c%c, description='%s'\n",
741 f->index, f->type, f->flags,
742 (f->pixelformat & 0xff),
743 (f->pixelformat >> 8) & 0xff,
744 (f->pixelformat >> 16) & 0xff,
745 (f->pixelformat >> 24) & 0xff,
746 f->description);
747 break;
748 }
749 case VIDIOC_G_FMT:
750 {
751 struct v4l2_format *f = (struct v4l2_format *)arg;
752
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300753 /* FIXME: Should be one dump per type */
754 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
755
756 switch (f->type) {
757 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300758 if (ops->vidioc_g_fmt_vid_cap)
759 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300760 if (!ret)
761 v4l_print_pix_fmt(vfd, &f->fmt.pix);
762 break;
763 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300764 if (ops->vidioc_g_fmt_vid_overlay)
765 ret = ops->vidioc_g_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300766 fh, f);
767 break;
768 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300769 if (ops->vidioc_g_fmt_vid_out)
770 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300771 if (!ret)
772 v4l_print_pix_fmt(vfd, &f->fmt.pix);
773 break;
774 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300775 if (ops->vidioc_g_fmt_vid_out_overlay)
776 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300777 fh, f);
778 break;
779 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300780 if (ops->vidioc_g_fmt_vbi_cap)
781 ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300782 break;
783 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300784 if (ops->vidioc_g_fmt_vbi_out)
785 ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300786 break;
787 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300788 if (ops->vidioc_g_fmt_sliced_vbi_cap)
789 ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300790 fh, f);
791 break;
792 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300793 if (ops->vidioc_g_fmt_sliced_vbi_out)
794 ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300795 fh, f);
796 break;
797 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300798 if (ops->vidioc_g_fmt_type_private)
799 ret = ops->vidioc_g_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300800 fh, f);
801 break;
802 }
803
804 break;
805 }
806 case VIDIOC_S_FMT:
807 {
808 struct v4l2_format *f = (struct v4l2_format *)arg;
809
810 /* FIXME: Should be one dump per type */
811 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
812
813 switch (f->type) {
814 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
815 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300816 if (ops->vidioc_s_fmt_vid_cap)
817 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300818 break;
819 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300820 if (ops->vidioc_s_fmt_vid_overlay)
821 ret = ops->vidioc_s_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300822 fh, f);
823 break;
824 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
825 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300826 if (ops->vidioc_s_fmt_vid_out)
827 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300828 break;
829 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300830 if (ops->vidioc_s_fmt_vid_out_overlay)
831 ret = ops->vidioc_s_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300832 fh, f);
833 break;
834 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300835 if (ops->vidioc_s_fmt_vbi_cap)
836 ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300837 break;
838 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300839 if (ops->vidioc_s_fmt_vbi_out)
840 ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300841 break;
842 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300843 if (ops->vidioc_s_fmt_sliced_vbi_cap)
844 ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300845 fh, f);
846 break;
847 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300848 if (ops->vidioc_s_fmt_sliced_vbi_out)
849 ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300850 fh, f);
851 break;
852 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300853 if (ops->vidioc_s_fmt_type_private)
854 ret = ops->vidioc_s_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300855 fh, f);
856 break;
857 }
858 break;
859 }
860 case VIDIOC_TRY_FMT:
861 {
862 struct v4l2_format *f = (struct v4l2_format *)arg;
863
864 /* FIXME: Should be one dump per type */
865 dbgarg(cmd, "type=%s\n", prt_names(f->type,
866 v4l2_type_names));
867 switch (f->type) {
868 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300869 if (ops->vidioc_try_fmt_vid_cap)
870 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300871 if (!ret)
872 v4l_print_pix_fmt(vfd, &f->fmt.pix);
873 break;
874 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300875 if (ops->vidioc_try_fmt_vid_overlay)
876 ret = ops->vidioc_try_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300877 fh, f);
878 break;
879 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300880 if (ops->vidioc_try_fmt_vid_out)
881 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300882 if (!ret)
883 v4l_print_pix_fmt(vfd, &f->fmt.pix);
884 break;
885 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300886 if (ops->vidioc_try_fmt_vid_out_overlay)
887 ret = ops->vidioc_try_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300888 fh, f);
889 break;
890 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300891 if (ops->vidioc_try_fmt_vbi_cap)
892 ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300893 break;
894 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300895 if (ops->vidioc_try_fmt_vbi_out)
896 ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300897 break;
898 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300899 if (ops->vidioc_try_fmt_sliced_vbi_cap)
900 ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300901 fh, f);
902 break;
903 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300904 if (ops->vidioc_try_fmt_sliced_vbi_out)
905 ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300906 fh, f);
907 break;
908 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300909 if (ops->vidioc_try_fmt_type_private)
910 ret = ops->vidioc_try_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300911 fh, f);
912 break;
913 }
914
915 break;
916 }
917 /* FIXME: Those buf reqs could be handled here,
918 with some changes on videobuf to allow its header to be included at
919 videodev2.h or being merged at videodev2.
920 */
921 case VIDIOC_REQBUFS:
922 {
923 struct v4l2_requestbuffers *p = arg;
924
Hans Verkuila3998102008-07-21 02:57:38 -0300925 if (!ops->vidioc_reqbufs)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300926 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300927 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300928 if (ret)
929 break;
930
Hans Verkuila3998102008-07-21 02:57:38 -0300931 ret = ops->vidioc_reqbufs(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300932 dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
933 p->count,
934 prt_names(p->type, v4l2_type_names),
935 prt_names(p->memory, v4l2_memory_names));
936 break;
937 }
938 case VIDIOC_QUERYBUF:
939 {
940 struct v4l2_buffer *p = arg;
941
Hans Verkuila3998102008-07-21 02:57:38 -0300942 if (!ops->vidioc_querybuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300943 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300944 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300945 if (ret)
946 break;
947
Hans Verkuila3998102008-07-21 02:57:38 -0300948 ret = ops->vidioc_querybuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300949 if (!ret)
950 dbgbuf(cmd, vfd, p);
951 break;
952 }
953 case VIDIOC_QBUF:
954 {
955 struct v4l2_buffer *p = arg;
956
Hans Verkuila3998102008-07-21 02:57:38 -0300957 if (!ops->vidioc_qbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300958 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300959 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300960 if (ret)
961 break;
962
Hans Verkuila3998102008-07-21 02:57:38 -0300963 ret = ops->vidioc_qbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300964 if (!ret)
965 dbgbuf(cmd, vfd, p);
966 break;
967 }
968 case VIDIOC_DQBUF:
969 {
970 struct v4l2_buffer *p = arg;
971
Hans Verkuila3998102008-07-21 02:57:38 -0300972 if (!ops->vidioc_dqbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300973 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300974 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300975 if (ret)
976 break;
977
Hans Verkuila3998102008-07-21 02:57:38 -0300978 ret = ops->vidioc_dqbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300979 if (!ret)
980 dbgbuf(cmd, vfd, p);
981 break;
982 }
983 case VIDIOC_OVERLAY:
984 {
985 int *i = arg;
986
Hans Verkuila3998102008-07-21 02:57:38 -0300987 if (!ops->vidioc_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300988 break;
989 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -0300990 ret = ops->vidioc_overlay(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300991 break;
992 }
993 case VIDIOC_G_FBUF:
994 {
995 struct v4l2_framebuffer *p = arg;
996
Hans Verkuila3998102008-07-21 02:57:38 -0300997 if (!ops->vidioc_g_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300998 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300999 ret = ops->vidioc_g_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001000 if (!ret) {
1001 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1002 p->capability, p->flags,
1003 (unsigned long)p->base);
1004 v4l_print_pix_fmt(vfd, &p->fmt);
1005 }
1006 break;
1007 }
1008 case VIDIOC_S_FBUF:
1009 {
1010 struct v4l2_framebuffer *p = arg;
1011
Hans Verkuila3998102008-07-21 02:57:38 -03001012 if (!ops->vidioc_s_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001013 break;
1014 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1015 p->capability, p->flags, (unsigned long)p->base);
1016 v4l_print_pix_fmt(vfd, &p->fmt);
Hans Verkuila3998102008-07-21 02:57:38 -03001017 ret = ops->vidioc_s_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001018 break;
1019 }
1020 case VIDIOC_STREAMON:
1021 {
1022 enum v4l2_buf_type i = *(int *)arg;
1023
Hans Verkuila3998102008-07-21 02:57:38 -03001024 if (!ops->vidioc_streamon)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001025 break;
1026 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001027 ret = ops->vidioc_streamon(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001028 break;
1029 }
1030 case VIDIOC_STREAMOFF:
1031 {
1032 enum v4l2_buf_type i = *(int *)arg;
1033
Hans Verkuila3998102008-07-21 02:57:38 -03001034 if (!ops->vidioc_streamoff)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001035 break;
1036 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001037 ret = ops->vidioc_streamoff(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001038 break;
1039 }
1040 /* ---------- tv norms ---------- */
1041 case VIDIOC_ENUMSTD:
1042 {
1043 struct v4l2_standard *p = arg;
1044 v4l2_std_id id = vfd->tvnorms, curr_id = 0;
1045 unsigned int index = p->index, i, j = 0;
1046 const char *descr = "";
1047
1048 /* Return norm array in a canonical way */
1049 for (i = 0; i <= index && id; i++) {
1050 /* last std value in the standards array is 0, so this
1051 while always ends there since (id & 0) == 0. */
1052 while ((id & standards[j].std) != standards[j].std)
1053 j++;
1054 curr_id = standards[j].std;
1055 descr = standards[j].descr;
1056 j++;
1057 if (curr_id == 0)
1058 break;
1059 if (curr_id != V4L2_STD_PAL &&
1060 curr_id != V4L2_STD_SECAM &&
1061 curr_id != V4L2_STD_NTSC)
1062 id &= ~curr_id;
1063 }
1064 if (i <= index)
1065 return -EINVAL;
1066
1067 v4l2_video_std_construct(p, curr_id, descr);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001068
1069 dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
1070 "framelines=%d\n", p->index,
1071 (unsigned long long)p->id, p->name,
1072 p->frameperiod.numerator,
1073 p->frameperiod.denominator,
1074 p->framelines);
1075
1076 ret = 0;
1077 break;
1078 }
1079 case VIDIOC_G_STD:
1080 {
1081 v4l2_std_id *id = arg;
1082
1083 ret = 0;
1084 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001085 if (ops->vidioc_g_std)
1086 ret = ops->vidioc_g_std(file, fh, id);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001087 else
1088 *id = vfd->current_norm;
1089
1090 if (!ret)
1091 dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
1092 break;
1093 }
1094 case VIDIOC_S_STD:
1095 {
1096 v4l2_std_id *id = arg, norm;
1097
1098 dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
1099
1100 norm = (*id) & vfd->tvnorms;
1101 if (vfd->tvnorms && !norm) /* Check if std is supported */
1102 break;
1103
1104 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001105 if (ops->vidioc_s_std)
1106 ret = ops->vidioc_s_std(file, fh, &norm);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001107 else
1108 ret = -EINVAL;
1109
1110 /* Updates standard information */
1111 if (ret >= 0)
1112 vfd->current_norm = norm;
1113 break;
1114 }
1115 case VIDIOC_QUERYSTD:
1116 {
1117 v4l2_std_id *p = arg;
1118
Hans Verkuila3998102008-07-21 02:57:38 -03001119 if (!ops->vidioc_querystd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001120 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001121 ret = ops->vidioc_querystd(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001122 if (!ret)
1123 dbgarg(cmd, "detected std=%08Lx\n",
1124 (unsigned long long)*p);
1125 break;
1126 }
1127 /* ------ input switching ---------- */
1128 /* FIXME: Inputs can be handled inside videodev2 */
1129 case VIDIOC_ENUMINPUT:
1130 {
1131 struct v4l2_input *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001132
Hans Verkuila3998102008-07-21 02:57:38 -03001133 if (!ops->vidioc_enum_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001134 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001135
Hans Verkuila3998102008-07-21 02:57:38 -03001136 ret = ops->vidioc_enum_input(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001137 if (!ret)
1138 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1139 "audioset=%d, "
1140 "tuner=%d, std=%08Lx, status=%d\n",
1141 p->index, p->name, p->type, p->audioset,
1142 p->tuner,
1143 (unsigned long long)p->std,
1144 p->status);
1145 break;
1146 }
1147 case VIDIOC_G_INPUT:
1148 {
1149 unsigned int *i = arg;
1150
Hans Verkuila3998102008-07-21 02:57:38 -03001151 if (!ops->vidioc_g_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001152 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001153 ret = ops->vidioc_g_input(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001154 if (!ret)
1155 dbgarg(cmd, "value=%d\n", *i);
1156 break;
1157 }
1158 case VIDIOC_S_INPUT:
1159 {
1160 unsigned int *i = arg;
1161
Hans Verkuila3998102008-07-21 02:57:38 -03001162 if (!ops->vidioc_s_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001163 break;
1164 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001165 ret = ops->vidioc_s_input(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001166 break;
1167 }
1168
1169 /* ------ output switching ---------- */
1170 case VIDIOC_ENUMOUTPUT:
1171 {
1172 struct v4l2_output *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001173
Hans Verkuila3998102008-07-21 02:57:38 -03001174 if (!ops->vidioc_enum_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001175 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001176
Hans Verkuila3998102008-07-21 02:57:38 -03001177 ret = ops->vidioc_enum_output(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001178 if (!ret)
1179 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1180 "audioset=0x%x, "
1181 "modulator=%d, std=0x%08Lx\n",
1182 p->index, p->name, p->type, p->audioset,
1183 p->modulator, (unsigned long long)p->std);
1184 break;
1185 }
1186 case VIDIOC_G_OUTPUT:
1187 {
1188 unsigned int *i = arg;
1189
Hans Verkuila3998102008-07-21 02:57:38 -03001190 if (!ops->vidioc_g_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001191 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001192 ret = ops->vidioc_g_output(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001193 if (!ret)
1194 dbgarg(cmd, "value=%d\n", *i);
1195 break;
1196 }
1197 case VIDIOC_S_OUTPUT:
1198 {
1199 unsigned int *i = arg;
1200
Hans Verkuila3998102008-07-21 02:57:38 -03001201 if (!ops->vidioc_s_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001202 break;
1203 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001204 ret = ops->vidioc_s_output(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001205 break;
1206 }
1207
1208 /* --- controls ---------------------------------------------- */
1209 case VIDIOC_QUERYCTRL:
1210 {
1211 struct v4l2_queryctrl *p = arg;
1212
Hans Verkuila3998102008-07-21 02:57:38 -03001213 if (!ops->vidioc_queryctrl)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001214 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001215 ret = ops->vidioc_queryctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001216 if (!ret)
1217 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1218 "step=%d, default=%d, flags=0x%08x\n",
1219 p->id, p->type, p->name,
1220 p->minimum, p->maximum,
1221 p->step, p->default_value, p->flags);
1222 else
1223 dbgarg(cmd, "id=0x%x\n", p->id);
1224 break;
1225 }
1226 case VIDIOC_G_CTRL:
1227 {
1228 struct v4l2_control *p = arg;
1229
Hans Verkuila3998102008-07-21 02:57:38 -03001230 if (ops->vidioc_g_ctrl)
1231 ret = ops->vidioc_g_ctrl(file, fh, p);
1232 else if (ops->vidioc_g_ext_ctrls) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001233 struct v4l2_ext_controls ctrls;
1234 struct v4l2_ext_control ctrl;
1235
1236 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1237 ctrls.count = 1;
1238 ctrls.controls = &ctrl;
1239 ctrl.id = p->id;
1240 ctrl.value = p->value;
1241 if (check_ext_ctrls(&ctrls, 1)) {
Hans Verkuila3998102008-07-21 02:57:38 -03001242 ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001243 if (ret == 0)
1244 p->value = ctrl.value;
1245 }
1246 } else
1247 break;
1248 if (!ret)
1249 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1250 else
1251 dbgarg(cmd, "id=0x%x\n", p->id);
1252 break;
1253 }
1254 case VIDIOC_S_CTRL:
1255 {
1256 struct v4l2_control *p = arg;
1257 struct v4l2_ext_controls ctrls;
1258 struct v4l2_ext_control ctrl;
1259
Hans Verkuila3998102008-07-21 02:57:38 -03001260 if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001261 break;
1262
1263 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1264
Hans Verkuila3998102008-07-21 02:57:38 -03001265 if (ops->vidioc_s_ctrl) {
1266 ret = ops->vidioc_s_ctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001267 break;
1268 }
Hans Verkuila3998102008-07-21 02:57:38 -03001269 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001270 break;
1271
1272 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1273 ctrls.count = 1;
1274 ctrls.controls = &ctrl;
1275 ctrl.id = p->id;
1276 ctrl.value = p->value;
1277 if (check_ext_ctrls(&ctrls, 1))
Hans Verkuila3998102008-07-21 02:57:38 -03001278 ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001279 break;
1280 }
1281 case VIDIOC_G_EXT_CTRLS:
1282 {
1283 struct v4l2_ext_controls *p = arg;
1284
1285 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001286 if (!ops->vidioc_g_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001287 break;
1288 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001289 ret = ops->vidioc_g_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001290 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1291 break;
1292 }
1293 case VIDIOC_S_EXT_CTRLS:
1294 {
1295 struct v4l2_ext_controls *p = arg;
1296
1297 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001298 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001299 break;
1300 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1301 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001302 ret = ops->vidioc_s_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001303 break;
1304 }
1305 case VIDIOC_TRY_EXT_CTRLS:
1306 {
1307 struct v4l2_ext_controls *p = arg;
1308
1309 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001310 if (!ops->vidioc_try_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001311 break;
1312 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1313 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001314 ret = ops->vidioc_try_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001315 break;
1316 }
1317 case VIDIOC_QUERYMENU:
1318 {
1319 struct v4l2_querymenu *p = arg;
1320
Hans Verkuila3998102008-07-21 02:57:38 -03001321 if (!ops->vidioc_querymenu)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001322 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001323 ret = ops->vidioc_querymenu(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001324 if (!ret)
1325 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1326 p->id, p->index, p->name);
1327 else
1328 dbgarg(cmd, "id=0x%x, index=%d\n",
1329 p->id, p->index);
1330 break;
1331 }
1332 /* --- audio ---------------------------------------------- */
1333 case VIDIOC_ENUMAUDIO:
1334 {
1335 struct v4l2_audio *p = arg;
1336
Hans Verkuila3998102008-07-21 02:57:38 -03001337 if (!ops->vidioc_enumaudio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001338 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001339 ret = ops->vidioc_enumaudio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001340 if (!ret)
1341 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1342 "mode=0x%x\n", p->index, p->name,
1343 p->capability, p->mode);
1344 else
1345 dbgarg(cmd, "index=%d\n", p->index);
1346 break;
1347 }
1348 case VIDIOC_G_AUDIO:
1349 {
1350 struct v4l2_audio *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001351
Hans Verkuila3998102008-07-21 02:57:38 -03001352 if (!ops->vidioc_g_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001353 break;
1354
Hans Verkuila3998102008-07-21 02:57:38 -03001355 ret = ops->vidioc_g_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001356 if (!ret)
1357 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1358 "mode=0x%x\n", p->index,
1359 p->name, p->capability, p->mode);
1360 else
1361 dbgarg(cmd, "index=%d\n", p->index);
1362 break;
1363 }
1364 case VIDIOC_S_AUDIO:
1365 {
1366 struct v4l2_audio *p = arg;
1367
Hans Verkuila3998102008-07-21 02:57:38 -03001368 if (!ops->vidioc_s_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001369 break;
1370 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1371 "mode=0x%x\n", p->index, p->name,
1372 p->capability, p->mode);
Hans Verkuila3998102008-07-21 02:57:38 -03001373 ret = ops->vidioc_s_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001374 break;
1375 }
1376 case VIDIOC_ENUMAUDOUT:
1377 {
1378 struct v4l2_audioout *p = arg;
1379
Hans Verkuila3998102008-07-21 02:57:38 -03001380 if (!ops->vidioc_enumaudout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001381 break;
1382 dbgarg(cmd, "Enum for index=%d\n", p->index);
Hans Verkuila3998102008-07-21 02:57:38 -03001383 ret = ops->vidioc_enumaudout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001384 if (!ret)
1385 dbgarg2("index=%d, name=%s, capability=%d, "
1386 "mode=%d\n", p->index, p->name,
1387 p->capability, p->mode);
1388 break;
1389 }
1390 case VIDIOC_G_AUDOUT:
1391 {
1392 struct v4l2_audioout *p = arg;
1393
Hans Verkuila3998102008-07-21 02:57:38 -03001394 if (!ops->vidioc_g_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001395 break;
Trent Piepho337f9d22009-03-04 01:21:02 -03001396
Hans Verkuila3998102008-07-21 02:57:38 -03001397 ret = ops->vidioc_g_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001398 if (!ret)
1399 dbgarg2("index=%d, name=%s, capability=%d, "
1400 "mode=%d\n", p->index, p->name,
1401 p->capability, p->mode);
1402 break;
1403 }
1404 case VIDIOC_S_AUDOUT:
1405 {
1406 struct v4l2_audioout *p = arg;
1407
Hans Verkuila3998102008-07-21 02:57:38 -03001408 if (!ops->vidioc_s_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001409 break;
1410 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1411 "mode=%d\n", p->index, p->name,
1412 p->capability, p->mode);
1413
Hans Verkuila3998102008-07-21 02:57:38 -03001414 ret = ops->vidioc_s_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001415 break;
1416 }
1417 case VIDIOC_G_MODULATOR:
1418 {
1419 struct v4l2_modulator *p = arg;
1420
Hans Verkuila3998102008-07-21 02:57:38 -03001421 if (!ops->vidioc_g_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001422 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001423 ret = ops->vidioc_g_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001424 if (!ret)
1425 dbgarg(cmd, "index=%d, name=%s, "
1426 "capability=%d, rangelow=%d,"
1427 " rangehigh=%d, txsubchans=%d\n",
1428 p->index, p->name, p->capability,
1429 p->rangelow, p->rangehigh,
1430 p->txsubchans);
1431 break;
1432 }
1433 case VIDIOC_S_MODULATOR:
1434 {
1435 struct v4l2_modulator *p = arg;
1436
Hans Verkuila3998102008-07-21 02:57:38 -03001437 if (!ops->vidioc_s_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001438 break;
1439 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1440 "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1441 p->index, p->name, p->capability, p->rangelow,
1442 p->rangehigh, p->txsubchans);
Hans Verkuila3998102008-07-21 02:57:38 -03001443 ret = ops->vidioc_s_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001444 break;
1445 }
1446 case VIDIOC_G_CROP:
1447 {
1448 struct v4l2_crop *p = arg;
1449
Hans Verkuila3998102008-07-21 02:57:38 -03001450 if (!ops->vidioc_g_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001451 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001452
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001453 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001454 ret = ops->vidioc_g_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001455 if (!ret)
1456 dbgrect(vfd, "", &p->c);
1457 break;
1458 }
1459 case VIDIOC_S_CROP:
1460 {
1461 struct v4l2_crop *p = arg;
1462
Hans Verkuila3998102008-07-21 02:57:38 -03001463 if (!ops->vidioc_s_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001464 break;
1465 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1466 dbgrect(vfd, "", &p->c);
Hans Verkuila3998102008-07-21 02:57:38 -03001467 ret = ops->vidioc_s_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001468 break;
1469 }
1470 case VIDIOC_CROPCAP:
1471 {
1472 struct v4l2_cropcap *p = arg;
1473
1474 /*FIXME: Should also show v4l2_fract pixelaspect */
Hans Verkuila3998102008-07-21 02:57:38 -03001475 if (!ops->vidioc_cropcap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001476 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001477
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001478 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001479 ret = ops->vidioc_cropcap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001480 if (!ret) {
1481 dbgrect(vfd, "bounds ", &p->bounds);
1482 dbgrect(vfd, "defrect ", &p->defrect);
1483 }
1484 break;
1485 }
1486 case VIDIOC_G_JPEGCOMP:
1487 {
1488 struct v4l2_jpegcompression *p = arg;
1489
Hans Verkuila3998102008-07-21 02:57:38 -03001490 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001491 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001492
Hans Verkuila3998102008-07-21 02:57:38 -03001493 ret = ops->vidioc_g_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001494 if (!ret)
1495 dbgarg(cmd, "quality=%d, APPn=%d, "
1496 "APP_len=%d, COM_len=%d, "
1497 "jpeg_markers=%d\n",
1498 p->quality, p->APPn, p->APP_len,
1499 p->COM_len, p->jpeg_markers);
1500 break;
1501 }
1502 case VIDIOC_S_JPEGCOMP:
1503 {
1504 struct v4l2_jpegcompression *p = arg;
1505
Hans Verkuila3998102008-07-21 02:57:38 -03001506 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001507 break;
1508 dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
1509 "COM_len=%d, jpeg_markers=%d\n",
1510 p->quality, p->APPn, p->APP_len,
1511 p->COM_len, p->jpeg_markers);
Hans Verkuila3998102008-07-21 02:57:38 -03001512 ret = ops->vidioc_s_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001513 break;
1514 }
1515 case VIDIOC_G_ENC_INDEX:
1516 {
1517 struct v4l2_enc_idx *p = arg;
1518
Hans Verkuila3998102008-07-21 02:57:38 -03001519 if (!ops->vidioc_g_enc_index)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001520 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001521 ret = ops->vidioc_g_enc_index(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001522 if (!ret)
1523 dbgarg(cmd, "entries=%d, entries_cap=%d\n",
1524 p->entries, p->entries_cap);
1525 break;
1526 }
1527 case VIDIOC_ENCODER_CMD:
1528 {
1529 struct v4l2_encoder_cmd *p = arg;
1530
Hans Verkuila3998102008-07-21 02:57:38 -03001531 if (!ops->vidioc_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001532 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001533 ret = ops->vidioc_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001534 if (!ret)
1535 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1536 break;
1537 }
1538 case VIDIOC_TRY_ENCODER_CMD:
1539 {
1540 struct v4l2_encoder_cmd *p = arg;
1541
Hans Verkuila3998102008-07-21 02:57:38 -03001542 if (!ops->vidioc_try_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001543 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001544 ret = ops->vidioc_try_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001545 if (!ret)
1546 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1547 break;
1548 }
1549 case VIDIOC_G_PARM:
1550 {
1551 struct v4l2_streamparm *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001552
Hans Verkuila3998102008-07-21 02:57:38 -03001553 if (ops->vidioc_g_parm) {
1554 ret = ops->vidioc_g_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001555 } else {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001556 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1557 return -EINVAL;
1558
Trent Piepho51f0b8d52009-03-04 01:21:02 -03001559 v4l2_video_std_frame_period(vfd->current_norm,
1560 &p->parm.capture.timeperframe);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001561 ret = 0;
1562 }
1563
1564 dbgarg(cmd, "type=%d\n", p->type);
1565 break;
1566 }
1567 case VIDIOC_S_PARM:
1568 {
1569 struct v4l2_streamparm *p = arg;
1570
Hans Verkuila3998102008-07-21 02:57:38 -03001571 if (!ops->vidioc_s_parm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001572 break;
1573 dbgarg(cmd, "type=%d\n", p->type);
Hans Verkuila3998102008-07-21 02:57:38 -03001574 ret = ops->vidioc_s_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001575 break;
1576 }
1577 case VIDIOC_G_TUNER:
1578 {
1579 struct v4l2_tuner *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001580
Hans Verkuila3998102008-07-21 02:57:38 -03001581 if (!ops->vidioc_g_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001582 break;
1583
Hans Verkuila3998102008-07-21 02:57:38 -03001584 ret = ops->vidioc_g_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001585 if (!ret)
1586 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1587 "capability=0x%x, rangelow=%d, "
1588 "rangehigh=%d, signal=%d, afc=%d, "
1589 "rxsubchans=0x%x, audmode=%d\n",
1590 p->index, p->name, p->type,
1591 p->capability, p->rangelow,
1592 p->rangehigh, p->signal, p->afc,
1593 p->rxsubchans, p->audmode);
1594 break;
1595 }
1596 case VIDIOC_S_TUNER:
1597 {
1598 struct v4l2_tuner *p = arg;
1599
Hans Verkuila3998102008-07-21 02:57:38 -03001600 if (!ops->vidioc_s_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001601 break;
1602 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1603 "capability=0x%x, rangelow=%d, "
1604 "rangehigh=%d, signal=%d, afc=%d, "
1605 "rxsubchans=0x%x, audmode=%d\n",
1606 p->index, p->name, p->type,
1607 p->capability, p->rangelow,
1608 p->rangehigh, p->signal, p->afc,
1609 p->rxsubchans, p->audmode);
Hans Verkuila3998102008-07-21 02:57:38 -03001610 ret = ops->vidioc_s_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001611 break;
1612 }
1613 case VIDIOC_G_FREQUENCY:
1614 {
1615 struct v4l2_frequency *p = arg;
1616
Hans Verkuila3998102008-07-21 02:57:38 -03001617 if (!ops->vidioc_g_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001618 break;
1619
Hans Verkuila3998102008-07-21 02:57:38 -03001620 ret = ops->vidioc_g_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001621 if (!ret)
1622 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1623 p->tuner, p->type, p->frequency);
1624 break;
1625 }
1626 case VIDIOC_S_FREQUENCY:
1627 {
1628 struct v4l2_frequency *p = arg;
1629
Hans Verkuila3998102008-07-21 02:57:38 -03001630 if (!ops->vidioc_s_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001631 break;
1632 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1633 p->tuner, p->type, p->frequency);
Hans Verkuila3998102008-07-21 02:57:38 -03001634 ret = ops->vidioc_s_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001635 break;
1636 }
1637 case VIDIOC_G_SLICED_VBI_CAP:
1638 {
1639 struct v4l2_sliced_vbi_cap *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001640
Hans Verkuila3998102008-07-21 02:57:38 -03001641 if (!ops->vidioc_g_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001642 break;
Trent Piepho19c96e42009-03-04 01:21:02 -03001643
1644 /* Clear up to type, everything after type is zerod already */
1645 memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
1646
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001647 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001648 ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001649 if (!ret)
1650 dbgarg2("service_set=%d\n", p->service_set);
1651 break;
1652 }
1653 case VIDIOC_LOG_STATUS:
1654 {
Hans Verkuila3998102008-07-21 02:57:38 -03001655 if (!ops->vidioc_log_status)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001656 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001657 ret = ops->vidioc_log_status(file, fh);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001658 break;
1659 }
1660#ifdef CONFIG_VIDEO_ADV_DEBUG
1661 case VIDIOC_DBG_G_REGISTER:
1662 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001663 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001664
1665 if (!capable(CAP_SYS_ADMIN))
1666 ret = -EPERM;
Hans Verkuila3998102008-07-21 02:57:38 -03001667 else if (ops->vidioc_g_register)
1668 ret = ops->vidioc_g_register(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001669 break;
1670 }
1671 case VIDIOC_DBG_S_REGISTER:
1672 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001673 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001674
1675 if (!capable(CAP_SYS_ADMIN))
1676 ret = -EPERM;
Hans Verkuila3998102008-07-21 02:57:38 -03001677 else if (ops->vidioc_s_register)
1678 ret = ops->vidioc_s_register(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001679 break;
1680 }
1681#endif
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001682 case VIDIOC_DBG_G_CHIP_IDENT:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001683 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001684 struct v4l2_dbg_chip_ident *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001685
Hans Verkuila3998102008-07-21 02:57:38 -03001686 if (!ops->vidioc_g_chip_ident)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001687 break;
Hans Verkuil80b36e02009-02-07 11:00:02 -03001688 p->ident = V4L2_IDENT_NONE;
1689 p->revision = 0;
Hans Verkuila3998102008-07-21 02:57:38 -03001690 ret = ops->vidioc_g_chip_ident(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001691 if (!ret)
1692 dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
1693 break;
1694 }
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001695 case VIDIOC_G_CHIP_IDENT_OLD:
1696 printk(KERN_ERR "VIDIOC_G_CHIP_IDENT has been deprecated and will disappear in 2.6.30.\n");
1697 printk(KERN_ERR "It is a debugging ioctl and must not be used in applications!\n");
1698 return -EINVAL;
1699
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001700 case VIDIOC_S_HW_FREQ_SEEK:
1701 {
1702 struct v4l2_hw_freq_seek *p = arg;
1703
Hans Verkuila3998102008-07-21 02:57:38 -03001704 if (!ops->vidioc_s_hw_freq_seek)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001705 break;
1706 dbgarg(cmd,
1707 "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
1708 p->tuner, p->type, p->seek_upward, p->wrap_around);
Hans Verkuila3998102008-07-21 02:57:38 -03001709 ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
1710 break;
1711 }
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001712 case VIDIOC_ENUM_FRAMESIZES:
1713 {
1714 struct v4l2_frmsizeenum *p = arg;
1715
1716 if (!ops->vidioc_enum_framesizes)
1717 break;
1718
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001719 ret = ops->vidioc_enum_framesizes(file, fh, p);
1720 dbgarg(cmd,
1721 "index=%d, pixelformat=%d, type=%d ",
1722 p->index, p->pixel_format, p->type);
1723 switch (p->type) {
1724 case V4L2_FRMSIZE_TYPE_DISCRETE:
1725 dbgarg2("width = %d, height=%d\n",
1726 p->discrete.width, p->discrete.height);
1727 break;
1728 case V4L2_FRMSIZE_TYPE_STEPWISE:
1729 dbgarg2("min %dx%d, max %dx%d, step %dx%d\n",
1730 p->stepwise.min_width, p->stepwise.min_height,
1731 p->stepwise.step_width, p->stepwise.step_height,
1732 p->stepwise.max_width, p->stepwise.max_height);
1733 break;
1734 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
1735 dbgarg2("continuous\n");
1736 break;
1737 default:
1738 dbgarg2("- Unknown type!\n");
1739 }
1740
1741 break;
1742 }
1743 case VIDIOC_ENUM_FRAMEINTERVALS:
1744 {
1745 struct v4l2_frmivalenum *p = arg;
1746
1747 if (!ops->vidioc_enum_frameintervals)
1748 break;
1749
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001750 ret = ops->vidioc_enum_frameintervals(file, fh, p);
1751 dbgarg(cmd,
1752 "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
1753 p->index, p->pixel_format,
1754 p->width, p->height, p->type);
1755 switch (p->type) {
1756 case V4L2_FRMIVAL_TYPE_DISCRETE:
1757 dbgarg2("fps=%d/%d\n",
1758 p->discrete.numerator,
1759 p->discrete.denominator);
1760 break;
1761 case V4L2_FRMIVAL_TYPE_STEPWISE:
Mauro Carvalho Chehab19585782008-11-12 01:03:02 -03001762 dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",
1763 p->stepwise.min.numerator,
1764 p->stepwise.min.denominator,
1765 p->stepwise.max.numerator,
1766 p->stepwise.max.denominator,
1767 p->stepwise.step.numerator,
1768 p->stepwise.step.denominator);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001769 break;
1770 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1771 dbgarg2("continuous\n");
1772 break;
1773 default:
1774 dbgarg2("- Unknown type!\n");
1775 }
1776 break;
1777 }
1778
Hans Verkuila3998102008-07-21 02:57:38 -03001779 default:
1780 {
1781 if (!ops->vidioc_default)
1782 break;
1783 ret = ops->vidioc_default(file, fh, cmd, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001784 break;
1785 }
1786 } /* switch */
1787
1788 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1789 if (ret < 0) {
1790 v4l_print_ioctl(vfd->name, cmd);
Hans Verkuil069b7472008-12-30 07:04:34 -03001791 printk(KERN_CONT " error %ld\n", ret);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001792 }
1793 }
1794
1795 return ret;
1796}
1797
Trent Piepho19c96e42009-03-04 01:21:02 -03001798/* In some cases, only a few fields are used as input, i.e. when the app sets
1799 * "index" and then the driver fills in the rest of the structure for the thing
1800 * with that index. We only need to copy up the first non-input field. */
1801static unsigned long cmd_input_size(unsigned int cmd)
1802{
1803 /* Size of structure up to and including 'field' */
1804#define CMDINSIZE(cmd, type, field) case _IOC_NR(VIDIOC_##cmd): return \
1805 offsetof(struct v4l2_##type, field) + \
1806 sizeof(((struct v4l2_##type *)0)->field);
1807
1808 switch (_IOC_NR(cmd)) {
1809 CMDINSIZE(ENUM_FMT, fmtdesc, type);
1810 CMDINSIZE(G_FMT, format, type);
1811 CMDINSIZE(QUERYBUF, buffer, type);
1812 CMDINSIZE(G_PARM, streamparm, type);
1813 CMDINSIZE(ENUMSTD, standard, index);
1814 CMDINSIZE(ENUMINPUT, input, index);
1815 CMDINSIZE(G_CTRL, control, id);
1816 CMDINSIZE(G_TUNER, tuner, index);
1817 CMDINSIZE(QUERYCTRL, queryctrl, id);
1818 CMDINSIZE(QUERYMENU, querymenu, index);
1819 CMDINSIZE(ENUMOUTPUT, output, index);
1820 CMDINSIZE(G_MODULATOR, modulator, index);
1821 CMDINSIZE(G_FREQUENCY, frequency, tuner);
1822 CMDINSIZE(CROPCAP, cropcap, type);
1823 CMDINSIZE(G_CROP, crop, type);
1824 CMDINSIZE(ENUMAUDIO, audio, index);
1825 CMDINSIZE(ENUMAUDOUT, audioout, index);
1826 CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
1827 CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
1828 CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
1829 CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
1830 CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
1831 default:
1832 return _IOC_SIZE(cmd);
1833 }
1834}
1835
Hans Verkuil069b7472008-12-30 07:04:34 -03001836long video_ioctl2(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001837 unsigned int cmd, unsigned long arg)
1838{
1839 char sbuf[128];
1840 void *mbuf = NULL;
1841 void *parg = NULL;
Hans Verkuil069b7472008-12-30 07:04:34 -03001842 long err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001843 int is_ext_ctrl;
1844 size_t ctrls_size = 0;
1845 void __user *user_ptr = NULL;
1846
1847#ifdef __OLD_VIDIOC_
1848 cmd = video_fix_command(cmd);
1849#endif
1850 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
1851 cmd == VIDIOC_TRY_EXT_CTRLS);
1852
1853 /* Copy arguments into temp kernel buffer */
Trent Piepho337f9d22009-03-04 01:21:02 -03001854 if (_IOC_DIR(cmd) != _IOC_NONE) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001855 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
1856 parg = sbuf;
1857 } else {
1858 /* too big to allocate from stack */
1859 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
1860 if (NULL == mbuf)
1861 return -ENOMEM;
1862 parg = mbuf;
1863 }
1864
1865 err = -EFAULT;
Trent Piepho19c96e42009-03-04 01:21:02 -03001866 if (_IOC_DIR(cmd) & _IOC_WRITE) {
1867 unsigned long n = cmd_input_size(cmd);
1868
1869 if (copy_from_user(parg, (void __user *)arg, n))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001870 goto out;
Trent Piepho19c96e42009-03-04 01:21:02 -03001871
1872 /* zero out anything we don't copy from userspace */
1873 if (n < _IOC_SIZE(cmd))
1874 memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
Trent Piepho337f9d22009-03-04 01:21:02 -03001875 } else {
1876 /* read-only ioctl */
1877 memset(parg, 0, _IOC_SIZE(cmd));
Trent Piepho19c96e42009-03-04 01:21:02 -03001878 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001879 }
1880
1881 if (is_ext_ctrl) {
1882 struct v4l2_ext_controls *p = parg;
1883
1884 /* In case of an error, tell the caller that it wasn't
1885 a specific control that caused it. */
1886 p->error_idx = p->count;
1887 user_ptr = (void __user *)p->controls;
1888 if (p->count) {
1889 ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
1890 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
1891 mbuf = kmalloc(ctrls_size, GFP_KERNEL);
1892 err = -ENOMEM;
1893 if (NULL == mbuf)
1894 goto out_ext_ctrl;
1895 err = -EFAULT;
1896 if (copy_from_user(mbuf, user_ptr, ctrls_size))
1897 goto out_ext_ctrl;
1898 p->controls = mbuf;
1899 }
1900 }
1901
1902 /* Handles IOCTL */
Mauro Carvalho Chehabb1f88402008-10-21 11:27:20 -03001903 err = __video_do_ioctl(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001904 if (err == -ENOIOCTLCMD)
1905 err = -EINVAL;
1906 if (is_ext_ctrl) {
1907 struct v4l2_ext_controls *p = parg;
1908
1909 p->controls = (void *)user_ptr;
1910 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
1911 err = -EFAULT;
1912 goto out_ext_ctrl;
1913 }
1914 if (err < 0)
1915 goto out;
1916
1917out_ext_ctrl:
1918 /* Copy results into user buffer */
1919 switch (_IOC_DIR(cmd)) {
1920 case _IOC_READ:
1921 case (_IOC_WRITE | _IOC_READ):
1922 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
1923 err = -EFAULT;
1924 break;
1925 }
1926
1927out:
1928 kfree(mbuf);
1929 return err;
1930}
Mauro Carvalho Chehab8a522c92008-10-21 11:58:39 -03001931EXPORT_SYMBOL(video_ioctl2);