blob: 3e6b6fa5771a0f3ee8c5ec7d9257dedcd6fdbe6e [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
Hans Verkuil35ea11f2008-07-20 08:12:02 -030020#include <linux/videodev2.h>
21
Hans Verkuil35ea11f2008-07-20 08:12:02 -030022#include <media/v4l2-common.h>
23#include <media/v4l2-ioctl.h>
Hans Verkuil11bbc1c2010-05-16 09:24:06 -030024#include <media/v4l2-ctrls.h>
Sakari Ailusd3d7c962010-03-27 11:02:10 -030025#include <media/v4l2-fh.h>
26#include <media/v4l2-event.h>
Hans Verkuil99cd47bc2011-03-11 19:00:56 -030027#include <media/v4l2-device.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
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -030045#define dbgarg3(fmt, arg...) \
46 do { \
47 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
48 printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\
49 } while (0)
50
Trent Piepho7ecc0cf2009-04-30 21:03:34 -030051/* Zero out the end of the struct pointed to by p. Everthing after, but
52 * not including, the specified field is cleared. */
53#define CLEAR_AFTER_FIELD(p, field) \
54 memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
55 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
56
Hans Verkuil35ea11f2008-07-20 08:12:02 -030057struct std_descr {
58 v4l2_std_id std;
59 const char *descr;
60};
61
62static const struct std_descr standards[] = {
63 { V4L2_STD_NTSC, "NTSC" },
64 { V4L2_STD_NTSC_M, "NTSC-M" },
65 { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" },
66 { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" },
67 { V4L2_STD_NTSC_443, "NTSC-443" },
68 { V4L2_STD_PAL, "PAL" },
69 { V4L2_STD_PAL_BG, "PAL-BG" },
70 { V4L2_STD_PAL_B, "PAL-B" },
71 { V4L2_STD_PAL_B1, "PAL-B1" },
72 { V4L2_STD_PAL_G, "PAL-G" },
73 { V4L2_STD_PAL_H, "PAL-H" },
74 { V4L2_STD_PAL_I, "PAL-I" },
75 { V4L2_STD_PAL_DK, "PAL-DK" },
76 { V4L2_STD_PAL_D, "PAL-D" },
77 { V4L2_STD_PAL_D1, "PAL-D1" },
78 { V4L2_STD_PAL_K, "PAL-K" },
79 { V4L2_STD_PAL_M, "PAL-M" },
80 { V4L2_STD_PAL_N, "PAL-N" },
81 { V4L2_STD_PAL_Nc, "PAL-Nc" },
82 { V4L2_STD_PAL_60, "PAL-60" },
83 { V4L2_STD_SECAM, "SECAM" },
84 { V4L2_STD_SECAM_B, "SECAM-B" },
85 { V4L2_STD_SECAM_G, "SECAM-G" },
86 { V4L2_STD_SECAM_H, "SECAM-H" },
87 { V4L2_STD_SECAM_DK, "SECAM-DK" },
88 { V4L2_STD_SECAM_D, "SECAM-D" },
89 { V4L2_STD_SECAM_K, "SECAM-K" },
90 { V4L2_STD_SECAM_K1, "SECAM-K1" },
91 { V4L2_STD_SECAM_L, "SECAM-L" },
92 { V4L2_STD_SECAM_LC, "SECAM-Lc" },
93 { 0, "Unknown" }
94};
95
96/* video4linux standard ID conversion to standard name
97 */
98const char *v4l2_norm_to_name(v4l2_std_id id)
99{
100 u32 myid = id;
101 int i;
102
103 /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
104 64 bit comparations. So, on that architecture, with some gcc
105 variants, compilation fails. Currently, the max value is 30bit wide.
106 */
107 BUG_ON(myid != id);
108
109 for (i = 0; standards[i].std; i++)
110 if (myid == standards[i].std)
111 break;
112 return standards[i].descr;
113}
114EXPORT_SYMBOL(v4l2_norm_to_name);
115
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300116/* Returns frame period for the given standard */
117void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
118{
119 if (id & V4L2_STD_525_60) {
120 frameperiod->numerator = 1001;
121 frameperiod->denominator = 30000;
122 } else {
123 frameperiod->numerator = 1;
124 frameperiod->denominator = 25;
125 }
126}
127EXPORT_SYMBOL(v4l2_video_std_frame_period);
128
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300129/* Fill in the fields of a v4l2_standard structure according to the
130 'id' and 'transmission' parameters. Returns negative on error. */
131int v4l2_video_std_construct(struct v4l2_standard *vs,
132 int id, const char *name)
133{
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300134 vs->id = id;
135 v4l2_video_std_frame_period(id, &vs->frameperiod);
136 vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300137 strlcpy(vs->name, name, sizeof(vs->name));
138 return 0;
139}
140EXPORT_SYMBOL(v4l2_video_std_construct);
141
142/* ----------------------------------------------------------------- */
143/* some arrays for pretty-printing debug messages of enum types */
144
145const char *v4l2_field_names[] = {
146 [V4L2_FIELD_ANY] = "any",
147 [V4L2_FIELD_NONE] = "none",
148 [V4L2_FIELD_TOP] = "top",
149 [V4L2_FIELD_BOTTOM] = "bottom",
150 [V4L2_FIELD_INTERLACED] = "interlaced",
151 [V4L2_FIELD_SEQ_TB] = "seq-tb",
152 [V4L2_FIELD_SEQ_BT] = "seq-bt",
153 [V4L2_FIELD_ALTERNATE] = "alternate",
154 [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
155 [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
156};
157EXPORT_SYMBOL(v4l2_field_names);
158
159const char *v4l2_type_names[] = {
160 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "vid-cap",
161 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "vid-overlay",
162 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "vid-out",
163 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
164 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
165 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
166 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
167 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
Pawel Osciakf8f39142010-07-29 14:44:25 -0300168 [V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
169 [V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300170};
171EXPORT_SYMBOL(v4l2_type_names);
172
173static const char *v4l2_memory_names[] = {
174 [V4L2_MEMORY_MMAP] = "mmap",
175 [V4L2_MEMORY_USERPTR] = "userptr",
176 [V4L2_MEMORY_OVERLAY] = "overlay",
177};
178
179#define prt_names(a, arr) ((((a) >= 0) && ((a) < ARRAY_SIZE(arr))) ? \
180 arr[a] : "unknown")
181
182/* ------------------------------------------------------------------ */
183/* debug help functions */
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300184static const char *v4l2_ioctls[] = {
185 [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
186 [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
187 [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
188 [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
189 [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
190 [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
191 [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
192 [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
193 [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
194 [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
195 [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
196 [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
197 [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
198 [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
199 [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
200 [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
201 [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
202 [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
203 [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
204 [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
205 [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
206 [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
207 [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
208 [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
209 [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
210 [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
211 [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
212 [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
213 [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
214 [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
215 [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
216 [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
217 [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
218 [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
219 [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
220 [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
221 [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
222 [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
223 [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
224 [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
225 [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
226 [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
227 [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
228 [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
229 [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
230 [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
231 [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
232 [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
233 [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
234 [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
235 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
236 [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
237 [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
238 [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
239 [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
240#if 1
241 [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
242 [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
243 [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
244 [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
245 [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
246
247 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
248 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
249
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300250 [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300251 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
252#endif
Muralidharan Karicherib6456c02009-11-19 12:00:31 -0300253 [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
254 [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
255 [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
256 [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
257 [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
258 [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
Sakari Ailusfda10212010-02-24 19:19:05 -0300259 [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
260 [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
261 [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300262};
263#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
264
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300265/* Common ioctl debug function. This function can be used by
266 external ioctl messages as well as internal V4L ioctl */
267void v4l_printk_ioctl(unsigned int cmd)
268{
269 char *dir, *type;
270
271 switch (_IOC_TYPE(cmd)) {
272 case 'd':
Hans Verkuil78a3b4d2009-04-01 03:41:09 -0300273 type = "v4l2_int";
274 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300275 case 'V':
276 if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
277 type = "v4l2";
278 break;
279 }
280 printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
281 return;
282 default:
283 type = "unknown";
284 }
285
286 switch (_IOC_DIR(cmd)) {
287 case _IOC_NONE: dir = "--"; break;
288 case _IOC_READ: dir = "r-"; break;
289 case _IOC_WRITE: dir = "-w"; break;
290 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
291 default: dir = "*ERR*"; break;
292 }
293 printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
294 type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
295}
296EXPORT_SYMBOL(v4l_printk_ioctl);
297
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300298static void dbgbuf(unsigned int cmd, struct video_device *vfd,
299 struct v4l2_buffer *p)
300{
301 struct v4l2_timecode *tc = &p->timecode;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300302 struct v4l2_plane *plane;
303 int i;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300304
305 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300306 "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300307 p->timestamp.tv_sec / 3600,
308 (int)(p->timestamp.tv_sec / 60) % 60,
309 (int)(p->timestamp.tv_sec % 60),
Alexander Beregalovb0459792008-09-03 16:47:38 -0300310 (long)p->timestamp.tv_usec,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300311 p->index,
312 prt_names(p->type, v4l2_type_names),
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300313 p->flags, p->field, p->sequence,
314 prt_names(p->memory, v4l2_memory_names));
315
316 if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
317 for (i = 0; i < p->length; ++i) {
318 plane = &p->m.planes[i];
319 dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x "
320 "offset/userptr=0x%08lx, length=%d\n",
321 i, plane->bytesused, plane->data_offset,
322 plane->m.userptr, plane->length);
323 }
324 } else {
325 dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n",
326 p->bytesused, p->m.userptr, p->length);
327 }
328
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300329 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
330 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
331 tc->hours, tc->minutes, tc->seconds,
332 tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
333}
334
335static inline void dbgrect(struct video_device *vfd, char *s,
336 struct v4l2_rect *r)
337{
338 dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
339 r->width, r->height);
340};
341
342static inline void v4l_print_pix_fmt(struct video_device *vfd,
343 struct v4l2_pix_format *fmt)
344{
345 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
346 "bytesperline=%d sizeimage=%d, colorspace=%d\n",
347 fmt->width, fmt->height,
348 (fmt->pixelformat & 0xff),
349 (fmt->pixelformat >> 8) & 0xff,
350 (fmt->pixelformat >> 16) & 0xff,
351 (fmt->pixelformat >> 24) & 0xff,
352 prt_names(fmt->field, v4l2_field_names),
353 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
354};
355
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300356static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd,
357 struct v4l2_pix_format_mplane *fmt)
358{
359 int i;
360
361 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
362 "colorspace=%d, num_planes=%d\n",
363 fmt->width, fmt->height,
364 (fmt->pixelformat & 0xff),
365 (fmt->pixelformat >> 8) & 0xff,
366 (fmt->pixelformat >> 16) & 0xff,
367 (fmt->pixelformat >> 24) & 0xff,
368 prt_names(fmt->field, v4l2_field_names),
369 fmt->colorspace, fmt->num_planes);
370
371 for (i = 0; i < fmt->num_planes; ++i)
372 dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i,
373 fmt->plane_fmt[i].bytesperline,
374 fmt->plane_fmt[i].sizeimage);
375}
376
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300377static inline void v4l_print_ext_ctrls(unsigned int cmd,
378 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
379{
380 __u32 i;
381
382 if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
383 return;
384 dbgarg(cmd, "");
385 printk(KERN_CONT "class=0x%x", c->ctrl_class);
386 for (i = 0; i < c->count; i++) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300387 if (show_vals && !c->controls[i].size)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300388 printk(KERN_CONT " id/val=0x%x/0x%x",
389 c->controls[i].id, c->controls[i].value);
390 else
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300391 printk(KERN_CONT " id=0x%x,size=%u",
392 c->controls[i].id, c->controls[i].size);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300393 }
394 printk(KERN_CONT "\n");
395};
396
397static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
398{
399 __u32 i;
400
401 /* zero the reserved fields */
402 c->reserved[0] = c->reserved[1] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300403 for (i = 0; i < c->count; i++)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300404 c->controls[i].reserved2[0] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300405
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300406 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
407 when using extended controls.
408 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
409 is it allowed for backwards compatibility.
410 */
411 if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
412 return 0;
413 /* Check that all controls are from the same control class. */
414 for (i = 0; i < c->count; i++) {
415 if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
416 c->error_idx = i;
417 return 0;
418 }
419 }
420 return 1;
421}
422
Hans Verkuila3998102008-07-21 02:57:38 -0300423static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300424{
Hans Verkuila3998102008-07-21 02:57:38 -0300425 if (ops == NULL)
426 return -EINVAL;
427
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300428 switch (type) {
429 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300430 if (ops->vidioc_g_fmt_vid_cap ||
431 ops->vidioc_g_fmt_vid_cap_mplane)
432 return 0;
433 break;
434 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
435 if (ops->vidioc_g_fmt_vid_cap_mplane)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300436 return 0;
437 break;
438 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300439 if (ops->vidioc_g_fmt_vid_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300440 return 0;
441 break;
442 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300443 if (ops->vidioc_g_fmt_vid_out ||
444 ops->vidioc_g_fmt_vid_out_mplane)
445 return 0;
446 break;
447 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
448 if (ops->vidioc_g_fmt_vid_out_mplane)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300449 return 0;
450 break;
451 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300452 if (ops->vidioc_g_fmt_vid_out_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300453 return 0;
454 break;
455 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300456 if (ops->vidioc_g_fmt_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300457 return 0;
458 break;
459 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300460 if (ops->vidioc_g_fmt_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300461 return 0;
462 break;
463 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300464 if (ops->vidioc_g_fmt_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300465 return 0;
466 break;
467 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300468 if (ops->vidioc_g_fmt_sliced_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300469 return 0;
470 break;
471 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho1175d612009-04-30 21:03:34 -0300472 if (ops->vidioc_g_fmt_type_private)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300473 return 0;
474 break;
475 }
476 return -EINVAL;
477}
478
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300479/**
480 * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
481 * equivalent
482 */
483static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
484 struct v4l2_format *f_mp)
485{
486 struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
487 const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
488
489 if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
490 f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
491 else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
492 f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
493 else
494 return -EINVAL;
495
496 pix_mp->width = pix->width;
497 pix_mp->height = pix->height;
498 pix_mp->pixelformat = pix->pixelformat;
499 pix_mp->field = pix->field;
500 pix_mp->colorspace = pix->colorspace;
501 pix_mp->num_planes = 1;
502 pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
503 pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
504
505 return 0;
506}
507
508/**
509 * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
510 * equivalent
511 */
512static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
513 struct v4l2_format *f_sp)
514{
515 const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
516 struct v4l2_pix_format *pix = &f_sp->fmt.pix;
517
518 if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
519 f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
520 else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
521 f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
522 else
523 return -EINVAL;
524
525 pix->width = pix_mp->width;
526 pix->height = pix_mp->height;
527 pix->pixelformat = pix_mp->pixelformat;
528 pix->field = pix_mp->field;
529 pix->colorspace = pix_mp->colorspace;
530 pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
531 pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
532
533 return 0;
534}
535
Hans Verkuil069b7472008-12-30 07:04:34 -0300536static long __video_do_ioctl(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300537 unsigned int cmd, void *arg)
538{
539 struct video_device *vfd = video_devdata(file);
Hans Verkuila3998102008-07-21 02:57:38 -0300540 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
Hans Verkuild5fbf322008-10-18 13:39:53 -0300541 void *fh = file->private_data;
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300542 struct v4l2_fh *vfh = NULL;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300543 struct v4l2_format f_copy;
Hans Verkuil069b7472008-12-30 07:04:34 -0300544 long ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300545
Hans Verkuil6a717882010-04-06 15:56:08 -0300546 if (ops == NULL) {
547 printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
548 vfd->name);
549 return -EINVAL;
550 }
551
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300552 if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
553 !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
554 v4l_print_ioctl(vfd->name, cmd);
555 printk(KERN_CONT "\n");
556 }
557
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300558 if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
559 vfh = file->private_data;
560
561 if (vfh && !ops->vidioc_s_priority) {
562 switch (cmd) {
563 case VIDIOC_S_CTRL:
564 case VIDIOC_S_STD:
565 case VIDIOC_S_INPUT:
566 case VIDIOC_S_OUTPUT:
567 case VIDIOC_S_TUNER:
568 case VIDIOC_S_FREQUENCY:
569 case VIDIOC_S_FMT:
570 case VIDIOC_S_CROP:
571 case VIDIOC_S_AUDIO:
572 case VIDIOC_S_AUDOUT:
573 case VIDIOC_S_EXT_CTRLS:
574 case VIDIOC_S_FBUF:
575 case VIDIOC_S_PRIORITY:
576 case VIDIOC_S_DV_PRESET:
577 case VIDIOC_S_DV_TIMINGS:
578 case VIDIOC_S_JPEGCOMP:
579 case VIDIOC_S_MODULATOR:
580 case VIDIOC_S_PARM:
581 case VIDIOC_S_HW_FREQ_SEEK:
582 case VIDIOC_ENCODER_CMD:
583 case VIDIOC_OVERLAY:
584 case VIDIOC_REQBUFS:
585 case VIDIOC_STREAMON:
586 case VIDIOC_STREAMOFF:
587 ret = v4l2_prio_check(vfd->prio, vfh->prio);
588 if (ret)
589 goto exit_prio;
590 ret = -EINVAL;
591 break;
592 }
593 }
594
Hans Verkuil6a717882010-04-06 15:56:08 -0300595 switch (cmd) {
Hans Verkuila3998102008-07-21 02:57:38 -0300596
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300597 /* --- capabilities ------------------------------------------ */
598 case VIDIOC_QUERYCAP:
599 {
600 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300601
Hans Verkuila3998102008-07-21 02:57:38 -0300602 if (!ops->vidioc_querycap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300603 break;
604
Hans Verkuila3998102008-07-21 02:57:38 -0300605 ret = ops->vidioc_querycap(file, fh, cap);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300606 if (!ret)
607 dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
608 "version=0x%08x, "
609 "capabilities=0x%08x\n",
610 cap->driver, cap->card, cap->bus_info,
611 cap->version,
612 cap->capabilities);
613 break;
614 }
615
616 /* --- priority ------------------------------------------ */
617 case VIDIOC_G_PRIORITY:
618 {
619 enum v4l2_priority *p = arg;
620
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300621 if (ops->vidioc_g_priority) {
622 ret = ops->vidioc_g_priority(file, fh, p);
623 } else if (vfh) {
624 *p = v4l2_prio_max(&vfd->v4l2_dev->prio);
625 ret = 0;
626 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300627 if (!ret)
628 dbgarg(cmd, "priority is %d\n", *p);
629 break;
630 }
631 case VIDIOC_S_PRIORITY:
632 {
633 enum v4l2_priority *p = arg;
634
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300635 if (!ops->vidioc_s_priority && vfh == NULL)
636 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300637 dbgarg(cmd, "setting priority to %d\n", *p);
Hans Verkuil99cd47bc2011-03-11 19:00:56 -0300638 if (ops->vidioc_s_priority)
639 ret = ops->vidioc_s_priority(file, fh, *p);
640 else
641 ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300642 break;
643 }
644
645 /* --- capture ioctls ---------------------------------------- */
646 case VIDIOC_ENUM_FMT:
647 {
648 struct v4l2_fmtdesc *f = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300649
Trent Piepho19c96e42009-03-04 01:21:02 -0300650 switch (f->type) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300651 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300652 if (ops->vidioc_enum_fmt_vid_cap)
653 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300654 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300655 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
656 if (ops->vidioc_enum_fmt_vid_cap_mplane)
657 ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
658 fh, f);
659 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300660 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300661 if (ops->vidioc_enum_fmt_vid_overlay)
662 ret = ops->vidioc_enum_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300663 fh, f);
664 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300665 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300666 if (ops->vidioc_enum_fmt_vid_out)
667 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300668 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300669 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
670 if (ops->vidioc_enum_fmt_vid_out_mplane)
671 ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
672 fh, f);
673 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300674 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300675 if (ops->vidioc_enum_fmt_type_private)
676 ret = ops->vidioc_enum_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300677 fh, f);
678 break;
679 default:
680 break;
681 }
682 if (!ret)
683 dbgarg(cmd, "index=%d, type=%d, flags=%d, "
684 "pixelformat=%c%c%c%c, description='%s'\n",
685 f->index, f->type, f->flags,
686 (f->pixelformat & 0xff),
687 (f->pixelformat >> 8) & 0xff,
688 (f->pixelformat >> 16) & 0xff,
689 (f->pixelformat >> 24) & 0xff,
690 f->description);
691 break;
692 }
693 case VIDIOC_G_FMT:
694 {
695 struct v4l2_format *f = (struct v4l2_format *)arg;
696
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300697 /* FIXME: Should be one dump per type */
698 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
699
700 switch (f->type) {
701 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300702 if (ops->vidioc_g_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300703 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300704 } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
705 if (fmt_sp_to_mp(f, &f_copy))
706 break;
707 ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
708 &f_copy);
709 if (ret)
710 break;
711
712 /* Driver is currently in multi-planar format,
713 * we can't return it in single-planar API*/
714 if (f_copy.fmt.pix_mp.num_planes > 1) {
715 ret = -EBUSY;
716 break;
717 }
718
719 ret = fmt_mp_to_sp(&f_copy, f);
720 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300721 if (!ret)
722 v4l_print_pix_fmt(vfd, &f->fmt.pix);
723 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300724 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
725 if (ops->vidioc_g_fmt_vid_cap_mplane) {
726 ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
727 fh, f);
728 } else if (ops->vidioc_g_fmt_vid_cap) {
729 if (fmt_mp_to_sp(f, &f_copy))
730 break;
731 ret = ops->vidioc_g_fmt_vid_cap(file,
732 fh, &f_copy);
733 if (ret)
734 break;
735
736 ret = fmt_sp_to_mp(&f_copy, f);
737 }
738 if (!ret)
739 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
740 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300741 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300742 if (ops->vidioc_g_fmt_vid_overlay)
743 ret = ops->vidioc_g_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300744 fh, f);
745 break;
746 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300747 if (ops->vidioc_g_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -0300748 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300749 } else if (ops->vidioc_g_fmt_vid_out_mplane) {
750 if (fmt_sp_to_mp(f, &f_copy))
751 break;
752 ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
753 &f_copy);
754 if (ret)
755 break;
756
757 /* Driver is currently in multi-planar format,
758 * we can't return it in single-planar API*/
759 if (f_copy.fmt.pix_mp.num_planes > 1) {
760 ret = -EBUSY;
761 break;
762 }
763
764 ret = fmt_mp_to_sp(&f_copy, f);
765 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300766 if (!ret)
767 v4l_print_pix_fmt(vfd, &f->fmt.pix);
768 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300769 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
770 if (ops->vidioc_g_fmt_vid_out_mplane) {
771 ret = ops->vidioc_g_fmt_vid_out_mplane(file,
772 fh, f);
773 } else if (ops->vidioc_g_fmt_vid_out) {
774 if (fmt_mp_to_sp(f, &f_copy))
775 break;
776 ret = ops->vidioc_g_fmt_vid_out(file,
777 fh, &f_copy);
778 if (ret)
779 break;
780
781 ret = fmt_sp_to_mp(&f_copy, f);
782 }
783 if (!ret)
784 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
785 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300786 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300787 if (ops->vidioc_g_fmt_vid_out_overlay)
788 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300789 fh, f);
790 break;
791 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300792 if (ops->vidioc_g_fmt_vbi_cap)
793 ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300794 break;
795 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300796 if (ops->vidioc_g_fmt_vbi_out)
797 ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300798 break;
799 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300800 if (ops->vidioc_g_fmt_sliced_vbi_cap)
801 ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300802 fh, f);
803 break;
804 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300805 if (ops->vidioc_g_fmt_sliced_vbi_out)
806 ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300807 fh, f);
808 break;
809 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300810 if (ops->vidioc_g_fmt_type_private)
811 ret = ops->vidioc_g_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300812 fh, f);
813 break;
814 }
815
816 break;
817 }
818 case VIDIOC_S_FMT:
819 {
820 struct v4l2_format *f = (struct v4l2_format *)arg;
821
822 /* FIXME: Should be one dump per type */
823 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
824
825 switch (f->type) {
826 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300827 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300828 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300829 if (ops->vidioc_s_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300830 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300831 } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
832 if (fmt_sp_to_mp(f, &f_copy))
833 break;
834 ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
835 &f_copy);
836 if (ret)
837 break;
838
839 if (f_copy.fmt.pix_mp.num_planes > 1) {
840 /* Drivers shouldn't adjust from 1-plane
841 * to more than 1-plane formats */
842 ret = -EBUSY;
843 WARN_ON(1);
844 break;
845 }
846
847 ret = fmt_mp_to_sp(&f_copy, f);
848 }
849 break;
850 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
851 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
852 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
853 if (ops->vidioc_s_fmt_vid_cap_mplane) {
854 ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
855 fh, f);
856 } else if (ops->vidioc_s_fmt_vid_cap &&
857 f->fmt.pix_mp.num_planes == 1) {
858 if (fmt_mp_to_sp(f, &f_copy))
859 break;
860 ret = ops->vidioc_s_fmt_vid_cap(file,
861 fh, &f_copy);
862 if (ret)
863 break;
864
865 ret = fmt_sp_to_mp(&f_copy, f);
866 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300867 break;
868 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300869 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300870 if (ops->vidioc_s_fmt_vid_overlay)
871 ret = ops->vidioc_s_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300872 fh, f);
873 break;
874 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300875 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300876 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300877 if (ops->vidioc_s_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -0300878 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300879 } else if (ops->vidioc_s_fmt_vid_out_mplane) {
880 if (fmt_sp_to_mp(f, &f_copy))
881 break;
882 ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
883 &f_copy);
884 if (ret)
885 break;
886
887 if (f_copy.fmt.pix_mp.num_planes > 1) {
888 /* Drivers shouldn't adjust from 1-plane
889 * to more than 1-plane formats */
890 ret = -EBUSY;
891 WARN_ON(1);
892 break;
893 }
894
895 ret = fmt_mp_to_sp(&f_copy, f);
896 }
897 break;
898 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
899 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
900 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
901 if (ops->vidioc_s_fmt_vid_out_mplane) {
902 ret = ops->vidioc_s_fmt_vid_out_mplane(file,
903 fh, f);
904 } else if (ops->vidioc_s_fmt_vid_out &&
905 f->fmt.pix_mp.num_planes == 1) {
906 if (fmt_mp_to_sp(f, &f_copy))
907 break;
908 ret = ops->vidioc_s_fmt_vid_out(file,
909 fh, &f_copy);
910 if (ret)
911 break;
912
913 ret = fmt_mp_to_sp(&f_copy, f);
914 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300915 break;
916 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300917 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300918 if (ops->vidioc_s_fmt_vid_out_overlay)
919 ret = ops->vidioc_s_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300920 fh, f);
921 break;
922 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300923 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300924 if (ops->vidioc_s_fmt_vbi_cap)
925 ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300926 break;
927 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300928 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300929 if (ops->vidioc_s_fmt_vbi_out)
930 ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300931 break;
932 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300933 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300934 if (ops->vidioc_s_fmt_sliced_vbi_cap)
935 ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300936 fh, f);
937 break;
938 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300939 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300940 if (ops->vidioc_s_fmt_sliced_vbi_out)
941 ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300942 fh, f);
943 break;
944 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300945 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -0300946 if (ops->vidioc_s_fmt_type_private)
947 ret = ops->vidioc_s_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300948 fh, f);
949 break;
950 }
951 break;
952 }
953 case VIDIOC_TRY_FMT:
954 {
955 struct v4l2_format *f = (struct v4l2_format *)arg;
956
957 /* FIXME: Should be one dump per type */
958 dbgarg(cmd, "type=%s\n", prt_names(f->type,
959 v4l2_type_names));
960 switch (f->type) {
961 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300962 CLEAR_AFTER_FIELD(f, fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300963 if (ops->vidioc_try_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300964 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300965 } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
966 if (fmt_sp_to_mp(f, &f_copy))
967 break;
968 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
969 fh, &f_copy);
970 if (ret)
971 break;
972
973 if (f_copy.fmt.pix_mp.num_planes > 1) {
974 /* Drivers shouldn't adjust from 1-plane
975 * to more than 1-plane formats */
976 ret = -EBUSY;
977 WARN_ON(1);
978 break;
979 }
980 ret = fmt_mp_to_sp(&f_copy, f);
981 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300982 if (!ret)
983 v4l_print_pix_fmt(vfd, &f->fmt.pix);
984 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300985 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
986 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
987 if (ops->vidioc_try_fmt_vid_cap_mplane) {
988 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
989 fh, f);
990 } else if (ops->vidioc_try_fmt_vid_cap &&
991 f->fmt.pix_mp.num_planes == 1) {
992 if (fmt_mp_to_sp(f, &f_copy))
993 break;
994 ret = ops->vidioc_try_fmt_vid_cap(file,
995 fh, &f_copy);
996 if (ret)
997 break;
998
999 ret = fmt_sp_to_mp(&f_copy, f);
1000 }
1001 if (!ret)
1002 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1003 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001004 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001005 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -03001006 if (ops->vidioc_try_fmt_vid_overlay)
1007 ret = ops->vidioc_try_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001008 fh, f);
1009 break;
1010 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001011 CLEAR_AFTER_FIELD(f, fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -03001012 if (ops->vidioc_try_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -03001013 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -03001014 } else if (ops->vidioc_try_fmt_vid_out_mplane) {
1015 if (fmt_sp_to_mp(f, &f_copy))
1016 break;
1017 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1018 fh, &f_copy);
1019 if (ret)
1020 break;
1021
1022 if (f_copy.fmt.pix_mp.num_planes > 1) {
1023 /* Drivers shouldn't adjust from 1-plane
1024 * to more than 1-plane formats */
1025 ret = -EBUSY;
1026 WARN_ON(1);
1027 break;
1028 }
1029 ret = fmt_mp_to_sp(&f_copy, f);
1030 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001031 if (!ret)
1032 v4l_print_pix_fmt(vfd, &f->fmt.pix);
1033 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03001034 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
1035 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
1036 if (ops->vidioc_try_fmt_vid_out_mplane) {
1037 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
1038 fh, f);
1039 } else if (ops->vidioc_try_fmt_vid_out &&
1040 f->fmt.pix_mp.num_planes == 1) {
1041 if (fmt_mp_to_sp(f, &f_copy))
1042 break;
1043 ret = ops->vidioc_try_fmt_vid_out(file,
1044 fh, &f_copy);
1045 if (ret)
1046 break;
1047
1048 ret = fmt_sp_to_mp(&f_copy, f);
1049 }
1050 if (!ret)
1051 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1052 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001053 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001054 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -03001055 if (ops->vidioc_try_fmt_vid_out_overlay)
1056 ret = ops->vidioc_try_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001057 fh, f);
1058 break;
1059 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001060 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -03001061 if (ops->vidioc_try_fmt_vbi_cap)
1062 ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001063 break;
1064 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001065 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -03001066 if (ops->vidioc_try_fmt_vbi_out)
1067 ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001068 break;
1069 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001070 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -03001071 if (ops->vidioc_try_fmt_sliced_vbi_cap)
1072 ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001073 fh, f);
1074 break;
1075 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001076 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -03001077 if (ops->vidioc_try_fmt_sliced_vbi_out)
1078 ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001079 fh, f);
1080 break;
1081 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001082 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -03001083 if (ops->vidioc_try_fmt_type_private)
1084 ret = ops->vidioc_try_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001085 fh, f);
1086 break;
1087 }
1088
1089 break;
1090 }
1091 /* FIXME: Those buf reqs could be handled here,
1092 with some changes on videobuf to allow its header to be included at
1093 videodev2.h or being merged at videodev2.
1094 */
1095 case VIDIOC_REQBUFS:
1096 {
1097 struct v4l2_requestbuffers *p = arg;
1098
Hans Verkuila3998102008-07-21 02:57:38 -03001099 if (!ops->vidioc_reqbufs)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001100 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001101 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001102 if (ret)
1103 break;
1104
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001105 if (p->type < V4L2_BUF_TYPE_PRIVATE)
1106 CLEAR_AFTER_FIELD(p, memory);
1107
Hans Verkuila3998102008-07-21 02:57:38 -03001108 ret = ops->vidioc_reqbufs(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001109 dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
1110 p->count,
1111 prt_names(p->type, v4l2_type_names),
1112 prt_names(p->memory, v4l2_memory_names));
1113 break;
1114 }
1115 case VIDIOC_QUERYBUF:
1116 {
1117 struct v4l2_buffer *p = arg;
1118
Hans Verkuila3998102008-07-21 02:57:38 -03001119 if (!ops->vidioc_querybuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001120 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001121 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001122 if (ret)
1123 break;
1124
Hans Verkuila3998102008-07-21 02:57:38 -03001125 ret = ops->vidioc_querybuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001126 if (!ret)
1127 dbgbuf(cmd, vfd, p);
1128 break;
1129 }
1130 case VIDIOC_QBUF:
1131 {
1132 struct v4l2_buffer *p = arg;
1133
Hans Verkuila3998102008-07-21 02:57:38 -03001134 if (!ops->vidioc_qbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001135 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001136 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001137 if (ret)
1138 break;
1139
Hans Verkuila3998102008-07-21 02:57:38 -03001140 ret = ops->vidioc_qbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001141 if (!ret)
1142 dbgbuf(cmd, vfd, p);
1143 break;
1144 }
1145 case VIDIOC_DQBUF:
1146 {
1147 struct v4l2_buffer *p = arg;
1148
Hans Verkuila3998102008-07-21 02:57:38 -03001149 if (!ops->vidioc_dqbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001150 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001151 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001152 if (ret)
1153 break;
1154
Hans Verkuila3998102008-07-21 02:57:38 -03001155 ret = ops->vidioc_dqbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001156 if (!ret)
1157 dbgbuf(cmd, vfd, p);
1158 break;
1159 }
1160 case VIDIOC_OVERLAY:
1161 {
1162 int *i = arg;
1163
Hans Verkuila3998102008-07-21 02:57:38 -03001164 if (!ops->vidioc_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001165 break;
1166 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001167 ret = ops->vidioc_overlay(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001168 break;
1169 }
1170 case VIDIOC_G_FBUF:
1171 {
1172 struct v4l2_framebuffer *p = arg;
1173
Hans Verkuila3998102008-07-21 02:57:38 -03001174 if (!ops->vidioc_g_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001175 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001176 ret = ops->vidioc_g_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001177 if (!ret) {
1178 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1179 p->capability, p->flags,
1180 (unsigned long)p->base);
1181 v4l_print_pix_fmt(vfd, &p->fmt);
1182 }
1183 break;
1184 }
1185 case VIDIOC_S_FBUF:
1186 {
1187 struct v4l2_framebuffer *p = arg;
1188
Hans Verkuila3998102008-07-21 02:57:38 -03001189 if (!ops->vidioc_s_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001190 break;
1191 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1192 p->capability, p->flags, (unsigned long)p->base);
1193 v4l_print_pix_fmt(vfd, &p->fmt);
Hans Verkuila3998102008-07-21 02:57:38 -03001194 ret = ops->vidioc_s_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001195 break;
1196 }
1197 case VIDIOC_STREAMON:
1198 {
1199 enum v4l2_buf_type i = *(int *)arg;
1200
Hans Verkuila3998102008-07-21 02:57:38 -03001201 if (!ops->vidioc_streamon)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001202 break;
1203 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001204 ret = ops->vidioc_streamon(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001205 break;
1206 }
1207 case VIDIOC_STREAMOFF:
1208 {
1209 enum v4l2_buf_type i = *(int *)arg;
1210
Hans Verkuila3998102008-07-21 02:57:38 -03001211 if (!ops->vidioc_streamoff)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001212 break;
1213 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001214 ret = ops->vidioc_streamoff(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001215 break;
1216 }
1217 /* ---------- tv norms ---------- */
1218 case VIDIOC_ENUMSTD:
1219 {
1220 struct v4l2_standard *p = arg;
1221 v4l2_std_id id = vfd->tvnorms, curr_id = 0;
1222 unsigned int index = p->index, i, j = 0;
1223 const char *descr = "";
1224
1225 /* Return norm array in a canonical way */
1226 for (i = 0; i <= index && id; i++) {
1227 /* last std value in the standards array is 0, so this
1228 while always ends there since (id & 0) == 0. */
1229 while ((id & standards[j].std) != standards[j].std)
1230 j++;
1231 curr_id = standards[j].std;
1232 descr = standards[j].descr;
1233 j++;
1234 if (curr_id == 0)
1235 break;
1236 if (curr_id != V4L2_STD_PAL &&
1237 curr_id != V4L2_STD_SECAM &&
1238 curr_id != V4L2_STD_NTSC)
1239 id &= ~curr_id;
1240 }
1241 if (i <= index)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001242 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001243
1244 v4l2_video_std_construct(p, curr_id, descr);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001245
1246 dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
1247 "framelines=%d\n", p->index,
1248 (unsigned long long)p->id, p->name,
1249 p->frameperiod.numerator,
1250 p->frameperiod.denominator,
1251 p->framelines);
1252
1253 ret = 0;
1254 break;
1255 }
1256 case VIDIOC_G_STD:
1257 {
1258 v4l2_std_id *id = arg;
1259
1260 ret = 0;
1261 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001262 if (ops->vidioc_g_std)
1263 ret = ops->vidioc_g_std(file, fh, id);
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001264 else if (vfd->current_norm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001265 *id = vfd->current_norm;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001266 else
1267 ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001268
1269 if (!ret)
1270 dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
1271 break;
1272 }
1273 case VIDIOC_S_STD:
1274 {
1275 v4l2_std_id *id = arg, norm;
1276
1277 dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
1278
1279 norm = (*id) & vfd->tvnorms;
1280 if (vfd->tvnorms && !norm) /* Check if std is supported */
1281 break;
1282
1283 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001284 if (ops->vidioc_s_std)
1285 ret = ops->vidioc_s_std(file, fh, &norm);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001286 else
1287 ret = -EINVAL;
1288
1289 /* Updates standard information */
1290 if (ret >= 0)
1291 vfd->current_norm = norm;
1292 break;
1293 }
1294 case VIDIOC_QUERYSTD:
1295 {
1296 v4l2_std_id *p = arg;
1297
Hans Verkuila3998102008-07-21 02:57:38 -03001298 if (!ops->vidioc_querystd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001299 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001300 ret = ops->vidioc_querystd(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001301 if (!ret)
1302 dbgarg(cmd, "detected std=%08Lx\n",
1303 (unsigned long long)*p);
1304 break;
1305 }
1306 /* ------ input switching ---------- */
1307 /* FIXME: Inputs can be handled inside videodev2 */
1308 case VIDIOC_ENUMINPUT:
1309 {
1310 struct v4l2_input *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001311
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001312 /*
1313 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1314 * CAP_STD here based on ioctl handler provided by the
1315 * driver. If the driver doesn't support these
1316 * for a specific input, it must override these flags.
1317 */
1318 if (ops->vidioc_s_std)
1319 p->capabilities |= V4L2_IN_CAP_STD;
1320 if (ops->vidioc_s_dv_preset)
1321 p->capabilities |= V4L2_IN_CAP_PRESETS;
1322 if (ops->vidioc_s_dv_timings)
1323 p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
1324
Hans Verkuila3998102008-07-21 02:57:38 -03001325 if (!ops->vidioc_enum_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001326 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001327
Hans Verkuila3998102008-07-21 02:57:38 -03001328 ret = ops->vidioc_enum_input(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001329 if (!ret)
1330 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1331 "audioset=%d, "
1332 "tuner=%d, std=%08Lx, status=%d\n",
1333 p->index, p->name, p->type, p->audioset,
1334 p->tuner,
1335 (unsigned long long)p->std,
1336 p->status);
1337 break;
1338 }
1339 case VIDIOC_G_INPUT:
1340 {
1341 unsigned int *i = arg;
1342
Hans Verkuila3998102008-07-21 02:57:38 -03001343 if (!ops->vidioc_g_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001344 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001345 ret = ops->vidioc_g_input(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001346 if (!ret)
1347 dbgarg(cmd, "value=%d\n", *i);
1348 break;
1349 }
1350 case VIDIOC_S_INPUT:
1351 {
1352 unsigned int *i = arg;
1353
Hans Verkuila3998102008-07-21 02:57:38 -03001354 if (!ops->vidioc_s_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001355 break;
1356 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001357 ret = ops->vidioc_s_input(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001358 break;
1359 }
1360
1361 /* ------ output switching ---------- */
1362 case VIDIOC_ENUMOUTPUT:
1363 {
1364 struct v4l2_output *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001365
Hans Verkuila3998102008-07-21 02:57:38 -03001366 if (!ops->vidioc_enum_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001367 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001368
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001369 /*
1370 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1371 * CAP_STD here based on ioctl handler provided by the
1372 * driver. If the driver doesn't support these
1373 * for a specific output, it must override these flags.
1374 */
1375 if (ops->vidioc_s_std)
1376 p->capabilities |= V4L2_OUT_CAP_STD;
1377 if (ops->vidioc_s_dv_preset)
1378 p->capabilities |= V4L2_OUT_CAP_PRESETS;
1379 if (ops->vidioc_s_dv_timings)
1380 p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
1381
Hans Verkuila3998102008-07-21 02:57:38 -03001382 ret = ops->vidioc_enum_output(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001383 if (!ret)
1384 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1385 "audioset=0x%x, "
1386 "modulator=%d, std=0x%08Lx\n",
1387 p->index, p->name, p->type, p->audioset,
1388 p->modulator, (unsigned long long)p->std);
1389 break;
1390 }
1391 case VIDIOC_G_OUTPUT:
1392 {
1393 unsigned int *i = arg;
1394
Hans Verkuila3998102008-07-21 02:57:38 -03001395 if (!ops->vidioc_g_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001396 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001397 ret = ops->vidioc_g_output(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001398 if (!ret)
1399 dbgarg(cmd, "value=%d\n", *i);
1400 break;
1401 }
1402 case VIDIOC_S_OUTPUT:
1403 {
1404 unsigned int *i = arg;
1405
Hans Verkuila3998102008-07-21 02:57:38 -03001406 if (!ops->vidioc_s_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001407 break;
1408 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001409 ret = ops->vidioc_s_output(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001410 break;
1411 }
1412
1413 /* --- controls ---------------------------------------------- */
1414 case VIDIOC_QUERYCTRL:
1415 {
1416 struct v4l2_queryctrl *p = arg;
1417
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001418 if (vfd->ctrl_handler)
1419 ret = v4l2_queryctrl(vfd->ctrl_handler, p);
1420 else if (ops->vidioc_queryctrl)
1421 ret = ops->vidioc_queryctrl(file, fh, p);
1422 else
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001423 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001424 if (!ret)
1425 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1426 "step=%d, default=%d, flags=0x%08x\n",
1427 p->id, p->type, p->name,
1428 p->minimum, p->maximum,
1429 p->step, p->default_value, p->flags);
1430 else
1431 dbgarg(cmd, "id=0x%x\n", p->id);
1432 break;
1433 }
1434 case VIDIOC_G_CTRL:
1435 {
1436 struct v4l2_control *p = arg;
1437
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001438 if (vfd->ctrl_handler)
1439 ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
1440 else if (ops->vidioc_g_ctrl)
Hans Verkuila3998102008-07-21 02:57:38 -03001441 ret = ops->vidioc_g_ctrl(file, fh, p);
1442 else if (ops->vidioc_g_ext_ctrls) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001443 struct v4l2_ext_controls ctrls;
1444 struct v4l2_ext_control ctrl;
1445
1446 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1447 ctrls.count = 1;
1448 ctrls.controls = &ctrl;
1449 ctrl.id = p->id;
1450 ctrl.value = p->value;
1451 if (check_ext_ctrls(&ctrls, 1)) {
Hans Verkuila3998102008-07-21 02:57:38 -03001452 ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001453 if (ret == 0)
1454 p->value = ctrl.value;
1455 }
1456 } else
1457 break;
1458 if (!ret)
1459 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1460 else
1461 dbgarg(cmd, "id=0x%x\n", p->id);
1462 break;
1463 }
1464 case VIDIOC_S_CTRL:
1465 {
1466 struct v4l2_control *p = arg;
1467 struct v4l2_ext_controls ctrls;
1468 struct v4l2_ext_control ctrl;
1469
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001470 if (!vfd->ctrl_handler &&
1471 !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001472 break;
1473
1474 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1475
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001476 if (vfd->ctrl_handler) {
1477 ret = v4l2_s_ctrl(vfd->ctrl_handler, p);
1478 break;
1479 }
Hans Verkuila3998102008-07-21 02:57:38 -03001480 if (ops->vidioc_s_ctrl) {
1481 ret = ops->vidioc_s_ctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001482 break;
1483 }
Hans Verkuila3998102008-07-21 02:57:38 -03001484 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001485 break;
1486
1487 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1488 ctrls.count = 1;
1489 ctrls.controls = &ctrl;
1490 ctrl.id = p->id;
1491 ctrl.value = p->value;
1492 if (check_ext_ctrls(&ctrls, 1))
Hans Verkuila3998102008-07-21 02:57:38 -03001493 ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001494 break;
1495 }
1496 case VIDIOC_G_EXT_CTRLS:
1497 {
1498 struct v4l2_ext_controls *p = arg;
1499
1500 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001501 if (vfd->ctrl_handler)
1502 ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
1503 else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001504 ret = ops->vidioc_g_ext_ctrls(file, fh, p);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001505 else
1506 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001507 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1508 break;
1509 }
1510 case VIDIOC_S_EXT_CTRLS:
1511 {
1512 struct v4l2_ext_controls *p = arg;
1513
1514 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001515 if (!vfd->ctrl_handler && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001516 break;
1517 v4l_print_ext_ctrls(cmd, vfd, p, 1);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001518 if (vfd->ctrl_handler)
1519 ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);
1520 else if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001521 ret = ops->vidioc_s_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001522 break;
1523 }
1524 case VIDIOC_TRY_EXT_CTRLS:
1525 {
1526 struct v4l2_ext_controls *p = arg;
1527
1528 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001529 if (!vfd->ctrl_handler && !ops->vidioc_try_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001530 break;
1531 v4l_print_ext_ctrls(cmd, vfd, p, 1);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001532 if (vfd->ctrl_handler)
1533 ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
1534 else if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001535 ret = ops->vidioc_try_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001536 break;
1537 }
1538 case VIDIOC_QUERYMENU:
1539 {
1540 struct v4l2_querymenu *p = arg;
1541
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001542 if (vfd->ctrl_handler)
1543 ret = v4l2_querymenu(vfd->ctrl_handler, p);
1544 else if (ops->vidioc_querymenu)
1545 ret = ops->vidioc_querymenu(file, fh, p);
1546 else
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001547 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001548 if (!ret)
1549 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1550 p->id, p->index, p->name);
1551 else
1552 dbgarg(cmd, "id=0x%x, index=%d\n",
1553 p->id, p->index);
1554 break;
1555 }
1556 /* --- audio ---------------------------------------------- */
1557 case VIDIOC_ENUMAUDIO:
1558 {
1559 struct v4l2_audio *p = arg;
1560
Hans Verkuila3998102008-07-21 02:57:38 -03001561 if (!ops->vidioc_enumaudio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001562 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001563 ret = ops->vidioc_enumaudio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001564 if (!ret)
1565 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1566 "mode=0x%x\n", p->index, p->name,
1567 p->capability, p->mode);
1568 else
1569 dbgarg(cmd, "index=%d\n", p->index);
1570 break;
1571 }
1572 case VIDIOC_G_AUDIO:
1573 {
1574 struct v4l2_audio *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001575
Hans Verkuila3998102008-07-21 02:57:38 -03001576 if (!ops->vidioc_g_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001577 break;
1578
Hans Verkuila3998102008-07-21 02:57:38 -03001579 ret = ops->vidioc_g_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001580 if (!ret)
1581 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1582 "mode=0x%x\n", p->index,
1583 p->name, p->capability, p->mode);
1584 else
1585 dbgarg(cmd, "index=%d\n", p->index);
1586 break;
1587 }
1588 case VIDIOC_S_AUDIO:
1589 {
1590 struct v4l2_audio *p = arg;
1591
Hans Verkuila3998102008-07-21 02:57:38 -03001592 if (!ops->vidioc_s_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001593 break;
1594 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1595 "mode=0x%x\n", p->index, p->name,
1596 p->capability, p->mode);
Hans Verkuila3998102008-07-21 02:57:38 -03001597 ret = ops->vidioc_s_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001598 break;
1599 }
1600 case VIDIOC_ENUMAUDOUT:
1601 {
1602 struct v4l2_audioout *p = arg;
1603
Hans Verkuila3998102008-07-21 02:57:38 -03001604 if (!ops->vidioc_enumaudout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001605 break;
1606 dbgarg(cmd, "Enum for index=%d\n", p->index);
Hans Verkuila3998102008-07-21 02:57:38 -03001607 ret = ops->vidioc_enumaudout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001608 if (!ret)
1609 dbgarg2("index=%d, name=%s, capability=%d, "
1610 "mode=%d\n", p->index, p->name,
1611 p->capability, p->mode);
1612 break;
1613 }
1614 case VIDIOC_G_AUDOUT:
1615 {
1616 struct v4l2_audioout *p = arg;
1617
Hans Verkuila3998102008-07-21 02:57:38 -03001618 if (!ops->vidioc_g_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001619 break;
Trent Piepho337f9d22009-03-04 01:21:02 -03001620
Hans Verkuila3998102008-07-21 02:57:38 -03001621 ret = ops->vidioc_g_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001622 if (!ret)
1623 dbgarg2("index=%d, name=%s, capability=%d, "
1624 "mode=%d\n", p->index, p->name,
1625 p->capability, p->mode);
1626 break;
1627 }
1628 case VIDIOC_S_AUDOUT:
1629 {
1630 struct v4l2_audioout *p = arg;
1631
Hans Verkuila3998102008-07-21 02:57:38 -03001632 if (!ops->vidioc_s_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001633 break;
1634 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1635 "mode=%d\n", p->index, p->name,
1636 p->capability, p->mode);
1637
Hans Verkuila3998102008-07-21 02:57:38 -03001638 ret = ops->vidioc_s_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001639 break;
1640 }
1641 case VIDIOC_G_MODULATOR:
1642 {
1643 struct v4l2_modulator *p = arg;
1644
Hans Verkuila3998102008-07-21 02:57:38 -03001645 if (!ops->vidioc_g_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001646 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001647 ret = ops->vidioc_g_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001648 if (!ret)
1649 dbgarg(cmd, "index=%d, name=%s, "
1650 "capability=%d, rangelow=%d,"
1651 " rangehigh=%d, txsubchans=%d\n",
1652 p->index, p->name, p->capability,
1653 p->rangelow, p->rangehigh,
1654 p->txsubchans);
1655 break;
1656 }
1657 case VIDIOC_S_MODULATOR:
1658 {
1659 struct v4l2_modulator *p = arg;
1660
Hans Verkuila3998102008-07-21 02:57:38 -03001661 if (!ops->vidioc_s_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001662 break;
1663 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1664 "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1665 p->index, p->name, p->capability, p->rangelow,
1666 p->rangehigh, p->txsubchans);
Hans Verkuila3998102008-07-21 02:57:38 -03001667 ret = ops->vidioc_s_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001668 break;
1669 }
1670 case VIDIOC_G_CROP:
1671 {
1672 struct v4l2_crop *p = arg;
1673
Hans Verkuila3998102008-07-21 02:57:38 -03001674 if (!ops->vidioc_g_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001675 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001676
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001677 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001678 ret = ops->vidioc_g_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001679 if (!ret)
1680 dbgrect(vfd, "", &p->c);
1681 break;
1682 }
1683 case VIDIOC_S_CROP:
1684 {
1685 struct v4l2_crop *p = arg;
1686
Hans Verkuila3998102008-07-21 02:57:38 -03001687 if (!ops->vidioc_s_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001688 break;
1689 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1690 dbgrect(vfd, "", &p->c);
Hans Verkuila3998102008-07-21 02:57:38 -03001691 ret = ops->vidioc_s_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001692 break;
1693 }
1694 case VIDIOC_CROPCAP:
1695 {
1696 struct v4l2_cropcap *p = arg;
1697
1698 /*FIXME: Should also show v4l2_fract pixelaspect */
Hans Verkuila3998102008-07-21 02:57:38 -03001699 if (!ops->vidioc_cropcap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001700 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001701
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001702 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001703 ret = ops->vidioc_cropcap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001704 if (!ret) {
1705 dbgrect(vfd, "bounds ", &p->bounds);
1706 dbgrect(vfd, "defrect ", &p->defrect);
1707 }
1708 break;
1709 }
1710 case VIDIOC_G_JPEGCOMP:
1711 {
1712 struct v4l2_jpegcompression *p = arg;
1713
Hans Verkuila3998102008-07-21 02:57:38 -03001714 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001715 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001716
Hans Verkuila3998102008-07-21 02:57:38 -03001717 ret = ops->vidioc_g_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001718 if (!ret)
1719 dbgarg(cmd, "quality=%d, APPn=%d, "
1720 "APP_len=%d, COM_len=%d, "
1721 "jpeg_markers=%d\n",
1722 p->quality, p->APPn, p->APP_len,
1723 p->COM_len, p->jpeg_markers);
1724 break;
1725 }
1726 case VIDIOC_S_JPEGCOMP:
1727 {
1728 struct v4l2_jpegcompression *p = arg;
1729
Hans Verkuila3998102008-07-21 02:57:38 -03001730 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001731 break;
1732 dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
1733 "COM_len=%d, jpeg_markers=%d\n",
1734 p->quality, p->APPn, p->APP_len,
1735 p->COM_len, p->jpeg_markers);
Hans Verkuila3998102008-07-21 02:57:38 -03001736 ret = ops->vidioc_s_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001737 break;
1738 }
1739 case VIDIOC_G_ENC_INDEX:
1740 {
1741 struct v4l2_enc_idx *p = arg;
1742
Hans Verkuila3998102008-07-21 02:57:38 -03001743 if (!ops->vidioc_g_enc_index)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001744 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001745 ret = ops->vidioc_g_enc_index(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001746 if (!ret)
1747 dbgarg(cmd, "entries=%d, entries_cap=%d\n",
1748 p->entries, p->entries_cap);
1749 break;
1750 }
1751 case VIDIOC_ENCODER_CMD:
1752 {
1753 struct v4l2_encoder_cmd *p = arg;
1754
Hans Verkuila3998102008-07-21 02:57:38 -03001755 if (!ops->vidioc_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001756 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001757 ret = ops->vidioc_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001758 if (!ret)
1759 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1760 break;
1761 }
1762 case VIDIOC_TRY_ENCODER_CMD:
1763 {
1764 struct v4l2_encoder_cmd *p = arg;
1765
Hans Verkuila3998102008-07-21 02:57:38 -03001766 if (!ops->vidioc_try_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001767 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001768 ret = ops->vidioc_try_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001769 if (!ret)
1770 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1771 break;
1772 }
1773 case VIDIOC_G_PARM:
1774 {
1775 struct v4l2_streamparm *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001776
Hans Verkuila3998102008-07-21 02:57:38 -03001777 if (ops->vidioc_g_parm) {
Trent Piepho34796bc2009-03-28 22:25:35 -03001778 ret = check_fmt(ops, p->type);
1779 if (ret)
1780 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001781 ret = ops->vidioc_g_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001782 } else {
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001783 v4l2_std_id std = vfd->current_norm;
1784
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001785 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001786 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001787
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001788 ret = 0;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001789 if (ops->vidioc_g_std)
1790 ret = ops->vidioc_g_std(file, fh, &std);
1791 else if (std == 0)
1792 ret = -EINVAL;
1793 if (ret == 0)
1794 v4l2_video_std_frame_period(std,
1795 &p->parm.capture.timeperframe);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001796 }
1797
1798 dbgarg(cmd, "type=%d\n", p->type);
1799 break;
1800 }
1801 case VIDIOC_S_PARM:
1802 {
1803 struct v4l2_streamparm *p = arg;
1804
Hans Verkuila3998102008-07-21 02:57:38 -03001805 if (!ops->vidioc_s_parm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001806 break;
Trent Piepho34796bc2009-03-28 22:25:35 -03001807 ret = check_fmt(ops, p->type);
1808 if (ret)
1809 break;
1810
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001811 dbgarg(cmd, "type=%d\n", p->type);
Hans Verkuila3998102008-07-21 02:57:38 -03001812 ret = ops->vidioc_s_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001813 break;
1814 }
1815 case VIDIOC_G_TUNER:
1816 {
1817 struct v4l2_tuner *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001818
Hans Verkuila3998102008-07-21 02:57:38 -03001819 if (!ops->vidioc_g_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001820 break;
1821
Hans Verkuila3998102008-07-21 02:57:38 -03001822 ret = ops->vidioc_g_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001823 if (!ret)
1824 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1825 "capability=0x%x, rangelow=%d, "
1826 "rangehigh=%d, signal=%d, afc=%d, "
1827 "rxsubchans=0x%x, audmode=%d\n",
1828 p->index, p->name, p->type,
1829 p->capability, p->rangelow,
1830 p->rangehigh, p->signal, p->afc,
1831 p->rxsubchans, p->audmode);
1832 break;
1833 }
1834 case VIDIOC_S_TUNER:
1835 {
1836 struct v4l2_tuner *p = arg;
1837
Hans Verkuila3998102008-07-21 02:57:38 -03001838 if (!ops->vidioc_s_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001839 break;
1840 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1841 "capability=0x%x, rangelow=%d, "
1842 "rangehigh=%d, signal=%d, afc=%d, "
1843 "rxsubchans=0x%x, audmode=%d\n",
1844 p->index, p->name, p->type,
1845 p->capability, p->rangelow,
1846 p->rangehigh, p->signal, p->afc,
1847 p->rxsubchans, p->audmode);
Hans Verkuila3998102008-07-21 02:57:38 -03001848 ret = ops->vidioc_s_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001849 break;
1850 }
1851 case VIDIOC_G_FREQUENCY:
1852 {
1853 struct v4l2_frequency *p = arg;
1854
Hans Verkuila3998102008-07-21 02:57:38 -03001855 if (!ops->vidioc_g_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001856 break;
1857
Hans Verkuila3998102008-07-21 02:57:38 -03001858 ret = ops->vidioc_g_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001859 if (!ret)
1860 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1861 p->tuner, p->type, p->frequency);
1862 break;
1863 }
1864 case VIDIOC_S_FREQUENCY:
1865 {
1866 struct v4l2_frequency *p = arg;
1867
Hans Verkuila3998102008-07-21 02:57:38 -03001868 if (!ops->vidioc_s_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001869 break;
1870 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1871 p->tuner, p->type, p->frequency);
Hans Verkuila3998102008-07-21 02:57:38 -03001872 ret = ops->vidioc_s_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001873 break;
1874 }
1875 case VIDIOC_G_SLICED_VBI_CAP:
1876 {
1877 struct v4l2_sliced_vbi_cap *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001878
Hans Verkuila3998102008-07-21 02:57:38 -03001879 if (!ops->vidioc_g_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001880 break;
Trent Piepho19c96e42009-03-04 01:21:02 -03001881
1882 /* Clear up to type, everything after type is zerod already */
1883 memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
1884
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001885 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001886 ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001887 if (!ret)
1888 dbgarg2("service_set=%d\n", p->service_set);
1889 break;
1890 }
1891 case VIDIOC_LOG_STATUS:
1892 {
Hans Verkuila3998102008-07-21 02:57:38 -03001893 if (!ops->vidioc_log_status)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001894 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001895 ret = ops->vidioc_log_status(file, fh);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001896 break;
1897 }
1898#ifdef CONFIG_VIDEO_ADV_DEBUG
1899 case VIDIOC_DBG_G_REGISTER:
1900 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001901 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001902
Hans Verkuila1198cc2011-01-08 09:53:32 -03001903 if (ops->vidioc_g_register) {
1904 if (!capable(CAP_SYS_ADMIN))
1905 ret = -EPERM;
1906 else
1907 ret = ops->vidioc_g_register(file, fh, p);
1908 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001909 break;
1910 }
1911 case VIDIOC_DBG_S_REGISTER:
1912 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001913 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001914
Hans Verkuila1198cc2011-01-08 09:53:32 -03001915 if (ops->vidioc_s_register) {
1916 if (!capable(CAP_SYS_ADMIN))
1917 ret = -EPERM;
1918 else
1919 ret = ops->vidioc_s_register(file, fh, p);
1920 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001921 break;
1922 }
1923#endif
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001924 case VIDIOC_DBG_G_CHIP_IDENT:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001925 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001926 struct v4l2_dbg_chip_ident *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001927
Hans Verkuila3998102008-07-21 02:57:38 -03001928 if (!ops->vidioc_g_chip_ident)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001929 break;
Hans Verkuil80b36e02009-02-07 11:00:02 -03001930 p->ident = V4L2_IDENT_NONE;
1931 p->revision = 0;
Hans Verkuila3998102008-07-21 02:57:38 -03001932 ret = ops->vidioc_g_chip_ident(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001933 if (!ret)
1934 dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
1935 break;
1936 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001937 case VIDIOC_S_HW_FREQ_SEEK:
1938 {
1939 struct v4l2_hw_freq_seek *p = arg;
1940
Hans Verkuila3998102008-07-21 02:57:38 -03001941 if (!ops->vidioc_s_hw_freq_seek)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001942 break;
1943 dbgarg(cmd,
1944 "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
1945 p->tuner, p->type, p->seek_upward, p->wrap_around);
Hans Verkuila3998102008-07-21 02:57:38 -03001946 ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
1947 break;
1948 }
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001949 case VIDIOC_ENUM_FRAMESIZES:
1950 {
1951 struct v4l2_frmsizeenum *p = arg;
1952
1953 if (!ops->vidioc_enum_framesizes)
1954 break;
1955
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001956 ret = ops->vidioc_enum_framesizes(file, fh, p);
1957 dbgarg(cmd,
Mauro Carvalho Chehabd1afe422009-06-21 22:37:12 -03001958 "index=%d, pixelformat=%c%c%c%c, type=%d ",
1959 p->index,
1960 (p->pixel_format & 0xff),
1961 (p->pixel_format >> 8) & 0xff,
1962 (p->pixel_format >> 16) & 0xff,
1963 (p->pixel_format >> 24) & 0xff,
1964 p->type);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001965 switch (p->type) {
1966 case V4L2_FRMSIZE_TYPE_DISCRETE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001967 dbgarg3("width = %d, height=%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001968 p->discrete.width, p->discrete.height);
1969 break;
1970 case V4L2_FRMSIZE_TYPE_STEPWISE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001971 dbgarg3("min %dx%d, max %dx%d, step %dx%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001972 p->stepwise.min_width, p->stepwise.min_height,
1973 p->stepwise.step_width, p->stepwise.step_height,
1974 p->stepwise.max_width, p->stepwise.max_height);
1975 break;
1976 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001977 dbgarg3("continuous\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001978 break;
1979 default:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001980 dbgarg3("- Unknown type!\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001981 }
1982
1983 break;
1984 }
1985 case VIDIOC_ENUM_FRAMEINTERVALS:
1986 {
1987 struct v4l2_frmivalenum *p = arg;
1988
1989 if (!ops->vidioc_enum_frameintervals)
1990 break;
1991
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001992 ret = ops->vidioc_enum_frameintervals(file, fh, p);
1993 dbgarg(cmd,
1994 "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
1995 p->index, p->pixel_format,
1996 p->width, p->height, p->type);
1997 switch (p->type) {
1998 case V4L2_FRMIVAL_TYPE_DISCRETE:
1999 dbgarg2("fps=%d/%d\n",
2000 p->discrete.numerator,
2001 p->discrete.denominator);
2002 break;
2003 case V4L2_FRMIVAL_TYPE_STEPWISE:
Mauro Carvalho Chehab19585782008-11-12 01:03:02 -03002004 dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",
2005 p->stepwise.min.numerator,
2006 p->stepwise.min.denominator,
2007 p->stepwise.max.numerator,
2008 p->stepwise.max.denominator,
2009 p->stepwise.step.numerator,
2010 p->stepwise.step.denominator);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03002011 break;
2012 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
2013 dbgarg2("continuous\n");
2014 break;
2015 default:
2016 dbgarg2("- Unknown type!\n");
2017 }
2018 break;
2019 }
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03002020 case VIDIOC_ENUM_DV_PRESETS:
2021 {
2022 struct v4l2_dv_enum_preset *p = arg;
2023
2024 if (!ops->vidioc_enum_dv_presets)
2025 break;
2026
2027 ret = ops->vidioc_enum_dv_presets(file, fh, p);
2028 if (!ret)
2029 dbgarg(cmd,
2030 "index=%d, preset=%d, name=%s, width=%d,"
2031 " height=%d ",
2032 p->index, p->preset, p->name, p->width,
2033 p->height);
2034 break;
2035 }
2036 case VIDIOC_S_DV_PRESET:
2037 {
2038 struct v4l2_dv_preset *p = arg;
2039
2040 if (!ops->vidioc_s_dv_preset)
2041 break;
2042
2043 dbgarg(cmd, "preset=%d\n", p->preset);
2044 ret = ops->vidioc_s_dv_preset(file, fh, p);
2045 break;
2046 }
2047 case VIDIOC_G_DV_PRESET:
2048 {
2049 struct v4l2_dv_preset *p = arg;
2050
2051 if (!ops->vidioc_g_dv_preset)
2052 break;
2053
2054 ret = ops->vidioc_g_dv_preset(file, fh, p);
2055 if (!ret)
2056 dbgarg(cmd, "preset=%d\n", p->preset);
2057 break;
2058 }
2059 case VIDIOC_QUERY_DV_PRESET:
2060 {
2061 struct v4l2_dv_preset *p = arg;
2062
2063 if (!ops->vidioc_query_dv_preset)
2064 break;
2065
2066 ret = ops->vidioc_query_dv_preset(file, fh, p);
2067 if (!ret)
2068 dbgarg(cmd, "preset=%d\n", p->preset);
2069 break;
2070 }
2071 case VIDIOC_S_DV_TIMINGS:
2072 {
2073 struct v4l2_dv_timings *p = arg;
2074
2075 if (!ops->vidioc_s_dv_timings)
2076 break;
2077
2078 switch (p->type) {
2079 case V4L2_DV_BT_656_1120:
2080 dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
2081 " width=%d, height=%d, polarities=%x,"
2082 " hfrontporch=%d, hsync=%d, hbackporch=%d,"
2083 " vfrontporch=%d, vsync=%d, vbackporch=%d,"
2084 " il_vfrontporch=%d, il_vsync=%d,"
2085 " il_vbackporch=%d\n",
2086 p->bt.interlaced, p->bt.pixelclock,
2087 p->bt.width, p->bt.height, p->bt.polarities,
2088 p->bt.hfrontporch, p->bt.hsync,
2089 p->bt.hbackporch, p->bt.vfrontporch,
2090 p->bt.vsync, p->bt.vbackporch,
2091 p->bt.il_vfrontporch, p->bt.il_vsync,
2092 p->bt.il_vbackporch);
2093 ret = ops->vidioc_s_dv_timings(file, fh, p);
2094 break;
2095 default:
2096 dbgarg2("Unknown type %d!\n", p->type);
2097 break;
2098 }
2099 break;
2100 }
2101 case VIDIOC_G_DV_TIMINGS:
2102 {
2103 struct v4l2_dv_timings *p = arg;
2104
2105 if (!ops->vidioc_g_dv_timings)
2106 break;
2107
2108 ret = ops->vidioc_g_dv_timings(file, fh, p);
2109 if (!ret) {
2110 switch (p->type) {
2111 case V4L2_DV_BT_656_1120:
2112 dbgarg2("bt-656/1120:interlaced=%d,"
2113 " pixelclock=%lld,"
2114 " width=%d, height=%d, polarities=%x,"
2115 " hfrontporch=%d, hsync=%d,"
2116 " hbackporch=%d, vfrontporch=%d,"
2117 " vsync=%d, vbackporch=%d,"
2118 " il_vfrontporch=%d, il_vsync=%d,"
2119 " il_vbackporch=%d\n",
2120 p->bt.interlaced, p->bt.pixelclock,
2121 p->bt.width, p->bt.height,
2122 p->bt.polarities, p->bt.hfrontporch,
2123 p->bt.hsync, p->bt.hbackporch,
2124 p->bt.vfrontporch, p->bt.vsync,
2125 p->bt.vbackporch, p->bt.il_vfrontporch,
2126 p->bt.il_vsync, p->bt.il_vbackporch);
2127 break;
2128 default:
2129 dbgarg2("Unknown type %d!\n", p->type);
2130 break;
2131 }
2132 }
2133 break;
2134 }
Sakari Ailusd3d7c962010-03-27 11:02:10 -03002135 case VIDIOC_DQEVENT:
2136 {
2137 struct v4l2_event *ev = arg;
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03002138
Sakari Ailusd3d7c962010-03-27 11:02:10 -03002139 if (!ops->vidioc_subscribe_event)
2140 break;
2141
2142 ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);
2143 if (ret < 0) {
2144 dbgarg(cmd, "no pending events?");
2145 break;
2146 }
2147 dbgarg(cmd,
2148 "pending=%d, type=0x%8.8x, sequence=%d, "
2149 "timestamp=%lu.%9.9lu ",
2150 ev->pending, ev->type, ev->sequence,
2151 ev->timestamp.tv_sec, ev->timestamp.tv_nsec);
2152 break;
2153 }
2154 case VIDIOC_SUBSCRIBE_EVENT:
2155 {
2156 struct v4l2_event_subscription *sub = arg;
2157
2158 if (!ops->vidioc_subscribe_event)
2159 break;
2160
2161 ret = ops->vidioc_subscribe_event(fh, sub);
2162 if (ret < 0) {
2163 dbgarg(cmd, "failed, ret=%ld", ret);
2164 break;
2165 }
2166 dbgarg(cmd, "type=0x%8.8x", sub->type);
2167 break;
2168 }
2169 case VIDIOC_UNSUBSCRIBE_EVENT:
2170 {
2171 struct v4l2_event_subscription *sub = arg;
2172
2173 if (!ops->vidioc_unsubscribe_event)
2174 break;
2175
2176 ret = ops->vidioc_unsubscribe_event(fh, sub);
2177 if (ret < 0) {
2178 dbgarg(cmd, "failed, ret=%ld", ret);
2179 break;
2180 }
2181 dbgarg(cmd, "type=0x%8.8x", sub->type);
2182 break;
2183 }
Hans Verkuila3998102008-07-21 02:57:38 -03002184 default:
2185 {
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03002186 bool valid_prio = true;
2187
Hans Verkuila3998102008-07-21 02:57:38 -03002188 if (!ops->vidioc_default)
2189 break;
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03002190 if (vfh && !ops->vidioc_s_priority)
2191 valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
2192 ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002193 break;
2194 }
2195 } /* switch */
2196
Hans Verkuil99cd47bc2011-03-11 19:00:56 -03002197exit_prio:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002198 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
2199 if (ret < 0) {
2200 v4l_print_ioctl(vfd->name, cmd);
Hans Verkuil069b7472008-12-30 07:04:34 -03002201 printk(KERN_CONT " error %ld\n", ret);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002202 }
2203 }
2204
2205 return ret;
2206}
2207
Trent Piepho19c96e42009-03-04 01:21:02 -03002208/* In some cases, only a few fields are used as input, i.e. when the app sets
2209 * "index" and then the driver fills in the rest of the structure for the thing
2210 * with that index. We only need to copy up the first non-input field. */
2211static unsigned long cmd_input_size(unsigned int cmd)
2212{
2213 /* Size of structure up to and including 'field' */
Hans Verkuil9f1a6932009-03-08 10:35:23 -03002214#define CMDINSIZE(cmd, type, field) \
2215 case VIDIOC_##cmd: \
2216 return offsetof(struct v4l2_##type, field) + \
2217 sizeof(((struct v4l2_##type *)0)->field);
Trent Piepho19c96e42009-03-04 01:21:02 -03002218
Hans Verkuil9f1a6932009-03-08 10:35:23 -03002219 switch (cmd) {
Trent Piepho19c96e42009-03-04 01:21:02 -03002220 CMDINSIZE(ENUM_FMT, fmtdesc, type);
2221 CMDINSIZE(G_FMT, format, type);
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002222 CMDINSIZE(QUERYBUF, buffer, length);
Trent Piepho19c96e42009-03-04 01:21:02 -03002223 CMDINSIZE(G_PARM, streamparm, type);
2224 CMDINSIZE(ENUMSTD, standard, index);
2225 CMDINSIZE(ENUMINPUT, input, index);
2226 CMDINSIZE(G_CTRL, control, id);
2227 CMDINSIZE(G_TUNER, tuner, index);
2228 CMDINSIZE(QUERYCTRL, queryctrl, id);
2229 CMDINSIZE(QUERYMENU, querymenu, index);
2230 CMDINSIZE(ENUMOUTPUT, output, index);
2231 CMDINSIZE(G_MODULATOR, modulator, index);
2232 CMDINSIZE(G_FREQUENCY, frequency, tuner);
2233 CMDINSIZE(CROPCAP, cropcap, type);
2234 CMDINSIZE(G_CROP, crop, type);
2235 CMDINSIZE(ENUMAUDIO, audio, index);
2236 CMDINSIZE(ENUMAUDOUT, audioout, index);
2237 CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
2238 CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
2239 CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
2240 CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
2241 CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
2242 default:
2243 return _IOC_SIZE(cmd);
2244 }
2245}
2246
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002247static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
2248 void * __user *user_ptr, void ***kernel_ptr)
2249{
2250 int ret = 0;
2251
2252 switch (cmd) {
2253 case VIDIOC_QUERYBUF:
2254 case VIDIOC_QBUF:
2255 case VIDIOC_DQBUF: {
2256 struct v4l2_buffer *buf = parg;
2257
2258 if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
2259 if (buf->length > VIDEO_MAX_PLANES) {
2260 ret = -EINVAL;
2261 break;
2262 }
2263 *user_ptr = (void __user *)buf->m.planes;
2264 *kernel_ptr = (void **)&buf->m.planes;
2265 *array_size = sizeof(struct v4l2_plane) * buf->length;
2266 ret = 1;
2267 }
2268 break;
2269 }
2270
2271 case VIDIOC_S_EXT_CTRLS:
2272 case VIDIOC_G_EXT_CTRLS:
2273 case VIDIOC_TRY_EXT_CTRLS: {
2274 struct v4l2_ext_controls *ctrls = parg;
2275
2276 if (ctrls->count != 0) {
2277 *user_ptr = (void __user *)ctrls->controls;
2278 *kernel_ptr = (void **)&ctrls->controls;
2279 *array_size = sizeof(struct v4l2_ext_control)
2280 * ctrls->count;
2281 ret = 1;
2282 }
2283 break;
2284 }
2285 }
2286
2287 return ret;
2288}
2289
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002290long
2291video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
2292 v4l2_kioctl func)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002293{
2294 char sbuf[128];
2295 void *mbuf = NULL;
Hans Verkuil1d94aa32010-04-06 08:12:21 -03002296 void *parg = (void *)arg;
Hans Verkuil069b7472008-12-30 07:04:34 -03002297 long err = -EINVAL;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002298 bool has_array_args;
2299 size_t array_size = 0;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002300 void __user *user_ptr = NULL;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002301 void **kernel_ptr = NULL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002302
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002303 /* Copy arguments into temp kernel buffer */
Trent Piepho337f9d22009-03-04 01:21:02 -03002304 if (_IOC_DIR(cmd) != _IOC_NONE) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002305 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
2306 parg = sbuf;
2307 } else {
2308 /* too big to allocate from stack */
2309 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
2310 if (NULL == mbuf)
2311 return -ENOMEM;
2312 parg = mbuf;
2313 }
2314
2315 err = -EFAULT;
Trent Piepho19c96e42009-03-04 01:21:02 -03002316 if (_IOC_DIR(cmd) & _IOC_WRITE) {
2317 unsigned long n = cmd_input_size(cmd);
2318
2319 if (copy_from_user(parg, (void __user *)arg, n))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002320 goto out;
Trent Piepho19c96e42009-03-04 01:21:02 -03002321
2322 /* zero out anything we don't copy from userspace */
2323 if (n < _IOC_SIZE(cmd))
2324 memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
Trent Piepho337f9d22009-03-04 01:21:02 -03002325 } else {
2326 /* read-only ioctl */
2327 memset(parg, 0, _IOC_SIZE(cmd));
Trent Piepho19c96e42009-03-04 01:21:02 -03002328 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002329 }
2330
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002331 err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
2332 if (err < 0)
2333 goto out;
2334 has_array_args = err;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002335
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002336 if (has_array_args) {
2337 /*
2338 * When adding new types of array args, make sure that the
2339 * parent argument to ioctl (which contains the pointer to the
2340 * array) fits into sbuf (so that mbuf will still remain
2341 * unused up to here).
2342 */
2343 mbuf = kmalloc(array_size, GFP_KERNEL);
2344 err = -ENOMEM;
2345 if (NULL == mbuf)
2346 goto out_array_args;
2347 err = -EFAULT;
2348 if (copy_from_user(mbuf, user_ptr, array_size))
2349 goto out_array_args;
2350 *kernel_ptr = mbuf;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002351 }
2352
2353 /* Handles IOCTL */
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002354 err = func(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002355 if (err == -ENOIOCTLCMD)
2356 err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002357
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002358 if (has_array_args) {
2359 *kernel_ptr = user_ptr;
2360 if (copy_to_user(user_ptr, mbuf, array_size))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002361 err = -EFAULT;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002362 goto out_array_args;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002363 }
2364 if (err < 0)
2365 goto out;
2366
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002367out_array_args:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002368 /* Copy results into user buffer */
2369 switch (_IOC_DIR(cmd)) {
2370 case _IOC_READ:
2371 case (_IOC_WRITE | _IOC_READ):
2372 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
2373 err = -EFAULT;
2374 break;
2375 }
2376
2377out:
2378 kfree(mbuf);
2379 return err;
2380}
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002381EXPORT_SYMBOL(video_usercopy);
2382
2383long video_ioctl2(struct file *file,
2384 unsigned int cmd, unsigned long arg)
2385{
2386 return video_usercopy(file, cmd, arg, __video_do_ioctl);
2387}
Mauro Carvalho Chehab8a522c92008-10-21 11:58:39 -03002388EXPORT_SYMBOL(video_ioctl2);