15bc3cb74SMauro Carvalho Chehab /*
25bc3cb74SMauro Carvalho Chehab  * Video capture interface for Linux version 2
35bc3cb74SMauro Carvalho Chehab  *
45bc3cb74SMauro Carvalho Chehab  * A generic framework to process V4L2 ioctl commands.
55bc3cb74SMauro Carvalho Chehab  *
65bc3cb74SMauro Carvalho Chehab  * This program is free software; you can redistribute it and/or
75bc3cb74SMauro Carvalho Chehab  * modify it under the terms of the GNU General Public License
85bc3cb74SMauro Carvalho Chehab  * as published by the Free Software Foundation; either version
95bc3cb74SMauro Carvalho Chehab  * 2 of the License, or (at your option) any later version.
105bc3cb74SMauro Carvalho Chehab  *
115bc3cb74SMauro Carvalho Chehab  * Authors:	Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
125bc3cb74SMauro Carvalho Chehab  *              Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
135bc3cb74SMauro Carvalho Chehab  */
145bc3cb74SMauro Carvalho Chehab 
155bc3cb74SMauro Carvalho Chehab #include <linux/module.h>
165bc3cb74SMauro Carvalho Chehab #include <linux/slab.h>
175bc3cb74SMauro Carvalho Chehab #include <linux/types.h>
185bc3cb74SMauro Carvalho Chehab #include <linux/kernel.h>
195bc3cb74SMauro Carvalho Chehab #include <linux/version.h>
205bc3cb74SMauro Carvalho Chehab 
215bc3cb74SMauro Carvalho Chehab #include <linux/videodev2.h>
225bc3cb74SMauro Carvalho Chehab 
235bc3cb74SMauro Carvalho Chehab #include <media/v4l2-common.h>
245bc3cb74SMauro Carvalho Chehab #include <media/v4l2-ioctl.h>
255bc3cb74SMauro Carvalho Chehab #include <media/v4l2-ctrls.h>
265bc3cb74SMauro Carvalho Chehab #include <media/v4l2-fh.h>
275bc3cb74SMauro Carvalho Chehab #include <media/v4l2-event.h>
285bc3cb74SMauro Carvalho Chehab #include <media/v4l2-device.h>
295bc3cb74SMauro Carvalho Chehab #include <media/v4l2-chip-ident.h>
305bc3cb74SMauro Carvalho Chehab #include <media/videobuf2-core.h>
315bc3cb74SMauro Carvalho Chehab 
325bc3cb74SMauro Carvalho Chehab /* Zero out the end of the struct pointed to by p.  Everything after, but
335bc3cb74SMauro Carvalho Chehab  * not including, the specified field is cleared. */
345bc3cb74SMauro Carvalho Chehab #define CLEAR_AFTER_FIELD(p, field) \
355bc3cb74SMauro Carvalho Chehab 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
365bc3cb74SMauro Carvalho Chehab 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
375bc3cb74SMauro Carvalho Chehab 
3873f35418SHans Verkuil #define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
3973f35418SHans Verkuil 
405bc3cb74SMauro Carvalho Chehab struct std_descr {
415bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
425bc3cb74SMauro Carvalho Chehab 	const char *descr;
435bc3cb74SMauro Carvalho Chehab };
445bc3cb74SMauro Carvalho Chehab 
455bc3cb74SMauro Carvalho Chehab static const struct std_descr standards[] = {
465bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC, 	"NTSC"      },
475bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M, 	"NTSC-M"    },
485bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_JP, 	"NTSC-M-JP" },
495bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_KR,	"NTSC-M-KR" },
505bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_443, 	"NTSC-443"  },
515bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL, 	"PAL"       },
525bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_BG, 	"PAL-BG"    },
535bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B, 	"PAL-B"     },
545bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B1, 	"PAL-B1"    },
555bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_G, 	"PAL-G"     },
565bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_H, 	"PAL-H"     },
575bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_I, 	"PAL-I"     },
585bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_DK, 	"PAL-DK"    },
595bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D, 	"PAL-D"     },
605bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D1, 	"PAL-D1"    },
615bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_K, 	"PAL-K"     },
625bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_M, 	"PAL-M"     },
635bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_N, 	"PAL-N"     },
645bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_Nc, 	"PAL-Nc"    },
655bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_60, 	"PAL-60"    },
665bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM, 	"SECAM"     },
675bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_B, 	"SECAM-B"   },
685bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_G, 	"SECAM-G"   },
695bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_H, 	"SECAM-H"   },
705bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_DK, 	"SECAM-DK"  },
715bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_D, 	"SECAM-D"   },
725bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K, 	"SECAM-K"   },
735bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K1, 	"SECAM-K1"  },
745bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_L, 	"SECAM-L"   },
755bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_LC, 	"SECAM-Lc"  },
765bc3cb74SMauro Carvalho Chehab 	{ 0, 			"Unknown"   }
775bc3cb74SMauro Carvalho Chehab };
785bc3cb74SMauro Carvalho Chehab 
795bc3cb74SMauro Carvalho Chehab /* video4linux standard ID conversion to standard name
805bc3cb74SMauro Carvalho Chehab  */
815bc3cb74SMauro Carvalho Chehab const char *v4l2_norm_to_name(v4l2_std_id id)
825bc3cb74SMauro Carvalho Chehab {
835bc3cb74SMauro Carvalho Chehab 	u32 myid = id;
845bc3cb74SMauro Carvalho Chehab 	int i;
855bc3cb74SMauro Carvalho Chehab 
865bc3cb74SMauro Carvalho Chehab 	/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
875bc3cb74SMauro Carvalho Chehab 	   64 bit comparations. So, on that architecture, with some gcc
885bc3cb74SMauro Carvalho Chehab 	   variants, compilation fails. Currently, the max value is 30bit wide.
895bc3cb74SMauro Carvalho Chehab 	 */
905bc3cb74SMauro Carvalho Chehab 	BUG_ON(myid != id);
915bc3cb74SMauro Carvalho Chehab 
925bc3cb74SMauro Carvalho Chehab 	for (i = 0; standards[i].std; i++)
935bc3cb74SMauro Carvalho Chehab 		if (myid == standards[i].std)
945bc3cb74SMauro Carvalho Chehab 			break;
955bc3cb74SMauro Carvalho Chehab 	return standards[i].descr;
965bc3cb74SMauro Carvalho Chehab }
975bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_norm_to_name);
985bc3cb74SMauro Carvalho Chehab 
995bc3cb74SMauro Carvalho Chehab /* Returns frame period for the given standard */
1005bc3cb74SMauro Carvalho Chehab void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
1015bc3cb74SMauro Carvalho Chehab {
1025bc3cb74SMauro Carvalho Chehab 	if (id & V4L2_STD_525_60) {
1035bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1001;
1045bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 30000;
1055bc3cb74SMauro Carvalho Chehab 	} else {
1065bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1;
1075bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 25;
1085bc3cb74SMauro Carvalho Chehab 	}
1095bc3cb74SMauro Carvalho Chehab }
1105bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_frame_period);
1115bc3cb74SMauro Carvalho Chehab 
1125bc3cb74SMauro Carvalho Chehab /* Fill in the fields of a v4l2_standard structure according to the
1135bc3cb74SMauro Carvalho Chehab    'id' and 'transmission' parameters.  Returns negative on error.  */
1145bc3cb74SMauro Carvalho Chehab int v4l2_video_std_construct(struct v4l2_standard *vs,
1155bc3cb74SMauro Carvalho Chehab 			     int id, const char *name)
1165bc3cb74SMauro Carvalho Chehab {
1175bc3cb74SMauro Carvalho Chehab 	vs->id = id;
1185bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_frame_period(id, &vs->frameperiod);
1195bc3cb74SMauro Carvalho Chehab 	vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
1205bc3cb74SMauro Carvalho Chehab 	strlcpy(vs->name, name, sizeof(vs->name));
1215bc3cb74SMauro Carvalho Chehab 	return 0;
1225bc3cb74SMauro Carvalho Chehab }
1235bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_construct);
1245bc3cb74SMauro Carvalho Chehab 
1255bc3cb74SMauro Carvalho Chehab /* ----------------------------------------------------------------- */
1265bc3cb74SMauro Carvalho Chehab /* some arrays for pretty-printing debug messages of enum types      */
1275bc3cb74SMauro Carvalho Chehab 
1285bc3cb74SMauro Carvalho Chehab const char *v4l2_field_names[] = {
1295bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ANY]        = "any",
1305bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_NONE]       = "none",
1315bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_TOP]        = "top",
1325bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_BOTTOM]     = "bottom",
1335bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED] = "interlaced",
1345bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_TB]     = "seq-tb",
1355bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_BT]     = "seq-bt",
1365bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ALTERNATE]  = "alternate",
1375bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
1385bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
1395bc3cb74SMauro Carvalho Chehab };
1405bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_field_names);
1415bc3cb74SMauro Carvalho Chehab 
1425bc3cb74SMauro Carvalho Chehab const char *v4l2_type_names[] = {
1435bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "vid-cap",
1445bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "vid-overlay",
1455bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "vid-out",
1465bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
1475bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
1485bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
1495bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
1505bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
1515bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
1525bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
1535bc3cb74SMauro Carvalho Chehab };
1545bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_type_names);
1555bc3cb74SMauro Carvalho Chehab 
1565bc3cb74SMauro Carvalho Chehab static const char *v4l2_memory_names[] = {
1575bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_MMAP]    = "mmap",
1585bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_USERPTR] = "userptr",
1595bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_OVERLAY] = "overlay",
160051c7788SSumit Semwal 	[V4L2_MEMORY_DMABUF] = "dmabuf",
1615bc3cb74SMauro Carvalho Chehab };
1625bc3cb74SMauro Carvalho Chehab 
163d9246240SHans Verkuil #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
1645bc3cb74SMauro Carvalho Chehab 
1655bc3cb74SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
1665bc3cb74SMauro Carvalho Chehab /* debug help functions                                               */
1675bc3cb74SMauro Carvalho Chehab 
1685bc3cb74SMauro Carvalho Chehab static void v4l_print_querycap(const void *arg, bool write_only)
1695bc3cb74SMauro Carvalho Chehab {
1705bc3cb74SMauro Carvalho Chehab 	const struct v4l2_capability *p = arg;
1715bc3cb74SMauro Carvalho Chehab 
17227d5a87cSHans Verkuil 	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, "
1735bc3cb74SMauro Carvalho Chehab 		"capabilities=0x%08x, device_caps=0x%08x\n",
17427d5a87cSHans Verkuil 		(int)sizeof(p->driver), p->driver,
17527d5a87cSHans Verkuil 		(int)sizeof(p->card), p->card,
17627d5a87cSHans Verkuil 		(int)sizeof(p->bus_info), p->bus_info,
1775bc3cb74SMauro Carvalho Chehab 		p->version, p->capabilities, p->device_caps);
1785bc3cb74SMauro Carvalho Chehab }
1795bc3cb74SMauro Carvalho Chehab 
1805bc3cb74SMauro Carvalho Chehab static void v4l_print_enuminput(const void *arg, bool write_only)
1815bc3cb74SMauro Carvalho Chehab {
1825bc3cb74SMauro Carvalho Chehab 	const struct v4l2_input *p = arg;
1835bc3cb74SMauro Carvalho Chehab 
18427d5a87cSHans Verkuil 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, "
1855bc3cb74SMauro Carvalho Chehab 		"std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
18627d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
18727d5a87cSHans Verkuil 		p->tuner, (unsigned long long)p->std, p->status,
18827d5a87cSHans Verkuil 		p->capabilities);
1895bc3cb74SMauro Carvalho Chehab }
1905bc3cb74SMauro Carvalho Chehab 
1915bc3cb74SMauro Carvalho Chehab static void v4l_print_enumoutput(const void *arg, bool write_only)
1925bc3cb74SMauro Carvalho Chehab {
1935bc3cb74SMauro Carvalho Chehab 	const struct v4l2_output *p = arg;
1945bc3cb74SMauro Carvalho Chehab 
19527d5a87cSHans Verkuil 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, "
1965bc3cb74SMauro Carvalho Chehab 		"modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
19727d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
19827d5a87cSHans Verkuil 		p->modulator, (unsigned long long)p->std, p->capabilities);
1995bc3cb74SMauro Carvalho Chehab }
2005bc3cb74SMauro Carvalho Chehab 
2015bc3cb74SMauro Carvalho Chehab static void v4l_print_audio(const void *arg, bool write_only)
2025bc3cb74SMauro Carvalho Chehab {
2035bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audio *p = arg;
2045bc3cb74SMauro Carvalho Chehab 
2055bc3cb74SMauro Carvalho Chehab 	if (write_only)
2065bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, mode=0x%x\n", p->index, p->mode);
2075bc3cb74SMauro Carvalho Chehab 	else
20827d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
20927d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
21027d5a87cSHans Verkuil 			p->capability, p->mode);
2115bc3cb74SMauro Carvalho Chehab }
2125bc3cb74SMauro Carvalho Chehab 
2135bc3cb74SMauro Carvalho Chehab static void v4l_print_audioout(const void *arg, bool write_only)
2145bc3cb74SMauro Carvalho Chehab {
2155bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audioout *p = arg;
2165bc3cb74SMauro Carvalho Chehab 
2175bc3cb74SMauro Carvalho Chehab 	if (write_only)
2185bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u\n", p->index);
2195bc3cb74SMauro Carvalho Chehab 	else
22027d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
22127d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
22227d5a87cSHans Verkuil 			p->capability, p->mode);
2235bc3cb74SMauro Carvalho Chehab }
2245bc3cb74SMauro Carvalho Chehab 
2255bc3cb74SMauro Carvalho Chehab static void v4l_print_fmtdesc(const void *arg, bool write_only)
2265bc3cb74SMauro Carvalho Chehab {
2275bc3cb74SMauro Carvalho Chehab 	const struct v4l2_fmtdesc *p = arg;
2285bc3cb74SMauro Carvalho Chehab 
22927d5a87cSHans Verkuil 	pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n",
2305bc3cb74SMauro Carvalho Chehab 		p->index, prt_names(p->type, v4l2_type_names),
2315bc3cb74SMauro Carvalho Chehab 		p->flags, (p->pixelformat & 0xff),
2325bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >>  8) & 0xff,
2335bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 16) & 0xff,
2345bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 24) & 0xff,
23527d5a87cSHans Verkuil 		(int)sizeof(p->description), p->description);
2365bc3cb74SMauro Carvalho Chehab }
2375bc3cb74SMauro Carvalho Chehab 
2385bc3cb74SMauro Carvalho Chehab static void v4l_print_format(const void *arg, bool write_only)
2395bc3cb74SMauro Carvalho Chehab {
2405bc3cb74SMauro Carvalho Chehab 	const struct v4l2_format *p = arg;
2415bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format *pix;
2425bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format_mplane *mp;
2435bc3cb74SMauro Carvalho Chehab 	const struct v4l2_vbi_format *vbi;
2445bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_format *sliced;
2455bc3cb74SMauro Carvalho Chehab 	const struct v4l2_window *win;
2465bc3cb74SMauro Carvalho Chehab 	const struct v4l2_clip *clip;
2475bc3cb74SMauro Carvalho Chehab 	unsigned i;
2485bc3cb74SMauro Carvalho Chehab 
2495bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
2505bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
2515bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2525bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2535bc3cb74SMauro Carvalho Chehab 		pix = &p->fmt.pix;
2545bc3cb74SMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, "
2555bc3cb74SMauro Carvalho Chehab 			"pixelformat=%c%c%c%c, field=%s, "
2565bc3cb74SMauro Carvalho Chehab 			"bytesperline=%u sizeimage=%u, colorspace=%d\n",
2575bc3cb74SMauro Carvalho Chehab 			pix->width, pix->height,
2585bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat & 0xff),
2595bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >>  8) & 0xff,
2605bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 16) & 0xff,
2615bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 24) & 0xff,
2625bc3cb74SMauro Carvalho Chehab 			prt_names(pix->field, v4l2_field_names),
2635bc3cb74SMauro Carvalho Chehab 			pix->bytesperline, pix->sizeimage,
2645bc3cb74SMauro Carvalho Chehab 			pix->colorspace);
2655bc3cb74SMauro Carvalho Chehab 		break;
2665bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
2675bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2685bc3cb74SMauro Carvalho Chehab 		mp = &p->fmt.pix_mp;
2695bc3cb74SMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, "
2705bc3cb74SMauro Carvalho Chehab 			"format=%c%c%c%c, field=%s, "
2715bc3cb74SMauro Carvalho Chehab 			"colorspace=%d, num_planes=%u\n",
2725bc3cb74SMauro Carvalho Chehab 			mp->width, mp->height,
2735bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat & 0xff),
2745bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >>  8) & 0xff,
2755bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 16) & 0xff,
2765bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 24) & 0xff,
2775bc3cb74SMauro Carvalho Chehab 			prt_names(mp->field, v4l2_field_names),
2785bc3cb74SMauro Carvalho Chehab 			mp->colorspace, mp->num_planes);
2795bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < mp->num_planes; i++)
2805bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
2815bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].bytesperline,
2825bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].sizeimage);
2835bc3cb74SMauro Carvalho Chehab 		break;
2845bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2855bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
2865bc3cb74SMauro Carvalho Chehab 		win = &p->fmt.win;
2875bc3cb74SMauro Carvalho Chehab 		pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, "
2885bc3cb74SMauro Carvalho Chehab 			"chromakey=0x%08x, bitmap=%p, "
2895bc3cb74SMauro Carvalho Chehab 			"global_alpha=0x%02x\n",
2905bc3cb74SMauro Carvalho Chehab 			win->w.width, win->w.height,
2915bc3cb74SMauro Carvalho Chehab 			win->w.left, win->w.top,
2925bc3cb74SMauro Carvalho Chehab 			prt_names(win->field, v4l2_field_names),
2935bc3cb74SMauro Carvalho Chehab 			win->chromakey, win->bitmap, win->global_alpha);
2945bc3cb74SMauro Carvalho Chehab 		clip = win->clips;
2955bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < win->clipcount; i++) {
2965bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "clip %u: wxh=%dx%d, x,y=%d,%d\n",
2975bc3cb74SMauro Carvalho Chehab 					i, clip->c.width, clip->c.height,
2985bc3cb74SMauro Carvalho Chehab 					clip->c.left, clip->c.top);
2995bc3cb74SMauro Carvalho Chehab 			clip = clip->next;
3005bc3cb74SMauro Carvalho Chehab 		}
3015bc3cb74SMauro Carvalho Chehab 		break;
3025bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
3035bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
3045bc3cb74SMauro Carvalho Chehab 		vbi = &p->fmt.vbi;
3055bc3cb74SMauro Carvalho Chehab 		pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, "
3065bc3cb74SMauro Carvalho Chehab 			"sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n",
3075bc3cb74SMauro Carvalho Chehab 			vbi->sampling_rate, vbi->offset,
3085bc3cb74SMauro Carvalho Chehab 			vbi->samples_per_line,
3095bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format & 0xff),
3105bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >>  8) & 0xff,
3115bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 16) & 0xff,
3125bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 24) & 0xff,
3135bc3cb74SMauro Carvalho Chehab 			vbi->start[0], vbi->start[1],
3145bc3cb74SMauro Carvalho Chehab 			vbi->count[0], vbi->count[1]);
3155bc3cb74SMauro Carvalho Chehab 		break;
3165bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
3175bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
3185bc3cb74SMauro Carvalho Chehab 		sliced = &p->fmt.sliced;
3195bc3cb74SMauro Carvalho Chehab 		pr_cont(", service_set=0x%08x, io_size=%d\n",
3205bc3cb74SMauro Carvalho Chehab 				sliced->service_set, sliced->io_size);
3215bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < 24; i++)
3225bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
3235bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[0][i],
3245bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[1][i]);
3255bc3cb74SMauro Carvalho Chehab 		break;
3265bc3cb74SMauro Carvalho Chehab 	}
3275bc3cb74SMauro Carvalho Chehab }
3285bc3cb74SMauro Carvalho Chehab 
3295bc3cb74SMauro Carvalho Chehab static void v4l_print_framebuffer(const void *arg, bool write_only)
3305bc3cb74SMauro Carvalho Chehab {
3315bc3cb74SMauro Carvalho Chehab 	const struct v4l2_framebuffer *p = arg;
3325bc3cb74SMauro Carvalho Chehab 
3335bc3cb74SMauro Carvalho Chehab 	pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, "
3345bc3cb74SMauro Carvalho Chehab 		"height=%u, pixelformat=%c%c%c%c, "
3355bc3cb74SMauro Carvalho Chehab 		"bytesperline=%u sizeimage=%u, colorspace=%d\n",
3365bc3cb74SMauro Carvalho Chehab 			p->capability, p->flags, p->base,
3375bc3cb74SMauro Carvalho Chehab 			p->fmt.width, p->fmt.height,
3385bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat & 0xff),
3395bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >>  8) & 0xff,
3405bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 16) & 0xff,
3415bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 24) & 0xff,
3425bc3cb74SMauro Carvalho Chehab 			p->fmt.bytesperline, p->fmt.sizeimage,
3435bc3cb74SMauro Carvalho Chehab 			p->fmt.colorspace);
3445bc3cb74SMauro Carvalho Chehab }
3455bc3cb74SMauro Carvalho Chehab 
3465bc3cb74SMauro Carvalho Chehab static void v4l_print_buftype(const void *arg, bool write_only)
3475bc3cb74SMauro Carvalho Chehab {
3485bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names));
3495bc3cb74SMauro Carvalho Chehab }
3505bc3cb74SMauro Carvalho Chehab 
3515bc3cb74SMauro Carvalho Chehab static void v4l_print_modulator(const void *arg, bool write_only)
3525bc3cb74SMauro Carvalho Chehab {
3535bc3cb74SMauro Carvalho Chehab 	const struct v4l2_modulator *p = arg;
3545bc3cb74SMauro Carvalho Chehab 
3555bc3cb74SMauro Carvalho Chehab 	if (write_only)
3565bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, txsubchans=0x%x", p->index, p->txsubchans);
3575bc3cb74SMauro Carvalho Chehab 	else
35827d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, "
3595bc3cb74SMauro Carvalho Chehab 			"rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
36027d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->capability,
3615bc3cb74SMauro Carvalho Chehab 			p->rangelow, p->rangehigh, p->txsubchans);
3625bc3cb74SMauro Carvalho Chehab }
3635bc3cb74SMauro Carvalho Chehab 
3645bc3cb74SMauro Carvalho Chehab static void v4l_print_tuner(const void *arg, bool write_only)
3655bc3cb74SMauro Carvalho Chehab {
3665bc3cb74SMauro Carvalho Chehab 	const struct v4l2_tuner *p = arg;
3675bc3cb74SMauro Carvalho Chehab 
3685bc3cb74SMauro Carvalho Chehab 	if (write_only)
3695bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
3705bc3cb74SMauro Carvalho Chehab 	else
37127d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, "
3725bc3cb74SMauro Carvalho Chehab 			"rangelow=%u, rangehigh=%u, signal=%u, afc=%d, "
3735bc3cb74SMauro Carvalho Chehab 			"rxsubchans=0x%x, audmode=%u\n",
37427d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->type,
3755bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
3765bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->signal, p->afc,
3775bc3cb74SMauro Carvalho Chehab 			p->rxsubchans, p->audmode);
3785bc3cb74SMauro Carvalho Chehab }
3795bc3cb74SMauro Carvalho Chehab 
3805bc3cb74SMauro Carvalho Chehab static void v4l_print_frequency(const void *arg, bool write_only)
3815bc3cb74SMauro Carvalho Chehab {
3825bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency *p = arg;
3835bc3cb74SMauro Carvalho Chehab 
3845bc3cb74SMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, frequency=%u\n",
3855bc3cb74SMauro Carvalho Chehab 				p->tuner, p->type, p->frequency);
3865bc3cb74SMauro Carvalho Chehab }
3875bc3cb74SMauro Carvalho Chehab 
3885bc3cb74SMauro Carvalho Chehab static void v4l_print_standard(const void *arg, bool write_only)
3895bc3cb74SMauro Carvalho Chehab {
3905bc3cb74SMauro Carvalho Chehab 	const struct v4l2_standard *p = arg;
3915bc3cb74SMauro Carvalho Chehab 
39227d5a87cSHans Verkuil 	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, "
3935bc3cb74SMauro Carvalho Chehab 		"framelines=%u\n", p->index,
39427d5a87cSHans Verkuil 		(unsigned long long)p->id, (int)sizeof(p->name), p->name,
3955bc3cb74SMauro Carvalho Chehab 		p->frameperiod.numerator,
3965bc3cb74SMauro Carvalho Chehab 		p->frameperiod.denominator,
3975bc3cb74SMauro Carvalho Chehab 		p->framelines);
3985bc3cb74SMauro Carvalho Chehab }
3995bc3cb74SMauro Carvalho Chehab 
4005bc3cb74SMauro Carvalho Chehab static void v4l_print_std(const void *arg, bool write_only)
4015bc3cb74SMauro Carvalho Chehab {
4025bc3cb74SMauro Carvalho Chehab 	pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg);
4035bc3cb74SMauro Carvalho Chehab }
4045bc3cb74SMauro Carvalho Chehab 
4055bc3cb74SMauro Carvalho Chehab static void v4l_print_hw_freq_seek(const void *arg, bool write_only)
4065bc3cb74SMauro Carvalho Chehab {
4075bc3cb74SMauro Carvalho Chehab 	const struct v4l2_hw_freq_seek *p = arg;
4085bc3cb74SMauro Carvalho Chehab 
40979e8c7beSMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, "
41079e8c7beSMauro Carvalho Chehab 		"rangelow=%u, rangehigh=%u\n",
41179e8c7beSMauro Carvalho Chehab 		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing,
41279e8c7beSMauro Carvalho Chehab 		p->rangelow, p->rangehigh);
4135bc3cb74SMauro Carvalho Chehab }
4145bc3cb74SMauro Carvalho Chehab 
4155bc3cb74SMauro Carvalho Chehab static void v4l_print_requestbuffers(const void *arg, bool write_only)
4165bc3cb74SMauro Carvalho Chehab {
4175bc3cb74SMauro Carvalho Chehab 	const struct v4l2_requestbuffers *p = arg;
4185bc3cb74SMauro Carvalho Chehab 
4195bc3cb74SMauro Carvalho Chehab 	pr_cont("count=%d, type=%s, memory=%s\n",
4205bc3cb74SMauro Carvalho Chehab 		p->count,
4215bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
4225bc3cb74SMauro Carvalho Chehab 		prt_names(p->memory, v4l2_memory_names));
4235bc3cb74SMauro Carvalho Chehab }
4245bc3cb74SMauro Carvalho Chehab 
4255bc3cb74SMauro Carvalho Chehab static void v4l_print_buffer(const void *arg, bool write_only)
4265bc3cb74SMauro Carvalho Chehab {
4275bc3cb74SMauro Carvalho Chehab 	const struct v4l2_buffer *p = arg;
4285bc3cb74SMauro Carvalho Chehab 	const struct v4l2_timecode *tc = &p->timecode;
4295bc3cb74SMauro Carvalho Chehab 	const struct v4l2_plane *plane;
4305bc3cb74SMauro Carvalho Chehab 	int i;
4315bc3cb74SMauro Carvalho Chehab 
4325bc3cb74SMauro Carvalho Chehab 	pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, "
4335bc3cb74SMauro Carvalho Chehab 		"flags=0x%08x, field=%s, sequence=%d, memory=%s",
4345bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec / 3600,
4355bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec / 60) % 60,
4365bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec % 60),
4375bc3cb74SMauro Carvalho Chehab 			(long)p->timestamp.tv_usec,
4385bc3cb74SMauro Carvalho Chehab 			p->index,
4395bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names),
4405bc3cb74SMauro Carvalho Chehab 			p->flags, prt_names(p->field, v4l2_field_names),
4415bc3cb74SMauro Carvalho Chehab 			p->sequence, prt_names(p->memory, v4l2_memory_names));
4425bc3cb74SMauro Carvalho Chehab 
4435bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
4445bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
4455bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < p->length; ++i) {
4465bc3cb74SMauro Carvalho Chehab 			plane = &p->m.planes[i];
4475bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG
4485bc3cb74SMauro Carvalho Chehab 				"plane %d: bytesused=%d, data_offset=0x%08x "
4495bc3cb74SMauro Carvalho Chehab 				"offset/userptr=0x%lx, length=%d\n",
4505bc3cb74SMauro Carvalho Chehab 				i, plane->bytesused, plane->data_offset,
4515bc3cb74SMauro Carvalho Chehab 				plane->m.userptr, plane->length);
4525bc3cb74SMauro Carvalho Chehab 		}
4535bc3cb74SMauro Carvalho Chehab 	} else {
4545bc3cb74SMauro Carvalho Chehab 		pr_cont("bytesused=%d, offset/userptr=0x%lx, length=%d\n",
4555bc3cb74SMauro Carvalho Chehab 			p->bytesused, p->m.userptr, p->length);
4565bc3cb74SMauro Carvalho Chehab 	}
4575bc3cb74SMauro Carvalho Chehab 
4585bc3cb74SMauro Carvalho Chehab 	printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, "
4595bc3cb74SMauro Carvalho Chehab 		"flags=0x%08x, frames=%d, userbits=0x%08x\n",
4605bc3cb74SMauro Carvalho Chehab 			tc->hours, tc->minutes, tc->seconds,
4615bc3cb74SMauro Carvalho Chehab 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
4625bc3cb74SMauro Carvalho Chehab }
4635bc3cb74SMauro Carvalho Chehab 
464b799d09aSTomasz Stanislawski static void v4l_print_exportbuffer(const void *arg, bool write_only)
465b799d09aSTomasz Stanislawski {
466b799d09aSTomasz Stanislawski 	const struct v4l2_exportbuffer *p = arg;
467b799d09aSTomasz Stanislawski 
468b799d09aSTomasz Stanislawski 	pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n",
469b799d09aSTomasz Stanislawski 		p->fd, prt_names(p->type, v4l2_type_names),
470b799d09aSTomasz Stanislawski 		p->index, p->plane, p->flags);
471b799d09aSTomasz Stanislawski }
472b799d09aSTomasz Stanislawski 
4735bc3cb74SMauro Carvalho Chehab static void v4l_print_create_buffers(const void *arg, bool write_only)
4745bc3cb74SMauro Carvalho Chehab {
4755bc3cb74SMauro Carvalho Chehab 	const struct v4l2_create_buffers *p = arg;
4765bc3cb74SMauro Carvalho Chehab 
4775bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%d, count=%d, memory=%s, ",
4785bc3cb74SMauro Carvalho Chehab 			p->index, p->count,
4795bc3cb74SMauro Carvalho Chehab 			prt_names(p->memory, v4l2_memory_names));
4805bc3cb74SMauro Carvalho Chehab 	v4l_print_format(&p->format, write_only);
4815bc3cb74SMauro Carvalho Chehab }
4825bc3cb74SMauro Carvalho Chehab 
4835bc3cb74SMauro Carvalho Chehab static void v4l_print_streamparm(const void *arg, bool write_only)
4845bc3cb74SMauro Carvalho Chehab {
4855bc3cb74SMauro Carvalho Chehab 	const struct v4l2_streamparm *p = arg;
4865bc3cb74SMauro Carvalho Chehab 
4875bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
4885bc3cb74SMauro Carvalho Chehab 
4895bc3cb74SMauro Carvalho Chehab 	if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
4905bc3cb74SMauro Carvalho Chehab 	    p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4915bc3cb74SMauro Carvalho Chehab 		const struct v4l2_captureparm *c = &p->parm.capture;
4925bc3cb74SMauro Carvalho Chehab 
4935bc3cb74SMauro Carvalho Chehab 		pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, "
4945bc3cb74SMauro Carvalho Chehab 			"extendedmode=%d, readbuffers=%d\n",
4955bc3cb74SMauro Carvalho Chehab 			c->capability, c->capturemode,
4965bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
4975bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->readbuffers);
4985bc3cb74SMauro Carvalho Chehab 	} else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
4995bc3cb74SMauro Carvalho Chehab 		   p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5005bc3cb74SMauro Carvalho Chehab 		const struct v4l2_outputparm *c = &p->parm.output;
5015bc3cb74SMauro Carvalho Chehab 
5025bc3cb74SMauro Carvalho Chehab 		pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, "
5035bc3cb74SMauro Carvalho Chehab 			"extendedmode=%d, writebuffers=%d\n",
5045bc3cb74SMauro Carvalho Chehab 			c->capability, c->outputmode,
5055bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
5065bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->writebuffers);
5075bc3cb74SMauro Carvalho Chehab 	}
5085bc3cb74SMauro Carvalho Chehab }
5095bc3cb74SMauro Carvalho Chehab 
5105bc3cb74SMauro Carvalho Chehab static void v4l_print_queryctrl(const void *arg, bool write_only)
5115bc3cb74SMauro Carvalho Chehab {
5125bc3cb74SMauro Carvalho Chehab 	const struct v4l2_queryctrl *p = arg;
5135bc3cb74SMauro Carvalho Chehab 
51427d5a87cSHans Verkuil 	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, "
5155bc3cb74SMauro Carvalho Chehab 		"step=%d, default=%d, flags=0x%08x\n",
51627d5a87cSHans Verkuil 			p->id, p->type, (int)sizeof(p->name), p->name,
5175bc3cb74SMauro Carvalho Chehab 			p->minimum, p->maximum,
5185bc3cb74SMauro Carvalho Chehab 			p->step, p->default_value, p->flags);
5195bc3cb74SMauro Carvalho Chehab }
5205bc3cb74SMauro Carvalho Chehab 
5215bc3cb74SMauro Carvalho Chehab static void v4l_print_querymenu(const void *arg, bool write_only)
5225bc3cb74SMauro Carvalho Chehab {
5235bc3cb74SMauro Carvalho Chehab 	const struct v4l2_querymenu *p = arg;
5245bc3cb74SMauro Carvalho Chehab 
5255bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, index=%d\n", p->id, p->index);
5265bc3cb74SMauro Carvalho Chehab }
5275bc3cb74SMauro Carvalho Chehab 
5285bc3cb74SMauro Carvalho Chehab static void v4l_print_control(const void *arg, bool write_only)
5295bc3cb74SMauro Carvalho Chehab {
5305bc3cb74SMauro Carvalho Chehab 	const struct v4l2_control *p = arg;
5315bc3cb74SMauro Carvalho Chehab 
5325bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, value=%d\n", p->id, p->value);
5335bc3cb74SMauro Carvalho Chehab }
5345bc3cb74SMauro Carvalho Chehab 
5355bc3cb74SMauro Carvalho Chehab static void v4l_print_ext_controls(const void *arg, bool write_only)
5365bc3cb74SMauro Carvalho Chehab {
5375bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ext_controls *p = arg;
5385bc3cb74SMauro Carvalho Chehab 	int i;
5395bc3cb74SMauro Carvalho Chehab 
5405bc3cb74SMauro Carvalho Chehab 	pr_cont("class=0x%x, count=%d, error_idx=%d",
5415bc3cb74SMauro Carvalho Chehab 			p->ctrl_class, p->count, p->error_idx);
5425bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < p->count; i++) {
5435bc3cb74SMauro Carvalho Chehab 		if (p->controls[i].size)
5445bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/val=0x%x/0x%x",
5455bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].value);
5465bc3cb74SMauro Carvalho Chehab 		else
5475bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/size=0x%x/%u",
5485bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].size);
5495bc3cb74SMauro Carvalho Chehab 	}
5505bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
5515bc3cb74SMauro Carvalho Chehab }
5525bc3cb74SMauro Carvalho Chehab 
5535bc3cb74SMauro Carvalho Chehab static void v4l_print_cropcap(const void *arg, bool write_only)
5545bc3cb74SMauro Carvalho Chehab {
5555bc3cb74SMauro Carvalho Chehab 	const struct v4l2_cropcap *p = arg;
5565bc3cb74SMauro Carvalho Chehab 
5575bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, "
5585bc3cb74SMauro Carvalho Chehab 		"defrect wxh=%dx%d, x,y=%d,%d\n, "
5595bc3cb74SMauro Carvalho Chehab 		"pixelaspect %d/%d\n",
5605bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5615bc3cb74SMauro Carvalho Chehab 		p->bounds.width, p->bounds.height,
5625bc3cb74SMauro Carvalho Chehab 		p->bounds.left, p->bounds.top,
5635bc3cb74SMauro Carvalho Chehab 		p->defrect.width, p->defrect.height,
5645bc3cb74SMauro Carvalho Chehab 		p->defrect.left, p->defrect.top,
5655bc3cb74SMauro Carvalho Chehab 		p->pixelaspect.numerator, p->pixelaspect.denominator);
5665bc3cb74SMauro Carvalho Chehab }
5675bc3cb74SMauro Carvalho Chehab 
5685bc3cb74SMauro Carvalho Chehab static void v4l_print_crop(const void *arg, bool write_only)
5695bc3cb74SMauro Carvalho Chehab {
5705bc3cb74SMauro Carvalho Chehab 	const struct v4l2_crop *p = arg;
5715bc3cb74SMauro Carvalho Chehab 
5725bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n",
5735bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5745bc3cb74SMauro Carvalho Chehab 		p->c.width, p->c.height,
5755bc3cb74SMauro Carvalho Chehab 		p->c.left, p->c.top);
5765bc3cb74SMauro Carvalho Chehab }
5775bc3cb74SMauro Carvalho Chehab 
5785bc3cb74SMauro Carvalho Chehab static void v4l_print_selection(const void *arg, bool write_only)
5795bc3cb74SMauro Carvalho Chehab {
5805bc3cb74SMauro Carvalho Chehab 	const struct v4l2_selection *p = arg;
5815bc3cb74SMauro Carvalho Chehab 
5825bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n",
5835bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5845bc3cb74SMauro Carvalho Chehab 		p->target, p->flags,
5855bc3cb74SMauro Carvalho Chehab 		p->r.width, p->r.height, p->r.left, p->r.top);
5865bc3cb74SMauro Carvalho Chehab }
5875bc3cb74SMauro Carvalho Chehab 
5885bc3cb74SMauro Carvalho Chehab static void v4l_print_jpegcompression(const void *arg, bool write_only)
5895bc3cb74SMauro Carvalho Chehab {
5905bc3cb74SMauro Carvalho Chehab 	const struct v4l2_jpegcompression *p = arg;
5915bc3cb74SMauro Carvalho Chehab 
5925bc3cb74SMauro Carvalho Chehab 	pr_cont("quality=%d, APPn=%d, APP_len=%d, "
5935bc3cb74SMauro Carvalho Chehab 		"COM_len=%d, jpeg_markers=0x%x\n",
5945bc3cb74SMauro Carvalho Chehab 		p->quality, p->APPn, p->APP_len,
5955bc3cb74SMauro Carvalho Chehab 		p->COM_len, p->jpeg_markers);
5965bc3cb74SMauro Carvalho Chehab }
5975bc3cb74SMauro Carvalho Chehab 
5985bc3cb74SMauro Carvalho Chehab static void v4l_print_enc_idx(const void *arg, bool write_only)
5995bc3cb74SMauro Carvalho Chehab {
6005bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enc_idx *p = arg;
6015bc3cb74SMauro Carvalho Chehab 
6025bc3cb74SMauro Carvalho Chehab 	pr_cont("entries=%d, entries_cap=%d\n",
6035bc3cb74SMauro Carvalho Chehab 			p->entries, p->entries_cap);
6045bc3cb74SMauro Carvalho Chehab }
6055bc3cb74SMauro Carvalho Chehab 
6065bc3cb74SMauro Carvalho Chehab static void v4l_print_encoder_cmd(const void *arg, bool write_only)
6075bc3cb74SMauro Carvalho Chehab {
6085bc3cb74SMauro Carvalho Chehab 	const struct v4l2_encoder_cmd *p = arg;
6095bc3cb74SMauro Carvalho Chehab 
6105bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n",
6115bc3cb74SMauro Carvalho Chehab 			p->cmd, p->flags);
6125bc3cb74SMauro Carvalho Chehab }
6135bc3cb74SMauro Carvalho Chehab 
6145bc3cb74SMauro Carvalho Chehab static void v4l_print_decoder_cmd(const void *arg, bool write_only)
6155bc3cb74SMauro Carvalho Chehab {
6165bc3cb74SMauro Carvalho Chehab 	const struct v4l2_decoder_cmd *p = arg;
6175bc3cb74SMauro Carvalho Chehab 
6185bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags);
6195bc3cb74SMauro Carvalho Chehab 
6205bc3cb74SMauro Carvalho Chehab 	if (p->cmd == V4L2_DEC_CMD_START)
6215bc3cb74SMauro Carvalho Chehab 		pr_info("speed=%d, format=%u\n",
6225bc3cb74SMauro Carvalho Chehab 				p->start.speed, p->start.format);
6235bc3cb74SMauro Carvalho Chehab 	else if (p->cmd == V4L2_DEC_CMD_STOP)
6245bc3cb74SMauro Carvalho Chehab 		pr_info("pts=%llu\n", p->stop.pts);
6255bc3cb74SMauro Carvalho Chehab }
6265bc3cb74SMauro Carvalho Chehab 
6275bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_chip_ident(const void *arg, bool write_only)
6285bc3cb74SMauro Carvalho Chehab {
6295bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dbg_chip_ident *p = arg;
6305bc3cb74SMauro Carvalho Chehab 
6315bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%u, ", p->match.type);
63279b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
63379b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
63427d5a87cSHans Verkuil 		pr_cont("name=%.*s, ",
63527d5a87cSHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
6365bc3cb74SMauro Carvalho Chehab 	else
6375bc3cb74SMauro Carvalho Chehab 		pr_cont("addr=%u, ", p->match.addr);
6385bc3cb74SMauro Carvalho Chehab 	pr_cont("chip_ident=%u, revision=0x%x\n",
6395bc3cb74SMauro Carvalho Chehab 			p->ident, p->revision);
6405bc3cb74SMauro Carvalho Chehab }
6415bc3cb74SMauro Carvalho Chehab 
64279b0c640SHans Verkuil static void v4l_print_dbg_chip_name(const void *arg, bool write_only)
64379b0c640SHans Verkuil {
64479b0c640SHans Verkuil 	const struct v4l2_dbg_chip_name *p = arg;
64579b0c640SHans Verkuil 
64679b0c640SHans Verkuil 	pr_cont("type=%u, ", p->match.type);
64779b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
64879b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
64979b0c640SHans Verkuil 		pr_cont("name=%.*s, ",
65079b0c640SHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
65179b0c640SHans Verkuil 	else
65279b0c640SHans Verkuil 		pr_cont("addr=%u, ", p->match.addr);
65379b0c640SHans Verkuil 	pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name);
65479b0c640SHans Verkuil }
65579b0c640SHans Verkuil 
6565bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_register(const void *arg, bool write_only)
6575bc3cb74SMauro Carvalho Chehab {
6585bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dbg_register *p = arg;
6595bc3cb74SMauro Carvalho Chehab 
6605bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%u, ", p->match.type);
66179b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER ||
66279b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME)
66327d5a87cSHans Verkuil 		pr_cont("name=%.*s, ",
66427d5a87cSHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
6655bc3cb74SMauro Carvalho Chehab 	else
6665bc3cb74SMauro Carvalho Chehab 		pr_cont("addr=%u, ", p->match.addr);
6675bc3cb74SMauro Carvalho Chehab 	pr_cont("reg=0x%llx, val=0x%llx\n",
6685bc3cb74SMauro Carvalho Chehab 			p->reg, p->val);
6695bc3cb74SMauro Carvalho Chehab }
6705bc3cb74SMauro Carvalho Chehab 
6715bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings(const void *arg, bool write_only)
6725bc3cb74SMauro Carvalho Chehab {
6735bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings *p = arg;
6745bc3cb74SMauro Carvalho Chehab 
6755bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
6765bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
6775bc3cb74SMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, interlaced=%u, "
6785bc3cb74SMauro Carvalho Chehab 			"pixelclock=%llu, "
6795bc3cb74SMauro Carvalho Chehab 			"width=%u, height=%u, polarities=0x%x, "
6805bc3cb74SMauro Carvalho Chehab 			"hfrontporch=%u, hsync=%u, "
6815bc3cb74SMauro Carvalho Chehab 			"hbackporch=%u, vfrontporch=%u, "
6825bc3cb74SMauro Carvalho Chehab 			"vsync=%u, vbackporch=%u, "
6835bc3cb74SMauro Carvalho Chehab 			"il_vfrontporch=%u, il_vsync=%u, "
6845bc3cb74SMauro Carvalho Chehab 			"il_vbackporch=%u, standards=0x%x, flags=0x%x\n",
6855bc3cb74SMauro Carvalho Chehab 				p->bt.interlaced, p->bt.pixelclock,
6865bc3cb74SMauro Carvalho Chehab 				p->bt.width, p->bt.height,
6875bc3cb74SMauro Carvalho Chehab 				p->bt.polarities, p->bt.hfrontporch,
6885bc3cb74SMauro Carvalho Chehab 				p->bt.hsync, p->bt.hbackporch,
6895bc3cb74SMauro Carvalho Chehab 				p->bt.vfrontporch, p->bt.vsync,
6905bc3cb74SMauro Carvalho Chehab 				p->bt.vbackporch, p->bt.il_vfrontporch,
6915bc3cb74SMauro Carvalho Chehab 				p->bt.il_vsync, p->bt.il_vbackporch,
6925bc3cb74SMauro Carvalho Chehab 				p->bt.standards, p->bt.flags);
6935bc3cb74SMauro Carvalho Chehab 		break;
6945bc3cb74SMauro Carvalho Chehab 	default:
6955bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%d\n", p->type);
6965bc3cb74SMauro Carvalho Chehab 		break;
6975bc3cb74SMauro Carvalho Chehab 	}
6985bc3cb74SMauro Carvalho Chehab }
6995bc3cb74SMauro Carvalho Chehab 
7005bc3cb74SMauro Carvalho Chehab static void v4l_print_enum_dv_timings(const void *arg, bool write_only)
7015bc3cb74SMauro Carvalho Chehab {
7025bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enum_dv_timings *p = arg;
7035bc3cb74SMauro Carvalho Chehab 
7045bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, ", p->index);
7055bc3cb74SMauro Carvalho Chehab 	v4l_print_dv_timings(&p->timings, write_only);
7065bc3cb74SMauro Carvalho Chehab }
7075bc3cb74SMauro Carvalho Chehab 
7085bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings_cap(const void *arg, bool write_only)
7095bc3cb74SMauro Carvalho Chehab {
7105bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings_cap *p = arg;
7115bc3cb74SMauro Carvalho Chehab 
7125bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7135bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
7145bc3cb74SMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, "
7155bc3cb74SMauro Carvalho Chehab 			"pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n",
7165bc3cb74SMauro Carvalho Chehab 			p->bt.min_width, p->bt.max_width,
7175bc3cb74SMauro Carvalho Chehab 			p->bt.min_height, p->bt.max_height,
7185bc3cb74SMauro Carvalho Chehab 			p->bt.min_pixelclock, p->bt.max_pixelclock,
7195bc3cb74SMauro Carvalho Chehab 			p->bt.standards, p->bt.capabilities);
7205bc3cb74SMauro Carvalho Chehab 		break;
7215bc3cb74SMauro Carvalho Chehab 	default:
7225bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%u\n", p->type);
7235bc3cb74SMauro Carvalho Chehab 		break;
7245bc3cb74SMauro Carvalho Chehab 	}
7255bc3cb74SMauro Carvalho Chehab }
7265bc3cb74SMauro Carvalho Chehab 
7275bc3cb74SMauro Carvalho Chehab static void v4l_print_frmsizeenum(const void *arg, bool write_only)
7285bc3cb74SMauro Carvalho Chehab {
7295bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmsizeenum *p = arg;
7305bc3cb74SMauro Carvalho Chehab 
7315bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u",
7325bc3cb74SMauro Carvalho Chehab 			p->index,
7335bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7345bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7355bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7365bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7375bc3cb74SMauro Carvalho Chehab 			p->type);
7385bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7395bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_DISCRETE:
7405bc3cb74SMauro Carvalho Chehab 		pr_cont(" wxh=%ux%u\n",
7415bc3cb74SMauro Carvalho Chehab 			p->discrete.width, p->discrete.height);
7425bc3cb74SMauro Carvalho Chehab 		break;
7435bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_STEPWISE:
7445bc3cb74SMauro Carvalho Chehab 		pr_cont(" min=%ux%u, max=%ux%u, step=%ux%u\n",
7455bc3cb74SMauro Carvalho Chehab 				p->stepwise.min_width,  p->stepwise.min_height,
7465bc3cb74SMauro Carvalho Chehab 				p->stepwise.step_width, p->stepwise.step_height,
7475bc3cb74SMauro Carvalho Chehab 				p->stepwise.max_width,  p->stepwise.max_height);
7485bc3cb74SMauro Carvalho Chehab 		break;
7495bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_CONTINUOUS:
7505bc3cb74SMauro Carvalho Chehab 		/* fall through */
7515bc3cb74SMauro Carvalho Chehab 	default:
7525bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7535bc3cb74SMauro Carvalho Chehab 		break;
7545bc3cb74SMauro Carvalho Chehab 	}
7555bc3cb74SMauro Carvalho Chehab }
7565bc3cb74SMauro Carvalho Chehab 
7575bc3cb74SMauro Carvalho Chehab static void v4l_print_frmivalenum(const void *arg, bool write_only)
7585bc3cb74SMauro Carvalho Chehab {
7595bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmivalenum *p = arg;
7605bc3cb74SMauro Carvalho Chehab 
7615bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u",
7625bc3cb74SMauro Carvalho Chehab 			p->index,
7635bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7645bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7655bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7665bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7675bc3cb74SMauro Carvalho Chehab 			p->width, p->height, p->type);
7685bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7695bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_DISCRETE:
7705bc3cb74SMauro Carvalho Chehab 		pr_cont(" fps=%d/%d\n",
7715bc3cb74SMauro Carvalho Chehab 				p->discrete.numerator,
7725bc3cb74SMauro Carvalho Chehab 				p->discrete.denominator);
7735bc3cb74SMauro Carvalho Chehab 		break;
7745bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_STEPWISE:
7755bc3cb74SMauro Carvalho Chehab 		pr_cont(" min=%d/%d, max=%d/%d, step=%d/%d\n",
7765bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.numerator,
7775bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.denominator,
7785bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.numerator,
7795bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.denominator,
7805bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.numerator,
7815bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.denominator);
7825bc3cb74SMauro Carvalho Chehab 		break;
7835bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_CONTINUOUS:
7845bc3cb74SMauro Carvalho Chehab 		/* fall through */
7855bc3cb74SMauro Carvalho Chehab 	default:
7865bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7875bc3cb74SMauro Carvalho Chehab 		break;
7885bc3cb74SMauro Carvalho Chehab 	}
7895bc3cb74SMauro Carvalho Chehab }
7905bc3cb74SMauro Carvalho Chehab 
7915bc3cb74SMauro Carvalho Chehab static void v4l_print_event(const void *arg, bool write_only)
7925bc3cb74SMauro Carvalho Chehab {
7935bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event *p = arg;
7945bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_ctrl *c;
7955bc3cb74SMauro Carvalho Chehab 
7965bc3cb74SMauro Carvalho Chehab 	pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, "
7975bc3cb74SMauro Carvalho Chehab 		"timestamp=%lu.%9.9lu\n",
7985bc3cb74SMauro Carvalho Chehab 			p->type, p->pending, p->sequence, p->id,
7995bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec, p->timestamp.tv_nsec);
8005bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
8015bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_VSYNC:
8025bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "field=%s\n",
8035bc3cb74SMauro Carvalho Chehab 			prt_names(p->u.vsync.field, v4l2_field_names));
8045bc3cb74SMauro Carvalho Chehab 		break;
8055bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_CTRL:
8065bc3cb74SMauro Carvalho Chehab 		c = &p->u.ctrl;
8075bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "changes=0x%x, type=%u, ",
8085bc3cb74SMauro Carvalho Chehab 			c->changes, c->type);
8095bc3cb74SMauro Carvalho Chehab 		if (c->type == V4L2_CTRL_TYPE_INTEGER64)
8105bc3cb74SMauro Carvalho Chehab 			pr_cont("value64=%lld, ", c->value64);
8115bc3cb74SMauro Carvalho Chehab 		else
8125bc3cb74SMauro Carvalho Chehab 			pr_cont("value=%d, ", c->value);
8135bc3cb74SMauro Carvalho Chehab 		pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d,"
8145bc3cb74SMauro Carvalho Chehab 				" default_value=%d\n",
8155bc3cb74SMauro Carvalho Chehab 			c->flags, c->minimum, c->maximum,
8165bc3cb74SMauro Carvalho Chehab 			c->step, c->default_value);
8175bc3cb74SMauro Carvalho Chehab 		break;
8185bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_FRAME_SYNC:
8195bc3cb74SMauro Carvalho Chehab 		pr_cont("frame_sequence=%u\n",
8205bc3cb74SMauro Carvalho Chehab 			p->u.frame_sync.frame_sequence);
8215bc3cb74SMauro Carvalho Chehab 		break;
8225bc3cb74SMauro Carvalho Chehab 	}
8235bc3cb74SMauro Carvalho Chehab }
8245bc3cb74SMauro Carvalho Chehab 
8255bc3cb74SMauro Carvalho Chehab static void v4l_print_event_subscription(const void *arg, bool write_only)
8265bc3cb74SMauro Carvalho Chehab {
8275bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_subscription *p = arg;
8285bc3cb74SMauro Carvalho Chehab 
8295bc3cb74SMauro Carvalho Chehab 	pr_cont("type=0x%x, id=0x%x, flags=0x%x\n",
8305bc3cb74SMauro Carvalho Chehab 			p->type, p->id, p->flags);
8315bc3cb74SMauro Carvalho Chehab }
8325bc3cb74SMauro Carvalho Chehab 
8335bc3cb74SMauro Carvalho Chehab static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only)
8345bc3cb74SMauro Carvalho Chehab {
8355bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_cap *p = arg;
8365bc3cb74SMauro Carvalho Chehab 	int i;
8375bc3cb74SMauro Carvalho Chehab 
8385bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, service_set=0x%08x\n",
8395bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names), p->service_set);
8405bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < 24; i++)
8415bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
8425bc3cb74SMauro Carvalho Chehab 				p->service_lines[0][i],
8435bc3cb74SMauro Carvalho Chehab 				p->service_lines[1][i]);
8445bc3cb74SMauro Carvalho Chehab }
8455bc3cb74SMauro Carvalho Chehab 
8465bc3cb74SMauro Carvalho Chehab static void v4l_print_freq_band(const void *arg, bool write_only)
8475bc3cb74SMauro Carvalho Chehab {
8485bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency_band *p = arg;
8495bc3cb74SMauro Carvalho Chehab 
8505bc3cb74SMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, "
8515bc3cb74SMauro Carvalho Chehab 			"rangelow=%u, rangehigh=%u, modulation=0x%x\n",
8525bc3cb74SMauro Carvalho Chehab 			p->tuner, p->type, p->index,
8535bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
8545bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->modulation);
8555bc3cb74SMauro Carvalho Chehab }
8565bc3cb74SMauro Carvalho Chehab 
8575bc3cb74SMauro Carvalho Chehab static void v4l_print_u32(const void *arg, bool write_only)
8585bc3cb74SMauro Carvalho Chehab {
8595bc3cb74SMauro Carvalho Chehab 	pr_cont("value=%u\n", *(const u32 *)arg);
8605bc3cb74SMauro Carvalho Chehab }
8615bc3cb74SMauro Carvalho Chehab 
8625bc3cb74SMauro Carvalho Chehab static void v4l_print_newline(const void *arg, bool write_only)
8635bc3cb74SMauro Carvalho Chehab {
8645bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
8655bc3cb74SMauro Carvalho Chehab }
8665bc3cb74SMauro Carvalho Chehab 
8675bc3cb74SMauro Carvalho Chehab static void v4l_print_default(const void *arg, bool write_only)
8685bc3cb74SMauro Carvalho Chehab {
8695bc3cb74SMauro Carvalho Chehab 	pr_cont("driver-specific ioctl\n");
8705bc3cb74SMauro Carvalho Chehab }
8715bc3cb74SMauro Carvalho Chehab 
8725bc3cb74SMauro Carvalho Chehab static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
8735bc3cb74SMauro Carvalho Chehab {
8745bc3cb74SMauro Carvalho Chehab 	__u32 i;
8755bc3cb74SMauro Carvalho Chehab 
8765bc3cb74SMauro Carvalho Chehab 	/* zero the reserved fields */
8775bc3cb74SMauro Carvalho Chehab 	c->reserved[0] = c->reserved[1] = 0;
8785bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++)
8795bc3cb74SMauro Carvalho Chehab 		c->controls[i].reserved2[0] = 0;
8805bc3cb74SMauro Carvalho Chehab 
8815bc3cb74SMauro Carvalho Chehab 	/* V4L2_CID_PRIVATE_BASE cannot be used as control class
8825bc3cb74SMauro Carvalho Chehab 	   when using extended controls.
8835bc3cb74SMauro Carvalho Chehab 	   Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
8845bc3cb74SMauro Carvalho Chehab 	   is it allowed for backwards compatibility.
8855bc3cb74SMauro Carvalho Chehab 	 */
8865bc3cb74SMauro Carvalho Chehab 	if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
8875bc3cb74SMauro Carvalho Chehab 		return 0;
8885bc3cb74SMauro Carvalho Chehab 	/* Check that all controls are from the same control class. */
8895bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++) {
8905bc3cb74SMauro Carvalho Chehab 		if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
8915bc3cb74SMauro Carvalho Chehab 			c->error_idx = i;
8925bc3cb74SMauro Carvalho Chehab 			return 0;
8935bc3cb74SMauro Carvalho Chehab 		}
8945bc3cb74SMauro Carvalho Chehab 	}
8955bc3cb74SMauro Carvalho Chehab 	return 1;
8965bc3cb74SMauro Carvalho Chehab }
8975bc3cb74SMauro Carvalho Chehab 
8984b20259fSHans Verkuil static int check_fmt(struct file *file, enum v4l2_buf_type type)
8995bc3cb74SMauro Carvalho Chehab {
9004b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
9014b20259fSHans Verkuil 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
9024b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
9034b20259fSHans Verkuil 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
9044b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
9054b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
9064b20259fSHans Verkuil 
9075bc3cb74SMauro Carvalho Chehab 	if (ops == NULL)
9085bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
9095bc3cb74SMauro Carvalho Chehab 
9105bc3cb74SMauro Carvalho Chehab 	switch (type) {
9115bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
9124b20259fSHans Verkuil 		if (is_vid && is_rx &&
9134b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane))
9145bc3cb74SMauro Carvalho Chehab 			return 0;
9155bc3cb74SMauro Carvalho Chehab 		break;
9165bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
9174b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane)
9185bc3cb74SMauro Carvalho Chehab 			return 0;
9195bc3cb74SMauro Carvalho Chehab 		break;
9205bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
9214b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay)
9225bc3cb74SMauro Carvalho Chehab 			return 0;
9235bc3cb74SMauro Carvalho Chehab 		break;
9245bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
9254b20259fSHans Verkuil 		if (is_vid && is_tx &&
9264b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane))
9275bc3cb74SMauro Carvalho Chehab 			return 0;
9285bc3cb74SMauro Carvalho Chehab 		break;
9295bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
9304b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane)
9315bc3cb74SMauro Carvalho Chehab 			return 0;
9325bc3cb74SMauro Carvalho Chehab 		break;
9335bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
9344b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay)
9355bc3cb74SMauro Carvalho Chehab 			return 0;
9365bc3cb74SMauro Carvalho Chehab 		break;
9375bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
9384b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap)
9395bc3cb74SMauro Carvalho Chehab 			return 0;
9405bc3cb74SMauro Carvalho Chehab 		break;
9415bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
9424b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out)
9435bc3cb74SMauro Carvalho Chehab 			return 0;
9445bc3cb74SMauro Carvalho Chehab 		break;
9455bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
9464b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap)
9475bc3cb74SMauro Carvalho Chehab 			return 0;
9485bc3cb74SMauro Carvalho Chehab 		break;
9495bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
9504b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
9515bc3cb74SMauro Carvalho Chehab 			return 0;
9525bc3cb74SMauro Carvalho Chehab 		break;
953633c98e5SHans Verkuil 	default:
9545bc3cb74SMauro Carvalho Chehab 		break;
9555bc3cb74SMauro Carvalho Chehab 	}
9565bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
9575bc3cb74SMauro Carvalho Chehab }
9585bc3cb74SMauro Carvalho Chehab 
9595bc3cb74SMauro Carvalho Chehab static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
9605bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9615bc3cb74SMauro Carvalho Chehab {
9625bc3cb74SMauro Carvalho Chehab 	struct v4l2_capability *cap = (struct v4l2_capability *)arg;
9635bc3cb74SMauro Carvalho Chehab 
9645bc3cb74SMauro Carvalho Chehab 	cap->version = LINUX_VERSION_CODE;
9655bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_querycap(file, fh, cap);
9665bc3cb74SMauro Carvalho Chehab }
9675bc3cb74SMauro Carvalho Chehab 
9685bc3cb74SMauro Carvalho Chehab static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
9695bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9705bc3cb74SMauro Carvalho Chehab {
9715bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_input(file, fh, *(unsigned int *)arg);
9725bc3cb74SMauro Carvalho Chehab }
9735bc3cb74SMauro Carvalho Chehab 
9745bc3cb74SMauro Carvalho Chehab static int v4l_s_output(const struct v4l2_ioctl_ops *ops,
9755bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9765bc3cb74SMauro Carvalho Chehab {
9775bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_output(file, fh, *(unsigned int *)arg);
9785bc3cb74SMauro Carvalho Chehab }
9795bc3cb74SMauro Carvalho Chehab 
9805bc3cb74SMauro Carvalho Chehab static int v4l_g_priority(const struct v4l2_ioctl_ops *ops,
9815bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9825bc3cb74SMauro Carvalho Chehab {
9835bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
9845bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
9855bc3cb74SMauro Carvalho Chehab 
9865bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_priority)
9875bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_priority(file, fh, arg);
9885bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
9895bc3cb74SMauro Carvalho Chehab 	*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
9905bc3cb74SMauro Carvalho Chehab 	return 0;
9915bc3cb74SMauro Carvalho Chehab }
9925bc3cb74SMauro Carvalho Chehab 
9935bc3cb74SMauro Carvalho Chehab static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
9945bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9955bc3cb74SMauro Carvalho Chehab {
9965bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
9975bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh;
9985bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
9995bc3cb74SMauro Carvalho Chehab 
10005bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_priority)
10015bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_priority(file, fh, *p);
10025bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
10035bc3cb74SMauro Carvalho Chehab 	vfh = file->private_data;
10045bc3cb74SMauro Carvalho Chehab 	return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
10055bc3cb74SMauro Carvalho Chehab }
10065bc3cb74SMauro Carvalho Chehab 
10075bc3cb74SMauro Carvalho Chehab static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
10085bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10095bc3cb74SMauro Carvalho Chehab {
101073f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10115bc3cb74SMauro Carvalho Chehab 	struct v4l2_input *p = arg;
10125bc3cb74SMauro Carvalho Chehab 
10135bc3cb74SMauro Carvalho Chehab 	/*
101402fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10155bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10165bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10175bc3cb74SMauro Carvalho Chehab 	 * for a specific input, it must override these flags.
10185bc3cb74SMauro Carvalho Chehab 	 */
101973f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10205bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_IN_CAP_STD;
10215bc3cb74SMauro Carvalho Chehab 
10225bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_input(file, fh, p);
10235bc3cb74SMauro Carvalho Chehab }
10245bc3cb74SMauro Carvalho Chehab 
10255bc3cb74SMauro Carvalho Chehab static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
10265bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10275bc3cb74SMauro Carvalho Chehab {
102873f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10295bc3cb74SMauro Carvalho Chehab 	struct v4l2_output *p = arg;
10305bc3cb74SMauro Carvalho Chehab 
10315bc3cb74SMauro Carvalho Chehab 	/*
103202fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10335bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10345bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10355bc3cb74SMauro Carvalho Chehab 	 * for a specific output, it must override these flags.
10365bc3cb74SMauro Carvalho Chehab 	 */
103773f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10385bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_OUT_CAP_STD;
10395bc3cb74SMauro Carvalho Chehab 
10405bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_output(file, fh, p);
10415bc3cb74SMauro Carvalho Chehab }
10425bc3cb74SMauro Carvalho Chehab 
10435bc3cb74SMauro Carvalho Chehab static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
10445bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10455bc3cb74SMauro Carvalho Chehab {
10465bc3cb74SMauro Carvalho Chehab 	struct v4l2_fmtdesc *p = arg;
10474b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
10484b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
10494b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
10505bc3cb74SMauro Carvalho Chehab 
10515bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
10525bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
10534b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap))
10545bc3cb74SMauro Carvalho Chehab 			break;
10555bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
10565bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
10574b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane))
10585bc3cb74SMauro Carvalho Chehab 			break;
10595bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
10605bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
10614b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay))
10625bc3cb74SMauro Carvalho Chehab 			break;
10635bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
10645bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
10654b20259fSHans Verkuil 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out))
10665bc3cb74SMauro Carvalho Chehab 			break;
10675bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
10685bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
10694b20259fSHans Verkuil 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
10705bc3cb74SMauro Carvalho Chehab 			break;
10715bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
10725bc3cb74SMauro Carvalho Chehab 	}
10735bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
10745bc3cb74SMauro Carvalho Chehab }
10755bc3cb74SMauro Carvalho Chehab 
10765bc3cb74SMauro Carvalho Chehab static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
10775bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10785bc3cb74SMauro Carvalho Chehab {
10795bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
10804b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
10814b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
10824b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
10834b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
10845bc3cb74SMauro Carvalho Chehab 
10855bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
10865bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
10874b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
10885bc3cb74SMauro Carvalho Chehab 			break;
10895bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
10905bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
10914b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
10925bc3cb74SMauro Carvalho Chehab 			break;
10935bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
10945bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
10954b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay))
10965bc3cb74SMauro Carvalho Chehab 			break;
10975bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_overlay(file, fh, arg);
10984b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
10994b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap))
11004b20259fSHans Verkuil 			break;
11014b20259fSHans Verkuil 		return ops->vidioc_g_fmt_vbi_cap(file, fh, arg);
11024b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
11034b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap))
11044b20259fSHans Verkuil 			break;
11054b20259fSHans Verkuil 		return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg);
11065bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
11074b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
11085bc3cb74SMauro Carvalho Chehab 			break;
11095bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out(file, fh, arg);
11105bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
11114b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
11125bc3cb74SMauro Carvalho Chehab 			break;
11135bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg);
11145bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
11154b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay))
11165bc3cb74SMauro Carvalho Chehab 			break;
11175bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg);
11185bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
11194b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out))
11205bc3cb74SMauro Carvalho Chehab 			break;
11215bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vbi_out(file, fh, arg);
11225bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
11234b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
11245bc3cb74SMauro Carvalho Chehab 			break;
11255bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
11265bc3cb74SMauro Carvalho Chehab 	}
11275bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
11285bc3cb74SMauro Carvalho Chehab }
11295bc3cb74SMauro Carvalho Chehab 
11305bc3cb74SMauro Carvalho Chehab static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
11315bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
11325bc3cb74SMauro Carvalho Chehab {
11335bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
11344b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
11354b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
11364b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
11374b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
11385bc3cb74SMauro Carvalho Chehab 
11395bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
11405bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
11414b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
11425bc3cb74SMauro Carvalho Chehab 			break;
11435bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
11445bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_cap(file, fh, arg);
11455bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
11464b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
11475bc3cb74SMauro Carvalho Chehab 			break;
11485bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
11495bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
11505bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
11514b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay))
11525bc3cb74SMauro Carvalho Chehab 			break;
11535bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
11545bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_overlay(file, fh, arg);
11554b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
11564b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap))
11574b20259fSHans Verkuil 			break;
11584b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
11594b20259fSHans Verkuil 		return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
11604b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
11614b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap))
11624b20259fSHans Verkuil 			break;
11634b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
11644b20259fSHans Verkuil 		return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
11655bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
11664b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
11675bc3cb74SMauro Carvalho Chehab 			break;
11685bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
11695bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out(file, fh, arg);
11705bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
11714b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
11725bc3cb74SMauro Carvalho Chehab 			break;
11735bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
11745bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
11755bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
11764b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay))
11775bc3cb74SMauro Carvalho Chehab 			break;
11785bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
11795bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg);
11805bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
11814b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out))
11825bc3cb74SMauro Carvalho Chehab 			break;
11835bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
11845bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vbi_out(file, fh, arg);
11855bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
11864b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out))
11875bc3cb74SMauro Carvalho Chehab 			break;
11885bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
11895bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
11905bc3cb74SMauro Carvalho Chehab 	}
11915bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
11925bc3cb74SMauro Carvalho Chehab }
11935bc3cb74SMauro Carvalho Chehab 
11945bc3cb74SMauro Carvalho Chehab static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
11955bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
11965bc3cb74SMauro Carvalho Chehab {
11975bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
11984b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
11994b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
12004b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
12014b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
12025bc3cb74SMauro Carvalho Chehab 
12035bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
12045bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
12054b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
12065bc3cb74SMauro Carvalho Chehab 			break;
12075bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
12085bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_cap(file, fh, arg);
12095bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
12104b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
12115bc3cb74SMauro Carvalho Chehab 			break;
12125bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
12135bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
12145bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
12154b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay))
12165bc3cb74SMauro Carvalho Chehab 			break;
12175bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
12185bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_overlay(file, fh, arg);
12194b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
12204b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap))
12214b20259fSHans Verkuil 			break;
12224b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
12234b20259fSHans Verkuil 		return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
12244b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
12254b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap))
12264b20259fSHans Verkuil 			break;
12274b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
12284b20259fSHans Verkuil 		return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
12295bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
12304b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
12315bc3cb74SMauro Carvalho Chehab 			break;
12325bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
12335bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out(file, fh, arg);
12345bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
12354b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
12365bc3cb74SMauro Carvalho Chehab 			break;
12375bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
12385bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
12395bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
12404b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay))
12415bc3cb74SMauro Carvalho Chehab 			break;
12425bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
12435bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg);
12445bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
12454b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out))
12465bc3cb74SMauro Carvalho Chehab 			break;
12475bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
12485bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vbi_out(file, fh, arg);
12495bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
12504b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out))
12515bc3cb74SMauro Carvalho Chehab 			break;
12525bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
12535bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
12545bc3cb74SMauro Carvalho Chehab 	}
12555bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
12565bc3cb74SMauro Carvalho Chehab }
12575bc3cb74SMauro Carvalho Chehab 
12585bc3cb74SMauro Carvalho Chehab static int v4l_streamon(const struct v4l2_ioctl_ops *ops,
12595bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12605bc3cb74SMauro Carvalho Chehab {
12615bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamon(file, fh, *(unsigned int *)arg);
12625bc3cb74SMauro Carvalho Chehab }
12635bc3cb74SMauro Carvalho Chehab 
12645bc3cb74SMauro Carvalho Chehab static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
12655bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12665bc3cb74SMauro Carvalho Chehab {
12675bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
12685bc3cb74SMauro Carvalho Chehab }
12695bc3cb74SMauro Carvalho Chehab 
12705bc3cb74SMauro Carvalho Chehab static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
12715bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12725bc3cb74SMauro Carvalho Chehab {
12735bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
12745bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
12755bc3cb74SMauro Carvalho Chehab 	int err;
12765bc3cb74SMauro Carvalho Chehab 
12775bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
12785bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
12795bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_tuner(file, fh, p);
12805bc3cb74SMauro Carvalho Chehab 	if (!err)
12815bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
12825bc3cb74SMauro Carvalho Chehab 	return err;
12835bc3cb74SMauro Carvalho Chehab }
12845bc3cb74SMauro Carvalho Chehab 
12855bc3cb74SMauro Carvalho Chehab static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
12865bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12875bc3cb74SMauro Carvalho Chehab {
12885bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
12895bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
12905bc3cb74SMauro Carvalho Chehab 
12915bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
12925bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
12935bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_tuner(file, fh, p);
12945bc3cb74SMauro Carvalho Chehab }
12955bc3cb74SMauro Carvalho Chehab 
12965bc3cb74SMauro Carvalho Chehab static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops,
12975bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12985bc3cb74SMauro Carvalho Chehab {
12995bc3cb74SMauro Carvalho Chehab 	struct v4l2_modulator *p = arg;
13005bc3cb74SMauro Carvalho Chehab 	int err;
13015bc3cb74SMauro Carvalho Chehab 
13025bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_modulator(file, fh, p);
13035bc3cb74SMauro Carvalho Chehab 	if (!err)
13045bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
13055bc3cb74SMauro Carvalho Chehab 	return err;
13065bc3cb74SMauro Carvalho Chehab }
13075bc3cb74SMauro Carvalho Chehab 
13085bc3cb74SMauro Carvalho Chehab static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
13095bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13105bc3cb74SMauro Carvalho Chehab {
13115bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13125bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency *p = arg;
13135bc3cb74SMauro Carvalho Chehab 
13145bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13155bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
13165bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_frequency(file, fh, p);
13175bc3cb74SMauro Carvalho Chehab }
13185bc3cb74SMauro Carvalho Chehab 
13195bc3cb74SMauro Carvalho Chehab static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
13205bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13215bc3cb74SMauro Carvalho Chehab {
13225bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1323b530a447SHans Verkuil 	const struct v4l2_frequency *p = arg;
13245bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
13255bc3cb74SMauro Carvalho Chehab 
13265bc3cb74SMauro Carvalho Chehab 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13275bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
13285bc3cb74SMauro Carvalho Chehab 	if (p->type != type)
13295bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
13305bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_frequency(file, fh, p);
13315bc3cb74SMauro Carvalho Chehab }
13325bc3cb74SMauro Carvalho Chehab 
13335bc3cb74SMauro Carvalho Chehab static int v4l_enumstd(const struct v4l2_ioctl_ops *ops,
13345bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13355bc3cb74SMauro Carvalho Chehab {
13365bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13375bc3cb74SMauro Carvalho Chehab 	struct v4l2_standard *p = arg;
13385bc3cb74SMauro Carvalho Chehab 	v4l2_std_id id = vfd->tvnorms, curr_id = 0;
13395bc3cb74SMauro Carvalho Chehab 	unsigned int index = p->index, i, j = 0;
13405bc3cb74SMauro Carvalho Chehab 	const char *descr = "";
13415bc3cb74SMauro Carvalho Chehab 
1342a5338190SHans Verkuil 	/* Return -ENODATA if the tvnorms for the current input
1343a5338190SHans Verkuil 	   or output is 0, meaning that it doesn't support this API. */
1344a5338190SHans Verkuil 	if (id == 0)
1345a5338190SHans Verkuil 		return -ENODATA;
1346a5338190SHans Verkuil 
13475bc3cb74SMauro Carvalho Chehab 	/* Return norm array in a canonical way */
13485bc3cb74SMauro Carvalho Chehab 	for (i = 0; i <= index && id; i++) {
13495bc3cb74SMauro Carvalho Chehab 		/* last std value in the standards array is 0, so this
13505bc3cb74SMauro Carvalho Chehab 		   while always ends there since (id & 0) == 0. */
13515bc3cb74SMauro Carvalho Chehab 		while ((id & standards[j].std) != standards[j].std)
13525bc3cb74SMauro Carvalho Chehab 			j++;
13535bc3cb74SMauro Carvalho Chehab 		curr_id = standards[j].std;
13545bc3cb74SMauro Carvalho Chehab 		descr = standards[j].descr;
13555bc3cb74SMauro Carvalho Chehab 		j++;
13565bc3cb74SMauro Carvalho Chehab 		if (curr_id == 0)
13575bc3cb74SMauro Carvalho Chehab 			break;
13585bc3cb74SMauro Carvalho Chehab 		if (curr_id != V4L2_STD_PAL &&
13595bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_SECAM &&
13605bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_NTSC)
13615bc3cb74SMauro Carvalho Chehab 			id &= ~curr_id;
13625bc3cb74SMauro Carvalho Chehab 	}
13635bc3cb74SMauro Carvalho Chehab 	if (i <= index)
13645bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
13655bc3cb74SMauro Carvalho Chehab 
13665bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_construct(p, curr_id, descr);
13675bc3cb74SMauro Carvalho Chehab 	return 0;
13685bc3cb74SMauro Carvalho Chehab }
13695bc3cb74SMauro Carvalho Chehab 
13705bc3cb74SMauro Carvalho Chehab static int v4l_g_std(const struct v4l2_ioctl_ops *ops,
13715bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13725bc3cb74SMauro Carvalho Chehab {
13735bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13745bc3cb74SMauro Carvalho Chehab 	v4l2_std_id *id = arg;
13755bc3cb74SMauro Carvalho Chehab 
13765bc3cb74SMauro Carvalho Chehab 	/* Calls the specific handler */
13775bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_std)
13785bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_std(file, fh, arg);
13795bc3cb74SMauro Carvalho Chehab 	if (vfd->current_norm) {
13805bc3cb74SMauro Carvalho Chehab 		*id = vfd->current_norm;
13815bc3cb74SMauro Carvalho Chehab 		return 0;
13825bc3cb74SMauro Carvalho Chehab 	}
13835bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
13845bc3cb74SMauro Carvalho Chehab }
13855bc3cb74SMauro Carvalho Chehab 
13865bc3cb74SMauro Carvalho Chehab static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
13875bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13885bc3cb74SMauro Carvalho Chehab {
13895bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1390314527acSHans Verkuil 	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
13915bc3cb74SMauro Carvalho Chehab 	int ret;
13925bc3cb74SMauro Carvalho Chehab 
1393314527acSHans Verkuil 	norm = id & vfd->tvnorms;
13945bc3cb74SMauro Carvalho Chehab 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
13955bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
13965bc3cb74SMauro Carvalho Chehab 
13975bc3cb74SMauro Carvalho Chehab 	/* Calls the specific handler */
1398314527acSHans Verkuil 	ret = ops->vidioc_s_std(file, fh, norm);
13995bc3cb74SMauro Carvalho Chehab 
14005bc3cb74SMauro Carvalho Chehab 	/* Updates standard information */
14015bc3cb74SMauro Carvalho Chehab 	if (ret >= 0)
14025bc3cb74SMauro Carvalho Chehab 		vfd->current_norm = norm;
14035bc3cb74SMauro Carvalho Chehab 	return ret;
14045bc3cb74SMauro Carvalho Chehab }
14055bc3cb74SMauro Carvalho Chehab 
14065bc3cb74SMauro Carvalho Chehab static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
14075bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14085bc3cb74SMauro Carvalho Chehab {
14095bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
14105bc3cb74SMauro Carvalho Chehab 	v4l2_std_id *p = arg;
14115bc3cb74SMauro Carvalho Chehab 
14125bc3cb74SMauro Carvalho Chehab 	/*
14135bc3cb74SMauro Carvalho Chehab 	 * If nothing detected, it should return all supported
14145bc3cb74SMauro Carvalho Chehab 	 * standard.
14155bc3cb74SMauro Carvalho Chehab 	 * Drivers just need to mask the std argument, in order
14165bc3cb74SMauro Carvalho Chehab 	 * to remove the standards that don't apply from the mask.
14175bc3cb74SMauro Carvalho Chehab 	 * This means that tuners, audio and video decoders can join
14185bc3cb74SMauro Carvalho Chehab 	 * their efforts to improve the standards detection.
14195bc3cb74SMauro Carvalho Chehab 	 */
14205bc3cb74SMauro Carvalho Chehab 	*p = vfd->tvnorms;
14215bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_querystd(file, fh, arg);
14225bc3cb74SMauro Carvalho Chehab }
14235bc3cb74SMauro Carvalho Chehab 
14245bc3cb74SMauro Carvalho Chehab static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
14255bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14265bc3cb74SMauro Carvalho Chehab {
14275bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
14285bc3cb74SMauro Carvalho Chehab 	struct v4l2_hw_freq_seek *p = arg;
14295bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
14305bc3cb74SMauro Carvalho Chehab 
14315bc3cb74SMauro Carvalho Chehab 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
14325bc3cb74SMauro Carvalho Chehab 		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
14335bc3cb74SMauro Carvalho Chehab 	if (p->type != type)
14345bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
14355bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_hw_freq_seek(file, fh, p);
14365bc3cb74SMauro Carvalho Chehab }
14375bc3cb74SMauro Carvalho Chehab 
1438737c097bSHans Verkuil static int v4l_overlay(const struct v4l2_ioctl_ops *ops,
1439737c097bSHans Verkuil 				struct file *file, void *fh, void *arg)
1440737c097bSHans Verkuil {
1441737c097bSHans Verkuil 	return ops->vidioc_overlay(file, fh, *(unsigned int *)arg);
1442737c097bSHans Verkuil }
1443737c097bSHans Verkuil 
14445bc3cb74SMauro Carvalho Chehab static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
14455bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14465bc3cb74SMauro Carvalho Chehab {
14475bc3cb74SMauro Carvalho Chehab 	struct v4l2_requestbuffers *p = arg;
14484b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14495bc3cb74SMauro Carvalho Chehab 
14505bc3cb74SMauro Carvalho Chehab 	if (ret)
14515bc3cb74SMauro Carvalho Chehab 		return ret;
14525bc3cb74SMauro Carvalho Chehab 
14535bc3cb74SMauro Carvalho Chehab 	CLEAR_AFTER_FIELD(p, memory);
14545bc3cb74SMauro Carvalho Chehab 
14555bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_reqbufs(file, fh, p);
14565bc3cb74SMauro Carvalho Chehab }
14575bc3cb74SMauro Carvalho Chehab 
14585bc3cb74SMauro Carvalho Chehab static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,
14595bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14605bc3cb74SMauro Carvalho Chehab {
14615bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14624b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14635bc3cb74SMauro Carvalho Chehab 
14645bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_querybuf(file, fh, p);
14655bc3cb74SMauro Carvalho Chehab }
14665bc3cb74SMauro Carvalho Chehab 
14675bc3cb74SMauro Carvalho Chehab static int v4l_qbuf(const struct v4l2_ioctl_ops *ops,
14685bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14695bc3cb74SMauro Carvalho Chehab {
14705bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14714b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14725bc3cb74SMauro Carvalho Chehab 
14735bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_qbuf(file, fh, p);
14745bc3cb74SMauro Carvalho Chehab }
14755bc3cb74SMauro Carvalho Chehab 
14765bc3cb74SMauro Carvalho Chehab static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,
14775bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14785bc3cb74SMauro Carvalho Chehab {
14795bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14804b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14815bc3cb74SMauro Carvalho Chehab 
14825bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
14835bc3cb74SMauro Carvalho Chehab }
14845bc3cb74SMauro Carvalho Chehab 
14855bc3cb74SMauro Carvalho Chehab static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
14865bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14875bc3cb74SMauro Carvalho Chehab {
14885bc3cb74SMauro Carvalho Chehab 	struct v4l2_create_buffers *create = arg;
14894b20259fSHans Verkuil 	int ret = check_fmt(file, create->format.type);
14905bc3cb74SMauro Carvalho Chehab 
14915bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
14925bc3cb74SMauro Carvalho Chehab }
14935bc3cb74SMauro Carvalho Chehab 
14945bc3cb74SMauro Carvalho Chehab static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
14955bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14965bc3cb74SMauro Carvalho Chehab {
14975bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *b = arg;
14984b20259fSHans Verkuil 	int ret = check_fmt(file, b->type);
14995bc3cb74SMauro Carvalho Chehab 
15005bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
15015bc3cb74SMauro Carvalho Chehab }
15025bc3cb74SMauro Carvalho Chehab 
15035bc3cb74SMauro Carvalho Chehab static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
15045bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15055bc3cb74SMauro Carvalho Chehab {
15065bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15075bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
15085bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
15094b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
15105bc3cb74SMauro Carvalho Chehab 
15115bc3cb74SMauro Carvalho Chehab 	if (ret)
15125bc3cb74SMauro Carvalho Chehab 		return ret;
15135bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_parm)
15145bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_parm(file, fh, p);
15155bc3cb74SMauro Carvalho Chehab 	std = vfd->current_norm;
15165bc3cb74SMauro Carvalho Chehab 	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
15175bc3cb74SMauro Carvalho Chehab 	    p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
15185bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
15195bc3cb74SMauro Carvalho Chehab 	p->parm.capture.readbuffers = 2;
152073f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_STD) && ops->vidioc_g_std)
15215bc3cb74SMauro Carvalho Chehab 		ret = ops->vidioc_g_std(file, fh, &std);
15225bc3cb74SMauro Carvalho Chehab 	if (ret == 0)
15235bc3cb74SMauro Carvalho Chehab 		v4l2_video_std_frame_period(std,
15245bc3cb74SMauro Carvalho Chehab 			    &p->parm.capture.timeperframe);
15255bc3cb74SMauro Carvalho Chehab 	return ret;
15265bc3cb74SMauro Carvalho Chehab }
15275bc3cb74SMauro Carvalho Chehab 
15285bc3cb74SMauro Carvalho Chehab static int v4l_s_parm(const struct v4l2_ioctl_ops *ops,
15295bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15305bc3cb74SMauro Carvalho Chehab {
15315bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
15324b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
15335bc3cb74SMauro Carvalho Chehab 
15345bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_s_parm(file, fh, p);
15355bc3cb74SMauro Carvalho Chehab }
15365bc3cb74SMauro Carvalho Chehab 
15375bc3cb74SMauro Carvalho Chehab static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
15385bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15395bc3cb74SMauro Carvalho Chehab {
15405bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15415bc3cb74SMauro Carvalho Chehab 	struct v4l2_queryctrl *p = arg;
15425bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15435bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15445bc3cb74SMauro Carvalho Chehab 
15455bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15465bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfh->ctrl_handler, p);
15475bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15485bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfd->ctrl_handler, p);
15495bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_queryctrl)
15505bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_queryctrl(file, fh, p);
15515bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
15525bc3cb74SMauro Carvalho Chehab }
15535bc3cb74SMauro Carvalho Chehab 
15545bc3cb74SMauro Carvalho Chehab static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
15555bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15565bc3cb74SMauro Carvalho Chehab {
15575bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15585bc3cb74SMauro Carvalho Chehab 	struct v4l2_querymenu *p = arg;
15595bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15605bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15615bc3cb74SMauro Carvalho Chehab 
15625bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15635bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfh->ctrl_handler, p);
15645bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15655bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfd->ctrl_handler, p);
15665bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_querymenu)
15675bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_querymenu(file, fh, p);
15685bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
15695bc3cb74SMauro Carvalho Chehab }
15705bc3cb74SMauro Carvalho Chehab 
15715bc3cb74SMauro Carvalho Chehab static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,
15725bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15735bc3cb74SMauro Carvalho Chehab {
15745bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15755bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
15765bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15775bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15785bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
15795bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
15805bc3cb74SMauro Carvalho Chehab 
15815bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15825bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfh->ctrl_handler, p);
15835bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15845bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfd->ctrl_handler, p);
15855bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ctrl)
15865bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_ctrl(file, fh, p);
15875bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
15885bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
15895bc3cb74SMauro Carvalho Chehab 
15905bc3cb74SMauro Carvalho Chehab 	ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
15915bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
15925bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
15935bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
15945bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
15955bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1)) {
15965bc3cb74SMauro Carvalho Chehab 		int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
15975bc3cb74SMauro Carvalho Chehab 
15985bc3cb74SMauro Carvalho Chehab 		if (ret == 0)
15995bc3cb74SMauro Carvalho Chehab 			p->value = ctrl.value;
16005bc3cb74SMauro Carvalho Chehab 		return ret;
16015bc3cb74SMauro Carvalho Chehab 	}
16025bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
16035bc3cb74SMauro Carvalho Chehab }
16045bc3cb74SMauro Carvalho Chehab 
16055bc3cb74SMauro Carvalho Chehab static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
16065bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16075bc3cb74SMauro Carvalho Chehab {
16085bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16095bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
16105bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16115bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16125bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
16135bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
16145bc3cb74SMauro Carvalho Chehab 
16155bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16165bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
16175bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16185bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
16195bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ctrl)
16205bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ctrl(file, fh, p);
16215bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
16225bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16235bc3cb74SMauro Carvalho Chehab 
16245bc3cb74SMauro Carvalho Chehab 	ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
16255bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
16265bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
16275bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
16285bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
16295bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1))
16305bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
16315bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
16325bc3cb74SMauro Carvalho Chehab }
16335bc3cb74SMauro Carvalho Chehab 
16345bc3cb74SMauro Carvalho Chehab static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16355bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16365bc3cb74SMauro Carvalho Chehab {
16375bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16385bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16395bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16405bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16415bc3cb74SMauro Carvalho Chehab 
16425bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16435bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16445bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
16455bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16465bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
16475bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
16485bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16495bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) :
16505bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16515bc3cb74SMauro Carvalho Chehab }
16525bc3cb74SMauro Carvalho Chehab 
16535bc3cb74SMauro Carvalho Chehab static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16545bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16555bc3cb74SMauro Carvalho Chehab {
16565bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16575bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16585bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16595bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16605bc3cb74SMauro Carvalho Chehab 
16615bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16625bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16635bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
16645bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16655bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
16665bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
16675bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16685bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) :
16695bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16705bc3cb74SMauro Carvalho Chehab }
16715bc3cb74SMauro Carvalho Chehab 
16725bc3cb74SMauro Carvalho Chehab static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16735bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16745bc3cb74SMauro Carvalho Chehab {
16755bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16765bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16775bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16785bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16795bc3cb74SMauro Carvalho Chehab 
16805bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16815bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16825bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
16835bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16845bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
16855bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_try_ext_ctrls == NULL)
16865bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16875bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) :
16885bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16895bc3cb74SMauro Carvalho Chehab }
16905bc3cb74SMauro Carvalho Chehab 
16915bc3cb74SMauro Carvalho Chehab static int v4l_g_crop(const struct v4l2_ioctl_ops *ops,
16925bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16935bc3cb74SMauro Carvalho Chehab {
16945bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
16955bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
16965bc3cb74SMauro Carvalho Chehab 		.type = p->type,
16975bc3cb74SMauro Carvalho Chehab 	};
16985bc3cb74SMauro Carvalho Chehab 	int ret;
16995bc3cb74SMauro Carvalho Chehab 
17005bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_crop)
17015bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_crop(file, fh, p);
17025bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
17035bc3cb74SMauro Carvalho Chehab 
17045bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
17055bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17065bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
17075bc3cb74SMauro Carvalho Chehab 	else
17085bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
17095bc3cb74SMauro Carvalho Chehab 
17105bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17115bc3cb74SMauro Carvalho Chehab 
17125bc3cb74SMauro Carvalho Chehab 	/* copying results to old structure on success */
17135bc3cb74SMauro Carvalho Chehab 	if (!ret)
17145bc3cb74SMauro Carvalho Chehab 		p->c = s.r;
17155bc3cb74SMauro Carvalho Chehab 	return ret;
17165bc3cb74SMauro Carvalho Chehab }
17175bc3cb74SMauro Carvalho Chehab 
17185bc3cb74SMauro Carvalho Chehab static int v4l_s_crop(const struct v4l2_ioctl_ops *ops,
17195bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17205bc3cb74SMauro Carvalho Chehab {
17215bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
17225bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
17235bc3cb74SMauro Carvalho Chehab 		.type = p->type,
17245bc3cb74SMauro Carvalho Chehab 		.r = p->c,
17255bc3cb74SMauro Carvalho Chehab 	};
17265bc3cb74SMauro Carvalho Chehab 
17275bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_crop)
17285bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_crop(file, fh, p);
17295bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
17305bc3cb74SMauro Carvalho Chehab 
17315bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
17325bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17335bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
17345bc3cb74SMauro Carvalho Chehab 	else
17355bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
17365bc3cb74SMauro Carvalho Chehab 
17375bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_selection(file, fh, &s);
17385bc3cb74SMauro Carvalho Chehab }
17395bc3cb74SMauro Carvalho Chehab 
17405bc3cb74SMauro Carvalho Chehab static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
17415bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17425bc3cb74SMauro Carvalho Chehab {
17435bc3cb74SMauro Carvalho Chehab 	struct v4l2_cropcap *p = arg;
17445bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = { .type = p->type };
17455bc3cb74SMauro Carvalho Chehab 	int ret;
17465bc3cb74SMauro Carvalho Chehab 
17475bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_cropcap)
17485bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_cropcap(file, fh, p);
17495bc3cb74SMauro Carvalho Chehab 
17505bc3cb74SMauro Carvalho Chehab 	/* obtaining bounds */
17515bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17525bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
17535bc3cb74SMauro Carvalho Chehab 	else
17545bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_BOUNDS;
17555bc3cb74SMauro Carvalho Chehab 
17565bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17575bc3cb74SMauro Carvalho Chehab 	if (ret)
17585bc3cb74SMauro Carvalho Chehab 		return ret;
17595bc3cb74SMauro Carvalho Chehab 	p->bounds = s.r;
17605bc3cb74SMauro Carvalho Chehab 
17615bc3cb74SMauro Carvalho Chehab 	/* obtaining defrect */
17625bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17635bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
17645bc3cb74SMauro Carvalho Chehab 	else
17655bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_DEFAULT;
17665bc3cb74SMauro Carvalho Chehab 
17675bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17685bc3cb74SMauro Carvalho Chehab 	if (ret)
17695bc3cb74SMauro Carvalho Chehab 		return ret;
17705bc3cb74SMauro Carvalho Chehab 	p->defrect = s.r;
17715bc3cb74SMauro Carvalho Chehab 
17725bc3cb74SMauro Carvalho Chehab 	/* setting trivial pixelaspect */
17735bc3cb74SMauro Carvalho Chehab 	p->pixelaspect.numerator = 1;
17745bc3cb74SMauro Carvalho Chehab 	p->pixelaspect.denominator = 1;
17755bc3cb74SMauro Carvalho Chehab 	return 0;
17765bc3cb74SMauro Carvalho Chehab }
17775bc3cb74SMauro Carvalho Chehab 
17785bc3cb74SMauro Carvalho Chehab static int v4l_log_status(const struct v4l2_ioctl_ops *ops,
17795bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17805bc3cb74SMauro Carvalho Chehab {
17815bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
17825bc3cb74SMauro Carvalho Chehab 	int ret;
17835bc3cb74SMauro Carvalho Chehab 
17845bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
17855bc3cb74SMauro Carvalho Chehab 		pr_info("%s: =================  START STATUS  =================\n",
17865bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
17875bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_log_status(file, fh);
17885bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
17895bc3cb74SMauro Carvalho Chehab 		pr_info("%s: ==================  END STATUS  ==================\n",
17905bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
17915bc3cb74SMauro Carvalho Chehab 	return ret;
17925bc3cb74SMauro Carvalho Chehab }
17935bc3cb74SMauro Carvalho Chehab 
179479b0c640SHans Verkuil static bool v4l_dbg_found_match(const struct v4l2_dbg_match *match,
179579b0c640SHans Verkuil 		struct v4l2_subdev *sd, int idx)
179679b0c640SHans Verkuil {
179779b0c640SHans Verkuil 	if (match->type == V4L2_CHIP_MATCH_SUBDEV_IDX)
179879b0c640SHans Verkuil 		return match->addr == idx;
179979b0c640SHans Verkuil 	return !strcmp(match->name, sd->name);
180079b0c640SHans Verkuil }
180179b0c640SHans Verkuil 
18025bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops,
18035bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18045bc3cb74SMauro Carvalho Chehab {
18055bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
18065bc3cb74SMauro Carvalho Chehab 	struct v4l2_dbg_register *p = arg;
180779b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
180879b0c640SHans Verkuil 	struct v4l2_subdev *sd;
180979b0c640SHans Verkuil 	int idx = 0;
18105bc3cb74SMauro Carvalho Chehab 
18115bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
18125bc3cb74SMauro Carvalho Chehab 		return -EPERM;
181379b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX ||
181479b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME) {
181579b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
181679b0c640SHans Verkuil 			return -EINVAL;
181779b0c640SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
181879b0c640SHans Verkuil 			if (v4l_dbg_found_match(&p->match, sd, idx++))
181979b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, g_register, p);
182079b0c640SHans Verkuil 		}
182179b0c640SHans Verkuil 		return -EINVAL;
182279b0c640SHans Verkuil 	}
182379b0c640SHans Verkuil 	if (ops->vidioc_g_register)
18245bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_register(file, fh, p);
182579b0c640SHans Verkuil 	return -EINVAL;
18265bc3cb74SMauro Carvalho Chehab #else
18275bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
18285bc3cb74SMauro Carvalho Chehab #endif
18295bc3cb74SMauro Carvalho Chehab }
18305bc3cb74SMauro Carvalho Chehab 
18315bc3cb74SMauro Carvalho Chehab static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops,
18325bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18335bc3cb74SMauro Carvalho Chehab {
18345bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
1835977ba3b1SHans Verkuil 	const struct v4l2_dbg_register *p = arg;
183679b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
183779b0c640SHans Verkuil 	struct v4l2_subdev *sd;
183879b0c640SHans Verkuil 	int idx = 0;
18395bc3cb74SMauro Carvalho Chehab 
18405bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
18415bc3cb74SMauro Carvalho Chehab 		return -EPERM;
184279b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX ||
184379b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME) {
184479b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
184579b0c640SHans Verkuil 			return -EINVAL;
184679b0c640SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
184779b0c640SHans Verkuil 			if (v4l_dbg_found_match(&p->match, sd, idx++))
184879b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, s_register, p);
184979b0c640SHans Verkuil 		}
185079b0c640SHans Verkuil 		return -EINVAL;
185179b0c640SHans Verkuil 	}
185279b0c640SHans Verkuil 	if (ops->vidioc_s_register)
18535bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_register(file, fh, p);
185479b0c640SHans Verkuil 	return -EINVAL;
18555bc3cb74SMauro Carvalho Chehab #else
18565bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
18575bc3cb74SMauro Carvalho Chehab #endif
18585bc3cb74SMauro Carvalho Chehab }
18595bc3cb74SMauro Carvalho Chehab 
18605bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_chip_ident(const struct v4l2_ioctl_ops *ops,
18615bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18625bc3cb74SMauro Carvalho Chehab {
18635bc3cb74SMauro Carvalho Chehab 	struct v4l2_dbg_chip_ident *p = arg;
18645bc3cb74SMauro Carvalho Chehab 
18655bc3cb74SMauro Carvalho Chehab 	p->ident = V4L2_IDENT_NONE;
18665bc3cb74SMauro Carvalho Chehab 	p->revision = 0;
186779b0c640SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV_NAME ||
186879b0c640SHans Verkuil 	    p->match.type == V4L2_CHIP_MATCH_SUBDEV_IDX)
186979b0c640SHans Verkuil 		return -EINVAL;
18705bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_chip_ident(file, fh, p);
18715bc3cb74SMauro Carvalho Chehab }
18725bc3cb74SMauro Carvalho Chehab 
187379b0c640SHans Verkuil static int v4l_dbg_g_chip_name(const struct v4l2_ioctl_ops *ops,
187479b0c640SHans Verkuil 				struct file *file, void *fh, void *arg)
187579b0c640SHans Verkuil {
187679b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
187779b0c640SHans Verkuil 	struct v4l2_dbg_chip_name *p = arg;
187879b0c640SHans Verkuil 	struct v4l2_subdev *sd;
187979b0c640SHans Verkuil 	int idx = 0;
188079b0c640SHans Verkuil 
188179b0c640SHans Verkuil 	switch (p->match.type) {
188279b0c640SHans Verkuil 	case V4L2_CHIP_MATCH_BRIDGE:
188379b0c640SHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
188479b0c640SHans Verkuil 		if (ops->vidioc_s_register)
188579b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_WRITABLE;
188679b0c640SHans Verkuil 		if (ops->vidioc_g_register)
188779b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_READABLE;
188879b0c640SHans Verkuil #endif
188979b0c640SHans Verkuil 		if (ops->vidioc_g_chip_name)
189079b0c640SHans Verkuil 			return ops->vidioc_g_chip_name(file, fh, arg);
189179b0c640SHans Verkuil 		if (p->match.addr)
189279b0c640SHans Verkuil 			return -EINVAL;
189379b0c640SHans Verkuil 		if (vfd->v4l2_dev)
189479b0c640SHans Verkuil 			strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
189579b0c640SHans Verkuil 		else if (vfd->parent)
189679b0c640SHans Verkuil 			strlcpy(p->name, vfd->parent->driver->name, sizeof(p->name));
189779b0c640SHans Verkuil 		else
189879b0c640SHans Verkuil 			strlcpy(p->name, "bridge", sizeof(p->name));
189979b0c640SHans Verkuil 		return 0;
190079b0c640SHans Verkuil 
190179b0c640SHans Verkuil 	case V4L2_CHIP_MATCH_SUBDEV_IDX:
190279b0c640SHans Verkuil 	case V4L2_CHIP_MATCH_SUBDEV_NAME:
190379b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
190479b0c640SHans Verkuil 			break;
190579b0c640SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
190679b0c640SHans Verkuil 			if (v4l_dbg_found_match(&p->match, sd, idx++)) {
190779b0c640SHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
190879b0c640SHans Verkuil 				if (sd->ops->core && sd->ops->core->s_register)
190979b0c640SHans Verkuil 					p->flags |= V4L2_CHIP_FL_WRITABLE;
191079b0c640SHans Verkuil 				if (sd->ops->core && sd->ops->core->g_register)
191179b0c640SHans Verkuil 					p->flags |= V4L2_CHIP_FL_READABLE;
191279b0c640SHans Verkuil #endif
191379b0c640SHans Verkuil 				strlcpy(p->name, sd->name, sizeof(p->name));
191479b0c640SHans Verkuil 				return 0;
191579b0c640SHans Verkuil 			}
191679b0c640SHans Verkuil 		}
191779b0c640SHans Verkuil 		break;
191879b0c640SHans Verkuil 	}
191979b0c640SHans Verkuil 	return -EINVAL;
192079b0c640SHans Verkuil }
192179b0c640SHans Verkuil 
19225bc3cb74SMauro Carvalho Chehab static int v4l_dqevent(const struct v4l2_ioctl_ops *ops,
19235bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19245bc3cb74SMauro Carvalho Chehab {
19255bc3cb74SMauro Carvalho Chehab 	return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
19265bc3cb74SMauro Carvalho Chehab }
19275bc3cb74SMauro Carvalho Chehab 
19285bc3cb74SMauro Carvalho Chehab static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops,
19295bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19305bc3cb74SMauro Carvalho Chehab {
19315bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_subscribe_event(fh, arg);
19325bc3cb74SMauro Carvalho Chehab }
19335bc3cb74SMauro Carvalho Chehab 
19345bc3cb74SMauro Carvalho Chehab static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops,
19355bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19365bc3cb74SMauro Carvalho Chehab {
19375bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_unsubscribe_event(fh, arg);
19385bc3cb74SMauro Carvalho Chehab }
19395bc3cb74SMauro Carvalho Chehab 
19405bc3cb74SMauro Carvalho Chehab static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops,
19415bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19425bc3cb74SMauro Carvalho Chehab {
19435bc3cb74SMauro Carvalho Chehab 	struct v4l2_sliced_vbi_cap *p = arg;
19444b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19454b20259fSHans Verkuil 
19464b20259fSHans Verkuil 	if (ret)
19474b20259fSHans Verkuil 		return ret;
19485bc3cb74SMauro Carvalho Chehab 
19495bc3cb74SMauro Carvalho Chehab 	/* Clear up to type, everything after type is zeroed already */
19505bc3cb74SMauro Carvalho Chehab 	memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
19515bc3cb74SMauro Carvalho Chehab 
19525bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_sliced_vbi_cap(file, fh, p);
19535bc3cb74SMauro Carvalho Chehab }
19545bc3cb74SMauro Carvalho Chehab 
19555bc3cb74SMauro Carvalho Chehab static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
19565bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19575bc3cb74SMauro Carvalho Chehab {
19585bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
19595bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency_band *p = arg;
19605bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
19615bc3cb74SMauro Carvalho Chehab 	int err;
19625bc3cb74SMauro Carvalho Chehab 
19635bc3cb74SMauro Carvalho Chehab 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
19645bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
19655bc3cb74SMauro Carvalho Chehab 
19665bc3cb74SMauro Carvalho Chehab 	if (type != p->type)
19675bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
19685bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_enum_freq_bands)
19695bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_freq_bands(file, fh, p);
197073f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
19715bc3cb74SMauro Carvalho Chehab 		struct v4l2_tuner t = {
19725bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
19735bc3cb74SMauro Carvalho Chehab 			.type = type,
19745bc3cb74SMauro Carvalho Chehab 		};
19755bc3cb74SMauro Carvalho Chehab 
197679e8c7beSMauro Carvalho Chehab 		if (p->index)
197779e8c7beSMauro Carvalho Chehab 			return -EINVAL;
19785bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_tuner(file, fh, &t);
19795bc3cb74SMauro Carvalho Chehab 		if (err)
19805bc3cb74SMauro Carvalho Chehab 			return err;
19815bc3cb74SMauro Carvalho Chehab 		p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS;
19825bc3cb74SMauro Carvalho Chehab 		p->rangelow = t.rangelow;
19835bc3cb74SMauro Carvalho Chehab 		p->rangehigh = t.rangehigh;
19845bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
19855bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
19865bc3cb74SMauro Carvalho Chehab 		return 0;
19875bc3cb74SMauro Carvalho Chehab 	}
198873f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) {
19895bc3cb74SMauro Carvalho Chehab 		struct v4l2_modulator m = {
19905bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
19915bc3cb74SMauro Carvalho Chehab 		};
19925bc3cb74SMauro Carvalho Chehab 
19935bc3cb74SMauro Carvalho Chehab 		if (type != V4L2_TUNER_RADIO)
19945bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
199579e8c7beSMauro Carvalho Chehab 		if (p->index)
199679e8c7beSMauro Carvalho Chehab 			return -EINVAL;
19975bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_modulator(file, fh, &m);
19985bc3cb74SMauro Carvalho Chehab 		if (err)
19995bc3cb74SMauro Carvalho Chehab 			return err;
20005bc3cb74SMauro Carvalho Chehab 		p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS;
20015bc3cb74SMauro Carvalho Chehab 		p->rangelow = m.rangelow;
20025bc3cb74SMauro Carvalho Chehab 		p->rangehigh = m.rangehigh;
20035bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
20045bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
20055bc3cb74SMauro Carvalho Chehab 		return 0;
20065bc3cb74SMauro Carvalho Chehab 	}
20075bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
20085bc3cb74SMauro Carvalho Chehab }
20095bc3cb74SMauro Carvalho Chehab 
20105bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info {
20115bc3cb74SMauro Carvalho Chehab 	unsigned int ioctl;
20125bc3cb74SMauro Carvalho Chehab 	u32 flags;
20135bc3cb74SMauro Carvalho Chehab 	const char * const name;
20145bc3cb74SMauro Carvalho Chehab 	union {
20155bc3cb74SMauro Carvalho Chehab 		u32 offset;
20165bc3cb74SMauro Carvalho Chehab 		int (*func)(const struct v4l2_ioctl_ops *ops,
20175bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *p);
20185bc3cb74SMauro Carvalho Chehab 	} u;
20195bc3cb74SMauro Carvalho Chehab 	void (*debug)(const void *arg, bool write_only);
20205bc3cb74SMauro Carvalho Chehab };
20215bc3cb74SMauro Carvalho Chehab 
20225bc3cb74SMauro Carvalho Chehab /* This control needs a priority check */
20235bc3cb74SMauro Carvalho Chehab #define INFO_FL_PRIO	(1 << 0)
20245bc3cb74SMauro Carvalho Chehab /* This control can be valid if the filehandle passes a control handler. */
20255bc3cb74SMauro Carvalho Chehab #define INFO_FL_CTRL	(1 << 1)
20265bc3cb74SMauro Carvalho Chehab /* This is a standard ioctl, no need for special code */
20275bc3cb74SMauro Carvalho Chehab #define INFO_FL_STD	(1 << 2)
20285bc3cb74SMauro Carvalho Chehab /* This is ioctl has its own function */
20295bc3cb74SMauro Carvalho Chehab #define INFO_FL_FUNC	(1 << 3)
20305bc3cb74SMauro Carvalho Chehab /* Queuing ioctl */
20315bc3cb74SMauro Carvalho Chehab #define INFO_FL_QUEUE	(1 << 4)
20325bc3cb74SMauro Carvalho Chehab /* Zero struct from after the field to the end */
20335bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR(v4l2_struct, field)			\
20345bc3cb74SMauro Carvalho Chehab 	((offsetof(struct v4l2_struct, field) +			\
20355bc3cb74SMauro Carvalho Chehab 	  sizeof(((struct v4l2_struct *)0)->field)) << 16)
20365bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16)
20375bc3cb74SMauro Carvalho Chehab 
20385bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags)			\
20395bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
20405bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
20415bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_STD,				\
20425bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
20435bc3cb74SMauro Carvalho Chehab 		.u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc),	\
20445bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
20455bc3cb74SMauro Carvalho Chehab 	}
20465bc3cb74SMauro Carvalho Chehab 
20475bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags)			\
20485bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
20495bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
20505bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_FUNC,				\
20515bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
20525bc3cb74SMauro Carvalho Chehab 		.u.func = _func,					\
20535bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
20545bc3cb74SMauro Carvalho Chehab 	}
20555bc3cb74SMauro Carvalho Chehab 
20565bc3cb74SMauro Carvalho Chehab static struct v4l2_ioctl_info v4l2_ioctls[] = {
20575bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
20585bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
20595bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)),
20605bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
20615bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
20625bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
20635bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0),
20645bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
2065737c097bSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
20665bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
2067b799d09aSTomasz Stanislawski 	IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
20685bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
20695bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
20705bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
20715bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)),
20725bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO),
20735bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_STD, v4l_g_std, v4l_print_std, 0),
20745bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO),
20755bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)),
20765bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)),
20775bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)),
20785bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL),
20795bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)),
20805bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO),
20815bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0),
20825bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO),
20835bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
20845bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
20855bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
20865bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
20875bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
20885bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
20895bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
20905bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
20915bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
20925bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
20935bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
20945bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
20955bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
20965bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
20975bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
20985bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
20995bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0),
21005bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO),
21015bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
21025bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
21035bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
21045bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0),
21055bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)),
21065bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)),
21075bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0),
21085bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO),
21095bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_SLICED_VBI_CAP, v4l_g_sliced_vbi_cap, v4l_print_sliced_vbi_cap, INFO_FL_CLEAR(v4l2_sliced_vbi_cap, type)),
21105bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0),
21115bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
21125bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL),
21135bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
21145bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
21155bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
21165bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0),
21175bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENCODER_CMD, vidioc_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
21185bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
21195bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO),
21205bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0),
21215bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0),
21225bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
21235bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_IDENT, v4l_dbg_g_chip_ident, v4l_print_dbg_chip_ident, 0),
21245bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
21255bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO),
21265bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0),
21275bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0),
21285bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0),
21295bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0),
21305bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE),
21315bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE),
21325bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0),
21335bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0),
21345bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
21355bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
213679b0c640SHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_NAME, v4l_dbg_g_chip_name, v4l_print_dbg_chip_name, INFO_FL_CLEAR(v4l2_dbg_chip_name, match)),
21375bc3cb74SMauro Carvalho Chehab };
21385bc3cb74SMauro Carvalho Chehab #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
21395bc3cb74SMauro Carvalho Chehab 
21405bc3cb74SMauro Carvalho Chehab bool v4l2_is_known_ioctl(unsigned int cmd)
21415bc3cb74SMauro Carvalho Chehab {
21425bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
21435bc3cb74SMauro Carvalho Chehab 		return false;
21445bc3cb74SMauro Carvalho Chehab 	return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd;
21455bc3cb74SMauro Carvalho Chehab }
21465bc3cb74SMauro Carvalho Chehab 
21475bc3cb74SMauro Carvalho Chehab struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd)
21485bc3cb74SMauro Carvalho Chehab {
21495bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
21505bc3cb74SMauro Carvalho Chehab 		return vdev->lock;
21515bc3cb74SMauro Carvalho Chehab 	if (test_bit(_IOC_NR(cmd), vdev->disable_locking))
21525bc3cb74SMauro Carvalho Chehab 		return NULL;
21535bc3cb74SMauro Carvalho Chehab 	if (vdev->queue && vdev->queue->lock &&
21545bc3cb74SMauro Carvalho Chehab 			(v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE))
21555bc3cb74SMauro Carvalho Chehab 		return vdev->queue->lock;
21565bc3cb74SMauro Carvalho Chehab 	return vdev->lock;
21575bc3cb74SMauro Carvalho Chehab }
21585bc3cb74SMauro Carvalho Chehab 
21595bc3cb74SMauro Carvalho Chehab /* Common ioctl debug function. This function can be used by
21605bc3cb74SMauro Carvalho Chehab    external ioctl messages as well as internal V4L ioctl */
21615bc3cb74SMauro Carvalho Chehab void v4l_printk_ioctl(const char *prefix, unsigned int cmd)
21625bc3cb74SMauro Carvalho Chehab {
21635bc3cb74SMauro Carvalho Chehab 	const char *dir, *type;
21645bc3cb74SMauro Carvalho Chehab 
21655bc3cb74SMauro Carvalho Chehab 	if (prefix)
21665bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "%s: ", prefix);
21675bc3cb74SMauro Carvalho Chehab 
21685bc3cb74SMauro Carvalho Chehab 	switch (_IOC_TYPE(cmd)) {
21695bc3cb74SMauro Carvalho Chehab 	case 'd':
21705bc3cb74SMauro Carvalho Chehab 		type = "v4l2_int";
21715bc3cb74SMauro Carvalho Chehab 		break;
21725bc3cb74SMauro Carvalho Chehab 	case 'V':
21735bc3cb74SMauro Carvalho Chehab 		if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
21745bc3cb74SMauro Carvalho Chehab 			type = "v4l2";
21755bc3cb74SMauro Carvalho Chehab 			break;
21765bc3cb74SMauro Carvalho Chehab 		}
21775bc3cb74SMauro Carvalho Chehab 		pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name);
21785bc3cb74SMauro Carvalho Chehab 		return;
21795bc3cb74SMauro Carvalho Chehab 	default:
21805bc3cb74SMauro Carvalho Chehab 		type = "unknown";
21815bc3cb74SMauro Carvalho Chehab 		break;
21825bc3cb74SMauro Carvalho Chehab 	}
21835bc3cb74SMauro Carvalho Chehab 
21845bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
21855bc3cb74SMauro Carvalho Chehab 	case _IOC_NONE:              dir = "--"; break;
21865bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:              dir = "r-"; break;
21875bc3cb74SMauro Carvalho Chehab 	case _IOC_WRITE:             dir = "-w"; break;
21885bc3cb74SMauro Carvalho Chehab 	case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
21895bc3cb74SMauro Carvalho Chehab 	default:                     dir = "*ERR*"; break;
21905bc3cb74SMauro Carvalho Chehab 	}
21915bc3cb74SMauro Carvalho Chehab 	pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)",
21925bc3cb74SMauro Carvalho Chehab 		type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
21935bc3cb74SMauro Carvalho Chehab }
21945bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l_printk_ioctl);
21955bc3cb74SMauro Carvalho Chehab 
21965bc3cb74SMauro Carvalho Chehab static long __video_do_ioctl(struct file *file,
21975bc3cb74SMauro Carvalho Chehab 		unsigned int cmd, void *arg)
21985bc3cb74SMauro Carvalho Chehab {
21995bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
22005bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
22015bc3cb74SMauro Carvalho Chehab 	bool write_only = false;
22025bc3cb74SMauro Carvalho Chehab 	struct v4l2_ioctl_info default_info;
22035bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_info *info;
22045bc3cb74SMauro Carvalho Chehab 	void *fh = file->private_data;
22055bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh = NULL;
22065bc3cb74SMauro Carvalho Chehab 	int use_fh_prio = 0;
22075bc3cb74SMauro Carvalho Chehab 	int debug = vfd->debug;
22085bc3cb74SMauro Carvalho Chehab 	long ret = -ENOTTY;
22095bc3cb74SMauro Carvalho Chehab 
22105bc3cb74SMauro Carvalho Chehab 	if (ops == NULL) {
22115bc3cb74SMauro Carvalho Chehab 		pr_warn("%s: has no ioctl_ops.\n",
22125bc3cb74SMauro Carvalho Chehab 				video_device_node_name(vfd));
22135bc3cb74SMauro Carvalho Chehab 		return ret;
22145bc3cb74SMauro Carvalho Chehab 	}
22155bc3cb74SMauro Carvalho Chehab 
22165bc3cb74SMauro Carvalho Chehab 	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
22175bc3cb74SMauro Carvalho Chehab 		vfh = file->private_data;
22185bc3cb74SMauro Carvalho Chehab 		use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
22195bc3cb74SMauro Carvalho Chehab 	}
22205bc3cb74SMauro Carvalho Chehab 
22215bc3cb74SMauro Carvalho Chehab 	if (v4l2_is_known_ioctl(cmd)) {
22225bc3cb74SMauro Carvalho Chehab 		info = &v4l2_ioctls[_IOC_NR(cmd)];
22235bc3cb74SMauro Carvalho Chehab 
22245bc3cb74SMauro Carvalho Chehab 	        if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
22255bc3cb74SMauro Carvalho Chehab 		    !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
22265bc3cb74SMauro Carvalho Chehab 			goto done;
22275bc3cb74SMauro Carvalho Chehab 
22285bc3cb74SMauro Carvalho Chehab 		if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
22295bc3cb74SMauro Carvalho Chehab 			ret = v4l2_prio_check(vfd->prio, vfh->prio);
22305bc3cb74SMauro Carvalho Chehab 			if (ret)
22315bc3cb74SMauro Carvalho Chehab 				goto done;
22325bc3cb74SMauro Carvalho Chehab 		}
22335bc3cb74SMauro Carvalho Chehab 	} else {
22345bc3cb74SMauro Carvalho Chehab 		default_info.ioctl = cmd;
22355bc3cb74SMauro Carvalho Chehab 		default_info.flags = 0;
22365bc3cb74SMauro Carvalho Chehab 		default_info.debug = v4l_print_default;
22375bc3cb74SMauro Carvalho Chehab 		info = &default_info;
22385bc3cb74SMauro Carvalho Chehab 	}
22395bc3cb74SMauro Carvalho Chehab 
22405bc3cb74SMauro Carvalho Chehab 	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
22415bc3cb74SMauro Carvalho Chehab 	if (info->flags & INFO_FL_STD) {
22425bc3cb74SMauro Carvalho Chehab 		typedef int (*vidioc_op)(struct file *file, void *fh, void *p);
22435bc3cb74SMauro Carvalho Chehab 		const void *p = vfd->ioctl_ops;
22445bc3cb74SMauro Carvalho Chehab 		const vidioc_op *vidioc = p + info->u.offset;
22455bc3cb74SMauro Carvalho Chehab 
22465bc3cb74SMauro Carvalho Chehab 		ret = (*vidioc)(file, fh, arg);
22475bc3cb74SMauro Carvalho Chehab 	} else if (info->flags & INFO_FL_FUNC) {
22485bc3cb74SMauro Carvalho Chehab 		ret = info->u.func(ops, file, fh, arg);
22495bc3cb74SMauro Carvalho Chehab 	} else if (!ops->vidioc_default) {
22505bc3cb74SMauro Carvalho Chehab 		ret = -ENOTTY;
22515bc3cb74SMauro Carvalho Chehab 	} else {
22525bc3cb74SMauro Carvalho Chehab 		ret = ops->vidioc_default(file, fh,
22535bc3cb74SMauro Carvalho Chehab 			use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
22545bc3cb74SMauro Carvalho Chehab 			cmd, arg);
22555bc3cb74SMauro Carvalho Chehab 	}
22565bc3cb74SMauro Carvalho Chehab 
22575bc3cb74SMauro Carvalho Chehab done:
22585bc3cb74SMauro Carvalho Chehab 	if (debug) {
22595bc3cb74SMauro Carvalho Chehab 		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
22605bc3cb74SMauro Carvalho Chehab 		if (ret < 0)
2261505d04bdSHans Verkuil 			pr_cont(": error %ld", ret);
2262505d04bdSHans Verkuil 		if (debug == V4L2_DEBUG_IOCTL)
22635bc3cb74SMauro Carvalho Chehab 			pr_cont("\n");
22645bc3cb74SMauro Carvalho Chehab 		else if (_IOC_DIR(cmd) == _IOC_NONE)
22655bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
22665bc3cb74SMauro Carvalho Chehab 		else {
22675bc3cb74SMauro Carvalho Chehab 			pr_cont(": ");
22685bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
22695bc3cb74SMauro Carvalho Chehab 		}
22705bc3cb74SMauro Carvalho Chehab 	}
22715bc3cb74SMauro Carvalho Chehab 
22725bc3cb74SMauro Carvalho Chehab 	return ret;
22735bc3cb74SMauro Carvalho Chehab }
22745bc3cb74SMauro Carvalho Chehab 
22755bc3cb74SMauro Carvalho Chehab static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
22765bc3cb74SMauro Carvalho Chehab 			    void * __user *user_ptr, void ***kernel_ptr)
22775bc3cb74SMauro Carvalho Chehab {
22785bc3cb74SMauro Carvalho Chehab 	int ret = 0;
22795bc3cb74SMauro Carvalho Chehab 
22805bc3cb74SMauro Carvalho Chehab 	switch (cmd) {
228196b1a702SHans Verkuil 	case VIDIOC_PREPARE_BUF:
22825bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QUERYBUF:
22835bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QBUF:
22845bc3cb74SMauro Carvalho Chehab 	case VIDIOC_DQBUF: {
22855bc3cb74SMauro Carvalho Chehab 		struct v4l2_buffer *buf = parg;
22865bc3cb74SMauro Carvalho Chehab 
22875bc3cb74SMauro Carvalho Chehab 		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
22885bc3cb74SMauro Carvalho Chehab 			if (buf->length > VIDEO_MAX_PLANES) {
22895bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
22905bc3cb74SMauro Carvalho Chehab 				break;
22915bc3cb74SMauro Carvalho Chehab 			}
22925bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)buf->m.planes;
22935bc3cb74SMauro Carvalho Chehab 			*kernel_ptr = (void *)&buf->m.planes;
22945bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_plane) * buf->length;
22955bc3cb74SMauro Carvalho Chehab 			ret = 1;
22965bc3cb74SMauro Carvalho Chehab 		}
22975bc3cb74SMauro Carvalho Chehab 		break;
22985bc3cb74SMauro Carvalho Chehab 	}
22995bc3cb74SMauro Carvalho Chehab 
2300ed45ce2cSHans Verkuil 	case VIDIOC_SUBDEV_G_EDID:
2301ed45ce2cSHans Verkuil 	case VIDIOC_SUBDEV_S_EDID: {
2302ed45ce2cSHans Verkuil 		struct v4l2_subdev_edid *edid = parg;
2303ed45ce2cSHans Verkuil 
2304ed45ce2cSHans Verkuil 		if (edid->blocks) {
23051b8b10ccSHans Verkuil 			if (edid->blocks > 256) {
23061b8b10ccSHans Verkuil 				ret = -EINVAL;
23071b8b10ccSHans Verkuil 				break;
23081b8b10ccSHans Verkuil 			}
2309ed45ce2cSHans Verkuil 			*user_ptr = (void __user *)edid->edid;
2310ed45ce2cSHans Verkuil 			*kernel_ptr = (void *)&edid->edid;
2311ed45ce2cSHans Verkuil 			*array_size = edid->blocks * 128;
2312ed45ce2cSHans Verkuil 			ret = 1;
2313ed45ce2cSHans Verkuil 		}
2314ed45ce2cSHans Verkuil 		break;
2315ed45ce2cSHans Verkuil 	}
2316ed45ce2cSHans Verkuil 
23175bc3cb74SMauro Carvalho Chehab 	case VIDIOC_S_EXT_CTRLS:
23185bc3cb74SMauro Carvalho Chehab 	case VIDIOC_G_EXT_CTRLS:
23195bc3cb74SMauro Carvalho Chehab 	case VIDIOC_TRY_EXT_CTRLS: {
23205bc3cb74SMauro Carvalho Chehab 		struct v4l2_ext_controls *ctrls = parg;
23215bc3cb74SMauro Carvalho Chehab 
23225bc3cb74SMauro Carvalho Chehab 		if (ctrls->count != 0) {
23235bc3cb74SMauro Carvalho Chehab 			if (ctrls->count > V4L2_CID_MAX_CTRLS) {
23245bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
23255bc3cb74SMauro Carvalho Chehab 				break;
23265bc3cb74SMauro Carvalho Chehab 			}
23275bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)ctrls->controls;
23285bc3cb74SMauro Carvalho Chehab 			*kernel_ptr = (void *)&ctrls->controls;
23295bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_ext_control)
23305bc3cb74SMauro Carvalho Chehab 				    * ctrls->count;
23315bc3cb74SMauro Carvalho Chehab 			ret = 1;
23325bc3cb74SMauro Carvalho Chehab 		}
23335bc3cb74SMauro Carvalho Chehab 		break;
23345bc3cb74SMauro Carvalho Chehab 	}
23355bc3cb74SMauro Carvalho Chehab 	}
23365bc3cb74SMauro Carvalho Chehab 
23375bc3cb74SMauro Carvalho Chehab 	return ret;
23385bc3cb74SMauro Carvalho Chehab }
23395bc3cb74SMauro Carvalho Chehab 
23405bc3cb74SMauro Carvalho Chehab long
23415bc3cb74SMauro Carvalho Chehab video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
23425bc3cb74SMauro Carvalho Chehab 	       v4l2_kioctl func)
23435bc3cb74SMauro Carvalho Chehab {
23445bc3cb74SMauro Carvalho Chehab 	char	sbuf[128];
23455bc3cb74SMauro Carvalho Chehab 	void    *mbuf = NULL;
23465bc3cb74SMauro Carvalho Chehab 	void	*parg = (void *)arg;
23475bc3cb74SMauro Carvalho Chehab 	long	err  = -EINVAL;
23485bc3cb74SMauro Carvalho Chehab 	bool	has_array_args;
23495bc3cb74SMauro Carvalho Chehab 	size_t  array_size = 0;
23505bc3cb74SMauro Carvalho Chehab 	void __user *user_ptr = NULL;
23515bc3cb74SMauro Carvalho Chehab 	void	**kernel_ptr = NULL;
23525bc3cb74SMauro Carvalho Chehab 
23535bc3cb74SMauro Carvalho Chehab 	/*  Copy arguments into temp kernel buffer  */
23545bc3cb74SMauro Carvalho Chehab 	if (_IOC_DIR(cmd) != _IOC_NONE) {
23555bc3cb74SMauro Carvalho Chehab 		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
23565bc3cb74SMauro Carvalho Chehab 			parg = sbuf;
23575bc3cb74SMauro Carvalho Chehab 		} else {
23585bc3cb74SMauro Carvalho Chehab 			/* too big to allocate from stack */
23595bc3cb74SMauro Carvalho Chehab 			mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
23605bc3cb74SMauro Carvalho Chehab 			if (NULL == mbuf)
23615bc3cb74SMauro Carvalho Chehab 				return -ENOMEM;
23625bc3cb74SMauro Carvalho Chehab 			parg = mbuf;
23635bc3cb74SMauro Carvalho Chehab 		}
23645bc3cb74SMauro Carvalho Chehab 
23655bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
23665bc3cb74SMauro Carvalho Chehab 		if (_IOC_DIR(cmd) & _IOC_WRITE) {
23675bc3cb74SMauro Carvalho Chehab 			unsigned int n = _IOC_SIZE(cmd);
23685bc3cb74SMauro Carvalho Chehab 
23695bc3cb74SMauro Carvalho Chehab 			/*
23705bc3cb74SMauro Carvalho Chehab 			 * In some cases, only a few fields are used as input,
23715bc3cb74SMauro Carvalho Chehab 			 * i.e. when the app sets "index" and then the driver
23725bc3cb74SMauro Carvalho Chehab 			 * fills in the rest of the structure for the thing
23735bc3cb74SMauro Carvalho Chehab 			 * with that index.  We only need to copy up the first
23745bc3cb74SMauro Carvalho Chehab 			 * non-input field.
23755bc3cb74SMauro Carvalho Chehab 			 */
23765bc3cb74SMauro Carvalho Chehab 			if (v4l2_is_known_ioctl(cmd)) {
23775bc3cb74SMauro Carvalho Chehab 				u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;
23785bc3cb74SMauro Carvalho Chehab 				if (flags & INFO_FL_CLEAR_MASK)
23795bc3cb74SMauro Carvalho Chehab 					n = (flags & INFO_FL_CLEAR_MASK) >> 16;
23805bc3cb74SMauro Carvalho Chehab 			}
23815bc3cb74SMauro Carvalho Chehab 
23825bc3cb74SMauro Carvalho Chehab 			if (copy_from_user(parg, (void __user *)arg, n))
23835bc3cb74SMauro Carvalho Chehab 				goto out;
23845bc3cb74SMauro Carvalho Chehab 
23855bc3cb74SMauro Carvalho Chehab 			/* zero out anything we don't copy from userspace */
23865bc3cb74SMauro Carvalho Chehab 			if (n < _IOC_SIZE(cmd))
23875bc3cb74SMauro Carvalho Chehab 				memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
23885bc3cb74SMauro Carvalho Chehab 		} else {
23895bc3cb74SMauro Carvalho Chehab 			/* read-only ioctl */
23905bc3cb74SMauro Carvalho Chehab 			memset(parg, 0, _IOC_SIZE(cmd));
23915bc3cb74SMauro Carvalho Chehab 		}
23925bc3cb74SMauro Carvalho Chehab 	}
23935bc3cb74SMauro Carvalho Chehab 
23945bc3cb74SMauro Carvalho Chehab 	err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
23955bc3cb74SMauro Carvalho Chehab 	if (err < 0)
23965bc3cb74SMauro Carvalho Chehab 		goto out;
23975bc3cb74SMauro Carvalho Chehab 	has_array_args = err;
23985bc3cb74SMauro Carvalho Chehab 
23995bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
24005bc3cb74SMauro Carvalho Chehab 		/*
24015bc3cb74SMauro Carvalho Chehab 		 * When adding new types of array args, make sure that the
24025bc3cb74SMauro Carvalho Chehab 		 * parent argument to ioctl (which contains the pointer to the
24035bc3cb74SMauro Carvalho Chehab 		 * array) fits into sbuf (so that mbuf will still remain
24045bc3cb74SMauro Carvalho Chehab 		 * unused up to here).
24055bc3cb74SMauro Carvalho Chehab 		 */
24065bc3cb74SMauro Carvalho Chehab 		mbuf = kmalloc(array_size, GFP_KERNEL);
24075bc3cb74SMauro Carvalho Chehab 		err = -ENOMEM;
24085bc3cb74SMauro Carvalho Chehab 		if (NULL == mbuf)
24095bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
24105bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
24115bc3cb74SMauro Carvalho Chehab 		if (copy_from_user(mbuf, user_ptr, array_size))
24125bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
24135bc3cb74SMauro Carvalho Chehab 		*kernel_ptr = mbuf;
24145bc3cb74SMauro Carvalho Chehab 	}
24155bc3cb74SMauro Carvalho Chehab 
24165bc3cb74SMauro Carvalho Chehab 	/* Handles IOCTL */
24175bc3cb74SMauro Carvalho Chehab 	err = func(file, cmd, parg);
24185bc3cb74SMauro Carvalho Chehab 	if (err == -ENOIOCTLCMD)
24195bc3cb74SMauro Carvalho Chehab 		err = -ENOTTY;
24205bc3cb74SMauro Carvalho Chehab 
24215bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
24225bc3cb74SMauro Carvalho Chehab 		*kernel_ptr = user_ptr;
24235bc3cb74SMauro Carvalho Chehab 		if (copy_to_user(user_ptr, mbuf, array_size))
24245bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
24255bc3cb74SMauro Carvalho Chehab 		goto out_array_args;
24265bc3cb74SMauro Carvalho Chehab 	}
24275bc3cb74SMauro Carvalho Chehab 	/* VIDIOC_QUERY_DV_TIMINGS can return an error, but still have valid
24285bc3cb74SMauro Carvalho Chehab 	   results that must be returned. */
24295bc3cb74SMauro Carvalho Chehab 	if (err < 0 && cmd != VIDIOC_QUERY_DV_TIMINGS)
24305bc3cb74SMauro Carvalho Chehab 		goto out;
24315bc3cb74SMauro Carvalho Chehab 
24325bc3cb74SMauro Carvalho Chehab out_array_args:
24335bc3cb74SMauro Carvalho Chehab 	/*  Copy results into user buffer  */
24345bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
24355bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:
24365bc3cb74SMauro Carvalho Chehab 	case (_IOC_WRITE | _IOC_READ):
24375bc3cb74SMauro Carvalho Chehab 		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
24385bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
24395bc3cb74SMauro Carvalho Chehab 		break;
24405bc3cb74SMauro Carvalho Chehab 	}
24415bc3cb74SMauro Carvalho Chehab 
24425bc3cb74SMauro Carvalho Chehab out:
24435bc3cb74SMauro Carvalho Chehab 	kfree(mbuf);
24445bc3cb74SMauro Carvalho Chehab 	return err;
24455bc3cb74SMauro Carvalho Chehab }
24465bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_usercopy);
24475bc3cb74SMauro Carvalho Chehab 
24485bc3cb74SMauro Carvalho Chehab long video_ioctl2(struct file *file,
24495bc3cb74SMauro Carvalho Chehab 	       unsigned int cmd, unsigned long arg)
24505bc3cb74SMauro Carvalho Chehab {
24515bc3cb74SMauro Carvalho Chehab 	return video_usercopy(file, cmd, arg, __video_do_ioctl);
24525bc3cb74SMauro Carvalho Chehab }
24535bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_ioctl2);
2454