blob: 3da8d8f041d8440780b19d7416e5dfd3c9f22898 [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>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030017#include <linux/types.h>
18#include <linux/kernel.h>
19
20#define __OLD_VIDIOC_ /* To allow fixing old calls */
Mauro Carvalho Chehab7e0a16f2009-03-10 05:31:34 -030021#include <linux/videodev.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030022#include <linux/videodev2.h>
23
24#ifdef CONFIG_VIDEO_V4L1
25#include <linux/videodev.h>
26#endif
27#include <media/v4l2-common.h>
28#include <media/v4l2-ioctl.h>
Hans Verkuil80b36e02009-02-07 11:00:02 -030029#include <media/v4l2-chip-ident.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030030
31#define dbgarg(cmd, fmt, arg...) \
32 do { \
33 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
34 printk(KERN_DEBUG "%s: ", vfd->name); \
35 v4l_printk_ioctl(cmd); \
36 printk(" " fmt, ## arg); \
37 } \
38 } while (0)
39
40#define dbgarg2(fmt, arg...) \
41 do { \
42 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
43 printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
44 } while (0)
45
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -030046#define dbgarg3(fmt, arg...) \
47 do { \
48 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
49 printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\
50 } while (0)
51
Trent Piepho7ecc0cf2009-04-30 21:03:34 -030052/* Zero out the end of the struct pointed to by p. Everthing after, but
53 * not including, the specified field is cleared. */
54#define CLEAR_AFTER_FIELD(p, field) \
55 memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
56 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
57
Hans Verkuil35ea11f2008-07-20 08:12:02 -030058struct std_descr {
59 v4l2_std_id std;
60 const char *descr;
61};
62
63static const struct std_descr standards[] = {
64 { V4L2_STD_NTSC, "NTSC" },
65 { V4L2_STD_NTSC_M, "NTSC-M" },
66 { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" },
67 { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" },
68 { V4L2_STD_NTSC_443, "NTSC-443" },
69 { V4L2_STD_PAL, "PAL" },
70 { V4L2_STD_PAL_BG, "PAL-BG" },
71 { V4L2_STD_PAL_B, "PAL-B" },
72 { V4L2_STD_PAL_B1, "PAL-B1" },
73 { V4L2_STD_PAL_G, "PAL-G" },
74 { V4L2_STD_PAL_H, "PAL-H" },
75 { V4L2_STD_PAL_I, "PAL-I" },
76 { V4L2_STD_PAL_DK, "PAL-DK" },
77 { V4L2_STD_PAL_D, "PAL-D" },
78 { V4L2_STD_PAL_D1, "PAL-D1" },
79 { V4L2_STD_PAL_K, "PAL-K" },
80 { V4L2_STD_PAL_M, "PAL-M" },
81 { V4L2_STD_PAL_N, "PAL-N" },
82 { V4L2_STD_PAL_Nc, "PAL-Nc" },
83 { V4L2_STD_PAL_60, "PAL-60" },
84 { V4L2_STD_SECAM, "SECAM" },
85 { V4L2_STD_SECAM_B, "SECAM-B" },
86 { V4L2_STD_SECAM_G, "SECAM-G" },
87 { V4L2_STD_SECAM_H, "SECAM-H" },
88 { V4L2_STD_SECAM_DK, "SECAM-DK" },
89 { V4L2_STD_SECAM_D, "SECAM-D" },
90 { V4L2_STD_SECAM_K, "SECAM-K" },
91 { V4L2_STD_SECAM_K1, "SECAM-K1" },
92 { V4L2_STD_SECAM_L, "SECAM-L" },
93 { V4L2_STD_SECAM_LC, "SECAM-Lc" },
94 { 0, "Unknown" }
95};
96
97/* video4linux standard ID conversion to standard name
98 */
99const char *v4l2_norm_to_name(v4l2_std_id id)
100{
101 u32 myid = id;
102 int i;
103
104 /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
105 64 bit comparations. So, on that architecture, with some gcc
106 variants, compilation fails. Currently, the max value is 30bit wide.
107 */
108 BUG_ON(myid != id);
109
110 for (i = 0; standards[i].std; i++)
111 if (myid == standards[i].std)
112 break;
113 return standards[i].descr;
114}
115EXPORT_SYMBOL(v4l2_norm_to_name);
116
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300117/* Returns frame period for the given standard */
118void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
119{
120 if (id & V4L2_STD_525_60) {
121 frameperiod->numerator = 1001;
122 frameperiod->denominator = 30000;
123 } else {
124 frameperiod->numerator = 1;
125 frameperiod->denominator = 25;
126 }
127}
128EXPORT_SYMBOL(v4l2_video_std_frame_period);
129
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300130/* Fill in the fields of a v4l2_standard structure according to the
131 'id' and 'transmission' parameters. Returns negative on error. */
132int v4l2_video_std_construct(struct v4l2_standard *vs,
133 int id, const char *name)
134{
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300135 vs->id = id;
136 v4l2_video_std_frame_period(id, &vs->frameperiod);
137 vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300138 strlcpy(vs->name, name, sizeof(vs->name));
139 return 0;
140}
141EXPORT_SYMBOL(v4l2_video_std_construct);
142
143/* ----------------------------------------------------------------- */
144/* some arrays for pretty-printing debug messages of enum types */
145
146const char *v4l2_field_names[] = {
147 [V4L2_FIELD_ANY] = "any",
148 [V4L2_FIELD_NONE] = "none",
149 [V4L2_FIELD_TOP] = "top",
150 [V4L2_FIELD_BOTTOM] = "bottom",
151 [V4L2_FIELD_INTERLACED] = "interlaced",
152 [V4L2_FIELD_SEQ_TB] = "seq-tb",
153 [V4L2_FIELD_SEQ_BT] = "seq-bt",
154 [V4L2_FIELD_ALTERNATE] = "alternate",
155 [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
156 [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
157};
158EXPORT_SYMBOL(v4l2_field_names);
159
160const char *v4l2_type_names[] = {
161 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "vid-cap",
162 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "vid-overlay",
163 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "vid-out",
164 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
165 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
166 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
167 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
168 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
169};
170EXPORT_SYMBOL(v4l2_type_names);
171
172static const char *v4l2_memory_names[] = {
173 [V4L2_MEMORY_MMAP] = "mmap",
174 [V4L2_MEMORY_USERPTR] = "userptr",
175 [V4L2_MEMORY_OVERLAY] = "overlay",
176};
177
178#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
179 arr[a] : "unknown")
180
181/* ------------------------------------------------------------------ */
182/* debug help functions */
183
184#ifdef CONFIG_VIDEO_V4L1_COMPAT
185static const char *v4l1_ioctls[] = {
186 [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP",
187 [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN",
188 [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN",
189 [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER",
190 [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER",
191 [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT",
192 [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT",
193 [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE",
194 [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN",
195 [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN",
196 [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF",
197 [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF",
198 [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY",
199 [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ",
200 [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ",
201 [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO",
202 [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO",
203 [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC",
204 [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE",
205 [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF",
206 [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT",
207 [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE",
208 [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE",
209 [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE",
210 [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE",
211 [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO",
212 [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE",
213 [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT",
214 [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT"
215};
216#define V4L1_IOCTLS ARRAY_SIZE(v4l1_ioctls)
217#endif
218
219static const char *v4l2_ioctls[] = {
220 [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
221 [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
222 [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
223 [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
224 [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
225 [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
226 [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
227 [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
228 [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
229 [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
230 [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
231 [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
232 [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
233 [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
234 [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
235 [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
236 [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
237 [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
238 [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
239 [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
240 [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
241 [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
242 [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
243 [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
244 [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
245 [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
246 [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
247 [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
248 [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
249 [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
250 [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
251 [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
252 [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
253 [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
254 [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
255 [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
256 [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
257 [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
258 [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
259 [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
260 [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
261 [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
262 [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
263 [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
264 [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
265 [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
266 [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
267 [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
268 [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
269 [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
270 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
271 [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
272 [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
273 [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
274 [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
275#if 1
276 [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
277 [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
278 [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
279 [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
280 [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
281
282 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
283 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
284
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300285 [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300286 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
287#endif
Muralidharan Karicherib6456c02009-11-19 12:00:31 -0300288 [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
289 [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
290 [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
291 [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
292 [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
293 [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300294};
295#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
296
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300297/* Common ioctl debug function. This function can be used by
298 external ioctl messages as well as internal V4L ioctl */
299void v4l_printk_ioctl(unsigned int cmd)
300{
301 char *dir, *type;
302
303 switch (_IOC_TYPE(cmd)) {
304 case 'd':
Hans Verkuil78a3b4d2009-04-01 03:41:09 -0300305 type = "v4l2_int";
306 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300307#ifdef CONFIG_VIDEO_V4L1_COMPAT
308 case 'v':
309 if (_IOC_NR(cmd) >= V4L1_IOCTLS) {
310 type = "v4l1";
311 break;
312 }
313 printk("%s", v4l1_ioctls[_IOC_NR(cmd)]);
314 return;
315#endif
316 case 'V':
317 if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
318 type = "v4l2";
319 break;
320 }
321 printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
322 return;
323 default:
324 type = "unknown";
325 }
326
327 switch (_IOC_DIR(cmd)) {
328 case _IOC_NONE: dir = "--"; break;
329 case _IOC_READ: dir = "r-"; break;
330 case _IOC_WRITE: dir = "-w"; break;
331 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
332 default: dir = "*ERR*"; break;
333 }
334 printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
335 type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
336}
337EXPORT_SYMBOL(v4l_printk_ioctl);
338
339/*
340 * helper function -- handles userspace copying for ioctl arguments
341 */
342
343#ifdef __OLD_VIDIOC_
344static unsigned int
345video_fix_command(unsigned int cmd)
346{
347 switch (cmd) {
348 case VIDIOC_OVERLAY_OLD:
349 cmd = VIDIOC_OVERLAY;
350 break;
351 case VIDIOC_S_PARM_OLD:
352 cmd = VIDIOC_S_PARM;
353 break;
354 case VIDIOC_S_CTRL_OLD:
355 cmd = VIDIOC_S_CTRL;
356 break;
357 case VIDIOC_G_AUDIO_OLD:
358 cmd = VIDIOC_G_AUDIO;
359 break;
360 case VIDIOC_G_AUDOUT_OLD:
361 cmd = VIDIOC_G_AUDOUT;
362 break;
363 case VIDIOC_CROPCAP_OLD:
364 cmd = VIDIOC_CROPCAP;
365 break;
366 }
367 return cmd;
368}
369#endif
370
371/*
372 * Obsolete usercopy function - Should be removed soon
373 */
Hans Verkuil069b7472008-12-30 07:04:34 -0300374long
Hans Verkuilf473bf72008-11-01 08:25:11 -0300375video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
376 v4l2_kioctl func)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300377{
378 char sbuf[128];
379 void *mbuf = NULL;
380 void *parg = NULL;
Hans Verkuil069b7472008-12-30 07:04:34 -0300381 long err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300382 int is_ext_ctrl;
383 size_t ctrls_size = 0;
384 void __user *user_ptr = NULL;
385
386#ifdef __OLD_VIDIOC_
387 cmd = video_fix_command(cmd);
388#endif
389 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
390 cmd == VIDIOC_TRY_EXT_CTRLS);
391
392 /* Copy arguments into temp kernel buffer */
393 switch (_IOC_DIR(cmd)) {
394 case _IOC_NONE:
395 parg = NULL;
396 break;
397 case _IOC_READ:
398 case _IOC_WRITE:
399 case (_IOC_WRITE | _IOC_READ):
400 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
401 parg = sbuf;
402 } else {
403 /* too big to allocate from stack */
404 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
405 if (NULL == mbuf)
406 return -ENOMEM;
407 parg = mbuf;
408 }
409
410 err = -EFAULT;
411 if (_IOC_DIR(cmd) & _IOC_WRITE)
412 if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
413 goto out;
414 break;
415 }
416 if (is_ext_ctrl) {
417 struct v4l2_ext_controls *p = parg;
418
419 /* In case of an error, tell the caller that it wasn't
420 a specific control that caused it. */
421 p->error_idx = p->count;
422 user_ptr = (void __user *)p->controls;
423 if (p->count) {
424 ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
425 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
426 mbuf = kmalloc(ctrls_size, GFP_KERNEL);
427 err = -ENOMEM;
428 if (NULL == mbuf)
429 goto out_ext_ctrl;
430 err = -EFAULT;
431 if (copy_from_user(mbuf, user_ptr, ctrls_size))
432 goto out_ext_ctrl;
433 p->controls = mbuf;
434 }
435 }
436
437 /* call driver */
Hans Verkuilf473bf72008-11-01 08:25:11 -0300438 err = func(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300439 if (err == -ENOIOCTLCMD)
440 err = -EINVAL;
441 if (is_ext_ctrl) {
442 struct v4l2_ext_controls *p = parg;
443
444 p->controls = (void *)user_ptr;
445 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
446 err = -EFAULT;
447 goto out_ext_ctrl;
448 }
449 if (err < 0)
450 goto out;
451
452out_ext_ctrl:
453 /* Copy results into user buffer */
454 switch (_IOC_DIR(cmd)) {
455 case _IOC_READ:
456 case (_IOC_WRITE | _IOC_READ):
457 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
458 err = -EFAULT;
459 break;
460 }
461
462out:
463 kfree(mbuf);
464 return err;
465}
466EXPORT_SYMBOL(video_usercopy);
467
468static void dbgbuf(unsigned int cmd, struct video_device *vfd,
469 struct v4l2_buffer *p)
470{
471 struct v4l2_timecode *tc = &p->timecode;
472
473 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
474 "bytesused=%d, flags=0x%08d, "
475 "field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
476 p->timestamp.tv_sec / 3600,
477 (int)(p->timestamp.tv_sec / 60) % 60,
478 (int)(p->timestamp.tv_sec % 60),
Alexander Beregalovb0459792008-09-03 16:47:38 -0300479 (long)p->timestamp.tv_usec,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300480 p->index,
481 prt_names(p->type, v4l2_type_names),
482 p->bytesused, p->flags,
483 p->field, p->sequence,
484 prt_names(p->memory, v4l2_memory_names),
485 p->m.userptr, p->length);
486 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
487 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
488 tc->hours, tc->minutes, tc->seconds,
489 tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
490}
491
492static inline void dbgrect(struct video_device *vfd, char *s,
493 struct v4l2_rect *r)
494{
495 dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
496 r->width, r->height);
497};
498
499static inline void v4l_print_pix_fmt(struct video_device *vfd,
500 struct v4l2_pix_format *fmt)
501{
502 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
503 "bytesperline=%d sizeimage=%d, colorspace=%d\n",
504 fmt->width, fmt->height,
505 (fmt->pixelformat & 0xff),
506 (fmt->pixelformat >> 8) & 0xff,
507 (fmt->pixelformat >> 16) & 0xff,
508 (fmt->pixelformat >> 24) & 0xff,
509 prt_names(fmt->field, v4l2_field_names),
510 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
511};
512
513static inline void v4l_print_ext_ctrls(unsigned int cmd,
514 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
515{
516 __u32 i;
517
518 if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
519 return;
520 dbgarg(cmd, "");
521 printk(KERN_CONT "class=0x%x", c->ctrl_class);
522 for (i = 0; i < c->count; i++) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300523 if (show_vals && !c->controls[i].size)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300524 printk(KERN_CONT " id/val=0x%x/0x%x",
525 c->controls[i].id, c->controls[i].value);
526 else
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300527 printk(KERN_CONT " id=0x%x,size=%u",
528 c->controls[i].id, c->controls[i].size);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300529 }
530 printk(KERN_CONT "\n");
531};
532
533static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
534{
535 __u32 i;
536
537 /* zero the reserved fields */
538 c->reserved[0] = c->reserved[1] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300539 for (i = 0; i < c->count; i++)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300540 c->controls[i].reserved2[0] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300541
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300542 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
543 when using extended controls.
544 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
545 is it allowed for backwards compatibility.
546 */
547 if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
548 return 0;
549 /* Check that all controls are from the same control class. */
550 for (i = 0; i < c->count; i++) {
551 if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
552 c->error_idx = i;
553 return 0;
554 }
555 }
556 return 1;
557}
558
Hans Verkuila3998102008-07-21 02:57:38 -0300559static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300560{
Hans Verkuila3998102008-07-21 02:57:38 -0300561 if (ops == NULL)
562 return -EINVAL;
563
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300564 switch (type) {
565 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300566 if (ops->vidioc_g_fmt_vid_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300567 return 0;
568 break;
569 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300570 if (ops->vidioc_g_fmt_vid_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300571 return 0;
572 break;
573 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300574 if (ops->vidioc_g_fmt_vid_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300575 return 0;
576 break;
577 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300578 if (ops->vidioc_g_fmt_vid_out_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300579 return 0;
580 break;
581 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300582 if (ops->vidioc_g_fmt_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300583 return 0;
584 break;
585 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300586 if (ops->vidioc_g_fmt_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300587 return 0;
588 break;
589 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300590 if (ops->vidioc_g_fmt_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300591 return 0;
592 break;
593 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300594 if (ops->vidioc_g_fmt_sliced_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300595 return 0;
596 break;
597 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho1175d612009-04-30 21:03:34 -0300598 if (ops->vidioc_g_fmt_type_private)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300599 return 0;
600 break;
601 }
602 return -EINVAL;
603}
604
Hans Verkuil069b7472008-12-30 07:04:34 -0300605static long __video_do_ioctl(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300606 unsigned int cmd, void *arg)
607{
608 struct video_device *vfd = video_devdata(file);
Hans Verkuila3998102008-07-21 02:57:38 -0300609 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
Hans Verkuild5fbf322008-10-18 13:39:53 -0300610 void *fh = file->private_data;
Hans Verkuil069b7472008-12-30 07:04:34 -0300611 long ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300612
Hans Verkuil6a717882010-04-06 15:56:08 -0300613 if (ops == NULL) {
614 printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
615 vfd->name);
616 return -EINVAL;
617 }
618
619#ifdef CONFIG_VIDEO_V4L1_COMPAT
620 /********************************************************
621 All other V4L1 calls are handled by v4l1_compat module.
622 Those calls will be translated into V4L2 calls, and
623 __video_do_ioctl will be called again, with one or more
624 V4L2 ioctls.
625 ********************************************************/
626 if (_IOC_TYPE(cmd) == 'v' && cmd != VIDIOCGMBUF &&
627 _IOC_NR(cmd) < BASE_VIDIOCPRIVATE) {
628 return v4l_compat_translate_ioctl(file, cmd, arg,
629 __video_do_ioctl);
630 }
631#endif
632
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300633 if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
634 !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
635 v4l_print_ioctl(vfd->name, cmd);
636 printk(KERN_CONT "\n");
637 }
638
Hans Verkuil6a717882010-04-06 15:56:08 -0300639 switch (cmd) {
Hans Verkuila3998102008-07-21 02:57:38 -0300640
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300641#ifdef CONFIG_VIDEO_V4L1_COMPAT
642 /***********************************************************
643 Handles calls to the obsoleted V4L1 API
644 Due to the nature of VIDIOCGMBUF, each driver that supports
645 V4L1 should implement its own handler for this ioctl.
646 ***********************************************************/
647
648 /* --- streaming capture ------------------------------------- */
Hans Verkuil6a717882010-04-06 15:56:08 -0300649 case VIDIOCGMBUF:
650 {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300651 struct video_mbuf *p = arg;
652
Hans Verkuila3998102008-07-21 02:57:38 -0300653 if (!ops->vidiocgmbuf)
Hans Verkuil6a717882010-04-06 15:56:08 -0300654 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300655 ret = ops->vidiocgmbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300656 if (!ret)
657 dbgarg(cmd, "size=%d, frames=%d, offsets=0x%08lx\n",
658 p->size, p->frames,
659 (unsigned long)p->offsets);
Hans Verkuil6a717882010-04-06 15:56:08 -0300660 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300661 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300662#endif
663
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300664 /* --- capabilities ------------------------------------------ */
665 case VIDIOC_QUERYCAP:
666 {
667 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300668
Hans Verkuila3998102008-07-21 02:57:38 -0300669 if (!ops->vidioc_querycap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300670 break;
671
Hans Verkuila3998102008-07-21 02:57:38 -0300672 ret = ops->vidioc_querycap(file, fh, cap);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300673 if (!ret)
674 dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
675 "version=0x%08x, "
676 "capabilities=0x%08x\n",
677 cap->driver, cap->card, cap->bus_info,
678 cap->version,
679 cap->capabilities);
680 break;
681 }
682
683 /* --- priority ------------------------------------------ */
684 case VIDIOC_G_PRIORITY:
685 {
686 enum v4l2_priority *p = arg;
687
Hans Verkuila3998102008-07-21 02:57:38 -0300688 if (!ops->vidioc_g_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300689 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300690 ret = ops->vidioc_g_priority(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300691 if (!ret)
692 dbgarg(cmd, "priority is %d\n", *p);
693 break;
694 }
695 case VIDIOC_S_PRIORITY:
696 {
697 enum v4l2_priority *p = arg;
698
Hans Verkuila3998102008-07-21 02:57:38 -0300699 if (!ops->vidioc_s_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300700 break;
701 dbgarg(cmd, "setting priority to %d\n", *p);
Hans Verkuila3998102008-07-21 02:57:38 -0300702 ret = ops->vidioc_s_priority(file, fh, *p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300703 break;
704 }
705
706 /* --- capture ioctls ---------------------------------------- */
707 case VIDIOC_ENUM_FMT:
708 {
709 struct v4l2_fmtdesc *f = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300710
Trent Piepho19c96e42009-03-04 01:21:02 -0300711 switch (f->type) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300712 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300713 if (ops->vidioc_enum_fmt_vid_cap)
714 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300715 break;
716 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300717 if (ops->vidioc_enum_fmt_vid_overlay)
718 ret = ops->vidioc_enum_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300719 fh, f);
720 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300721 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300722 if (ops->vidioc_enum_fmt_vid_out)
723 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300724 break;
725 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300726 if (ops->vidioc_enum_fmt_type_private)
727 ret = ops->vidioc_enum_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300728 fh, f);
729 break;
730 default:
731 break;
732 }
733 if (!ret)
734 dbgarg(cmd, "index=%d, type=%d, flags=%d, "
735 "pixelformat=%c%c%c%c, description='%s'\n",
736 f->index, f->type, f->flags,
737 (f->pixelformat & 0xff),
738 (f->pixelformat >> 8) & 0xff,
739 (f->pixelformat >> 16) & 0xff,
740 (f->pixelformat >> 24) & 0xff,
741 f->description);
742 break;
743 }
744 case VIDIOC_G_FMT:
745 {
746 struct v4l2_format *f = (struct v4l2_format *)arg;
747
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300748 /* FIXME: Should be one dump per type */
749 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
750
751 switch (f->type) {
752 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300753 if (ops->vidioc_g_fmt_vid_cap)
754 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300755 if (!ret)
756 v4l_print_pix_fmt(vfd, &f->fmt.pix);
757 break;
758 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300759 if (ops->vidioc_g_fmt_vid_overlay)
760 ret = ops->vidioc_g_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300761 fh, f);
762 break;
763 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300764 if (ops->vidioc_g_fmt_vid_out)
765 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300766 if (!ret)
767 v4l_print_pix_fmt(vfd, &f->fmt.pix);
768 break;
769 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300770 if (ops->vidioc_g_fmt_vid_out_overlay)
771 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300772 fh, f);
773 break;
774 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300775 if (ops->vidioc_g_fmt_vbi_cap)
776 ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300777 break;
778 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300779 if (ops->vidioc_g_fmt_vbi_out)
780 ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300781 break;
782 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300783 if (ops->vidioc_g_fmt_sliced_vbi_cap)
784 ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300785 fh, f);
786 break;
787 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300788 if (ops->vidioc_g_fmt_sliced_vbi_out)
789 ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300790 fh, f);
791 break;
792 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300793 if (ops->vidioc_g_fmt_type_private)
794 ret = ops->vidioc_g_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300795 fh, f);
796 break;
797 }
798
799 break;
800 }
801 case VIDIOC_S_FMT:
802 {
803 struct v4l2_format *f = (struct v4l2_format *)arg;
804
805 /* FIXME: Should be one dump per type */
806 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
807
808 switch (f->type) {
809 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300810 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300811 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300812 if (ops->vidioc_s_fmt_vid_cap)
813 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300814 break;
815 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300816 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300817 if (ops->vidioc_s_fmt_vid_overlay)
818 ret = ops->vidioc_s_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300819 fh, f);
820 break;
821 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300822 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300823 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300824 if (ops->vidioc_s_fmt_vid_out)
825 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300826 break;
827 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300828 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300829 if (ops->vidioc_s_fmt_vid_out_overlay)
830 ret = ops->vidioc_s_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300831 fh, f);
832 break;
833 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300834 CLEAR_AFTER_FIELD(f, fmt.vbi);
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:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300839 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300840 if (ops->vidioc_s_fmt_vbi_out)
841 ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300842 break;
843 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300844 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300845 if (ops->vidioc_s_fmt_sliced_vbi_cap)
846 ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300847 fh, f);
848 break;
849 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300850 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300851 if (ops->vidioc_s_fmt_sliced_vbi_out)
852 ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300853 fh, f);
854 break;
855 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300856 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -0300857 if (ops->vidioc_s_fmt_type_private)
858 ret = ops->vidioc_s_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300859 fh, f);
860 break;
861 }
862 break;
863 }
864 case VIDIOC_TRY_FMT:
865 {
866 struct v4l2_format *f = (struct v4l2_format *)arg;
867
868 /* FIXME: Should be one dump per type */
869 dbgarg(cmd, "type=%s\n", prt_names(f->type,
870 v4l2_type_names));
871 switch (f->type) {
872 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300873 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300874 if (ops->vidioc_try_fmt_vid_cap)
875 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300876 if (!ret)
877 v4l_print_pix_fmt(vfd, &f->fmt.pix);
878 break;
879 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300880 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300881 if (ops->vidioc_try_fmt_vid_overlay)
882 ret = ops->vidioc_try_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300883 fh, f);
884 break;
885 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300886 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuila3998102008-07-21 02:57:38 -0300887 if (ops->vidioc_try_fmt_vid_out)
888 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300889 if (!ret)
890 v4l_print_pix_fmt(vfd, &f->fmt.pix);
891 break;
892 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300893 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300894 if (ops->vidioc_try_fmt_vid_out_overlay)
895 ret = ops->vidioc_try_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300896 fh, f);
897 break;
898 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300899 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300900 if (ops->vidioc_try_fmt_vbi_cap)
901 ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300902 break;
903 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300904 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300905 if (ops->vidioc_try_fmt_vbi_out)
906 ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300907 break;
908 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300909 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300910 if (ops->vidioc_try_fmt_sliced_vbi_cap)
911 ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300912 fh, f);
913 break;
914 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300915 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300916 if (ops->vidioc_try_fmt_sliced_vbi_out)
917 ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300918 fh, f);
919 break;
920 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300921 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -0300922 if (ops->vidioc_try_fmt_type_private)
923 ret = ops->vidioc_try_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300924 fh, f);
925 break;
926 }
927
928 break;
929 }
930 /* FIXME: Those buf reqs could be handled here,
931 with some changes on videobuf to allow its header to be included at
932 videodev2.h or being merged at videodev2.
933 */
934 case VIDIOC_REQBUFS:
935 {
936 struct v4l2_requestbuffers *p = arg;
937
Hans Verkuila3998102008-07-21 02:57:38 -0300938 if (!ops->vidioc_reqbufs)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300939 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300940 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300941 if (ret)
942 break;
943
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300944 if (p->type < V4L2_BUF_TYPE_PRIVATE)
945 CLEAR_AFTER_FIELD(p, memory);
946
Hans Verkuila3998102008-07-21 02:57:38 -0300947 ret = ops->vidioc_reqbufs(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300948 dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
949 p->count,
950 prt_names(p->type, v4l2_type_names),
951 prt_names(p->memory, v4l2_memory_names));
952 break;
953 }
954 case VIDIOC_QUERYBUF:
955 {
956 struct v4l2_buffer *p = arg;
957
Hans Verkuila3998102008-07-21 02:57:38 -0300958 if (!ops->vidioc_querybuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300959 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300960 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300961 if (ret)
962 break;
963
Hans Verkuila3998102008-07-21 02:57:38 -0300964 ret = ops->vidioc_querybuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300965 if (!ret)
966 dbgbuf(cmd, vfd, p);
967 break;
968 }
969 case VIDIOC_QBUF:
970 {
971 struct v4l2_buffer *p = arg;
972
Hans Verkuila3998102008-07-21 02:57:38 -0300973 if (!ops->vidioc_qbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300974 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300975 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300976 if (ret)
977 break;
978
Hans Verkuila3998102008-07-21 02:57:38 -0300979 ret = ops->vidioc_qbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300980 if (!ret)
981 dbgbuf(cmd, vfd, p);
982 break;
983 }
984 case VIDIOC_DQBUF:
985 {
986 struct v4l2_buffer *p = arg;
987
Hans Verkuila3998102008-07-21 02:57:38 -0300988 if (!ops->vidioc_dqbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300989 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300990 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300991 if (ret)
992 break;
993
Hans Verkuila3998102008-07-21 02:57:38 -0300994 ret = ops->vidioc_dqbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300995 if (!ret)
996 dbgbuf(cmd, vfd, p);
997 break;
998 }
999 case VIDIOC_OVERLAY:
1000 {
1001 int *i = arg;
1002
Hans Verkuila3998102008-07-21 02:57:38 -03001003 if (!ops->vidioc_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001004 break;
1005 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001006 ret = ops->vidioc_overlay(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001007 break;
1008 }
1009 case VIDIOC_G_FBUF:
1010 {
1011 struct v4l2_framebuffer *p = arg;
1012
Hans Verkuila3998102008-07-21 02:57:38 -03001013 if (!ops->vidioc_g_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001014 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001015 ret = ops->vidioc_g_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001016 if (!ret) {
1017 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1018 p->capability, p->flags,
1019 (unsigned long)p->base);
1020 v4l_print_pix_fmt(vfd, &p->fmt);
1021 }
1022 break;
1023 }
1024 case VIDIOC_S_FBUF:
1025 {
1026 struct v4l2_framebuffer *p = arg;
1027
Hans Verkuila3998102008-07-21 02:57:38 -03001028 if (!ops->vidioc_s_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001029 break;
1030 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1031 p->capability, p->flags, (unsigned long)p->base);
1032 v4l_print_pix_fmt(vfd, &p->fmt);
Hans Verkuila3998102008-07-21 02:57:38 -03001033 ret = ops->vidioc_s_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001034 break;
1035 }
1036 case VIDIOC_STREAMON:
1037 {
1038 enum v4l2_buf_type i = *(int *)arg;
1039
Hans Verkuila3998102008-07-21 02:57:38 -03001040 if (!ops->vidioc_streamon)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001041 break;
1042 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001043 ret = ops->vidioc_streamon(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001044 break;
1045 }
1046 case VIDIOC_STREAMOFF:
1047 {
1048 enum v4l2_buf_type i = *(int *)arg;
1049
Hans Verkuila3998102008-07-21 02:57:38 -03001050 if (!ops->vidioc_streamoff)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001051 break;
1052 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001053 ret = ops->vidioc_streamoff(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001054 break;
1055 }
1056 /* ---------- tv norms ---------- */
1057 case VIDIOC_ENUMSTD:
1058 {
1059 struct v4l2_standard *p = arg;
1060 v4l2_std_id id = vfd->tvnorms, curr_id = 0;
1061 unsigned int index = p->index, i, j = 0;
1062 const char *descr = "";
1063
1064 /* Return norm array in a canonical way */
1065 for (i = 0; i <= index && id; i++) {
1066 /* last std value in the standards array is 0, so this
1067 while always ends there since (id & 0) == 0. */
1068 while ((id & standards[j].std) != standards[j].std)
1069 j++;
1070 curr_id = standards[j].std;
1071 descr = standards[j].descr;
1072 j++;
1073 if (curr_id == 0)
1074 break;
1075 if (curr_id != V4L2_STD_PAL &&
1076 curr_id != V4L2_STD_SECAM &&
1077 curr_id != V4L2_STD_NTSC)
1078 id &= ~curr_id;
1079 }
1080 if (i <= index)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001081 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001082
1083 v4l2_video_std_construct(p, curr_id, descr);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001084
1085 dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
1086 "framelines=%d\n", p->index,
1087 (unsigned long long)p->id, p->name,
1088 p->frameperiod.numerator,
1089 p->frameperiod.denominator,
1090 p->framelines);
1091
1092 ret = 0;
1093 break;
1094 }
1095 case VIDIOC_G_STD:
1096 {
1097 v4l2_std_id *id = arg;
1098
1099 ret = 0;
1100 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001101 if (ops->vidioc_g_std)
1102 ret = ops->vidioc_g_std(file, fh, id);
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001103 else if (vfd->current_norm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001104 *id = vfd->current_norm;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001105 else
1106 ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001107
1108 if (!ret)
1109 dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
1110 break;
1111 }
1112 case VIDIOC_S_STD:
1113 {
1114 v4l2_std_id *id = arg, norm;
1115
1116 dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
1117
1118 norm = (*id) & vfd->tvnorms;
1119 if (vfd->tvnorms && !norm) /* Check if std is supported */
1120 break;
1121
1122 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001123 if (ops->vidioc_s_std)
1124 ret = ops->vidioc_s_std(file, fh, &norm);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001125 else
1126 ret = -EINVAL;
1127
1128 /* Updates standard information */
1129 if (ret >= 0)
1130 vfd->current_norm = norm;
1131 break;
1132 }
1133 case VIDIOC_QUERYSTD:
1134 {
1135 v4l2_std_id *p = arg;
1136
Hans Verkuila3998102008-07-21 02:57:38 -03001137 if (!ops->vidioc_querystd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001138 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001139 ret = ops->vidioc_querystd(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001140 if (!ret)
1141 dbgarg(cmd, "detected std=%08Lx\n",
1142 (unsigned long long)*p);
1143 break;
1144 }
1145 /* ------ input switching ---------- */
1146 /* FIXME: Inputs can be handled inside videodev2 */
1147 case VIDIOC_ENUMINPUT:
1148 {
1149 struct v4l2_input *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001150
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001151 /*
1152 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1153 * CAP_STD here based on ioctl handler provided by the
1154 * driver. If the driver doesn't support these
1155 * for a specific input, it must override these flags.
1156 */
1157 if (ops->vidioc_s_std)
1158 p->capabilities |= V4L2_IN_CAP_STD;
1159 if (ops->vidioc_s_dv_preset)
1160 p->capabilities |= V4L2_IN_CAP_PRESETS;
1161 if (ops->vidioc_s_dv_timings)
1162 p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
1163
Hans Verkuila3998102008-07-21 02:57:38 -03001164 if (!ops->vidioc_enum_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001165 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001166
Hans Verkuila3998102008-07-21 02:57:38 -03001167 ret = ops->vidioc_enum_input(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001168 if (!ret)
1169 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1170 "audioset=%d, "
1171 "tuner=%d, std=%08Lx, status=%d\n",
1172 p->index, p->name, p->type, p->audioset,
1173 p->tuner,
1174 (unsigned long long)p->std,
1175 p->status);
1176 break;
1177 }
1178 case VIDIOC_G_INPUT:
1179 {
1180 unsigned int *i = arg;
1181
Hans Verkuila3998102008-07-21 02:57:38 -03001182 if (!ops->vidioc_g_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001183 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001184 ret = ops->vidioc_g_input(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001185 if (!ret)
1186 dbgarg(cmd, "value=%d\n", *i);
1187 break;
1188 }
1189 case VIDIOC_S_INPUT:
1190 {
1191 unsigned int *i = arg;
1192
Hans Verkuila3998102008-07-21 02:57:38 -03001193 if (!ops->vidioc_s_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001194 break;
1195 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001196 ret = ops->vidioc_s_input(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001197 break;
1198 }
1199
1200 /* ------ output switching ---------- */
1201 case VIDIOC_ENUMOUTPUT:
1202 {
1203 struct v4l2_output *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001204
Hans Verkuila3998102008-07-21 02:57:38 -03001205 if (!ops->vidioc_enum_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001206 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001207
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001208 /*
1209 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1210 * CAP_STD here based on ioctl handler provided by the
1211 * driver. If the driver doesn't support these
1212 * for a specific output, it must override these flags.
1213 */
1214 if (ops->vidioc_s_std)
1215 p->capabilities |= V4L2_OUT_CAP_STD;
1216 if (ops->vidioc_s_dv_preset)
1217 p->capabilities |= V4L2_OUT_CAP_PRESETS;
1218 if (ops->vidioc_s_dv_timings)
1219 p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
1220
Hans Verkuila3998102008-07-21 02:57:38 -03001221 ret = ops->vidioc_enum_output(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001222 if (!ret)
1223 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1224 "audioset=0x%x, "
1225 "modulator=%d, std=0x%08Lx\n",
1226 p->index, p->name, p->type, p->audioset,
1227 p->modulator, (unsigned long long)p->std);
1228 break;
1229 }
1230 case VIDIOC_G_OUTPUT:
1231 {
1232 unsigned int *i = arg;
1233
Hans Verkuila3998102008-07-21 02:57:38 -03001234 if (!ops->vidioc_g_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001235 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001236 ret = ops->vidioc_g_output(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001237 if (!ret)
1238 dbgarg(cmd, "value=%d\n", *i);
1239 break;
1240 }
1241 case VIDIOC_S_OUTPUT:
1242 {
1243 unsigned int *i = arg;
1244
Hans Verkuila3998102008-07-21 02:57:38 -03001245 if (!ops->vidioc_s_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001246 break;
1247 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001248 ret = ops->vidioc_s_output(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001249 break;
1250 }
1251
1252 /* --- controls ---------------------------------------------- */
1253 case VIDIOC_QUERYCTRL:
1254 {
1255 struct v4l2_queryctrl *p = arg;
1256
Hans Verkuila3998102008-07-21 02:57:38 -03001257 if (!ops->vidioc_queryctrl)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001258 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001259 ret = ops->vidioc_queryctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001260 if (!ret)
1261 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1262 "step=%d, default=%d, flags=0x%08x\n",
1263 p->id, p->type, p->name,
1264 p->minimum, p->maximum,
1265 p->step, p->default_value, p->flags);
1266 else
1267 dbgarg(cmd, "id=0x%x\n", p->id);
1268 break;
1269 }
1270 case VIDIOC_G_CTRL:
1271 {
1272 struct v4l2_control *p = arg;
1273
Hans Verkuila3998102008-07-21 02:57:38 -03001274 if (ops->vidioc_g_ctrl)
1275 ret = ops->vidioc_g_ctrl(file, fh, p);
1276 else if (ops->vidioc_g_ext_ctrls) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001277 struct v4l2_ext_controls ctrls;
1278 struct v4l2_ext_control ctrl;
1279
1280 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1281 ctrls.count = 1;
1282 ctrls.controls = &ctrl;
1283 ctrl.id = p->id;
1284 ctrl.value = p->value;
1285 if (check_ext_ctrls(&ctrls, 1)) {
Hans Verkuila3998102008-07-21 02:57:38 -03001286 ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001287 if (ret == 0)
1288 p->value = ctrl.value;
1289 }
1290 } else
1291 break;
1292 if (!ret)
1293 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1294 else
1295 dbgarg(cmd, "id=0x%x\n", p->id);
1296 break;
1297 }
1298 case VIDIOC_S_CTRL:
1299 {
1300 struct v4l2_control *p = arg;
1301 struct v4l2_ext_controls ctrls;
1302 struct v4l2_ext_control ctrl;
1303
Hans Verkuila3998102008-07-21 02:57:38 -03001304 if (!ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001305 break;
1306
1307 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1308
Hans Verkuila3998102008-07-21 02:57:38 -03001309 if (ops->vidioc_s_ctrl) {
1310 ret = ops->vidioc_s_ctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001311 break;
1312 }
Hans Verkuila3998102008-07-21 02:57:38 -03001313 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001314 break;
1315
1316 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1317 ctrls.count = 1;
1318 ctrls.controls = &ctrl;
1319 ctrl.id = p->id;
1320 ctrl.value = p->value;
1321 if (check_ext_ctrls(&ctrls, 1))
Hans Verkuila3998102008-07-21 02:57:38 -03001322 ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001323 break;
1324 }
1325 case VIDIOC_G_EXT_CTRLS:
1326 {
1327 struct v4l2_ext_controls *p = arg;
1328
1329 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001330 if (!ops->vidioc_g_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001331 break;
1332 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001333 ret = ops->vidioc_g_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001334 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1335 break;
1336 }
1337 case VIDIOC_S_EXT_CTRLS:
1338 {
1339 struct v4l2_ext_controls *p = arg;
1340
1341 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001342 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001343 break;
1344 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1345 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001346 ret = ops->vidioc_s_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001347 break;
1348 }
1349 case VIDIOC_TRY_EXT_CTRLS:
1350 {
1351 struct v4l2_ext_controls *p = arg;
1352
1353 p->error_idx = p->count;
Hans Verkuila3998102008-07-21 02:57:38 -03001354 if (!ops->vidioc_try_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001355 break;
1356 v4l_print_ext_ctrls(cmd, vfd, p, 1);
1357 if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001358 ret = ops->vidioc_try_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001359 break;
1360 }
1361 case VIDIOC_QUERYMENU:
1362 {
1363 struct v4l2_querymenu *p = arg;
1364
Hans Verkuila3998102008-07-21 02:57:38 -03001365 if (!ops->vidioc_querymenu)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001366 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001367 ret = ops->vidioc_querymenu(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001368 if (!ret)
1369 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1370 p->id, p->index, p->name);
1371 else
1372 dbgarg(cmd, "id=0x%x, index=%d\n",
1373 p->id, p->index);
1374 break;
1375 }
1376 /* --- audio ---------------------------------------------- */
1377 case VIDIOC_ENUMAUDIO:
1378 {
1379 struct v4l2_audio *p = arg;
1380
Hans Verkuila3998102008-07-21 02:57:38 -03001381 if (!ops->vidioc_enumaudio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001382 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001383 ret = ops->vidioc_enumaudio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001384 if (!ret)
1385 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1386 "mode=0x%x\n", p->index, p->name,
1387 p->capability, p->mode);
1388 else
1389 dbgarg(cmd, "index=%d\n", p->index);
1390 break;
1391 }
1392 case VIDIOC_G_AUDIO:
1393 {
1394 struct v4l2_audio *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001395
Hans Verkuila3998102008-07-21 02:57:38 -03001396 if (!ops->vidioc_g_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001397 break;
1398
Hans Verkuila3998102008-07-21 02:57:38 -03001399 ret = ops->vidioc_g_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001400 if (!ret)
1401 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1402 "mode=0x%x\n", p->index,
1403 p->name, p->capability, p->mode);
1404 else
1405 dbgarg(cmd, "index=%d\n", p->index);
1406 break;
1407 }
1408 case VIDIOC_S_AUDIO:
1409 {
1410 struct v4l2_audio *p = arg;
1411
Hans Verkuila3998102008-07-21 02:57:38 -03001412 if (!ops->vidioc_s_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001413 break;
1414 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1415 "mode=0x%x\n", p->index, p->name,
1416 p->capability, p->mode);
Hans Verkuila3998102008-07-21 02:57:38 -03001417 ret = ops->vidioc_s_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001418 break;
1419 }
1420 case VIDIOC_ENUMAUDOUT:
1421 {
1422 struct v4l2_audioout *p = arg;
1423
Hans Verkuila3998102008-07-21 02:57:38 -03001424 if (!ops->vidioc_enumaudout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001425 break;
1426 dbgarg(cmd, "Enum for index=%d\n", p->index);
Hans Verkuila3998102008-07-21 02:57:38 -03001427 ret = ops->vidioc_enumaudout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001428 if (!ret)
1429 dbgarg2("index=%d, name=%s, capability=%d, "
1430 "mode=%d\n", p->index, p->name,
1431 p->capability, p->mode);
1432 break;
1433 }
1434 case VIDIOC_G_AUDOUT:
1435 {
1436 struct v4l2_audioout *p = arg;
1437
Hans Verkuila3998102008-07-21 02:57:38 -03001438 if (!ops->vidioc_g_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001439 break;
Trent Piepho337f9d22009-03-04 01:21:02 -03001440
Hans Verkuila3998102008-07-21 02:57:38 -03001441 ret = ops->vidioc_g_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001442 if (!ret)
1443 dbgarg2("index=%d, name=%s, capability=%d, "
1444 "mode=%d\n", p->index, p->name,
1445 p->capability, p->mode);
1446 break;
1447 }
1448 case VIDIOC_S_AUDOUT:
1449 {
1450 struct v4l2_audioout *p = arg;
1451
Hans Verkuila3998102008-07-21 02:57:38 -03001452 if (!ops->vidioc_s_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001453 break;
1454 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1455 "mode=%d\n", p->index, p->name,
1456 p->capability, p->mode);
1457
Hans Verkuila3998102008-07-21 02:57:38 -03001458 ret = ops->vidioc_s_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001459 break;
1460 }
1461 case VIDIOC_G_MODULATOR:
1462 {
1463 struct v4l2_modulator *p = arg;
1464
Hans Verkuila3998102008-07-21 02:57:38 -03001465 if (!ops->vidioc_g_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001466 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001467 ret = ops->vidioc_g_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001468 if (!ret)
1469 dbgarg(cmd, "index=%d, name=%s, "
1470 "capability=%d, rangelow=%d,"
1471 " rangehigh=%d, txsubchans=%d\n",
1472 p->index, p->name, p->capability,
1473 p->rangelow, p->rangehigh,
1474 p->txsubchans);
1475 break;
1476 }
1477 case VIDIOC_S_MODULATOR:
1478 {
1479 struct v4l2_modulator *p = arg;
1480
Hans Verkuila3998102008-07-21 02:57:38 -03001481 if (!ops->vidioc_s_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001482 break;
1483 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1484 "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1485 p->index, p->name, p->capability, p->rangelow,
1486 p->rangehigh, p->txsubchans);
Hans Verkuila3998102008-07-21 02:57:38 -03001487 ret = ops->vidioc_s_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001488 break;
1489 }
1490 case VIDIOC_G_CROP:
1491 {
1492 struct v4l2_crop *p = arg;
1493
Hans Verkuila3998102008-07-21 02:57:38 -03001494 if (!ops->vidioc_g_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001495 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001496
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001497 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001498 ret = ops->vidioc_g_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001499 if (!ret)
1500 dbgrect(vfd, "", &p->c);
1501 break;
1502 }
1503 case VIDIOC_S_CROP:
1504 {
1505 struct v4l2_crop *p = arg;
1506
Hans Verkuila3998102008-07-21 02:57:38 -03001507 if (!ops->vidioc_s_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001508 break;
1509 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1510 dbgrect(vfd, "", &p->c);
Hans Verkuila3998102008-07-21 02:57:38 -03001511 ret = ops->vidioc_s_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001512 break;
1513 }
1514 case VIDIOC_CROPCAP:
1515 {
1516 struct v4l2_cropcap *p = arg;
1517
1518 /*FIXME: Should also show v4l2_fract pixelaspect */
Hans Verkuila3998102008-07-21 02:57:38 -03001519 if (!ops->vidioc_cropcap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001520 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001521
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001522 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001523 ret = ops->vidioc_cropcap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001524 if (!ret) {
1525 dbgrect(vfd, "bounds ", &p->bounds);
1526 dbgrect(vfd, "defrect ", &p->defrect);
1527 }
1528 break;
1529 }
1530 case VIDIOC_G_JPEGCOMP:
1531 {
1532 struct v4l2_jpegcompression *p = arg;
1533
Hans Verkuila3998102008-07-21 02:57:38 -03001534 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001535 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001536
Hans Verkuila3998102008-07-21 02:57:38 -03001537 ret = ops->vidioc_g_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001538 if (!ret)
1539 dbgarg(cmd, "quality=%d, APPn=%d, "
1540 "APP_len=%d, COM_len=%d, "
1541 "jpeg_markers=%d\n",
1542 p->quality, p->APPn, p->APP_len,
1543 p->COM_len, p->jpeg_markers);
1544 break;
1545 }
1546 case VIDIOC_S_JPEGCOMP:
1547 {
1548 struct v4l2_jpegcompression *p = arg;
1549
Hans Verkuila3998102008-07-21 02:57:38 -03001550 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001551 break;
1552 dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
1553 "COM_len=%d, jpeg_markers=%d\n",
1554 p->quality, p->APPn, p->APP_len,
1555 p->COM_len, p->jpeg_markers);
Hans Verkuila3998102008-07-21 02:57:38 -03001556 ret = ops->vidioc_s_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001557 break;
1558 }
1559 case VIDIOC_G_ENC_INDEX:
1560 {
1561 struct v4l2_enc_idx *p = arg;
1562
Hans Verkuila3998102008-07-21 02:57:38 -03001563 if (!ops->vidioc_g_enc_index)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001564 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001565 ret = ops->vidioc_g_enc_index(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001566 if (!ret)
1567 dbgarg(cmd, "entries=%d, entries_cap=%d\n",
1568 p->entries, p->entries_cap);
1569 break;
1570 }
1571 case VIDIOC_ENCODER_CMD:
1572 {
1573 struct v4l2_encoder_cmd *p = arg;
1574
Hans Verkuila3998102008-07-21 02:57:38 -03001575 if (!ops->vidioc_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001576 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001577 ret = ops->vidioc_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001578 if (!ret)
1579 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1580 break;
1581 }
1582 case VIDIOC_TRY_ENCODER_CMD:
1583 {
1584 struct v4l2_encoder_cmd *p = arg;
1585
Hans Verkuila3998102008-07-21 02:57:38 -03001586 if (!ops->vidioc_try_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001587 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001588 ret = ops->vidioc_try_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001589 if (!ret)
1590 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1591 break;
1592 }
1593 case VIDIOC_G_PARM:
1594 {
1595 struct v4l2_streamparm *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001596
Hans Verkuila3998102008-07-21 02:57:38 -03001597 if (ops->vidioc_g_parm) {
Trent Piepho34796bc2009-03-28 22:25:35 -03001598 ret = check_fmt(ops, p->type);
1599 if (ret)
1600 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001601 ret = ops->vidioc_g_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001602 } else {
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001603 v4l2_std_id std = vfd->current_norm;
1604
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001605 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001606 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001607
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001608 ret = 0;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001609 if (ops->vidioc_g_std)
1610 ret = ops->vidioc_g_std(file, fh, &std);
1611 else if (std == 0)
1612 ret = -EINVAL;
1613 if (ret == 0)
1614 v4l2_video_std_frame_period(std,
1615 &p->parm.capture.timeperframe);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001616 }
1617
1618 dbgarg(cmd, "type=%d\n", p->type);
1619 break;
1620 }
1621 case VIDIOC_S_PARM:
1622 {
1623 struct v4l2_streamparm *p = arg;
1624
Hans Verkuila3998102008-07-21 02:57:38 -03001625 if (!ops->vidioc_s_parm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001626 break;
Trent Piepho34796bc2009-03-28 22:25:35 -03001627 ret = check_fmt(ops, p->type);
1628 if (ret)
1629 break;
1630
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001631 dbgarg(cmd, "type=%d\n", p->type);
Hans Verkuila3998102008-07-21 02:57:38 -03001632 ret = ops->vidioc_s_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001633 break;
1634 }
1635 case VIDIOC_G_TUNER:
1636 {
1637 struct v4l2_tuner *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001638
Hans Verkuila3998102008-07-21 02:57:38 -03001639 if (!ops->vidioc_g_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001640 break;
1641
Hans Verkuila3998102008-07-21 02:57:38 -03001642 ret = ops->vidioc_g_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001643 if (!ret)
1644 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1645 "capability=0x%x, rangelow=%d, "
1646 "rangehigh=%d, signal=%d, afc=%d, "
1647 "rxsubchans=0x%x, audmode=%d\n",
1648 p->index, p->name, p->type,
1649 p->capability, p->rangelow,
1650 p->rangehigh, p->signal, p->afc,
1651 p->rxsubchans, p->audmode);
1652 break;
1653 }
1654 case VIDIOC_S_TUNER:
1655 {
1656 struct v4l2_tuner *p = arg;
1657
Hans Verkuila3998102008-07-21 02:57:38 -03001658 if (!ops->vidioc_s_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001659 break;
1660 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1661 "capability=0x%x, rangelow=%d, "
1662 "rangehigh=%d, signal=%d, afc=%d, "
1663 "rxsubchans=0x%x, audmode=%d\n",
1664 p->index, p->name, p->type,
1665 p->capability, p->rangelow,
1666 p->rangehigh, p->signal, p->afc,
1667 p->rxsubchans, p->audmode);
Hans Verkuila3998102008-07-21 02:57:38 -03001668 ret = ops->vidioc_s_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001669 break;
1670 }
1671 case VIDIOC_G_FREQUENCY:
1672 {
1673 struct v4l2_frequency *p = arg;
1674
Hans Verkuila3998102008-07-21 02:57:38 -03001675 if (!ops->vidioc_g_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001676 break;
1677
Hans Verkuila3998102008-07-21 02:57:38 -03001678 ret = ops->vidioc_g_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001679 if (!ret)
1680 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1681 p->tuner, p->type, p->frequency);
1682 break;
1683 }
1684 case VIDIOC_S_FREQUENCY:
1685 {
1686 struct v4l2_frequency *p = arg;
1687
Hans Verkuila3998102008-07-21 02:57:38 -03001688 if (!ops->vidioc_s_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001689 break;
1690 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1691 p->tuner, p->type, p->frequency);
Hans Verkuila3998102008-07-21 02:57:38 -03001692 ret = ops->vidioc_s_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001693 break;
1694 }
1695 case VIDIOC_G_SLICED_VBI_CAP:
1696 {
1697 struct v4l2_sliced_vbi_cap *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001698
Hans Verkuila3998102008-07-21 02:57:38 -03001699 if (!ops->vidioc_g_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001700 break;
Trent Piepho19c96e42009-03-04 01:21:02 -03001701
1702 /* Clear up to type, everything after type is zerod already */
1703 memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
1704
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001705 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001706 ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001707 if (!ret)
1708 dbgarg2("service_set=%d\n", p->service_set);
1709 break;
1710 }
1711 case VIDIOC_LOG_STATUS:
1712 {
Hans Verkuila3998102008-07-21 02:57:38 -03001713 if (!ops->vidioc_log_status)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001714 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001715 ret = ops->vidioc_log_status(file, fh);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001716 break;
1717 }
1718#ifdef CONFIG_VIDEO_ADV_DEBUG
1719 case VIDIOC_DBG_G_REGISTER:
1720 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001721 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001722
1723 if (!capable(CAP_SYS_ADMIN))
1724 ret = -EPERM;
Hans Verkuila3998102008-07-21 02:57:38 -03001725 else if (ops->vidioc_g_register)
1726 ret = ops->vidioc_g_register(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001727 break;
1728 }
1729 case VIDIOC_DBG_S_REGISTER:
1730 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001731 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001732
1733 if (!capable(CAP_SYS_ADMIN))
1734 ret = -EPERM;
Hans Verkuila3998102008-07-21 02:57:38 -03001735 else if (ops->vidioc_s_register)
1736 ret = ops->vidioc_s_register(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001737 break;
1738 }
1739#endif
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001740 case VIDIOC_DBG_G_CHIP_IDENT:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001741 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001742 struct v4l2_dbg_chip_ident *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001743
Hans Verkuila3998102008-07-21 02:57:38 -03001744 if (!ops->vidioc_g_chip_ident)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001745 break;
Hans Verkuil80b36e02009-02-07 11:00:02 -03001746 p->ident = V4L2_IDENT_NONE;
1747 p->revision = 0;
Hans Verkuila3998102008-07-21 02:57:38 -03001748 ret = ops->vidioc_g_chip_ident(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001749 if (!ret)
1750 dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
1751 break;
1752 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001753 case VIDIOC_S_HW_FREQ_SEEK:
1754 {
1755 struct v4l2_hw_freq_seek *p = arg;
1756
Hans Verkuila3998102008-07-21 02:57:38 -03001757 if (!ops->vidioc_s_hw_freq_seek)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001758 break;
1759 dbgarg(cmd,
1760 "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
1761 p->tuner, p->type, p->seek_upward, p->wrap_around);
Hans Verkuila3998102008-07-21 02:57:38 -03001762 ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
1763 break;
1764 }
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001765 case VIDIOC_ENUM_FRAMESIZES:
1766 {
1767 struct v4l2_frmsizeenum *p = arg;
1768
1769 if (!ops->vidioc_enum_framesizes)
1770 break;
1771
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001772 ret = ops->vidioc_enum_framesizes(file, fh, p);
1773 dbgarg(cmd,
Mauro Carvalho Chehabd1afe422009-06-21 22:37:12 -03001774 "index=%d, pixelformat=%c%c%c%c, type=%d ",
1775 p->index,
1776 (p->pixel_format & 0xff),
1777 (p->pixel_format >> 8) & 0xff,
1778 (p->pixel_format >> 16) & 0xff,
1779 (p->pixel_format >> 24) & 0xff,
1780 p->type);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001781 switch (p->type) {
1782 case V4L2_FRMSIZE_TYPE_DISCRETE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001783 dbgarg3("width = %d, height=%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001784 p->discrete.width, p->discrete.height);
1785 break;
1786 case V4L2_FRMSIZE_TYPE_STEPWISE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001787 dbgarg3("min %dx%d, max %dx%d, step %dx%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001788 p->stepwise.min_width, p->stepwise.min_height,
1789 p->stepwise.step_width, p->stepwise.step_height,
1790 p->stepwise.max_width, p->stepwise.max_height);
1791 break;
1792 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001793 dbgarg3("continuous\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001794 break;
1795 default:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001796 dbgarg3("- Unknown type!\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001797 }
1798
1799 break;
1800 }
1801 case VIDIOC_ENUM_FRAMEINTERVALS:
1802 {
1803 struct v4l2_frmivalenum *p = arg;
1804
1805 if (!ops->vidioc_enum_frameintervals)
1806 break;
1807
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001808 ret = ops->vidioc_enum_frameintervals(file, fh, p);
1809 dbgarg(cmd,
1810 "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
1811 p->index, p->pixel_format,
1812 p->width, p->height, p->type);
1813 switch (p->type) {
1814 case V4L2_FRMIVAL_TYPE_DISCRETE:
1815 dbgarg2("fps=%d/%d\n",
1816 p->discrete.numerator,
1817 p->discrete.denominator);
1818 break;
1819 case V4L2_FRMIVAL_TYPE_STEPWISE:
Mauro Carvalho Chehab19585782008-11-12 01:03:02 -03001820 dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",
1821 p->stepwise.min.numerator,
1822 p->stepwise.min.denominator,
1823 p->stepwise.max.numerator,
1824 p->stepwise.max.denominator,
1825 p->stepwise.step.numerator,
1826 p->stepwise.step.denominator);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001827 break;
1828 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1829 dbgarg2("continuous\n");
1830 break;
1831 default:
1832 dbgarg2("- Unknown type!\n");
1833 }
1834 break;
1835 }
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001836 case VIDIOC_ENUM_DV_PRESETS:
1837 {
1838 struct v4l2_dv_enum_preset *p = arg;
1839
1840 if (!ops->vidioc_enum_dv_presets)
1841 break;
1842
1843 ret = ops->vidioc_enum_dv_presets(file, fh, p);
1844 if (!ret)
1845 dbgarg(cmd,
1846 "index=%d, preset=%d, name=%s, width=%d,"
1847 " height=%d ",
1848 p->index, p->preset, p->name, p->width,
1849 p->height);
1850 break;
1851 }
1852 case VIDIOC_S_DV_PRESET:
1853 {
1854 struct v4l2_dv_preset *p = arg;
1855
1856 if (!ops->vidioc_s_dv_preset)
1857 break;
1858
1859 dbgarg(cmd, "preset=%d\n", p->preset);
1860 ret = ops->vidioc_s_dv_preset(file, fh, p);
1861 break;
1862 }
1863 case VIDIOC_G_DV_PRESET:
1864 {
1865 struct v4l2_dv_preset *p = arg;
1866
1867 if (!ops->vidioc_g_dv_preset)
1868 break;
1869
1870 ret = ops->vidioc_g_dv_preset(file, fh, p);
1871 if (!ret)
1872 dbgarg(cmd, "preset=%d\n", p->preset);
1873 break;
1874 }
1875 case VIDIOC_QUERY_DV_PRESET:
1876 {
1877 struct v4l2_dv_preset *p = arg;
1878
1879 if (!ops->vidioc_query_dv_preset)
1880 break;
1881
1882 ret = ops->vidioc_query_dv_preset(file, fh, p);
1883 if (!ret)
1884 dbgarg(cmd, "preset=%d\n", p->preset);
1885 break;
1886 }
1887 case VIDIOC_S_DV_TIMINGS:
1888 {
1889 struct v4l2_dv_timings *p = arg;
1890
1891 if (!ops->vidioc_s_dv_timings)
1892 break;
1893
1894 switch (p->type) {
1895 case V4L2_DV_BT_656_1120:
1896 dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
1897 " width=%d, height=%d, polarities=%x,"
1898 " hfrontporch=%d, hsync=%d, hbackporch=%d,"
1899 " vfrontporch=%d, vsync=%d, vbackporch=%d,"
1900 " il_vfrontporch=%d, il_vsync=%d,"
1901 " il_vbackporch=%d\n",
1902 p->bt.interlaced, p->bt.pixelclock,
1903 p->bt.width, p->bt.height, p->bt.polarities,
1904 p->bt.hfrontporch, p->bt.hsync,
1905 p->bt.hbackporch, p->bt.vfrontporch,
1906 p->bt.vsync, p->bt.vbackporch,
1907 p->bt.il_vfrontporch, p->bt.il_vsync,
1908 p->bt.il_vbackporch);
1909 ret = ops->vidioc_s_dv_timings(file, fh, p);
1910 break;
1911 default:
1912 dbgarg2("Unknown type %d!\n", p->type);
1913 break;
1914 }
1915 break;
1916 }
1917 case VIDIOC_G_DV_TIMINGS:
1918 {
1919 struct v4l2_dv_timings *p = arg;
1920
1921 if (!ops->vidioc_g_dv_timings)
1922 break;
1923
1924 ret = ops->vidioc_g_dv_timings(file, fh, p);
1925 if (!ret) {
1926 switch (p->type) {
1927 case V4L2_DV_BT_656_1120:
1928 dbgarg2("bt-656/1120:interlaced=%d,"
1929 " pixelclock=%lld,"
1930 " width=%d, height=%d, polarities=%x,"
1931 " hfrontporch=%d, hsync=%d,"
1932 " hbackporch=%d, vfrontporch=%d,"
1933 " vsync=%d, vbackporch=%d,"
1934 " il_vfrontporch=%d, il_vsync=%d,"
1935 " il_vbackporch=%d\n",
1936 p->bt.interlaced, p->bt.pixelclock,
1937 p->bt.width, p->bt.height,
1938 p->bt.polarities, p->bt.hfrontporch,
1939 p->bt.hsync, p->bt.hbackporch,
1940 p->bt.vfrontporch, p->bt.vsync,
1941 p->bt.vbackporch, p->bt.il_vfrontporch,
1942 p->bt.il_vsync, p->bt.il_vbackporch);
1943 break;
1944 default:
1945 dbgarg2("Unknown type %d!\n", p->type);
1946 break;
1947 }
1948 }
1949 break;
1950 }
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001951
Hans Verkuila3998102008-07-21 02:57:38 -03001952 default:
1953 {
1954 if (!ops->vidioc_default)
1955 break;
1956 ret = ops->vidioc_default(file, fh, cmd, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001957 break;
1958 }
1959 } /* switch */
1960
1961 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
1962 if (ret < 0) {
1963 v4l_print_ioctl(vfd->name, cmd);
Hans Verkuil069b7472008-12-30 07:04:34 -03001964 printk(KERN_CONT " error %ld\n", ret);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001965 }
1966 }
1967
1968 return ret;
1969}
1970
Trent Piepho19c96e42009-03-04 01:21:02 -03001971/* In some cases, only a few fields are used as input, i.e. when the app sets
1972 * "index" and then the driver fills in the rest of the structure for the thing
1973 * with that index. We only need to copy up the first non-input field. */
1974static unsigned long cmd_input_size(unsigned int cmd)
1975{
1976 /* Size of structure up to and including 'field' */
Hans Verkuil9f1a6932009-03-08 10:35:23 -03001977#define CMDINSIZE(cmd, type, field) \
1978 case VIDIOC_##cmd: \
1979 return offsetof(struct v4l2_##type, field) + \
1980 sizeof(((struct v4l2_##type *)0)->field);
Trent Piepho19c96e42009-03-04 01:21:02 -03001981
Hans Verkuil9f1a6932009-03-08 10:35:23 -03001982 switch (cmd) {
Trent Piepho19c96e42009-03-04 01:21:02 -03001983 CMDINSIZE(ENUM_FMT, fmtdesc, type);
1984 CMDINSIZE(G_FMT, format, type);
1985 CMDINSIZE(QUERYBUF, buffer, type);
1986 CMDINSIZE(G_PARM, streamparm, type);
1987 CMDINSIZE(ENUMSTD, standard, index);
1988 CMDINSIZE(ENUMINPUT, input, index);
1989 CMDINSIZE(G_CTRL, control, id);
1990 CMDINSIZE(G_TUNER, tuner, index);
1991 CMDINSIZE(QUERYCTRL, queryctrl, id);
1992 CMDINSIZE(QUERYMENU, querymenu, index);
1993 CMDINSIZE(ENUMOUTPUT, output, index);
1994 CMDINSIZE(G_MODULATOR, modulator, index);
1995 CMDINSIZE(G_FREQUENCY, frequency, tuner);
1996 CMDINSIZE(CROPCAP, cropcap, type);
1997 CMDINSIZE(G_CROP, crop, type);
1998 CMDINSIZE(ENUMAUDIO, audio, index);
1999 CMDINSIZE(ENUMAUDOUT, audioout, index);
2000 CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
2001 CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
2002 CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
2003 CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
2004 CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
2005 default:
2006 return _IOC_SIZE(cmd);
2007 }
2008}
2009
Hans Verkuil069b7472008-12-30 07:04:34 -03002010long video_ioctl2(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002011 unsigned int cmd, unsigned long arg)
2012{
2013 char sbuf[128];
2014 void *mbuf = NULL;
Hans Verkuil1d94aa32010-04-06 08:12:21 -03002015 void *parg = (void *)arg;
Hans Verkuil069b7472008-12-30 07:04:34 -03002016 long err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002017 int is_ext_ctrl;
2018 size_t ctrls_size = 0;
2019 void __user *user_ptr = NULL;
2020
2021#ifdef __OLD_VIDIOC_
2022 cmd = video_fix_command(cmd);
2023#endif
2024 is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
2025 cmd == VIDIOC_TRY_EXT_CTRLS);
2026
2027 /* Copy arguments into temp kernel buffer */
Trent Piepho337f9d22009-03-04 01:21:02 -03002028 if (_IOC_DIR(cmd) != _IOC_NONE) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002029 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
2030 parg = sbuf;
2031 } else {
2032 /* too big to allocate from stack */
2033 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
2034 if (NULL == mbuf)
2035 return -ENOMEM;
2036 parg = mbuf;
2037 }
2038
2039 err = -EFAULT;
Trent Piepho19c96e42009-03-04 01:21:02 -03002040 if (_IOC_DIR(cmd) & _IOC_WRITE) {
2041 unsigned long n = cmd_input_size(cmd);
2042
2043 if (copy_from_user(parg, (void __user *)arg, n))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002044 goto out;
Trent Piepho19c96e42009-03-04 01:21:02 -03002045
2046 /* zero out anything we don't copy from userspace */
2047 if (n < _IOC_SIZE(cmd))
2048 memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
Trent Piepho337f9d22009-03-04 01:21:02 -03002049 } else {
2050 /* read-only ioctl */
2051 memset(parg, 0, _IOC_SIZE(cmd));
Trent Piepho19c96e42009-03-04 01:21:02 -03002052 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002053 }
2054
2055 if (is_ext_ctrl) {
2056 struct v4l2_ext_controls *p = parg;
2057
2058 /* In case of an error, tell the caller that it wasn't
2059 a specific control that caused it. */
2060 p->error_idx = p->count;
2061 user_ptr = (void __user *)p->controls;
2062 if (p->count) {
2063 ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
2064 /* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
2065 mbuf = kmalloc(ctrls_size, GFP_KERNEL);
2066 err = -ENOMEM;
2067 if (NULL == mbuf)
2068 goto out_ext_ctrl;
2069 err = -EFAULT;
2070 if (copy_from_user(mbuf, user_ptr, ctrls_size))
2071 goto out_ext_ctrl;
2072 p->controls = mbuf;
2073 }
2074 }
2075
2076 /* Handles IOCTL */
Mauro Carvalho Chehabb1f88402008-10-21 11:27:20 -03002077 err = __video_do_ioctl(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002078 if (err == -ENOIOCTLCMD)
2079 err = -EINVAL;
2080 if (is_ext_ctrl) {
2081 struct v4l2_ext_controls *p = parg;
2082
2083 p->controls = (void *)user_ptr;
2084 if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
2085 err = -EFAULT;
2086 goto out_ext_ctrl;
2087 }
2088 if (err < 0)
2089 goto out;
2090
2091out_ext_ctrl:
2092 /* Copy results into user buffer */
2093 switch (_IOC_DIR(cmd)) {
2094 case _IOC_READ:
2095 case (_IOC_WRITE | _IOC_READ):
2096 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
2097 err = -EFAULT;
2098 break;
2099 }
2100
2101out:
2102 kfree(mbuf);
2103 return err;
2104}
Mauro Carvalho Chehab8a522c92008-10-21 11:58:39 -03002105EXPORT_SYMBOL(video_ioctl2);