blob: db6ec3868347b20bc9933ff7793bded0b831673b [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 Verkuil80b36e02009-02-07 11:00:02 -030027#include <media/v4l2-chip-ident.h>
Hans Verkuil35ea11f2008-07-20 08:12:02 -030028
29#define dbgarg(cmd, fmt, arg...) \
30 do { \
31 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) { \
32 printk(KERN_DEBUG "%s: ", vfd->name); \
33 v4l_printk_ioctl(cmd); \
34 printk(" " fmt, ## arg); \
35 } \
36 } while (0)
37
38#define dbgarg2(fmt, arg...) \
39 do { \
40 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
41 printk(KERN_DEBUG "%s: " fmt, vfd->name, ## arg);\
42 } while (0)
43
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -030044#define dbgarg3(fmt, arg...) \
45 do { \
46 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) \
47 printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\
48 } while (0)
49
Trent Piepho7ecc0cf2009-04-30 21:03:34 -030050/* Zero out the end of the struct pointed to by p. Everthing after, but
51 * not including, the specified field is cleared. */
52#define CLEAR_AFTER_FIELD(p, field) \
53 memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
54 0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
55
Hans Verkuil35ea11f2008-07-20 08:12:02 -030056struct std_descr {
57 v4l2_std_id std;
58 const char *descr;
59};
60
61static const struct std_descr standards[] = {
62 { V4L2_STD_NTSC, "NTSC" },
63 { V4L2_STD_NTSC_M, "NTSC-M" },
64 { V4L2_STD_NTSC_M_JP, "NTSC-M-JP" },
65 { V4L2_STD_NTSC_M_KR, "NTSC-M-KR" },
66 { V4L2_STD_NTSC_443, "NTSC-443" },
67 { V4L2_STD_PAL, "PAL" },
68 { V4L2_STD_PAL_BG, "PAL-BG" },
69 { V4L2_STD_PAL_B, "PAL-B" },
70 { V4L2_STD_PAL_B1, "PAL-B1" },
71 { V4L2_STD_PAL_G, "PAL-G" },
72 { V4L2_STD_PAL_H, "PAL-H" },
73 { V4L2_STD_PAL_I, "PAL-I" },
74 { V4L2_STD_PAL_DK, "PAL-DK" },
75 { V4L2_STD_PAL_D, "PAL-D" },
76 { V4L2_STD_PAL_D1, "PAL-D1" },
77 { V4L2_STD_PAL_K, "PAL-K" },
78 { V4L2_STD_PAL_M, "PAL-M" },
79 { V4L2_STD_PAL_N, "PAL-N" },
80 { V4L2_STD_PAL_Nc, "PAL-Nc" },
81 { V4L2_STD_PAL_60, "PAL-60" },
82 { V4L2_STD_SECAM, "SECAM" },
83 { V4L2_STD_SECAM_B, "SECAM-B" },
84 { V4L2_STD_SECAM_G, "SECAM-G" },
85 { V4L2_STD_SECAM_H, "SECAM-H" },
86 { V4L2_STD_SECAM_DK, "SECAM-DK" },
87 { V4L2_STD_SECAM_D, "SECAM-D" },
88 { V4L2_STD_SECAM_K, "SECAM-K" },
89 { V4L2_STD_SECAM_K1, "SECAM-K1" },
90 { V4L2_STD_SECAM_L, "SECAM-L" },
91 { V4L2_STD_SECAM_LC, "SECAM-Lc" },
92 { 0, "Unknown" }
93};
94
95/* video4linux standard ID conversion to standard name
96 */
97const char *v4l2_norm_to_name(v4l2_std_id id)
98{
99 u32 myid = id;
100 int i;
101
102 /* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
103 64 bit comparations. So, on that architecture, with some gcc
104 variants, compilation fails. Currently, the max value is 30bit wide.
105 */
106 BUG_ON(myid != id);
107
108 for (i = 0; standards[i].std; i++)
109 if (myid == standards[i].std)
110 break;
111 return standards[i].descr;
112}
113EXPORT_SYMBOL(v4l2_norm_to_name);
114
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300115/* Returns frame period for the given standard */
116void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
117{
118 if (id & V4L2_STD_525_60) {
119 frameperiod->numerator = 1001;
120 frameperiod->denominator = 30000;
121 } else {
122 frameperiod->numerator = 1;
123 frameperiod->denominator = 25;
124 }
125}
126EXPORT_SYMBOL(v4l2_video_std_frame_period);
127
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300128/* Fill in the fields of a v4l2_standard structure according to the
129 'id' and 'transmission' parameters. Returns negative on error. */
130int v4l2_video_std_construct(struct v4l2_standard *vs,
131 int id, const char *name)
132{
Trent Piepho51f0b8d52009-03-04 01:21:02 -0300133 vs->id = id;
134 v4l2_video_std_frame_period(id, &vs->frameperiod);
135 vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300136 strlcpy(vs->name, name, sizeof(vs->name));
137 return 0;
138}
139EXPORT_SYMBOL(v4l2_video_std_construct);
140
141/* ----------------------------------------------------------------- */
142/* some arrays for pretty-printing debug messages of enum types */
143
144const char *v4l2_field_names[] = {
145 [V4L2_FIELD_ANY] = "any",
146 [V4L2_FIELD_NONE] = "none",
147 [V4L2_FIELD_TOP] = "top",
148 [V4L2_FIELD_BOTTOM] = "bottom",
149 [V4L2_FIELD_INTERLACED] = "interlaced",
150 [V4L2_FIELD_SEQ_TB] = "seq-tb",
151 [V4L2_FIELD_SEQ_BT] = "seq-bt",
152 [V4L2_FIELD_ALTERNATE] = "alternate",
153 [V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
154 [V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
155};
156EXPORT_SYMBOL(v4l2_field_names);
157
158const char *v4l2_type_names[] = {
159 [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "vid-cap",
160 [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "vid-overlay",
161 [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "vid-out",
162 [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap",
163 [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out",
164 [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
165 [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "sliced-vbi-out",
166 [V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
Pawel Osciakf8f39142010-07-29 14:44:25 -0300167 [V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
168 [V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300169};
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 */
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300183static const char *v4l2_ioctls[] = {
184 [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP",
185 [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED",
186 [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT",
187 [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT",
188 [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT",
189 [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS",
190 [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF",
191 [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF",
192 [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF",
193 [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY",
194 [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF",
195 [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF",
196 [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON",
197 [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF",
198 [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM",
199 [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM",
200 [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD",
201 [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD",
202 [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD",
203 [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT",
204 [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL",
205 [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL",
206 [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER",
207 [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER",
208 [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO",
209 [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO",
210 [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL",
211 [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU",
212 [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT",
213 [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT",
214 [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT",
215 [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT",
216 [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT",
217 [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT",
218 [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT",
219 [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR",
220 [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR",
221 [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY",
222 [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY",
223 [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP",
224 [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP",
225 [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP",
226 [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP",
227 [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP",
228 [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD",
229 [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT",
230 [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO",
231 [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT",
232 [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY",
233 [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY",
234 [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP",
235 [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS",
236 [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS",
237 [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS",
238 [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS",
239#if 1
240 [_IOC_NR(VIDIOC_ENUM_FRAMESIZES)] = "VIDIOC_ENUM_FRAMESIZES",
241 [_IOC_NR(VIDIOC_ENUM_FRAMEINTERVALS)] = "VIDIOC_ENUM_FRAMEINTERVALS",
242 [_IOC_NR(VIDIOC_G_ENC_INDEX)] = "VIDIOC_G_ENC_INDEX",
243 [_IOC_NR(VIDIOC_ENCODER_CMD)] = "VIDIOC_ENCODER_CMD",
244 [_IOC_NR(VIDIOC_TRY_ENCODER_CMD)] = "VIDIOC_TRY_ENCODER_CMD",
245
246 [_IOC_NR(VIDIOC_DBG_S_REGISTER)] = "VIDIOC_DBG_S_REGISTER",
247 [_IOC_NR(VIDIOC_DBG_G_REGISTER)] = "VIDIOC_DBG_G_REGISTER",
248
Hans Verkuilaecde8b52008-12-30 07:14:19 -0300249 [_IOC_NR(VIDIOC_DBG_G_CHIP_IDENT)] = "VIDIOC_DBG_G_CHIP_IDENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300250 [_IOC_NR(VIDIOC_S_HW_FREQ_SEEK)] = "VIDIOC_S_HW_FREQ_SEEK",
251#endif
Muralidharan Karicherib6456c02009-11-19 12:00:31 -0300252 [_IOC_NR(VIDIOC_ENUM_DV_PRESETS)] = "VIDIOC_ENUM_DV_PRESETS",
253 [_IOC_NR(VIDIOC_S_DV_PRESET)] = "VIDIOC_S_DV_PRESET",
254 [_IOC_NR(VIDIOC_G_DV_PRESET)] = "VIDIOC_G_DV_PRESET",
255 [_IOC_NR(VIDIOC_QUERY_DV_PRESET)] = "VIDIOC_QUERY_DV_PRESET",
256 [_IOC_NR(VIDIOC_S_DV_TIMINGS)] = "VIDIOC_S_DV_TIMINGS",
257 [_IOC_NR(VIDIOC_G_DV_TIMINGS)] = "VIDIOC_G_DV_TIMINGS",
Sakari Ailusfda10212010-02-24 19:19:05 -0300258 [_IOC_NR(VIDIOC_DQEVENT)] = "VIDIOC_DQEVENT",
259 [_IOC_NR(VIDIOC_SUBSCRIBE_EVENT)] = "VIDIOC_SUBSCRIBE_EVENT",
260 [_IOC_NR(VIDIOC_UNSUBSCRIBE_EVENT)] = "VIDIOC_UNSUBSCRIBE_EVENT",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300261};
262#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
263
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300264/* Common ioctl debug function. This function can be used by
265 external ioctl messages as well as internal V4L ioctl */
266void v4l_printk_ioctl(unsigned int cmd)
267{
268 char *dir, *type;
269
270 switch (_IOC_TYPE(cmd)) {
271 case 'd':
Hans Verkuil78a3b4d2009-04-01 03:41:09 -0300272 type = "v4l2_int";
273 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300274 case 'V':
275 if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
276 type = "v4l2";
277 break;
278 }
279 printk("%s", v4l2_ioctls[_IOC_NR(cmd)]);
280 return;
281 default:
282 type = "unknown";
283 }
284
285 switch (_IOC_DIR(cmd)) {
286 case _IOC_NONE: dir = "--"; break;
287 case _IOC_READ: dir = "r-"; break;
288 case _IOC_WRITE: dir = "-w"; break;
289 case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
290 default: dir = "*ERR*"; break;
291 }
292 printk("%s ioctl '%c', dir=%s, #%d (0x%08x)",
293 type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
294}
295EXPORT_SYMBOL(v4l_printk_ioctl);
296
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300297static void dbgbuf(unsigned int cmd, struct video_device *vfd,
298 struct v4l2_buffer *p)
299{
300 struct v4l2_timecode *tc = &p->timecode;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300301 struct v4l2_plane *plane;
302 int i;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300303
304 dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300305 "flags=0x%08d, field=%0d, sequence=%d, memory=%s\n",
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300306 p->timestamp.tv_sec / 3600,
307 (int)(p->timestamp.tv_sec / 60) % 60,
308 (int)(p->timestamp.tv_sec % 60),
Alexander Beregalovb0459792008-09-03 16:47:38 -0300309 (long)p->timestamp.tv_usec,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300310 p->index,
311 prt_names(p->type, v4l2_type_names),
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300312 p->flags, p->field, p->sequence,
313 prt_names(p->memory, v4l2_memory_names));
314
315 if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
316 for (i = 0; i < p->length; ++i) {
317 plane = &p->m.planes[i];
318 dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x "
319 "offset/userptr=0x%08lx, length=%d\n",
320 i, plane->bytesused, plane->data_offset,
321 plane->m.userptr, plane->length);
322 }
323 } else {
324 dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n",
325 p->bytesused, p->m.userptr, p->length);
326 }
327
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300328 dbgarg2("timecode=%02d:%02d:%02d type=%d, "
329 "flags=0x%08d, frames=%d, userbits=0x%08x\n",
330 tc->hours, tc->minutes, tc->seconds,
331 tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
332}
333
334static inline void dbgrect(struct video_device *vfd, char *s,
335 struct v4l2_rect *r)
336{
337 dbgarg2("%sRect start at %dx%d, size=%dx%d\n", s, r->left, r->top,
338 r->width, r->height);
339};
340
341static inline void v4l_print_pix_fmt(struct video_device *vfd,
342 struct v4l2_pix_format *fmt)
343{
344 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
345 "bytesperline=%d sizeimage=%d, colorspace=%d\n",
346 fmt->width, fmt->height,
347 (fmt->pixelformat & 0xff),
348 (fmt->pixelformat >> 8) & 0xff,
349 (fmt->pixelformat >> 16) & 0xff,
350 (fmt->pixelformat >> 24) & 0xff,
351 prt_names(fmt->field, v4l2_field_names),
352 fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
353};
354
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300355static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd,
356 struct v4l2_pix_format_mplane *fmt)
357{
358 int i;
359
360 dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
361 "colorspace=%d, num_planes=%d\n",
362 fmt->width, fmt->height,
363 (fmt->pixelformat & 0xff),
364 (fmt->pixelformat >> 8) & 0xff,
365 (fmt->pixelformat >> 16) & 0xff,
366 (fmt->pixelformat >> 24) & 0xff,
367 prt_names(fmt->field, v4l2_field_names),
368 fmt->colorspace, fmt->num_planes);
369
370 for (i = 0; i < fmt->num_planes; ++i)
371 dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i,
372 fmt->plane_fmt[i].bytesperline,
373 fmt->plane_fmt[i].sizeimage);
374}
375
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300376static inline void v4l_print_ext_ctrls(unsigned int cmd,
377 struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
378{
379 __u32 i;
380
381 if (!(vfd->debug & V4L2_DEBUG_IOCTL_ARG))
382 return;
383 dbgarg(cmd, "");
384 printk(KERN_CONT "class=0x%x", c->ctrl_class);
385 for (i = 0; i < c->count; i++) {
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300386 if (show_vals && !c->controls[i].size)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300387 printk(KERN_CONT " id/val=0x%x/0x%x",
388 c->controls[i].id, c->controls[i].value);
389 else
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300390 printk(KERN_CONT " id=0x%x,size=%u",
391 c->controls[i].id, c->controls[i].size);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300392 }
393 printk(KERN_CONT "\n");
394};
395
396static inline int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
397{
398 __u32 i;
399
400 /* zero the reserved fields */
401 c->reserved[0] = c->reserved[1] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300402 for (i = 0; i < c->count; i++)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300403 c->controls[i].reserved2[0] = 0;
Hans Verkuil6b5a9492009-08-11 18:47:18 -0300404
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300405 /* V4L2_CID_PRIVATE_BASE cannot be used as control class
406 when using extended controls.
407 Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
408 is it allowed for backwards compatibility.
409 */
410 if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
411 return 0;
412 /* Check that all controls are from the same control class. */
413 for (i = 0; i < c->count; i++) {
414 if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
415 c->error_idx = i;
416 return 0;
417 }
418 }
419 return 1;
420}
421
Hans Verkuila3998102008-07-21 02:57:38 -0300422static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300423{
Hans Verkuila3998102008-07-21 02:57:38 -0300424 if (ops == NULL)
425 return -EINVAL;
426
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300427 switch (type) {
428 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300429 if (ops->vidioc_g_fmt_vid_cap ||
430 ops->vidioc_g_fmt_vid_cap_mplane)
431 return 0;
432 break;
433 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
434 if (ops->vidioc_g_fmt_vid_cap_mplane)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300435 return 0;
436 break;
437 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300438 if (ops->vidioc_g_fmt_vid_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300439 return 0;
440 break;
441 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300442 if (ops->vidioc_g_fmt_vid_out ||
443 ops->vidioc_g_fmt_vid_out_mplane)
444 return 0;
445 break;
446 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
447 if (ops->vidioc_g_fmt_vid_out_mplane)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300448 return 0;
449 break;
450 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho1175d612009-04-30 21:03:34 -0300451 if (ops->vidioc_g_fmt_vid_out_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300452 return 0;
453 break;
454 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300455 if (ops->vidioc_g_fmt_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300456 return 0;
457 break;
458 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300459 if (ops->vidioc_g_fmt_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300460 return 0;
461 break;
462 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho1175d612009-04-30 21:03:34 -0300463 if (ops->vidioc_g_fmt_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300464 return 0;
465 break;
466 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho1175d612009-04-30 21:03:34 -0300467 if (ops->vidioc_g_fmt_sliced_vbi_out)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300468 return 0;
469 break;
470 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho1175d612009-04-30 21:03:34 -0300471 if (ops->vidioc_g_fmt_type_private)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300472 return 0;
473 break;
474 }
475 return -EINVAL;
476}
477
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300478/**
479 * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
480 * equivalent
481 */
482static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
483 struct v4l2_format *f_mp)
484{
485 struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
486 const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
487
488 if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
489 f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
490 else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
491 f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
492 else
493 return -EINVAL;
494
495 pix_mp->width = pix->width;
496 pix_mp->height = pix->height;
497 pix_mp->pixelformat = pix->pixelformat;
498 pix_mp->field = pix->field;
499 pix_mp->colorspace = pix->colorspace;
500 pix_mp->num_planes = 1;
501 pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
502 pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
503
504 return 0;
505}
506
507/**
508 * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
509 * equivalent
510 */
511static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
512 struct v4l2_format *f_sp)
513{
514 const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
515 struct v4l2_pix_format *pix = &f_sp->fmt.pix;
516
517 if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
518 f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
519 else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
520 f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
521 else
522 return -EINVAL;
523
524 pix->width = pix_mp->width;
525 pix->height = pix_mp->height;
526 pix->pixelformat = pix_mp->pixelformat;
527 pix->field = pix_mp->field;
528 pix->colorspace = pix_mp->colorspace;
529 pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
530 pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
531
532 return 0;
533}
534
Hans Verkuil069b7472008-12-30 07:04:34 -0300535static long __video_do_ioctl(struct file *file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300536 unsigned int cmd, void *arg)
537{
538 struct video_device *vfd = video_devdata(file);
Hans Verkuila3998102008-07-21 02:57:38 -0300539 const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
Hans Verkuild5fbf322008-10-18 13:39:53 -0300540 void *fh = file->private_data;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300541 struct v4l2_format f_copy;
Hans Verkuil069b7472008-12-30 07:04:34 -0300542 long ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300543
Hans Verkuil6a717882010-04-06 15:56:08 -0300544 if (ops == NULL) {
545 printk(KERN_WARNING "videodev: \"%s\" has no ioctl_ops.\n",
546 vfd->name);
547 return -EINVAL;
548 }
549
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300550 if ((vfd->debug & V4L2_DEBUG_IOCTL) &&
551 !(vfd->debug & V4L2_DEBUG_IOCTL_ARG)) {
552 v4l_print_ioctl(vfd->name, cmd);
553 printk(KERN_CONT "\n");
554 }
555
Hans Verkuil6a717882010-04-06 15:56:08 -0300556 switch (cmd) {
Hans Verkuila3998102008-07-21 02:57:38 -0300557
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300558 /* --- capabilities ------------------------------------------ */
559 case VIDIOC_QUERYCAP:
560 {
561 struct v4l2_capability *cap = (struct v4l2_capability *)arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300562
Hans Verkuila3998102008-07-21 02:57:38 -0300563 if (!ops->vidioc_querycap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300564 break;
565
Hans Verkuila3998102008-07-21 02:57:38 -0300566 ret = ops->vidioc_querycap(file, fh, cap);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300567 if (!ret)
568 dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
569 "version=0x%08x, "
570 "capabilities=0x%08x\n",
571 cap->driver, cap->card, cap->bus_info,
572 cap->version,
573 cap->capabilities);
574 break;
575 }
576
577 /* --- priority ------------------------------------------ */
578 case VIDIOC_G_PRIORITY:
579 {
580 enum v4l2_priority *p = arg;
581
Hans Verkuila3998102008-07-21 02:57:38 -0300582 if (!ops->vidioc_g_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300583 break;
Hans Verkuila3998102008-07-21 02:57:38 -0300584 ret = ops->vidioc_g_priority(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300585 if (!ret)
586 dbgarg(cmd, "priority is %d\n", *p);
587 break;
588 }
589 case VIDIOC_S_PRIORITY:
590 {
591 enum v4l2_priority *p = arg;
592
Hans Verkuila3998102008-07-21 02:57:38 -0300593 if (!ops->vidioc_s_priority)
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300594 break;
595 dbgarg(cmd, "setting priority to %d\n", *p);
Hans Verkuila3998102008-07-21 02:57:38 -0300596 ret = ops->vidioc_s_priority(file, fh, *p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300597 break;
598 }
599
600 /* --- capture ioctls ---------------------------------------- */
601 case VIDIOC_ENUM_FMT:
602 {
603 struct v4l2_fmtdesc *f = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300604
Trent Piepho19c96e42009-03-04 01:21:02 -0300605 switch (f->type) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300606 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300607 if (ops->vidioc_enum_fmt_vid_cap)
608 ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300609 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300610 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
611 if (ops->vidioc_enum_fmt_vid_cap_mplane)
612 ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
613 fh, f);
614 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300615 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300616 if (ops->vidioc_enum_fmt_vid_overlay)
617 ret = ops->vidioc_enum_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300618 fh, f);
619 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300620 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300621 if (ops->vidioc_enum_fmt_vid_out)
622 ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300623 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300624 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
625 if (ops->vidioc_enum_fmt_vid_out_mplane)
626 ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
627 fh, f);
628 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300629 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300630 if (ops->vidioc_enum_fmt_type_private)
631 ret = ops->vidioc_enum_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300632 fh, f);
633 break;
634 default:
635 break;
636 }
637 if (!ret)
638 dbgarg(cmd, "index=%d, type=%d, flags=%d, "
639 "pixelformat=%c%c%c%c, description='%s'\n",
640 f->index, f->type, f->flags,
641 (f->pixelformat & 0xff),
642 (f->pixelformat >> 8) & 0xff,
643 (f->pixelformat >> 16) & 0xff,
644 (f->pixelformat >> 24) & 0xff,
645 f->description);
646 break;
647 }
648 case VIDIOC_G_FMT:
649 {
650 struct v4l2_format *f = (struct v4l2_format *)arg;
651
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300652 /* FIXME: Should be one dump per type */
653 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
654
655 switch (f->type) {
656 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300657 if (ops->vidioc_g_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300658 ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300659 } else if (ops->vidioc_g_fmt_vid_cap_mplane) {
660 if (fmt_sp_to_mp(f, &f_copy))
661 break;
662 ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
663 &f_copy);
664 if (ret)
665 break;
666
667 /* Driver is currently in multi-planar format,
668 * we can't return it in single-planar API*/
669 if (f_copy.fmt.pix_mp.num_planes > 1) {
670 ret = -EBUSY;
671 break;
672 }
673
674 ret = fmt_mp_to_sp(&f_copy, f);
675 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300676 if (!ret)
677 v4l_print_pix_fmt(vfd, &f->fmt.pix);
678 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300679 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
680 if (ops->vidioc_g_fmt_vid_cap_mplane) {
681 ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
682 fh, f);
683 } else if (ops->vidioc_g_fmt_vid_cap) {
684 if (fmt_mp_to_sp(f, &f_copy))
685 break;
686 ret = ops->vidioc_g_fmt_vid_cap(file,
687 fh, &f_copy);
688 if (ret)
689 break;
690
691 ret = fmt_sp_to_mp(&f_copy, f);
692 }
693 if (!ret)
694 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
695 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300696 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300697 if (ops->vidioc_g_fmt_vid_overlay)
698 ret = ops->vidioc_g_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300699 fh, f);
700 break;
701 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300702 if (ops->vidioc_g_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -0300703 ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300704 } else if (ops->vidioc_g_fmt_vid_out_mplane) {
705 if (fmt_sp_to_mp(f, &f_copy))
706 break;
707 ret = ops->vidioc_g_fmt_vid_out_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_OUTPUT_MPLANE:
725 if (ops->vidioc_g_fmt_vid_out_mplane) {
726 ret = ops->vidioc_g_fmt_vid_out_mplane(file,
727 fh, f);
728 } else if (ops->vidioc_g_fmt_vid_out) {
729 if (fmt_mp_to_sp(f, &f_copy))
730 break;
731 ret = ops->vidioc_g_fmt_vid_out(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_OUTPUT_OVERLAY:
Hans Verkuila3998102008-07-21 02:57:38 -0300742 if (ops->vidioc_g_fmt_vid_out_overlay)
743 ret = ops->vidioc_g_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300744 fh, f);
745 break;
746 case V4L2_BUF_TYPE_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300747 if (ops->vidioc_g_fmt_vbi_cap)
748 ret = ops->vidioc_g_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300749 break;
750 case V4L2_BUF_TYPE_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300751 if (ops->vidioc_g_fmt_vbi_out)
752 ret = ops->vidioc_g_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300753 break;
754 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Hans Verkuila3998102008-07-21 02:57:38 -0300755 if (ops->vidioc_g_fmt_sliced_vbi_cap)
756 ret = ops->vidioc_g_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300757 fh, f);
758 break;
759 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Hans Verkuila3998102008-07-21 02:57:38 -0300760 if (ops->vidioc_g_fmt_sliced_vbi_out)
761 ret = ops->vidioc_g_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300762 fh, f);
763 break;
764 case V4L2_BUF_TYPE_PRIVATE:
Hans Verkuila3998102008-07-21 02:57:38 -0300765 if (ops->vidioc_g_fmt_type_private)
766 ret = ops->vidioc_g_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300767 fh, f);
768 break;
769 }
770
771 break;
772 }
773 case VIDIOC_S_FMT:
774 {
775 struct v4l2_format *f = (struct v4l2_format *)arg;
776
777 /* FIXME: Should be one dump per type */
778 dbgarg(cmd, "type=%s\n", prt_names(f->type, v4l2_type_names));
779
780 switch (f->type) {
781 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300782 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300783 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300784 if (ops->vidioc_s_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300785 ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300786 } else if (ops->vidioc_s_fmt_vid_cap_mplane) {
787 if (fmt_sp_to_mp(f, &f_copy))
788 break;
789 ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
790 &f_copy);
791 if (ret)
792 break;
793
794 if (f_copy.fmt.pix_mp.num_planes > 1) {
795 /* Drivers shouldn't adjust from 1-plane
796 * to more than 1-plane formats */
797 ret = -EBUSY;
798 WARN_ON(1);
799 break;
800 }
801
802 ret = fmt_mp_to_sp(&f_copy, f);
803 }
804 break;
805 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
806 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
807 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
808 if (ops->vidioc_s_fmt_vid_cap_mplane) {
809 ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
810 fh, f);
811 } else if (ops->vidioc_s_fmt_vid_cap &&
812 f->fmt.pix_mp.num_planes == 1) {
813 if (fmt_mp_to_sp(f, &f_copy))
814 break;
815 ret = ops->vidioc_s_fmt_vid_cap(file,
816 fh, &f_copy);
817 if (ret)
818 break;
819
820 ret = fmt_sp_to_mp(&f_copy, f);
821 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300822 break;
823 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300824 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300825 if (ops->vidioc_s_fmt_vid_overlay)
826 ret = ops->vidioc_s_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300827 fh, f);
828 break;
829 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300830 CLEAR_AFTER_FIELD(f, fmt.pix);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300831 v4l_print_pix_fmt(vfd, &f->fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300832 if (ops->vidioc_s_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -0300833 ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300834 } else if (ops->vidioc_s_fmt_vid_out_mplane) {
835 if (fmt_sp_to_mp(f, &f_copy))
836 break;
837 ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
838 &f_copy);
839 if (ret)
840 break;
841
842 if (f_copy.fmt.pix_mp.num_planes > 1) {
843 /* Drivers shouldn't adjust from 1-plane
844 * to more than 1-plane formats */
845 ret = -EBUSY;
846 WARN_ON(1);
847 break;
848 }
849
850 ret = fmt_mp_to_sp(&f_copy, f);
851 }
852 break;
853 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
854 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
855 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
856 if (ops->vidioc_s_fmt_vid_out_mplane) {
857 ret = ops->vidioc_s_fmt_vid_out_mplane(file,
858 fh, f);
859 } else if (ops->vidioc_s_fmt_vid_out &&
860 f->fmt.pix_mp.num_planes == 1) {
861 if (fmt_mp_to_sp(f, &f_copy))
862 break;
863 ret = ops->vidioc_s_fmt_vid_out(file,
864 fh, &f_copy);
865 if (ret)
866 break;
867
868 ret = fmt_mp_to_sp(&f_copy, f);
869 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300870 break;
871 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300872 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300873 if (ops->vidioc_s_fmt_vid_out_overlay)
874 ret = ops->vidioc_s_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300875 fh, f);
876 break;
877 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300878 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300879 if (ops->vidioc_s_fmt_vbi_cap)
880 ret = ops->vidioc_s_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300881 break;
882 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300883 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -0300884 if (ops->vidioc_s_fmt_vbi_out)
885 ret = ops->vidioc_s_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300886 break;
887 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300888 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300889 if (ops->vidioc_s_fmt_sliced_vbi_cap)
890 ret = ops->vidioc_s_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300891 fh, f);
892 break;
893 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300894 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -0300895 if (ops->vidioc_s_fmt_sliced_vbi_out)
896 ret = ops->vidioc_s_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300897 fh, f);
898 break;
899 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300900 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -0300901 if (ops->vidioc_s_fmt_type_private)
902 ret = ops->vidioc_s_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300903 fh, f);
904 break;
905 }
906 break;
907 }
908 case VIDIOC_TRY_FMT:
909 {
910 struct v4l2_format *f = (struct v4l2_format *)arg;
911
912 /* FIXME: Should be one dump per type */
913 dbgarg(cmd, "type=%s\n", prt_names(f->type,
914 v4l2_type_names));
915 switch (f->type) {
916 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300917 CLEAR_AFTER_FIELD(f, fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300918 if (ops->vidioc_try_fmt_vid_cap) {
Hans Verkuila3998102008-07-21 02:57:38 -0300919 ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300920 } else if (ops->vidioc_try_fmt_vid_cap_mplane) {
921 if (fmt_sp_to_mp(f, &f_copy))
922 break;
923 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
924 fh, &f_copy);
925 if (ret)
926 break;
927
928 if (f_copy.fmt.pix_mp.num_planes > 1) {
929 /* Drivers shouldn't adjust from 1-plane
930 * to more than 1-plane formats */
931 ret = -EBUSY;
932 WARN_ON(1);
933 break;
934 }
935 ret = fmt_mp_to_sp(&f_copy, f);
936 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300937 if (!ret)
938 v4l_print_pix_fmt(vfd, &f->fmt.pix);
939 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300940 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
941 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
942 if (ops->vidioc_try_fmt_vid_cap_mplane) {
943 ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
944 fh, f);
945 } else if (ops->vidioc_try_fmt_vid_cap &&
946 f->fmt.pix_mp.num_planes == 1) {
947 if (fmt_mp_to_sp(f, &f_copy))
948 break;
949 ret = ops->vidioc_try_fmt_vid_cap(file,
950 fh, &f_copy);
951 if (ret)
952 break;
953
954 ret = fmt_sp_to_mp(&f_copy, f);
955 }
956 if (!ret)
957 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
958 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300959 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300960 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -0300961 if (ops->vidioc_try_fmt_vid_overlay)
962 ret = ops->vidioc_try_fmt_vid_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300963 fh, f);
964 break;
965 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -0300966 CLEAR_AFTER_FIELD(f, fmt.pix);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300967 if (ops->vidioc_try_fmt_vid_out) {
Hans Verkuila3998102008-07-21 02:57:38 -0300968 ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300969 } else if (ops->vidioc_try_fmt_vid_out_mplane) {
970 if (fmt_sp_to_mp(f, &f_copy))
971 break;
972 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
973 fh, &f_copy);
974 if (ret)
975 break;
976
977 if (f_copy.fmt.pix_mp.num_planes > 1) {
978 /* Drivers shouldn't adjust from 1-plane
979 * to more than 1-plane formats */
980 ret = -EBUSY;
981 WARN_ON(1);
982 break;
983 }
984 ret = fmt_mp_to_sp(&f_copy, f);
985 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -0300986 if (!ret)
987 v4l_print_pix_fmt(vfd, &f->fmt.pix);
988 break;
Pawel Osciakd14e6d72010-12-23 04:15:27 -0300989 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
990 CLEAR_AFTER_FIELD(f, fmt.pix_mp);
991 if (ops->vidioc_try_fmt_vid_out_mplane) {
992 ret = ops->vidioc_try_fmt_vid_out_mplane(file,
993 fh, f);
994 } else if (ops->vidioc_try_fmt_vid_out &&
995 f->fmt.pix_mp.num_planes == 1) {
996 if (fmt_mp_to_sp(f, &f_copy))
997 break;
998 ret = ops->vidioc_try_fmt_vid_out(file,
999 fh, &f_copy);
1000 if (ret)
1001 break;
1002
1003 ret = fmt_sp_to_mp(&f_copy, f);
1004 }
1005 if (!ret)
1006 v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
1007 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001008 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001009 CLEAR_AFTER_FIELD(f, fmt.win);
Hans Verkuila3998102008-07-21 02:57:38 -03001010 if (ops->vidioc_try_fmt_vid_out_overlay)
1011 ret = ops->vidioc_try_fmt_vid_out_overlay(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001012 fh, f);
1013 break;
1014 case V4L2_BUF_TYPE_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001015 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -03001016 if (ops->vidioc_try_fmt_vbi_cap)
1017 ret = ops->vidioc_try_fmt_vbi_cap(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001018 break;
1019 case V4L2_BUF_TYPE_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001020 CLEAR_AFTER_FIELD(f, fmt.vbi);
Hans Verkuila3998102008-07-21 02:57:38 -03001021 if (ops->vidioc_try_fmt_vbi_out)
1022 ret = ops->vidioc_try_fmt_vbi_out(file, fh, f);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001023 break;
1024 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001025 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -03001026 if (ops->vidioc_try_fmt_sliced_vbi_cap)
1027 ret = ops->vidioc_try_fmt_sliced_vbi_cap(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001028 fh, f);
1029 break;
1030 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001031 CLEAR_AFTER_FIELD(f, fmt.sliced);
Hans Verkuila3998102008-07-21 02:57:38 -03001032 if (ops->vidioc_try_fmt_sliced_vbi_out)
1033 ret = ops->vidioc_try_fmt_sliced_vbi_out(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001034 fh, f);
1035 break;
1036 case V4L2_BUF_TYPE_PRIVATE:
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001037 /* CLEAR_AFTER_FIELD(f, fmt.raw_data); <- does nothing */
Hans Verkuila3998102008-07-21 02:57:38 -03001038 if (ops->vidioc_try_fmt_type_private)
1039 ret = ops->vidioc_try_fmt_type_private(file,
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001040 fh, f);
1041 break;
1042 }
1043
1044 break;
1045 }
1046 /* FIXME: Those buf reqs could be handled here,
1047 with some changes on videobuf to allow its header to be included at
1048 videodev2.h or being merged at videodev2.
1049 */
1050 case VIDIOC_REQBUFS:
1051 {
1052 struct v4l2_requestbuffers *p = arg;
1053
Hans Verkuila3998102008-07-21 02:57:38 -03001054 if (!ops->vidioc_reqbufs)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001055 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001056 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001057 if (ret)
1058 break;
1059
Trent Piepho7ecc0cf2009-04-30 21:03:34 -03001060 if (p->type < V4L2_BUF_TYPE_PRIVATE)
1061 CLEAR_AFTER_FIELD(p, memory);
1062
Hans Verkuila3998102008-07-21 02:57:38 -03001063 ret = ops->vidioc_reqbufs(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001064 dbgarg(cmd, "count=%d, type=%s, memory=%s\n",
1065 p->count,
1066 prt_names(p->type, v4l2_type_names),
1067 prt_names(p->memory, v4l2_memory_names));
1068 break;
1069 }
1070 case VIDIOC_QUERYBUF:
1071 {
1072 struct v4l2_buffer *p = arg;
1073
Hans Verkuila3998102008-07-21 02:57:38 -03001074 if (!ops->vidioc_querybuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001075 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001076 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001077 if (ret)
1078 break;
1079
Hans Verkuila3998102008-07-21 02:57:38 -03001080 ret = ops->vidioc_querybuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001081 if (!ret)
1082 dbgbuf(cmd, vfd, p);
1083 break;
1084 }
1085 case VIDIOC_QBUF:
1086 {
1087 struct v4l2_buffer *p = arg;
1088
Hans Verkuila3998102008-07-21 02:57:38 -03001089 if (!ops->vidioc_qbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001090 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001091 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001092 if (ret)
1093 break;
1094
Hans Verkuila3998102008-07-21 02:57:38 -03001095 ret = ops->vidioc_qbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001096 if (!ret)
1097 dbgbuf(cmd, vfd, p);
1098 break;
1099 }
1100 case VIDIOC_DQBUF:
1101 {
1102 struct v4l2_buffer *p = arg;
1103
Hans Verkuila3998102008-07-21 02:57:38 -03001104 if (!ops->vidioc_dqbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001105 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001106 ret = check_fmt(ops, p->type);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001107 if (ret)
1108 break;
1109
Hans Verkuila3998102008-07-21 02:57:38 -03001110 ret = ops->vidioc_dqbuf(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001111 if (!ret)
1112 dbgbuf(cmd, vfd, p);
1113 break;
1114 }
1115 case VIDIOC_OVERLAY:
1116 {
1117 int *i = arg;
1118
Hans Verkuila3998102008-07-21 02:57:38 -03001119 if (!ops->vidioc_overlay)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001120 break;
1121 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001122 ret = ops->vidioc_overlay(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001123 break;
1124 }
1125 case VIDIOC_G_FBUF:
1126 {
1127 struct v4l2_framebuffer *p = arg;
1128
Hans Verkuila3998102008-07-21 02:57:38 -03001129 if (!ops->vidioc_g_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001130 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001131 ret = ops->vidioc_g_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001132 if (!ret) {
1133 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1134 p->capability, p->flags,
1135 (unsigned long)p->base);
1136 v4l_print_pix_fmt(vfd, &p->fmt);
1137 }
1138 break;
1139 }
1140 case VIDIOC_S_FBUF:
1141 {
1142 struct v4l2_framebuffer *p = arg;
1143
Hans Verkuila3998102008-07-21 02:57:38 -03001144 if (!ops->vidioc_s_fbuf)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001145 break;
1146 dbgarg(cmd, "capability=0x%x, flags=%d, base=0x%08lx\n",
1147 p->capability, p->flags, (unsigned long)p->base);
1148 v4l_print_pix_fmt(vfd, &p->fmt);
Hans Verkuila3998102008-07-21 02:57:38 -03001149 ret = ops->vidioc_s_fbuf(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001150 break;
1151 }
1152 case VIDIOC_STREAMON:
1153 {
1154 enum v4l2_buf_type i = *(int *)arg;
1155
Hans Verkuila3998102008-07-21 02:57:38 -03001156 if (!ops->vidioc_streamon)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001157 break;
1158 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001159 ret = ops->vidioc_streamon(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001160 break;
1161 }
1162 case VIDIOC_STREAMOFF:
1163 {
1164 enum v4l2_buf_type i = *(int *)arg;
1165
Hans Verkuila3998102008-07-21 02:57:38 -03001166 if (!ops->vidioc_streamoff)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001167 break;
1168 dbgarg(cmd, "type=%s\n", prt_names(i, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001169 ret = ops->vidioc_streamoff(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001170 break;
1171 }
1172 /* ---------- tv norms ---------- */
1173 case VIDIOC_ENUMSTD:
1174 {
1175 struct v4l2_standard *p = arg;
1176 v4l2_std_id id = vfd->tvnorms, curr_id = 0;
1177 unsigned int index = p->index, i, j = 0;
1178 const char *descr = "";
1179
1180 /* Return norm array in a canonical way */
1181 for (i = 0; i <= index && id; i++) {
1182 /* last std value in the standards array is 0, so this
1183 while always ends there since (id & 0) == 0. */
1184 while ((id & standards[j].std) != standards[j].std)
1185 j++;
1186 curr_id = standards[j].std;
1187 descr = standards[j].descr;
1188 j++;
1189 if (curr_id == 0)
1190 break;
1191 if (curr_id != V4L2_STD_PAL &&
1192 curr_id != V4L2_STD_SECAM &&
1193 curr_id != V4L2_STD_NTSC)
1194 id &= ~curr_id;
1195 }
1196 if (i <= index)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001197 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001198
1199 v4l2_video_std_construct(p, curr_id, descr);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001200
1201 dbgarg(cmd, "index=%d, id=0x%Lx, name=%s, fps=%d/%d, "
1202 "framelines=%d\n", p->index,
1203 (unsigned long long)p->id, p->name,
1204 p->frameperiod.numerator,
1205 p->frameperiod.denominator,
1206 p->framelines);
1207
1208 ret = 0;
1209 break;
1210 }
1211 case VIDIOC_G_STD:
1212 {
1213 v4l2_std_id *id = arg;
1214
1215 ret = 0;
1216 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001217 if (ops->vidioc_g_std)
1218 ret = ops->vidioc_g_std(file, fh, id);
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001219 else if (vfd->current_norm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001220 *id = vfd->current_norm;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001221 else
1222 ret = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001223
1224 if (!ret)
1225 dbgarg(cmd, "std=0x%08Lx\n", (long long unsigned)*id);
1226 break;
1227 }
1228 case VIDIOC_S_STD:
1229 {
1230 v4l2_std_id *id = arg, norm;
1231
1232 dbgarg(cmd, "std=%08Lx\n", (long long unsigned)*id);
1233
1234 norm = (*id) & vfd->tvnorms;
1235 if (vfd->tvnorms && !norm) /* Check if std is supported */
1236 break;
1237
1238 /* Calls the specific handler */
Hans Verkuila3998102008-07-21 02:57:38 -03001239 if (ops->vidioc_s_std)
1240 ret = ops->vidioc_s_std(file, fh, &norm);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001241 else
1242 ret = -EINVAL;
1243
1244 /* Updates standard information */
1245 if (ret >= 0)
1246 vfd->current_norm = norm;
1247 break;
1248 }
1249 case VIDIOC_QUERYSTD:
1250 {
1251 v4l2_std_id *p = arg;
1252
Hans Verkuila3998102008-07-21 02:57:38 -03001253 if (!ops->vidioc_querystd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001254 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001255 ret = ops->vidioc_querystd(file, fh, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001256 if (!ret)
1257 dbgarg(cmd, "detected std=%08Lx\n",
1258 (unsigned long long)*p);
1259 break;
1260 }
1261 /* ------ input switching ---------- */
1262 /* FIXME: Inputs can be handled inside videodev2 */
1263 case VIDIOC_ENUMINPUT:
1264 {
1265 struct v4l2_input *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001266
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001267 /*
1268 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1269 * CAP_STD here based on ioctl handler provided by the
1270 * driver. If the driver doesn't support these
1271 * for a specific input, it must override these flags.
1272 */
1273 if (ops->vidioc_s_std)
1274 p->capabilities |= V4L2_IN_CAP_STD;
1275 if (ops->vidioc_s_dv_preset)
1276 p->capabilities |= V4L2_IN_CAP_PRESETS;
1277 if (ops->vidioc_s_dv_timings)
1278 p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
1279
Hans Verkuila3998102008-07-21 02:57:38 -03001280 if (!ops->vidioc_enum_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001281 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001282
Hans Verkuila3998102008-07-21 02:57:38 -03001283 ret = ops->vidioc_enum_input(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001284 if (!ret)
1285 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1286 "audioset=%d, "
1287 "tuner=%d, std=%08Lx, status=%d\n",
1288 p->index, p->name, p->type, p->audioset,
1289 p->tuner,
1290 (unsigned long long)p->std,
1291 p->status);
1292 break;
1293 }
1294 case VIDIOC_G_INPUT:
1295 {
1296 unsigned int *i = arg;
1297
Hans Verkuila3998102008-07-21 02:57:38 -03001298 if (!ops->vidioc_g_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001299 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001300 ret = ops->vidioc_g_input(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001301 if (!ret)
1302 dbgarg(cmd, "value=%d\n", *i);
1303 break;
1304 }
1305 case VIDIOC_S_INPUT:
1306 {
1307 unsigned int *i = arg;
1308
Hans Verkuila3998102008-07-21 02:57:38 -03001309 if (!ops->vidioc_s_input)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001310 break;
1311 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001312 ret = ops->vidioc_s_input(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001313 break;
1314 }
1315
1316 /* ------ output switching ---------- */
1317 case VIDIOC_ENUMOUTPUT:
1318 {
1319 struct v4l2_output *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001320
Hans Verkuila3998102008-07-21 02:57:38 -03001321 if (!ops->vidioc_enum_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001322 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001323
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001324 /*
1325 * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
1326 * CAP_STD here based on ioctl handler provided by the
1327 * driver. If the driver doesn't support these
1328 * for a specific output, it must override these flags.
1329 */
1330 if (ops->vidioc_s_std)
1331 p->capabilities |= V4L2_OUT_CAP_STD;
1332 if (ops->vidioc_s_dv_preset)
1333 p->capabilities |= V4L2_OUT_CAP_PRESETS;
1334 if (ops->vidioc_s_dv_timings)
1335 p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
1336
Hans Verkuila3998102008-07-21 02:57:38 -03001337 ret = ops->vidioc_enum_output(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001338 if (!ret)
1339 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1340 "audioset=0x%x, "
1341 "modulator=%d, std=0x%08Lx\n",
1342 p->index, p->name, p->type, p->audioset,
1343 p->modulator, (unsigned long long)p->std);
1344 break;
1345 }
1346 case VIDIOC_G_OUTPUT:
1347 {
1348 unsigned int *i = arg;
1349
Hans Verkuila3998102008-07-21 02:57:38 -03001350 if (!ops->vidioc_g_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001351 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001352 ret = ops->vidioc_g_output(file, fh, i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001353 if (!ret)
1354 dbgarg(cmd, "value=%d\n", *i);
1355 break;
1356 }
1357 case VIDIOC_S_OUTPUT:
1358 {
1359 unsigned int *i = arg;
1360
Hans Verkuila3998102008-07-21 02:57:38 -03001361 if (!ops->vidioc_s_output)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001362 break;
1363 dbgarg(cmd, "value=%d\n", *i);
Hans Verkuila3998102008-07-21 02:57:38 -03001364 ret = ops->vidioc_s_output(file, fh, *i);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001365 break;
1366 }
1367
1368 /* --- controls ---------------------------------------------- */
1369 case VIDIOC_QUERYCTRL:
1370 {
1371 struct v4l2_queryctrl *p = arg;
1372
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001373 if (vfd->ctrl_handler)
1374 ret = v4l2_queryctrl(vfd->ctrl_handler, p);
1375 else if (ops->vidioc_queryctrl)
1376 ret = ops->vidioc_queryctrl(file, fh, p);
1377 else
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001378 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001379 if (!ret)
1380 dbgarg(cmd, "id=0x%x, type=%d, name=%s, min/max=%d/%d, "
1381 "step=%d, default=%d, flags=0x%08x\n",
1382 p->id, p->type, p->name,
1383 p->minimum, p->maximum,
1384 p->step, p->default_value, p->flags);
1385 else
1386 dbgarg(cmd, "id=0x%x\n", p->id);
1387 break;
1388 }
1389 case VIDIOC_G_CTRL:
1390 {
1391 struct v4l2_control *p = arg;
1392
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001393 if (vfd->ctrl_handler)
1394 ret = v4l2_g_ctrl(vfd->ctrl_handler, p);
1395 else if (ops->vidioc_g_ctrl)
Hans Verkuila3998102008-07-21 02:57:38 -03001396 ret = ops->vidioc_g_ctrl(file, fh, p);
1397 else if (ops->vidioc_g_ext_ctrls) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001398 struct v4l2_ext_controls ctrls;
1399 struct v4l2_ext_control ctrl;
1400
1401 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1402 ctrls.count = 1;
1403 ctrls.controls = &ctrl;
1404 ctrl.id = p->id;
1405 ctrl.value = p->value;
1406 if (check_ext_ctrls(&ctrls, 1)) {
Hans Verkuila3998102008-07-21 02:57:38 -03001407 ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001408 if (ret == 0)
1409 p->value = ctrl.value;
1410 }
1411 } else
1412 break;
1413 if (!ret)
1414 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1415 else
1416 dbgarg(cmd, "id=0x%x\n", p->id);
1417 break;
1418 }
1419 case VIDIOC_S_CTRL:
1420 {
1421 struct v4l2_control *p = arg;
1422 struct v4l2_ext_controls ctrls;
1423 struct v4l2_ext_control ctrl;
1424
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001425 if (!vfd->ctrl_handler &&
1426 !ops->vidioc_s_ctrl && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001427 break;
1428
1429 dbgarg(cmd, "id=0x%x, value=%d\n", p->id, p->value);
1430
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001431 if (vfd->ctrl_handler) {
1432 ret = v4l2_s_ctrl(vfd->ctrl_handler, p);
1433 break;
1434 }
Hans Verkuila3998102008-07-21 02:57:38 -03001435 if (ops->vidioc_s_ctrl) {
1436 ret = ops->vidioc_s_ctrl(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001437 break;
1438 }
Hans Verkuila3998102008-07-21 02:57:38 -03001439 if (!ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001440 break;
1441
1442 ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
1443 ctrls.count = 1;
1444 ctrls.controls = &ctrl;
1445 ctrl.id = p->id;
1446 ctrl.value = p->value;
1447 if (check_ext_ctrls(&ctrls, 1))
Hans Verkuila3998102008-07-21 02:57:38 -03001448 ret = ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001449 break;
1450 }
1451 case VIDIOC_G_EXT_CTRLS:
1452 {
1453 struct v4l2_ext_controls *p = arg;
1454
1455 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001456 if (vfd->ctrl_handler)
1457 ret = v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
1458 else if (ops->vidioc_g_ext_ctrls && check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001459 ret = ops->vidioc_g_ext_ctrls(file, fh, p);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001460 else
1461 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001462 v4l_print_ext_ctrls(cmd, vfd, p, !ret);
1463 break;
1464 }
1465 case VIDIOC_S_EXT_CTRLS:
1466 {
1467 struct v4l2_ext_controls *p = arg;
1468
1469 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001470 if (!vfd->ctrl_handler && !ops->vidioc_s_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001471 break;
1472 v4l_print_ext_ctrls(cmd, vfd, p, 1);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001473 if (vfd->ctrl_handler)
1474 ret = v4l2_s_ext_ctrls(vfd->ctrl_handler, p);
1475 else if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001476 ret = ops->vidioc_s_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001477 break;
1478 }
1479 case VIDIOC_TRY_EXT_CTRLS:
1480 {
1481 struct v4l2_ext_controls *p = arg;
1482
1483 p->error_idx = p->count;
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001484 if (!vfd->ctrl_handler && !ops->vidioc_try_ext_ctrls)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001485 break;
1486 v4l_print_ext_ctrls(cmd, vfd, p, 1);
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001487 if (vfd->ctrl_handler)
1488 ret = v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
1489 else if (check_ext_ctrls(p, 0))
Hans Verkuila3998102008-07-21 02:57:38 -03001490 ret = ops->vidioc_try_ext_ctrls(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001491 break;
1492 }
1493 case VIDIOC_QUERYMENU:
1494 {
1495 struct v4l2_querymenu *p = arg;
1496
Hans Verkuil11bbc1c2010-05-16 09:24:06 -03001497 if (vfd->ctrl_handler)
1498 ret = v4l2_querymenu(vfd->ctrl_handler, p);
1499 else if (ops->vidioc_querymenu)
1500 ret = ops->vidioc_querymenu(file, fh, p);
1501 else
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001502 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001503 if (!ret)
1504 dbgarg(cmd, "id=0x%x, index=%d, name=%s\n",
1505 p->id, p->index, p->name);
1506 else
1507 dbgarg(cmd, "id=0x%x, index=%d\n",
1508 p->id, p->index);
1509 break;
1510 }
1511 /* --- audio ---------------------------------------------- */
1512 case VIDIOC_ENUMAUDIO:
1513 {
1514 struct v4l2_audio *p = arg;
1515
Hans Verkuila3998102008-07-21 02:57:38 -03001516 if (!ops->vidioc_enumaudio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001517 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001518 ret = ops->vidioc_enumaudio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001519 if (!ret)
1520 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1521 "mode=0x%x\n", p->index, p->name,
1522 p->capability, p->mode);
1523 else
1524 dbgarg(cmd, "index=%d\n", p->index);
1525 break;
1526 }
1527 case VIDIOC_G_AUDIO:
1528 {
1529 struct v4l2_audio *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001530
Hans Verkuila3998102008-07-21 02:57:38 -03001531 if (!ops->vidioc_g_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001532 break;
1533
Hans Verkuila3998102008-07-21 02:57:38 -03001534 ret = ops->vidioc_g_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001535 if (!ret)
1536 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1537 "mode=0x%x\n", p->index,
1538 p->name, p->capability, p->mode);
1539 else
1540 dbgarg(cmd, "index=%d\n", p->index);
1541 break;
1542 }
1543 case VIDIOC_S_AUDIO:
1544 {
1545 struct v4l2_audio *p = arg;
1546
Hans Verkuila3998102008-07-21 02:57:38 -03001547 if (!ops->vidioc_s_audio)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001548 break;
1549 dbgarg(cmd, "index=%d, name=%s, capability=0x%x, "
1550 "mode=0x%x\n", p->index, p->name,
1551 p->capability, p->mode);
Hans Verkuila3998102008-07-21 02:57:38 -03001552 ret = ops->vidioc_s_audio(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001553 break;
1554 }
1555 case VIDIOC_ENUMAUDOUT:
1556 {
1557 struct v4l2_audioout *p = arg;
1558
Hans Verkuila3998102008-07-21 02:57:38 -03001559 if (!ops->vidioc_enumaudout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001560 break;
1561 dbgarg(cmd, "Enum for index=%d\n", p->index);
Hans Verkuila3998102008-07-21 02:57:38 -03001562 ret = ops->vidioc_enumaudout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001563 if (!ret)
1564 dbgarg2("index=%d, name=%s, capability=%d, "
1565 "mode=%d\n", p->index, p->name,
1566 p->capability, p->mode);
1567 break;
1568 }
1569 case VIDIOC_G_AUDOUT:
1570 {
1571 struct v4l2_audioout *p = arg;
1572
Hans Verkuila3998102008-07-21 02:57:38 -03001573 if (!ops->vidioc_g_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001574 break;
Trent Piepho337f9d22009-03-04 01:21:02 -03001575
Hans Verkuila3998102008-07-21 02:57:38 -03001576 ret = ops->vidioc_g_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001577 if (!ret)
1578 dbgarg2("index=%d, name=%s, capability=%d, "
1579 "mode=%d\n", p->index, p->name,
1580 p->capability, p->mode);
1581 break;
1582 }
1583 case VIDIOC_S_AUDOUT:
1584 {
1585 struct v4l2_audioout *p = arg;
1586
Hans Verkuila3998102008-07-21 02:57:38 -03001587 if (!ops->vidioc_s_audout)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001588 break;
1589 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1590 "mode=%d\n", p->index, p->name,
1591 p->capability, p->mode);
1592
Hans Verkuila3998102008-07-21 02:57:38 -03001593 ret = ops->vidioc_s_audout(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001594 break;
1595 }
1596 case VIDIOC_G_MODULATOR:
1597 {
1598 struct v4l2_modulator *p = arg;
1599
Hans Verkuila3998102008-07-21 02:57:38 -03001600 if (!ops->vidioc_g_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001601 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001602 ret = ops->vidioc_g_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001603 if (!ret)
1604 dbgarg(cmd, "index=%d, name=%s, "
1605 "capability=%d, rangelow=%d,"
1606 " rangehigh=%d, txsubchans=%d\n",
1607 p->index, p->name, p->capability,
1608 p->rangelow, p->rangehigh,
1609 p->txsubchans);
1610 break;
1611 }
1612 case VIDIOC_S_MODULATOR:
1613 {
1614 struct v4l2_modulator *p = arg;
1615
Hans Verkuila3998102008-07-21 02:57:38 -03001616 if (!ops->vidioc_s_modulator)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001617 break;
1618 dbgarg(cmd, "index=%d, name=%s, capability=%d, "
1619 "rangelow=%d, rangehigh=%d, txsubchans=%d\n",
1620 p->index, p->name, p->capability, p->rangelow,
1621 p->rangehigh, p->txsubchans);
Hans Verkuila3998102008-07-21 02:57:38 -03001622 ret = ops->vidioc_s_modulator(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001623 break;
1624 }
1625 case VIDIOC_G_CROP:
1626 {
1627 struct v4l2_crop *p = arg;
1628
Hans Verkuila3998102008-07-21 02:57:38 -03001629 if (!ops->vidioc_g_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001630 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001631
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001632 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001633 ret = ops->vidioc_g_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001634 if (!ret)
1635 dbgrect(vfd, "", &p->c);
1636 break;
1637 }
1638 case VIDIOC_S_CROP:
1639 {
1640 struct v4l2_crop *p = arg;
1641
Hans Verkuila3998102008-07-21 02:57:38 -03001642 if (!ops->vidioc_s_crop)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001643 break;
1644 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
1645 dbgrect(vfd, "", &p->c);
Hans Verkuila3998102008-07-21 02:57:38 -03001646 ret = ops->vidioc_s_crop(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001647 break;
1648 }
1649 case VIDIOC_CROPCAP:
1650 {
1651 struct v4l2_cropcap *p = arg;
1652
1653 /*FIXME: Should also show v4l2_fract pixelaspect */
Hans Verkuila3998102008-07-21 02:57:38 -03001654 if (!ops->vidioc_cropcap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001655 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001656
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001657 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001658 ret = ops->vidioc_cropcap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001659 if (!ret) {
1660 dbgrect(vfd, "bounds ", &p->bounds);
1661 dbgrect(vfd, "defrect ", &p->defrect);
1662 }
1663 break;
1664 }
1665 case VIDIOC_G_JPEGCOMP:
1666 {
1667 struct v4l2_jpegcompression *p = arg;
1668
Hans Verkuila3998102008-07-21 02:57:38 -03001669 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001670 break;
Mauro Carvalho Chehaba56a18c2008-11-11 21:15:03 -03001671
Hans Verkuila3998102008-07-21 02:57:38 -03001672 ret = ops->vidioc_g_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001673 if (!ret)
1674 dbgarg(cmd, "quality=%d, APPn=%d, "
1675 "APP_len=%d, COM_len=%d, "
1676 "jpeg_markers=%d\n",
1677 p->quality, p->APPn, p->APP_len,
1678 p->COM_len, p->jpeg_markers);
1679 break;
1680 }
1681 case VIDIOC_S_JPEGCOMP:
1682 {
1683 struct v4l2_jpegcompression *p = arg;
1684
Hans Verkuila3998102008-07-21 02:57:38 -03001685 if (!ops->vidioc_g_jpegcomp)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001686 break;
1687 dbgarg(cmd, "quality=%d, APPn=%d, APP_len=%d, "
1688 "COM_len=%d, jpeg_markers=%d\n",
1689 p->quality, p->APPn, p->APP_len,
1690 p->COM_len, p->jpeg_markers);
Hans Verkuila3998102008-07-21 02:57:38 -03001691 ret = ops->vidioc_s_jpegcomp(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001692 break;
1693 }
1694 case VIDIOC_G_ENC_INDEX:
1695 {
1696 struct v4l2_enc_idx *p = arg;
1697
Hans Verkuila3998102008-07-21 02:57:38 -03001698 if (!ops->vidioc_g_enc_index)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001699 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001700 ret = ops->vidioc_g_enc_index(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001701 if (!ret)
1702 dbgarg(cmd, "entries=%d, entries_cap=%d\n",
1703 p->entries, p->entries_cap);
1704 break;
1705 }
1706 case VIDIOC_ENCODER_CMD:
1707 {
1708 struct v4l2_encoder_cmd *p = arg;
1709
Hans Verkuila3998102008-07-21 02:57:38 -03001710 if (!ops->vidioc_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001711 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001712 ret = ops->vidioc_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001713 if (!ret)
1714 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1715 break;
1716 }
1717 case VIDIOC_TRY_ENCODER_CMD:
1718 {
1719 struct v4l2_encoder_cmd *p = arg;
1720
Hans Verkuila3998102008-07-21 02:57:38 -03001721 if (!ops->vidioc_try_encoder_cmd)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001722 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001723 ret = ops->vidioc_try_encoder_cmd(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001724 if (!ret)
1725 dbgarg(cmd, "cmd=%d, flags=%x\n", p->cmd, p->flags);
1726 break;
1727 }
1728 case VIDIOC_G_PARM:
1729 {
1730 struct v4l2_streamparm *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001731
Hans Verkuila3998102008-07-21 02:57:38 -03001732 if (ops->vidioc_g_parm) {
Trent Piepho34796bc2009-03-28 22:25:35 -03001733 ret = check_fmt(ops, p->type);
1734 if (ret)
1735 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001736 ret = ops->vidioc_g_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001737 } else {
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001738 v4l2_std_id std = vfd->current_norm;
1739
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001740 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuil3f5e1822010-04-06 08:14:11 -03001741 break;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001742
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001743 ret = 0;
Hans Verkuil9bedc7f2009-08-07 07:28:16 -03001744 if (ops->vidioc_g_std)
1745 ret = ops->vidioc_g_std(file, fh, &std);
1746 else if (std == 0)
1747 ret = -EINVAL;
1748 if (ret == 0)
1749 v4l2_video_std_frame_period(std,
1750 &p->parm.capture.timeperframe);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001751 }
1752
1753 dbgarg(cmd, "type=%d\n", p->type);
1754 break;
1755 }
1756 case VIDIOC_S_PARM:
1757 {
1758 struct v4l2_streamparm *p = arg;
1759
Hans Verkuila3998102008-07-21 02:57:38 -03001760 if (!ops->vidioc_s_parm)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001761 break;
Trent Piepho34796bc2009-03-28 22:25:35 -03001762 ret = check_fmt(ops, p->type);
1763 if (ret)
1764 break;
1765
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001766 dbgarg(cmd, "type=%d\n", p->type);
Hans Verkuila3998102008-07-21 02:57:38 -03001767 ret = ops->vidioc_s_parm(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001768 break;
1769 }
1770 case VIDIOC_G_TUNER:
1771 {
1772 struct v4l2_tuner *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001773
Hans Verkuila3998102008-07-21 02:57:38 -03001774 if (!ops->vidioc_g_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001775 break;
1776
Hans Verkuila3998102008-07-21 02:57:38 -03001777 ret = ops->vidioc_g_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001778 if (!ret)
1779 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1780 "capability=0x%x, rangelow=%d, "
1781 "rangehigh=%d, signal=%d, afc=%d, "
1782 "rxsubchans=0x%x, audmode=%d\n",
1783 p->index, p->name, p->type,
1784 p->capability, p->rangelow,
1785 p->rangehigh, p->signal, p->afc,
1786 p->rxsubchans, p->audmode);
1787 break;
1788 }
1789 case VIDIOC_S_TUNER:
1790 {
1791 struct v4l2_tuner *p = arg;
1792
Hans Verkuila3998102008-07-21 02:57:38 -03001793 if (!ops->vidioc_s_tuner)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001794 break;
1795 dbgarg(cmd, "index=%d, name=%s, type=%d, "
1796 "capability=0x%x, rangelow=%d, "
1797 "rangehigh=%d, signal=%d, afc=%d, "
1798 "rxsubchans=0x%x, audmode=%d\n",
1799 p->index, p->name, p->type,
1800 p->capability, p->rangelow,
1801 p->rangehigh, p->signal, p->afc,
1802 p->rxsubchans, p->audmode);
Hans Verkuila3998102008-07-21 02:57:38 -03001803 ret = ops->vidioc_s_tuner(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001804 break;
1805 }
1806 case VIDIOC_G_FREQUENCY:
1807 {
1808 struct v4l2_frequency *p = arg;
1809
Hans Verkuila3998102008-07-21 02:57:38 -03001810 if (!ops->vidioc_g_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001811 break;
1812
Hans Verkuila3998102008-07-21 02:57:38 -03001813 ret = ops->vidioc_g_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001814 if (!ret)
1815 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1816 p->tuner, p->type, p->frequency);
1817 break;
1818 }
1819 case VIDIOC_S_FREQUENCY:
1820 {
1821 struct v4l2_frequency *p = arg;
1822
Hans Verkuila3998102008-07-21 02:57:38 -03001823 if (!ops->vidioc_s_frequency)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001824 break;
1825 dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
1826 p->tuner, p->type, p->frequency);
Hans Verkuila3998102008-07-21 02:57:38 -03001827 ret = ops->vidioc_s_frequency(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001828 break;
1829 }
1830 case VIDIOC_G_SLICED_VBI_CAP:
1831 {
1832 struct v4l2_sliced_vbi_cap *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001833
Hans Verkuila3998102008-07-21 02:57:38 -03001834 if (!ops->vidioc_g_sliced_vbi_cap)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001835 break;
Trent Piepho19c96e42009-03-04 01:21:02 -03001836
1837 /* Clear up to type, everything after type is zerod already */
1838 memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
1839
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001840 dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names));
Hans Verkuila3998102008-07-21 02:57:38 -03001841 ret = ops->vidioc_g_sliced_vbi_cap(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001842 if (!ret)
1843 dbgarg2("service_set=%d\n", p->service_set);
1844 break;
1845 }
1846 case VIDIOC_LOG_STATUS:
1847 {
Hans Verkuila3998102008-07-21 02:57:38 -03001848 if (!ops->vidioc_log_status)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001849 break;
Hans Verkuila3998102008-07-21 02:57:38 -03001850 ret = ops->vidioc_log_status(file, fh);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001851 break;
1852 }
1853#ifdef CONFIG_VIDEO_ADV_DEBUG
1854 case VIDIOC_DBG_G_REGISTER:
1855 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001856 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001857
Hans Verkuila1198cc2011-01-08 09:53:32 -03001858 if (ops->vidioc_g_register) {
1859 if (!capable(CAP_SYS_ADMIN))
1860 ret = -EPERM;
1861 else
1862 ret = ops->vidioc_g_register(file, fh, p);
1863 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001864 break;
1865 }
1866 case VIDIOC_DBG_S_REGISTER:
1867 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001868 struct v4l2_dbg_register *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001869
Hans Verkuila1198cc2011-01-08 09:53:32 -03001870 if (ops->vidioc_s_register) {
1871 if (!capable(CAP_SYS_ADMIN))
1872 ret = -EPERM;
1873 else
1874 ret = ops->vidioc_s_register(file, fh, p);
1875 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001876 break;
1877 }
1878#endif
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001879 case VIDIOC_DBG_G_CHIP_IDENT:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001880 {
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001881 struct v4l2_dbg_chip_ident *p = arg;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001882
Hans Verkuila3998102008-07-21 02:57:38 -03001883 if (!ops->vidioc_g_chip_ident)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001884 break;
Hans Verkuil80b36e02009-02-07 11:00:02 -03001885 p->ident = V4L2_IDENT_NONE;
1886 p->revision = 0;
Hans Verkuila3998102008-07-21 02:57:38 -03001887 ret = ops->vidioc_g_chip_ident(file, fh, p);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001888 if (!ret)
1889 dbgarg(cmd, "chip_ident=%u, revision=0x%x\n", p->ident, p->revision);
1890 break;
1891 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001892 case VIDIOC_S_HW_FREQ_SEEK:
1893 {
1894 struct v4l2_hw_freq_seek *p = arg;
1895
Hans Verkuila3998102008-07-21 02:57:38 -03001896 if (!ops->vidioc_s_hw_freq_seek)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03001897 break;
1898 dbgarg(cmd,
1899 "tuner=%d, type=%d, seek_upward=%d, wrap_around=%d\n",
1900 p->tuner, p->type, p->seek_upward, p->wrap_around);
Hans Verkuila3998102008-07-21 02:57:38 -03001901 ret = ops->vidioc_s_hw_freq_seek(file, fh, p);
1902 break;
1903 }
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001904 case VIDIOC_ENUM_FRAMESIZES:
1905 {
1906 struct v4l2_frmsizeenum *p = arg;
1907
1908 if (!ops->vidioc_enum_framesizes)
1909 break;
1910
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001911 ret = ops->vidioc_enum_framesizes(file, fh, p);
1912 dbgarg(cmd,
Mauro Carvalho Chehabd1afe422009-06-21 22:37:12 -03001913 "index=%d, pixelformat=%c%c%c%c, type=%d ",
1914 p->index,
1915 (p->pixel_format & 0xff),
1916 (p->pixel_format >> 8) & 0xff,
1917 (p->pixel_format >> 16) & 0xff,
1918 (p->pixel_format >> 24) & 0xff,
1919 p->type);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001920 switch (p->type) {
1921 case V4L2_FRMSIZE_TYPE_DISCRETE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001922 dbgarg3("width = %d, height=%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001923 p->discrete.width, p->discrete.height);
1924 break;
1925 case V4L2_FRMSIZE_TYPE_STEPWISE:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001926 dbgarg3("min %dx%d, max %dx%d, step %dx%d\n",
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001927 p->stepwise.min_width, p->stepwise.min_height,
1928 p->stepwise.step_width, p->stepwise.step_height,
1929 p->stepwise.max_width, p->stepwise.max_height);
1930 break;
1931 case V4L2_FRMSIZE_TYPE_CONTINUOUS:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001932 dbgarg3("continuous\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001933 break;
1934 default:
Mauro Carvalho Chehabd33fbcb2009-07-02 17:07:32 -03001935 dbgarg3("- Unknown type!\n");
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001936 }
1937
1938 break;
1939 }
1940 case VIDIOC_ENUM_FRAMEINTERVALS:
1941 {
1942 struct v4l2_frmivalenum *p = arg;
1943
1944 if (!ops->vidioc_enum_frameintervals)
1945 break;
1946
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001947 ret = ops->vidioc_enum_frameintervals(file, fh, p);
1948 dbgarg(cmd,
1949 "index=%d, pixelformat=%d, width=%d, height=%d, type=%d ",
1950 p->index, p->pixel_format,
1951 p->width, p->height, p->type);
1952 switch (p->type) {
1953 case V4L2_FRMIVAL_TYPE_DISCRETE:
1954 dbgarg2("fps=%d/%d\n",
1955 p->discrete.numerator,
1956 p->discrete.denominator);
1957 break;
1958 case V4L2_FRMIVAL_TYPE_STEPWISE:
Mauro Carvalho Chehab19585782008-11-12 01:03:02 -03001959 dbgarg2("min=%d/%d, max=%d/%d, step=%d/%d\n",
1960 p->stepwise.min.numerator,
1961 p->stepwise.min.denominator,
1962 p->stepwise.max.numerator,
1963 p->stepwise.max.denominator,
1964 p->stepwise.step.numerator,
1965 p->stepwise.step.denominator);
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03001966 break;
1967 case V4L2_FRMIVAL_TYPE_CONTINUOUS:
1968 dbgarg2("continuous\n");
1969 break;
1970 default:
1971 dbgarg2("- Unknown type!\n");
1972 }
1973 break;
1974 }
Muralidharan Karicherib6456c02009-11-19 12:00:31 -03001975 case VIDIOC_ENUM_DV_PRESETS:
1976 {
1977 struct v4l2_dv_enum_preset *p = arg;
1978
1979 if (!ops->vidioc_enum_dv_presets)
1980 break;
1981
1982 ret = ops->vidioc_enum_dv_presets(file, fh, p);
1983 if (!ret)
1984 dbgarg(cmd,
1985 "index=%d, preset=%d, name=%s, width=%d,"
1986 " height=%d ",
1987 p->index, p->preset, p->name, p->width,
1988 p->height);
1989 break;
1990 }
1991 case VIDIOC_S_DV_PRESET:
1992 {
1993 struct v4l2_dv_preset *p = arg;
1994
1995 if (!ops->vidioc_s_dv_preset)
1996 break;
1997
1998 dbgarg(cmd, "preset=%d\n", p->preset);
1999 ret = ops->vidioc_s_dv_preset(file, fh, p);
2000 break;
2001 }
2002 case VIDIOC_G_DV_PRESET:
2003 {
2004 struct v4l2_dv_preset *p = arg;
2005
2006 if (!ops->vidioc_g_dv_preset)
2007 break;
2008
2009 ret = ops->vidioc_g_dv_preset(file, fh, p);
2010 if (!ret)
2011 dbgarg(cmd, "preset=%d\n", p->preset);
2012 break;
2013 }
2014 case VIDIOC_QUERY_DV_PRESET:
2015 {
2016 struct v4l2_dv_preset *p = arg;
2017
2018 if (!ops->vidioc_query_dv_preset)
2019 break;
2020
2021 ret = ops->vidioc_query_dv_preset(file, fh, p);
2022 if (!ret)
2023 dbgarg(cmd, "preset=%d\n", p->preset);
2024 break;
2025 }
2026 case VIDIOC_S_DV_TIMINGS:
2027 {
2028 struct v4l2_dv_timings *p = arg;
2029
2030 if (!ops->vidioc_s_dv_timings)
2031 break;
2032
2033 switch (p->type) {
2034 case V4L2_DV_BT_656_1120:
2035 dbgarg2("bt-656/1120:interlaced=%d, pixelclock=%lld,"
2036 " width=%d, height=%d, polarities=%x,"
2037 " hfrontporch=%d, hsync=%d, hbackporch=%d,"
2038 " vfrontporch=%d, vsync=%d, vbackporch=%d,"
2039 " il_vfrontporch=%d, il_vsync=%d,"
2040 " il_vbackporch=%d\n",
2041 p->bt.interlaced, p->bt.pixelclock,
2042 p->bt.width, p->bt.height, p->bt.polarities,
2043 p->bt.hfrontporch, p->bt.hsync,
2044 p->bt.hbackporch, p->bt.vfrontporch,
2045 p->bt.vsync, p->bt.vbackporch,
2046 p->bt.il_vfrontporch, p->bt.il_vsync,
2047 p->bt.il_vbackporch);
2048 ret = ops->vidioc_s_dv_timings(file, fh, p);
2049 break;
2050 default:
2051 dbgarg2("Unknown type %d!\n", p->type);
2052 break;
2053 }
2054 break;
2055 }
2056 case VIDIOC_G_DV_TIMINGS:
2057 {
2058 struct v4l2_dv_timings *p = arg;
2059
2060 if (!ops->vidioc_g_dv_timings)
2061 break;
2062
2063 ret = ops->vidioc_g_dv_timings(file, fh, p);
2064 if (!ret) {
2065 switch (p->type) {
2066 case V4L2_DV_BT_656_1120:
2067 dbgarg2("bt-656/1120:interlaced=%d,"
2068 " pixelclock=%lld,"
2069 " width=%d, height=%d, polarities=%x,"
2070 " hfrontporch=%d, hsync=%d,"
2071 " hbackporch=%d, vfrontporch=%d,"
2072 " vsync=%d, vbackporch=%d,"
2073 " il_vfrontporch=%d, il_vsync=%d,"
2074 " il_vbackporch=%d\n",
2075 p->bt.interlaced, p->bt.pixelclock,
2076 p->bt.width, p->bt.height,
2077 p->bt.polarities, p->bt.hfrontporch,
2078 p->bt.hsync, p->bt.hbackporch,
2079 p->bt.vfrontporch, p->bt.vsync,
2080 p->bt.vbackporch, p->bt.il_vfrontporch,
2081 p->bt.il_vsync, p->bt.il_vbackporch);
2082 break;
2083 default:
2084 dbgarg2("Unknown type %d!\n", p->type);
2085 break;
2086 }
2087 }
2088 break;
2089 }
Sakari Ailusd3d7c962010-03-27 11:02:10 -03002090 case VIDIOC_DQEVENT:
2091 {
2092 struct v4l2_event *ev = arg;
Mauro Carvalho Chehab74d83fa2008-11-11 21:13:47 -03002093
Sakari Ailusd3d7c962010-03-27 11:02:10 -03002094 if (!ops->vidioc_subscribe_event)
2095 break;
2096
2097 ret = v4l2_event_dequeue(fh, ev, file->f_flags & O_NONBLOCK);
2098 if (ret < 0) {
2099 dbgarg(cmd, "no pending events?");
2100 break;
2101 }
2102 dbgarg(cmd,
2103 "pending=%d, type=0x%8.8x, sequence=%d, "
2104 "timestamp=%lu.%9.9lu ",
2105 ev->pending, ev->type, ev->sequence,
2106 ev->timestamp.tv_sec, ev->timestamp.tv_nsec);
2107 break;
2108 }
2109 case VIDIOC_SUBSCRIBE_EVENT:
2110 {
2111 struct v4l2_event_subscription *sub = arg;
2112
2113 if (!ops->vidioc_subscribe_event)
2114 break;
2115
2116 ret = ops->vidioc_subscribe_event(fh, sub);
2117 if (ret < 0) {
2118 dbgarg(cmd, "failed, ret=%ld", ret);
2119 break;
2120 }
2121 dbgarg(cmd, "type=0x%8.8x", sub->type);
2122 break;
2123 }
2124 case VIDIOC_UNSUBSCRIBE_EVENT:
2125 {
2126 struct v4l2_event_subscription *sub = arg;
2127
2128 if (!ops->vidioc_unsubscribe_event)
2129 break;
2130
2131 ret = ops->vidioc_unsubscribe_event(fh, sub);
2132 if (ret < 0) {
2133 dbgarg(cmd, "failed, ret=%ld", ret);
2134 break;
2135 }
2136 dbgarg(cmd, "type=0x%8.8x", sub->type);
2137 break;
2138 }
Hans Verkuila3998102008-07-21 02:57:38 -03002139 default:
2140 {
2141 if (!ops->vidioc_default)
2142 break;
2143 ret = ops->vidioc_default(file, fh, cmd, arg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002144 break;
2145 }
2146 } /* switch */
2147
2148 if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
2149 if (ret < 0) {
2150 v4l_print_ioctl(vfd->name, cmd);
Hans Verkuil069b7472008-12-30 07:04:34 -03002151 printk(KERN_CONT " error %ld\n", ret);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002152 }
2153 }
2154
2155 return ret;
2156}
2157
Trent Piepho19c96e42009-03-04 01:21:02 -03002158/* In some cases, only a few fields are used as input, i.e. when the app sets
2159 * "index" and then the driver fills in the rest of the structure for the thing
2160 * with that index. We only need to copy up the first non-input field. */
2161static unsigned long cmd_input_size(unsigned int cmd)
2162{
2163 /* Size of structure up to and including 'field' */
Hans Verkuil9f1a6932009-03-08 10:35:23 -03002164#define CMDINSIZE(cmd, type, field) \
2165 case VIDIOC_##cmd: \
2166 return offsetof(struct v4l2_##type, field) + \
2167 sizeof(((struct v4l2_##type *)0)->field);
Trent Piepho19c96e42009-03-04 01:21:02 -03002168
Hans Verkuil9f1a6932009-03-08 10:35:23 -03002169 switch (cmd) {
Trent Piepho19c96e42009-03-04 01:21:02 -03002170 CMDINSIZE(ENUM_FMT, fmtdesc, type);
2171 CMDINSIZE(G_FMT, format, type);
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002172 CMDINSIZE(QUERYBUF, buffer, length);
Trent Piepho19c96e42009-03-04 01:21:02 -03002173 CMDINSIZE(G_PARM, streamparm, type);
2174 CMDINSIZE(ENUMSTD, standard, index);
2175 CMDINSIZE(ENUMINPUT, input, index);
2176 CMDINSIZE(G_CTRL, control, id);
2177 CMDINSIZE(G_TUNER, tuner, index);
2178 CMDINSIZE(QUERYCTRL, queryctrl, id);
2179 CMDINSIZE(QUERYMENU, querymenu, index);
2180 CMDINSIZE(ENUMOUTPUT, output, index);
2181 CMDINSIZE(G_MODULATOR, modulator, index);
2182 CMDINSIZE(G_FREQUENCY, frequency, tuner);
2183 CMDINSIZE(CROPCAP, cropcap, type);
2184 CMDINSIZE(G_CROP, crop, type);
2185 CMDINSIZE(ENUMAUDIO, audio, index);
2186 CMDINSIZE(ENUMAUDOUT, audioout, index);
2187 CMDINSIZE(ENCODER_CMD, encoder_cmd, flags);
2188 CMDINSIZE(TRY_ENCODER_CMD, encoder_cmd, flags);
2189 CMDINSIZE(G_SLICED_VBI_CAP, sliced_vbi_cap, type);
2190 CMDINSIZE(ENUM_FRAMESIZES, frmsizeenum, pixel_format);
2191 CMDINSIZE(ENUM_FRAMEINTERVALS, frmivalenum, height);
2192 default:
2193 return _IOC_SIZE(cmd);
2194 }
2195}
2196
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002197static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
2198 void * __user *user_ptr, void ***kernel_ptr)
2199{
2200 int ret = 0;
2201
2202 switch (cmd) {
2203 case VIDIOC_QUERYBUF:
2204 case VIDIOC_QBUF:
2205 case VIDIOC_DQBUF: {
2206 struct v4l2_buffer *buf = parg;
2207
2208 if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
2209 if (buf->length > VIDEO_MAX_PLANES) {
2210 ret = -EINVAL;
2211 break;
2212 }
2213 *user_ptr = (void __user *)buf->m.planes;
2214 *kernel_ptr = (void **)&buf->m.planes;
2215 *array_size = sizeof(struct v4l2_plane) * buf->length;
2216 ret = 1;
2217 }
2218 break;
2219 }
2220
2221 case VIDIOC_S_EXT_CTRLS:
2222 case VIDIOC_G_EXT_CTRLS:
2223 case VIDIOC_TRY_EXT_CTRLS: {
2224 struct v4l2_ext_controls *ctrls = parg;
2225
2226 if (ctrls->count != 0) {
2227 *user_ptr = (void __user *)ctrls->controls;
2228 *kernel_ptr = (void **)&ctrls->controls;
2229 *array_size = sizeof(struct v4l2_ext_control)
2230 * ctrls->count;
2231 ret = 1;
2232 }
2233 break;
2234 }
2235 }
2236
2237 return ret;
2238}
2239
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002240long
2241video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
2242 v4l2_kioctl func)
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002243{
2244 char sbuf[128];
2245 void *mbuf = NULL;
Hans Verkuil1d94aa32010-04-06 08:12:21 -03002246 void *parg = (void *)arg;
Hans Verkuil069b7472008-12-30 07:04:34 -03002247 long err = -EINVAL;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002248 bool has_array_args;
2249 size_t array_size = 0;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002250 void __user *user_ptr = NULL;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002251 void **kernel_ptr = NULL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002252
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002253 /* Copy arguments into temp kernel buffer */
Trent Piepho337f9d22009-03-04 01:21:02 -03002254 if (_IOC_DIR(cmd) != _IOC_NONE) {
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002255 if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
2256 parg = sbuf;
2257 } else {
2258 /* too big to allocate from stack */
2259 mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
2260 if (NULL == mbuf)
2261 return -ENOMEM;
2262 parg = mbuf;
2263 }
2264
2265 err = -EFAULT;
Trent Piepho19c96e42009-03-04 01:21:02 -03002266 if (_IOC_DIR(cmd) & _IOC_WRITE) {
2267 unsigned long n = cmd_input_size(cmd);
2268
2269 if (copy_from_user(parg, (void __user *)arg, n))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002270 goto out;
Trent Piepho19c96e42009-03-04 01:21:02 -03002271
2272 /* zero out anything we don't copy from userspace */
2273 if (n < _IOC_SIZE(cmd))
2274 memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
Trent Piepho337f9d22009-03-04 01:21:02 -03002275 } else {
2276 /* read-only ioctl */
2277 memset(parg, 0, _IOC_SIZE(cmd));
Trent Piepho19c96e42009-03-04 01:21:02 -03002278 }
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002279 }
2280
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002281 err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
2282 if (err < 0)
2283 goto out;
2284 has_array_args = err;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002285
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002286 if (has_array_args) {
2287 /*
2288 * When adding new types of array args, make sure that the
2289 * parent argument to ioctl (which contains the pointer to the
2290 * array) fits into sbuf (so that mbuf will still remain
2291 * unused up to here).
2292 */
2293 mbuf = kmalloc(array_size, GFP_KERNEL);
2294 err = -ENOMEM;
2295 if (NULL == mbuf)
2296 goto out_array_args;
2297 err = -EFAULT;
2298 if (copy_from_user(mbuf, user_ptr, array_size))
2299 goto out_array_args;
2300 *kernel_ptr = mbuf;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002301 }
2302
2303 /* Handles IOCTL */
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002304 err = func(file, cmd, parg);
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002305 if (err == -ENOIOCTLCMD)
2306 err = -EINVAL;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002307
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002308 if (has_array_args) {
2309 *kernel_ptr = user_ptr;
2310 if (copy_to_user(user_ptr, mbuf, array_size))
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002311 err = -EFAULT;
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002312 goto out_array_args;
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002313 }
2314 if (err < 0)
2315 goto out;
2316
Pawel Osciakd14e6d72010-12-23 04:15:27 -03002317out_array_args:
Hans Verkuil35ea11f2008-07-20 08:12:02 -03002318 /* Copy results into user buffer */
2319 switch (_IOC_DIR(cmd)) {
2320 case _IOC_READ:
2321 case (_IOC_WRITE | _IOC_READ):
2322 if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
2323 err = -EFAULT;
2324 break;
2325 }
2326
2327out:
2328 kfree(mbuf);
2329 return err;
2330}
Laurent Pinchartfc0a8072010-07-12 11:09:41 -03002331EXPORT_SYMBOL(video_usercopy);
2332
2333long video_ioctl2(struct file *file,
2334 unsigned int cmd, unsigned long arg)
2335{
2336 return video_usercopy(file, cmd, arg, __video_do_ioctl);
2337}
Mauro Carvalho Chehab8a522c92008-10-21 11:58:39 -03002338EXPORT_SYMBOL(video_ioctl2);