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/videobuf2-core.h>
305bc3cb74SMauro Carvalho Chehab 
31aa32f4c0SHans Verkuil #define CREATE_TRACE_POINTS
32aa32f4c0SHans Verkuil #include <trace/events/v4l2.h>
33aa32f4c0SHans Verkuil 
345bc3cb74SMauro Carvalho Chehab /* Zero out the end of the struct pointed to by p.  Everything after, but
355bc3cb74SMauro Carvalho Chehab  * not including, the specified field is cleared. */
365bc3cb74SMauro Carvalho Chehab #define CLEAR_AFTER_FIELD(p, field) \
375bc3cb74SMauro Carvalho Chehab 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
385bc3cb74SMauro Carvalho Chehab 	0, sizeof(*(p)) - offsetof(typeof(*(p)), field) - sizeof((p)->field))
395bc3cb74SMauro Carvalho Chehab 
4073f35418SHans Verkuil #define is_valid_ioctl(vfd, cmd) test_bit(_IOC_NR(cmd), (vfd)->valid_ioctls)
4173f35418SHans Verkuil 
425bc3cb74SMauro Carvalho Chehab struct std_descr {
435bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
445bc3cb74SMauro Carvalho Chehab 	const char *descr;
455bc3cb74SMauro Carvalho Chehab };
465bc3cb74SMauro Carvalho Chehab 
475bc3cb74SMauro Carvalho Chehab static const struct std_descr standards[] = {
485bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC, 	"NTSC"      },
495bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M, 	"NTSC-M"    },
505bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_JP, 	"NTSC-M-JP" },
515bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_M_KR,	"NTSC-M-KR" },
525bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_NTSC_443, 	"NTSC-443"  },
535bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL, 	"PAL"       },
545bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_BG, 	"PAL-BG"    },
555bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B, 	"PAL-B"     },
565bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_B1, 	"PAL-B1"    },
575bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_G, 	"PAL-G"     },
585bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_H, 	"PAL-H"     },
595bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_I, 	"PAL-I"     },
605bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_DK, 	"PAL-DK"    },
615bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D, 	"PAL-D"     },
625bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_D1, 	"PAL-D1"    },
635bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_K, 	"PAL-K"     },
645bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_M, 	"PAL-M"     },
655bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_N, 	"PAL-N"     },
665bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_Nc, 	"PAL-Nc"    },
675bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_PAL_60, 	"PAL-60"    },
685bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM, 	"SECAM"     },
695bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_B, 	"SECAM-B"   },
705bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_G, 	"SECAM-G"   },
715bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_H, 	"SECAM-H"   },
725bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_DK, 	"SECAM-DK"  },
735bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_D, 	"SECAM-D"   },
745bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K, 	"SECAM-K"   },
755bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_K1, 	"SECAM-K1"  },
765bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_L, 	"SECAM-L"   },
775bc3cb74SMauro Carvalho Chehab 	{ V4L2_STD_SECAM_LC, 	"SECAM-Lc"  },
785bc3cb74SMauro Carvalho Chehab 	{ 0, 			"Unknown"   }
795bc3cb74SMauro Carvalho Chehab };
805bc3cb74SMauro Carvalho Chehab 
815bc3cb74SMauro Carvalho Chehab /* video4linux standard ID conversion to standard name
825bc3cb74SMauro Carvalho Chehab  */
835bc3cb74SMauro Carvalho Chehab const char *v4l2_norm_to_name(v4l2_std_id id)
845bc3cb74SMauro Carvalho Chehab {
855bc3cb74SMauro Carvalho Chehab 	u32 myid = id;
865bc3cb74SMauro Carvalho Chehab 	int i;
875bc3cb74SMauro Carvalho Chehab 
885bc3cb74SMauro Carvalho Chehab 	/* HACK: ppc32 architecture doesn't have __ucmpdi2 function to handle
895bc3cb74SMauro Carvalho Chehab 	   64 bit comparations. So, on that architecture, with some gcc
905bc3cb74SMauro Carvalho Chehab 	   variants, compilation fails. Currently, the max value is 30bit wide.
915bc3cb74SMauro Carvalho Chehab 	 */
925bc3cb74SMauro Carvalho Chehab 	BUG_ON(myid != id);
935bc3cb74SMauro Carvalho Chehab 
945bc3cb74SMauro Carvalho Chehab 	for (i = 0; standards[i].std; i++)
955bc3cb74SMauro Carvalho Chehab 		if (myid == standards[i].std)
965bc3cb74SMauro Carvalho Chehab 			break;
975bc3cb74SMauro Carvalho Chehab 	return standards[i].descr;
985bc3cb74SMauro Carvalho Chehab }
995bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_norm_to_name);
1005bc3cb74SMauro Carvalho Chehab 
1015bc3cb74SMauro Carvalho Chehab /* Returns frame period for the given standard */
1025bc3cb74SMauro Carvalho Chehab void v4l2_video_std_frame_period(int id, struct v4l2_fract *frameperiod)
1035bc3cb74SMauro Carvalho Chehab {
1045bc3cb74SMauro Carvalho Chehab 	if (id & V4L2_STD_525_60) {
1055bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1001;
1065bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 30000;
1075bc3cb74SMauro Carvalho Chehab 	} else {
1085bc3cb74SMauro Carvalho Chehab 		frameperiod->numerator = 1;
1095bc3cb74SMauro Carvalho Chehab 		frameperiod->denominator = 25;
1105bc3cb74SMauro Carvalho Chehab 	}
1115bc3cb74SMauro Carvalho Chehab }
1125bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_frame_period);
1135bc3cb74SMauro Carvalho Chehab 
1145bc3cb74SMauro Carvalho Chehab /* Fill in the fields of a v4l2_standard structure according to the
1155bc3cb74SMauro Carvalho Chehab    'id' and 'transmission' parameters.  Returns negative on error.  */
1165bc3cb74SMauro Carvalho Chehab int v4l2_video_std_construct(struct v4l2_standard *vs,
1175bc3cb74SMauro Carvalho Chehab 			     int id, const char *name)
1185bc3cb74SMauro Carvalho Chehab {
1195bc3cb74SMauro Carvalho Chehab 	vs->id = id;
1205bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_frame_period(id, &vs->frameperiod);
1215bc3cb74SMauro Carvalho Chehab 	vs->framelines = (id & V4L2_STD_525_60) ? 525 : 625;
1225bc3cb74SMauro Carvalho Chehab 	strlcpy(vs->name, name, sizeof(vs->name));
1235bc3cb74SMauro Carvalho Chehab 	return 0;
1245bc3cb74SMauro Carvalho Chehab }
1255bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_video_std_construct);
1265bc3cb74SMauro Carvalho Chehab 
1275bc3cb74SMauro Carvalho Chehab /* ----------------------------------------------------------------- */
1285bc3cb74SMauro Carvalho Chehab /* some arrays for pretty-printing debug messages of enum types      */
1295bc3cb74SMauro Carvalho Chehab 
1305bc3cb74SMauro Carvalho Chehab const char *v4l2_field_names[] = {
1315bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ANY]        = "any",
1325bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_NONE]       = "none",
1335bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_TOP]        = "top",
1345bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_BOTTOM]     = "bottom",
1355bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED] = "interlaced",
1365bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_TB]     = "seq-tb",
1375bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_SEQ_BT]     = "seq-bt",
1385bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_ALTERNATE]  = "alternate",
1395bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_TB] = "interlaced-tb",
1405bc3cb74SMauro Carvalho Chehab 	[V4L2_FIELD_INTERLACED_BT] = "interlaced-bt",
1415bc3cb74SMauro Carvalho Chehab };
1425bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_field_names);
1435bc3cb74SMauro Carvalho Chehab 
1445bc3cb74SMauro Carvalho Chehab const char *v4l2_type_names[] = {
1455bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE]      = "vid-cap",
1465bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OVERLAY]      = "vid-overlay",
1475bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT]       = "vid-out",
1485bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_CAPTURE]        = "vbi-cap",
1495bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VBI_OUTPUT]         = "vbi-out",
1505bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
1515bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
1525bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
1535bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
1545bc3cb74SMauro Carvalho Chehab 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
1556f3073b8SAntti Palosaari 	[V4L2_BUF_TYPE_SDR_CAPTURE]        = "sdr-cap",
1565bc3cb74SMauro Carvalho Chehab };
1575bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l2_type_names);
1585bc3cb74SMauro Carvalho Chehab 
1595bc3cb74SMauro Carvalho Chehab static const char *v4l2_memory_names[] = {
1605bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_MMAP]    = "mmap",
1615bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_USERPTR] = "userptr",
1625bc3cb74SMauro Carvalho Chehab 	[V4L2_MEMORY_OVERLAY] = "overlay",
163051c7788SSumit Semwal 	[V4L2_MEMORY_DMABUF] = "dmabuf",
1645bc3cb74SMauro Carvalho Chehab };
1655bc3cb74SMauro Carvalho Chehab 
166d9246240SHans Verkuil #define prt_names(a, arr) (((unsigned)(a)) < ARRAY_SIZE(arr) ? arr[a] : "unknown")
1675bc3cb74SMauro Carvalho Chehab 
1685bc3cb74SMauro Carvalho Chehab /* ------------------------------------------------------------------ */
1695bc3cb74SMauro Carvalho Chehab /* debug help functions                                               */
1705bc3cb74SMauro Carvalho Chehab 
1715bc3cb74SMauro Carvalho Chehab static void v4l_print_querycap(const void *arg, bool write_only)
1725bc3cb74SMauro Carvalho Chehab {
1735bc3cb74SMauro Carvalho Chehab 	const struct v4l2_capability *p = arg;
1745bc3cb74SMauro Carvalho Chehab 
17527d5a87cSHans Verkuil 	pr_cont("driver=%.*s, card=%.*s, bus=%.*s, version=0x%08x, "
1765bc3cb74SMauro Carvalho Chehab 		"capabilities=0x%08x, device_caps=0x%08x\n",
17727d5a87cSHans Verkuil 		(int)sizeof(p->driver), p->driver,
17827d5a87cSHans Verkuil 		(int)sizeof(p->card), p->card,
17927d5a87cSHans Verkuil 		(int)sizeof(p->bus_info), p->bus_info,
1805bc3cb74SMauro Carvalho Chehab 		p->version, p->capabilities, p->device_caps);
1815bc3cb74SMauro Carvalho Chehab }
1825bc3cb74SMauro Carvalho Chehab 
1835bc3cb74SMauro Carvalho Chehab static void v4l_print_enuminput(const void *arg, bool write_only)
1845bc3cb74SMauro Carvalho Chehab {
1855bc3cb74SMauro Carvalho Chehab 	const struct v4l2_input *p = arg;
1865bc3cb74SMauro Carvalho Chehab 
18727d5a87cSHans Verkuil 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, tuner=%u, "
1885bc3cb74SMauro Carvalho Chehab 		"std=0x%08Lx, status=0x%x, capabilities=0x%x\n",
18927d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
19027d5a87cSHans Verkuil 		p->tuner, (unsigned long long)p->std, p->status,
19127d5a87cSHans Verkuil 		p->capabilities);
1925bc3cb74SMauro Carvalho Chehab }
1935bc3cb74SMauro Carvalho Chehab 
1945bc3cb74SMauro Carvalho Chehab static void v4l_print_enumoutput(const void *arg, bool write_only)
1955bc3cb74SMauro Carvalho Chehab {
1965bc3cb74SMauro Carvalho Chehab 	const struct v4l2_output *p = arg;
1975bc3cb74SMauro Carvalho Chehab 
19827d5a87cSHans Verkuil 	pr_cont("index=%u, name=%.*s, type=%u, audioset=0x%x, "
1995bc3cb74SMauro Carvalho Chehab 		"modulator=%u, std=0x%08Lx, capabilities=0x%x\n",
20027d5a87cSHans Verkuil 		p->index, (int)sizeof(p->name), p->name, p->type, p->audioset,
20127d5a87cSHans Verkuil 		p->modulator, (unsigned long long)p->std, p->capabilities);
2025bc3cb74SMauro Carvalho Chehab }
2035bc3cb74SMauro Carvalho Chehab 
2045bc3cb74SMauro Carvalho Chehab static void v4l_print_audio(const void *arg, bool write_only)
2055bc3cb74SMauro Carvalho Chehab {
2065bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audio *p = arg;
2075bc3cb74SMauro Carvalho Chehab 
2085bc3cb74SMauro Carvalho Chehab 	if (write_only)
2095bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, mode=0x%x\n", p->index, p->mode);
2105bc3cb74SMauro Carvalho Chehab 	else
21127d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
21227d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
21327d5a87cSHans Verkuil 			p->capability, p->mode);
2145bc3cb74SMauro Carvalho Chehab }
2155bc3cb74SMauro Carvalho Chehab 
2165bc3cb74SMauro Carvalho Chehab static void v4l_print_audioout(const void *arg, bool write_only)
2175bc3cb74SMauro Carvalho Chehab {
2185bc3cb74SMauro Carvalho Chehab 	const struct v4l2_audioout *p = arg;
2195bc3cb74SMauro Carvalho Chehab 
2205bc3cb74SMauro Carvalho Chehab 	if (write_only)
2215bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u\n", p->index);
2225bc3cb74SMauro Carvalho Chehab 	else
22327d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, mode=0x%x\n",
22427d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name,
22527d5a87cSHans Verkuil 			p->capability, p->mode);
2265bc3cb74SMauro Carvalho Chehab }
2275bc3cb74SMauro Carvalho Chehab 
2285bc3cb74SMauro Carvalho Chehab static void v4l_print_fmtdesc(const void *arg, bool write_only)
2295bc3cb74SMauro Carvalho Chehab {
2305bc3cb74SMauro Carvalho Chehab 	const struct v4l2_fmtdesc *p = arg;
2315bc3cb74SMauro Carvalho Chehab 
23227d5a87cSHans Verkuil 	pr_cont("index=%u, type=%s, flags=0x%x, pixelformat=%c%c%c%c, description='%.*s'\n",
2335bc3cb74SMauro Carvalho Chehab 		p->index, prt_names(p->type, v4l2_type_names),
2345bc3cb74SMauro Carvalho Chehab 		p->flags, (p->pixelformat & 0xff),
2355bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >>  8) & 0xff,
2365bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 16) & 0xff,
2375bc3cb74SMauro Carvalho Chehab 		(p->pixelformat >> 24) & 0xff,
23827d5a87cSHans Verkuil 		(int)sizeof(p->description), p->description);
2395bc3cb74SMauro Carvalho Chehab }
2405bc3cb74SMauro Carvalho Chehab 
2415bc3cb74SMauro Carvalho Chehab static void v4l_print_format(const void *arg, bool write_only)
2425bc3cb74SMauro Carvalho Chehab {
2435bc3cb74SMauro Carvalho Chehab 	const struct v4l2_format *p = arg;
2445bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format *pix;
2455bc3cb74SMauro Carvalho Chehab 	const struct v4l2_pix_format_mplane *mp;
2465bc3cb74SMauro Carvalho Chehab 	const struct v4l2_vbi_format *vbi;
2475bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_format *sliced;
2485bc3cb74SMauro Carvalho Chehab 	const struct v4l2_window *win;
249582c52cbSAntti Palosaari 	const struct v4l2_format_sdr *sdr;
2505bc3cb74SMauro Carvalho Chehab 	unsigned i;
2515bc3cb74SMauro Carvalho Chehab 
2525bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
2535bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
2545bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
2555bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
2565bc3cb74SMauro Carvalho Chehab 		pix = &p->fmt.pix;
2575bc3cb74SMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, "
2585bc3cb74SMauro Carvalho Chehab 			"pixelformat=%c%c%c%c, field=%s, "
259560dde24SHans Verkuil 			"bytesperline=%u, sizeimage=%u, colorspace=%d\n",
2605bc3cb74SMauro Carvalho Chehab 			pix->width, pix->height,
2615bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat & 0xff),
2625bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >>  8) & 0xff,
2635bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 16) & 0xff,
2645bc3cb74SMauro Carvalho Chehab 			(pix->pixelformat >> 24) & 0xff,
2655bc3cb74SMauro Carvalho Chehab 			prt_names(pix->field, v4l2_field_names),
2665bc3cb74SMauro Carvalho Chehab 			pix->bytesperline, pix->sizeimage,
2675bc3cb74SMauro Carvalho Chehab 			pix->colorspace);
2685bc3cb74SMauro Carvalho Chehab 		break;
2695bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
2705bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
2715bc3cb74SMauro Carvalho Chehab 		mp = &p->fmt.pix_mp;
2725bc3cb74SMauro Carvalho Chehab 		pr_cont(", width=%u, height=%u, "
2735bc3cb74SMauro Carvalho Chehab 			"format=%c%c%c%c, field=%s, "
2745bc3cb74SMauro Carvalho Chehab 			"colorspace=%d, num_planes=%u\n",
2755bc3cb74SMauro Carvalho Chehab 			mp->width, mp->height,
2765bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat & 0xff),
2775bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >>  8) & 0xff,
2785bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 16) & 0xff,
2795bc3cb74SMauro Carvalho Chehab 			(mp->pixelformat >> 24) & 0xff,
2805bc3cb74SMauro Carvalho Chehab 			prt_names(mp->field, v4l2_field_names),
2815bc3cb74SMauro Carvalho Chehab 			mp->colorspace, mp->num_planes);
2825bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < mp->num_planes; i++)
2835bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
2845bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].bytesperline,
2855bc3cb74SMauro Carvalho Chehab 					mp->plane_fmt[i].sizeimage);
2865bc3cb74SMauro Carvalho Chehab 		break;
2875bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
2885bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
2895bc3cb74SMauro Carvalho Chehab 		win = &p->fmt.win;
290560dde24SHans Verkuil 		/* Note: we can't print the clip list here since the clips
291560dde24SHans Verkuil 		 * pointer is a userspace pointer, not a kernelspace
292560dde24SHans Verkuil 		 * pointer. */
293560dde24SHans Verkuil 		pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, clipcount=%u, clips=%p, bitmap=%p, global_alpha=0x%02x\n",
294560dde24SHans Verkuil 			win->w.width, win->w.height, win->w.left, win->w.top,
2955bc3cb74SMauro Carvalho Chehab 			prt_names(win->field, v4l2_field_names),
296560dde24SHans Verkuil 			win->chromakey, win->clipcount, win->clips,
297560dde24SHans Verkuil 			win->bitmap, win->global_alpha);
2985bc3cb74SMauro Carvalho Chehab 		break;
2995bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
3005bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
3015bc3cb74SMauro Carvalho Chehab 		vbi = &p->fmt.vbi;
3025bc3cb74SMauro Carvalho Chehab 		pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, "
3035bc3cb74SMauro Carvalho Chehab 			"sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n",
3045bc3cb74SMauro Carvalho Chehab 			vbi->sampling_rate, vbi->offset,
3055bc3cb74SMauro Carvalho Chehab 			vbi->samples_per_line,
3065bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format & 0xff),
3075bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >>  8) & 0xff,
3085bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 16) & 0xff,
3095bc3cb74SMauro Carvalho Chehab 			(vbi->sample_format >> 24) & 0xff,
3105bc3cb74SMauro Carvalho Chehab 			vbi->start[0], vbi->start[1],
3115bc3cb74SMauro Carvalho Chehab 			vbi->count[0], vbi->count[1]);
3125bc3cb74SMauro Carvalho Chehab 		break;
3135bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
3145bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
3155bc3cb74SMauro Carvalho Chehab 		sliced = &p->fmt.sliced;
3165bc3cb74SMauro Carvalho Chehab 		pr_cont(", service_set=0x%08x, io_size=%d\n",
3175bc3cb74SMauro Carvalho Chehab 				sliced->service_set, sliced->io_size);
3185bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < 24; i++)
3195bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
3205bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[0][i],
3215bc3cb74SMauro Carvalho Chehab 				sliced->service_lines[1][i]);
3225bc3cb74SMauro Carvalho Chehab 		break;
323582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
324582c52cbSAntti Palosaari 		sdr = &p->fmt.sdr;
325582c52cbSAntti Palosaari 		pr_cont(", pixelformat=%c%c%c%c\n",
326582c52cbSAntti Palosaari 			(sdr->pixelformat >>  0) & 0xff,
327582c52cbSAntti Palosaari 			(sdr->pixelformat >>  8) & 0xff,
328582c52cbSAntti Palosaari 			(sdr->pixelformat >> 16) & 0xff,
329582c52cbSAntti Palosaari 			(sdr->pixelformat >> 24) & 0xff);
330582c52cbSAntti Palosaari 		break;
3315bc3cb74SMauro Carvalho Chehab 	}
3325bc3cb74SMauro Carvalho Chehab }
3335bc3cb74SMauro Carvalho Chehab 
3345bc3cb74SMauro Carvalho Chehab static void v4l_print_framebuffer(const void *arg, bool write_only)
3355bc3cb74SMauro Carvalho Chehab {
3365bc3cb74SMauro Carvalho Chehab 	const struct v4l2_framebuffer *p = arg;
3375bc3cb74SMauro Carvalho Chehab 
3385bc3cb74SMauro Carvalho Chehab 	pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, "
3395bc3cb74SMauro Carvalho Chehab 		"height=%u, pixelformat=%c%c%c%c, "
340560dde24SHans Verkuil 		"bytesperline=%u, sizeimage=%u, colorspace=%d\n",
3415bc3cb74SMauro Carvalho Chehab 			p->capability, p->flags, p->base,
3425bc3cb74SMauro Carvalho Chehab 			p->fmt.width, p->fmt.height,
3435bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat & 0xff),
3445bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >>  8) & 0xff,
3455bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 16) & 0xff,
3465bc3cb74SMauro Carvalho Chehab 			(p->fmt.pixelformat >> 24) & 0xff,
3475bc3cb74SMauro Carvalho Chehab 			p->fmt.bytesperline, p->fmt.sizeimage,
3485bc3cb74SMauro Carvalho Chehab 			p->fmt.colorspace);
3495bc3cb74SMauro Carvalho Chehab }
3505bc3cb74SMauro Carvalho Chehab 
3515bc3cb74SMauro Carvalho Chehab static void v4l_print_buftype(const void *arg, bool write_only)
3525bc3cb74SMauro Carvalho Chehab {
3535bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names));
3545bc3cb74SMauro Carvalho Chehab }
3555bc3cb74SMauro Carvalho Chehab 
3565bc3cb74SMauro Carvalho Chehab static void v4l_print_modulator(const void *arg, bool write_only)
3575bc3cb74SMauro Carvalho Chehab {
3585bc3cb74SMauro Carvalho Chehab 	const struct v4l2_modulator *p = arg;
3595bc3cb74SMauro Carvalho Chehab 
3605bc3cb74SMauro Carvalho Chehab 	if (write_only)
361560dde24SHans Verkuil 		pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans);
3625bc3cb74SMauro Carvalho Chehab 	else
36327d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, capability=0x%x, "
3645bc3cb74SMauro Carvalho Chehab 			"rangelow=%u, rangehigh=%u, txsubchans=0x%x\n",
36527d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->capability,
3665bc3cb74SMauro Carvalho Chehab 			p->rangelow, p->rangehigh, p->txsubchans);
3675bc3cb74SMauro Carvalho Chehab }
3685bc3cb74SMauro Carvalho Chehab 
3695bc3cb74SMauro Carvalho Chehab static void v4l_print_tuner(const void *arg, bool write_only)
3705bc3cb74SMauro Carvalho Chehab {
3715bc3cb74SMauro Carvalho Chehab 	const struct v4l2_tuner *p = arg;
3725bc3cb74SMauro Carvalho Chehab 
3735bc3cb74SMauro Carvalho Chehab 	if (write_only)
3745bc3cb74SMauro Carvalho Chehab 		pr_cont("index=%u, audmode=%u\n", p->index, p->audmode);
3755bc3cb74SMauro Carvalho Chehab 	else
37627d5a87cSHans Verkuil 		pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, "
3775bc3cb74SMauro Carvalho Chehab 			"rangelow=%u, rangehigh=%u, signal=%u, afc=%d, "
3785bc3cb74SMauro Carvalho Chehab 			"rxsubchans=0x%x, audmode=%u\n",
37927d5a87cSHans Verkuil 			p->index, (int)sizeof(p->name), p->name, p->type,
3805bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
3815bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->signal, p->afc,
3825bc3cb74SMauro Carvalho Chehab 			p->rxsubchans, p->audmode);
3835bc3cb74SMauro Carvalho Chehab }
3845bc3cb74SMauro Carvalho Chehab 
3855bc3cb74SMauro Carvalho Chehab static void v4l_print_frequency(const void *arg, bool write_only)
3865bc3cb74SMauro Carvalho Chehab {
3875bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency *p = arg;
3885bc3cb74SMauro Carvalho Chehab 
3895bc3cb74SMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, frequency=%u\n",
3905bc3cb74SMauro Carvalho Chehab 				p->tuner, p->type, p->frequency);
3915bc3cb74SMauro Carvalho Chehab }
3925bc3cb74SMauro Carvalho Chehab 
3935bc3cb74SMauro Carvalho Chehab static void v4l_print_standard(const void *arg, bool write_only)
3945bc3cb74SMauro Carvalho Chehab {
3955bc3cb74SMauro Carvalho Chehab 	const struct v4l2_standard *p = arg;
3965bc3cb74SMauro Carvalho Chehab 
39727d5a87cSHans Verkuil 	pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, "
3985bc3cb74SMauro Carvalho Chehab 		"framelines=%u\n", p->index,
39927d5a87cSHans Verkuil 		(unsigned long long)p->id, (int)sizeof(p->name), p->name,
4005bc3cb74SMauro Carvalho Chehab 		p->frameperiod.numerator,
4015bc3cb74SMauro Carvalho Chehab 		p->frameperiod.denominator,
4025bc3cb74SMauro Carvalho Chehab 		p->framelines);
4035bc3cb74SMauro Carvalho Chehab }
4045bc3cb74SMauro Carvalho Chehab 
4055bc3cb74SMauro Carvalho Chehab static void v4l_print_std(const void *arg, bool write_only)
4065bc3cb74SMauro Carvalho Chehab {
4075bc3cb74SMauro Carvalho Chehab 	pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg);
4085bc3cb74SMauro Carvalho Chehab }
4095bc3cb74SMauro Carvalho Chehab 
4105bc3cb74SMauro Carvalho Chehab static void v4l_print_hw_freq_seek(const void *arg, bool write_only)
4115bc3cb74SMauro Carvalho Chehab {
4125bc3cb74SMauro Carvalho Chehab 	const struct v4l2_hw_freq_seek *p = arg;
4135bc3cb74SMauro Carvalho Chehab 
41479e8c7beSMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, "
41579e8c7beSMauro Carvalho Chehab 		"rangelow=%u, rangehigh=%u\n",
41679e8c7beSMauro Carvalho Chehab 		p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing,
41779e8c7beSMauro Carvalho Chehab 		p->rangelow, p->rangehigh);
4185bc3cb74SMauro Carvalho Chehab }
4195bc3cb74SMauro Carvalho Chehab 
4205bc3cb74SMauro Carvalho Chehab static void v4l_print_requestbuffers(const void *arg, bool write_only)
4215bc3cb74SMauro Carvalho Chehab {
4225bc3cb74SMauro Carvalho Chehab 	const struct v4l2_requestbuffers *p = arg;
4235bc3cb74SMauro Carvalho Chehab 
4245bc3cb74SMauro Carvalho Chehab 	pr_cont("count=%d, type=%s, memory=%s\n",
4255bc3cb74SMauro Carvalho Chehab 		p->count,
4265bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
4275bc3cb74SMauro Carvalho Chehab 		prt_names(p->memory, v4l2_memory_names));
4285bc3cb74SMauro Carvalho Chehab }
4295bc3cb74SMauro Carvalho Chehab 
4305bc3cb74SMauro Carvalho Chehab static void v4l_print_buffer(const void *arg, bool write_only)
4315bc3cb74SMauro Carvalho Chehab {
4325bc3cb74SMauro Carvalho Chehab 	const struct v4l2_buffer *p = arg;
4335bc3cb74SMauro Carvalho Chehab 	const struct v4l2_timecode *tc = &p->timecode;
4345bc3cb74SMauro Carvalho Chehab 	const struct v4l2_plane *plane;
4355bc3cb74SMauro Carvalho Chehab 	int i;
4365bc3cb74SMauro Carvalho Chehab 
4375bc3cb74SMauro Carvalho Chehab 	pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, "
4385bc3cb74SMauro Carvalho Chehab 		"flags=0x%08x, field=%s, sequence=%d, memory=%s",
4395bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec / 3600,
4405bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec / 60) % 60,
4415bc3cb74SMauro Carvalho Chehab 			(int)(p->timestamp.tv_sec % 60),
4425bc3cb74SMauro Carvalho Chehab 			(long)p->timestamp.tv_usec,
4435bc3cb74SMauro Carvalho Chehab 			p->index,
4445bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names),
4455bc3cb74SMauro Carvalho Chehab 			p->flags, prt_names(p->field, v4l2_field_names),
4465bc3cb74SMauro Carvalho Chehab 			p->sequence, prt_names(p->memory, v4l2_memory_names));
4475bc3cb74SMauro Carvalho Chehab 
4485bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
4495bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
4505bc3cb74SMauro Carvalho Chehab 		for (i = 0; i < p->length; ++i) {
4515bc3cb74SMauro Carvalho Chehab 			plane = &p->m.planes[i];
4525bc3cb74SMauro Carvalho Chehab 			printk(KERN_DEBUG
453560dde24SHans Verkuil 				"plane %d: bytesused=%d, data_offset=0x%08x, "
4545bc3cb74SMauro Carvalho Chehab 				"offset/userptr=0x%lx, length=%d\n",
4555bc3cb74SMauro Carvalho Chehab 				i, plane->bytesused, plane->data_offset,
4565bc3cb74SMauro Carvalho Chehab 				plane->m.userptr, plane->length);
4575bc3cb74SMauro Carvalho Chehab 		}
4585bc3cb74SMauro Carvalho Chehab 	} else {
459560dde24SHans Verkuil 		pr_cont(", bytesused=%d, offset/userptr=0x%lx, length=%d\n",
4605bc3cb74SMauro Carvalho Chehab 			p->bytesused, p->m.userptr, p->length);
4615bc3cb74SMauro Carvalho Chehab 	}
4625bc3cb74SMauro Carvalho Chehab 
4635bc3cb74SMauro Carvalho Chehab 	printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, "
4645bc3cb74SMauro Carvalho Chehab 		"flags=0x%08x, frames=%d, userbits=0x%08x\n",
4655bc3cb74SMauro Carvalho Chehab 			tc->hours, tc->minutes, tc->seconds,
4665bc3cb74SMauro Carvalho Chehab 			tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits);
4675bc3cb74SMauro Carvalho Chehab }
4685bc3cb74SMauro Carvalho Chehab 
469b799d09aSTomasz Stanislawski static void v4l_print_exportbuffer(const void *arg, bool write_only)
470b799d09aSTomasz Stanislawski {
471b799d09aSTomasz Stanislawski 	const struct v4l2_exportbuffer *p = arg;
472b799d09aSTomasz Stanislawski 
473b799d09aSTomasz Stanislawski 	pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n",
474b799d09aSTomasz Stanislawski 		p->fd, prt_names(p->type, v4l2_type_names),
475b799d09aSTomasz Stanislawski 		p->index, p->plane, p->flags);
476b799d09aSTomasz Stanislawski }
477b799d09aSTomasz Stanislawski 
4785bc3cb74SMauro Carvalho Chehab static void v4l_print_create_buffers(const void *arg, bool write_only)
4795bc3cb74SMauro Carvalho Chehab {
4805bc3cb74SMauro Carvalho Chehab 	const struct v4l2_create_buffers *p = arg;
4815bc3cb74SMauro Carvalho Chehab 
4825bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%d, count=%d, memory=%s, ",
4835bc3cb74SMauro Carvalho Chehab 			p->index, p->count,
4845bc3cb74SMauro Carvalho Chehab 			prt_names(p->memory, v4l2_memory_names));
4855bc3cb74SMauro Carvalho Chehab 	v4l_print_format(&p->format, write_only);
4865bc3cb74SMauro Carvalho Chehab }
4875bc3cb74SMauro Carvalho Chehab 
4885bc3cb74SMauro Carvalho Chehab static void v4l_print_streamparm(const void *arg, bool write_only)
4895bc3cb74SMauro Carvalho Chehab {
4905bc3cb74SMauro Carvalho Chehab 	const struct v4l2_streamparm *p = arg;
4915bc3cb74SMauro Carvalho Chehab 
4925bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
4935bc3cb74SMauro Carvalho Chehab 
4945bc3cb74SMauro Carvalho Chehab 	if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
4955bc3cb74SMauro Carvalho Chehab 	    p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
4965bc3cb74SMauro Carvalho Chehab 		const struct v4l2_captureparm *c = &p->parm.capture;
4975bc3cb74SMauro Carvalho Chehab 
4985bc3cb74SMauro Carvalho Chehab 		pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, "
4995bc3cb74SMauro Carvalho Chehab 			"extendedmode=%d, readbuffers=%d\n",
5005bc3cb74SMauro Carvalho Chehab 			c->capability, c->capturemode,
5015bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
5025bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->readbuffers);
5035bc3cb74SMauro Carvalho Chehab 	} else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT ||
5045bc3cb74SMauro Carvalho Chehab 		   p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
5055bc3cb74SMauro Carvalho Chehab 		const struct v4l2_outputparm *c = &p->parm.output;
5065bc3cb74SMauro Carvalho Chehab 
5075bc3cb74SMauro Carvalho Chehab 		pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, "
5085bc3cb74SMauro Carvalho Chehab 			"extendedmode=%d, writebuffers=%d\n",
5095bc3cb74SMauro Carvalho Chehab 			c->capability, c->outputmode,
5105bc3cb74SMauro Carvalho Chehab 			c->timeperframe.numerator, c->timeperframe.denominator,
5115bc3cb74SMauro Carvalho Chehab 			c->extendedmode, c->writebuffers);
512560dde24SHans Verkuil 	} else {
513560dde24SHans Verkuil 		pr_cont("\n");
5145bc3cb74SMauro Carvalho Chehab 	}
5155bc3cb74SMauro Carvalho Chehab }
5165bc3cb74SMauro Carvalho Chehab 
5175bc3cb74SMauro Carvalho Chehab static void v4l_print_queryctrl(const void *arg, bool write_only)
5185bc3cb74SMauro Carvalho Chehab {
5195bc3cb74SMauro Carvalho Chehab 	const struct v4l2_queryctrl *p = arg;
5205bc3cb74SMauro Carvalho Chehab 
52127d5a87cSHans Verkuil 	pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, "
5225bc3cb74SMauro Carvalho Chehab 		"step=%d, default=%d, flags=0x%08x\n",
52327d5a87cSHans Verkuil 			p->id, p->type, (int)sizeof(p->name), p->name,
5245bc3cb74SMauro Carvalho Chehab 			p->minimum, p->maximum,
5255bc3cb74SMauro Carvalho Chehab 			p->step, p->default_value, p->flags);
5265bc3cb74SMauro Carvalho Chehab }
5275bc3cb74SMauro Carvalho Chehab 
5285bc3cb74SMauro Carvalho Chehab static void v4l_print_querymenu(const void *arg, bool write_only)
5295bc3cb74SMauro Carvalho Chehab {
5305bc3cb74SMauro Carvalho Chehab 	const struct v4l2_querymenu *p = arg;
5315bc3cb74SMauro Carvalho Chehab 
5325bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, index=%d\n", p->id, p->index);
5335bc3cb74SMauro Carvalho Chehab }
5345bc3cb74SMauro Carvalho Chehab 
5355bc3cb74SMauro Carvalho Chehab static void v4l_print_control(const void *arg, bool write_only)
5365bc3cb74SMauro Carvalho Chehab {
5375bc3cb74SMauro Carvalho Chehab 	const struct v4l2_control *p = arg;
5385bc3cb74SMauro Carvalho Chehab 
5395bc3cb74SMauro Carvalho Chehab 	pr_cont("id=0x%x, value=%d\n", p->id, p->value);
5405bc3cb74SMauro Carvalho Chehab }
5415bc3cb74SMauro Carvalho Chehab 
5425bc3cb74SMauro Carvalho Chehab static void v4l_print_ext_controls(const void *arg, bool write_only)
5435bc3cb74SMauro Carvalho Chehab {
5445bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ext_controls *p = arg;
5455bc3cb74SMauro Carvalho Chehab 	int i;
5465bc3cb74SMauro Carvalho Chehab 
5475bc3cb74SMauro Carvalho Chehab 	pr_cont("class=0x%x, count=%d, error_idx=%d",
5485bc3cb74SMauro Carvalho Chehab 			p->ctrl_class, p->count, p->error_idx);
5495bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < p->count; i++) {
5505bc3cb74SMauro Carvalho Chehab 		if (p->controls[i].size)
5515bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/val=0x%x/0x%x",
5525bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].value);
5535bc3cb74SMauro Carvalho Chehab 		else
5545bc3cb74SMauro Carvalho Chehab 			pr_cont(", id/size=0x%x/%u",
5555bc3cb74SMauro Carvalho Chehab 				p->controls[i].id, p->controls[i].size);
5565bc3cb74SMauro Carvalho Chehab 	}
5575bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
5585bc3cb74SMauro Carvalho Chehab }
5595bc3cb74SMauro Carvalho Chehab 
5605bc3cb74SMauro Carvalho Chehab static void v4l_print_cropcap(const void *arg, bool write_only)
5615bc3cb74SMauro Carvalho Chehab {
5625bc3cb74SMauro Carvalho Chehab 	const struct v4l2_cropcap *p = arg;
5635bc3cb74SMauro Carvalho Chehab 
5645bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, "
5655bc3cb74SMauro Carvalho Chehab 		"defrect wxh=%dx%d, x,y=%d,%d\n, "
5665bc3cb74SMauro Carvalho Chehab 		"pixelaspect %d/%d\n",
5675bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5685bc3cb74SMauro Carvalho Chehab 		p->bounds.width, p->bounds.height,
5695bc3cb74SMauro Carvalho Chehab 		p->bounds.left, p->bounds.top,
5705bc3cb74SMauro Carvalho Chehab 		p->defrect.width, p->defrect.height,
5715bc3cb74SMauro Carvalho Chehab 		p->defrect.left, p->defrect.top,
5725bc3cb74SMauro Carvalho Chehab 		p->pixelaspect.numerator, p->pixelaspect.denominator);
5735bc3cb74SMauro Carvalho Chehab }
5745bc3cb74SMauro Carvalho Chehab 
5755bc3cb74SMauro Carvalho Chehab static void v4l_print_crop(const void *arg, bool write_only)
5765bc3cb74SMauro Carvalho Chehab {
5775bc3cb74SMauro Carvalho Chehab 	const struct v4l2_crop *p = arg;
5785bc3cb74SMauro Carvalho Chehab 
5795bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n",
5805bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5815bc3cb74SMauro Carvalho Chehab 		p->c.width, p->c.height,
5825bc3cb74SMauro Carvalho Chehab 		p->c.left, p->c.top);
5835bc3cb74SMauro Carvalho Chehab }
5845bc3cb74SMauro Carvalho Chehab 
5855bc3cb74SMauro Carvalho Chehab static void v4l_print_selection(const void *arg, bool write_only)
5865bc3cb74SMauro Carvalho Chehab {
5875bc3cb74SMauro Carvalho Chehab 	const struct v4l2_selection *p = arg;
5885bc3cb74SMauro Carvalho Chehab 
5895bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n",
5905bc3cb74SMauro Carvalho Chehab 		prt_names(p->type, v4l2_type_names),
5915bc3cb74SMauro Carvalho Chehab 		p->target, p->flags,
5925bc3cb74SMauro Carvalho Chehab 		p->r.width, p->r.height, p->r.left, p->r.top);
5935bc3cb74SMauro Carvalho Chehab }
5945bc3cb74SMauro Carvalho Chehab 
5955bc3cb74SMauro Carvalho Chehab static void v4l_print_jpegcompression(const void *arg, bool write_only)
5965bc3cb74SMauro Carvalho Chehab {
5975bc3cb74SMauro Carvalho Chehab 	const struct v4l2_jpegcompression *p = arg;
5985bc3cb74SMauro Carvalho Chehab 
5995bc3cb74SMauro Carvalho Chehab 	pr_cont("quality=%d, APPn=%d, APP_len=%d, "
6005bc3cb74SMauro Carvalho Chehab 		"COM_len=%d, jpeg_markers=0x%x\n",
6015bc3cb74SMauro Carvalho Chehab 		p->quality, p->APPn, p->APP_len,
6025bc3cb74SMauro Carvalho Chehab 		p->COM_len, p->jpeg_markers);
6035bc3cb74SMauro Carvalho Chehab }
6045bc3cb74SMauro Carvalho Chehab 
6055bc3cb74SMauro Carvalho Chehab static void v4l_print_enc_idx(const void *arg, bool write_only)
6065bc3cb74SMauro Carvalho Chehab {
6075bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enc_idx *p = arg;
6085bc3cb74SMauro Carvalho Chehab 
6095bc3cb74SMauro Carvalho Chehab 	pr_cont("entries=%d, entries_cap=%d\n",
6105bc3cb74SMauro Carvalho Chehab 			p->entries, p->entries_cap);
6115bc3cb74SMauro Carvalho Chehab }
6125bc3cb74SMauro Carvalho Chehab 
6135bc3cb74SMauro Carvalho Chehab static void v4l_print_encoder_cmd(const void *arg, bool write_only)
6145bc3cb74SMauro Carvalho Chehab {
6155bc3cb74SMauro Carvalho Chehab 	const struct v4l2_encoder_cmd *p = arg;
6165bc3cb74SMauro Carvalho Chehab 
6175bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n",
6185bc3cb74SMauro Carvalho Chehab 			p->cmd, p->flags);
6195bc3cb74SMauro Carvalho Chehab }
6205bc3cb74SMauro Carvalho Chehab 
6215bc3cb74SMauro Carvalho Chehab static void v4l_print_decoder_cmd(const void *arg, bool write_only)
6225bc3cb74SMauro Carvalho Chehab {
6235bc3cb74SMauro Carvalho Chehab 	const struct v4l2_decoder_cmd *p = arg;
6245bc3cb74SMauro Carvalho Chehab 
6255bc3cb74SMauro Carvalho Chehab 	pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags);
6265bc3cb74SMauro Carvalho Chehab 
6275bc3cb74SMauro Carvalho Chehab 	if (p->cmd == V4L2_DEC_CMD_START)
6285bc3cb74SMauro Carvalho Chehab 		pr_info("speed=%d, format=%u\n",
6295bc3cb74SMauro Carvalho Chehab 				p->start.speed, p->start.format);
6305bc3cb74SMauro Carvalho Chehab 	else if (p->cmd == V4L2_DEC_CMD_STOP)
6315bc3cb74SMauro Carvalho Chehab 		pr_info("pts=%llu\n", p->stop.pts);
6325bc3cb74SMauro Carvalho Chehab }
6335bc3cb74SMauro Carvalho Chehab 
63496b03d2aSHans Verkuil static void v4l_print_dbg_chip_info(const void *arg, bool write_only)
63579b0c640SHans Verkuil {
63696b03d2aSHans Verkuil 	const struct v4l2_dbg_chip_info *p = arg;
63779b0c640SHans Verkuil 
63879b0c640SHans Verkuil 	pr_cont("type=%u, ", p->match.type);
6393eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
64079b0c640SHans Verkuil 		pr_cont("name=%.*s, ",
64179b0c640SHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
64279b0c640SHans Verkuil 	else
64379b0c640SHans Verkuil 		pr_cont("addr=%u, ", p->match.addr);
64479b0c640SHans Verkuil 	pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name);
64579b0c640SHans Verkuil }
64679b0c640SHans Verkuil 
6475bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_register(const void *arg, bool write_only)
6485bc3cb74SMauro Carvalho Chehab {
6495bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dbg_register *p = arg;
6505bc3cb74SMauro Carvalho Chehab 
6515bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%u, ", p->match.type);
6523eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER)
65327d5a87cSHans Verkuil 		pr_cont("name=%.*s, ",
65427d5a87cSHans Verkuil 				(int)sizeof(p->match.name), p->match.name);
6555bc3cb74SMauro Carvalho Chehab 	else
6565bc3cb74SMauro Carvalho Chehab 		pr_cont("addr=%u, ", p->match.addr);
6575bc3cb74SMauro Carvalho Chehab 	pr_cont("reg=0x%llx, val=0x%llx\n",
6585bc3cb74SMauro Carvalho Chehab 			p->reg, p->val);
6595bc3cb74SMauro Carvalho Chehab }
6605bc3cb74SMauro Carvalho Chehab 
6615bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings(const void *arg, bool write_only)
6625bc3cb74SMauro Carvalho Chehab {
6635bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings *p = arg;
6645bc3cb74SMauro Carvalho Chehab 
6655bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
6665bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
6675bc3cb74SMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, interlaced=%u, "
6685bc3cb74SMauro Carvalho Chehab 			"pixelclock=%llu, "
6695bc3cb74SMauro Carvalho Chehab 			"width=%u, height=%u, polarities=0x%x, "
6705bc3cb74SMauro Carvalho Chehab 			"hfrontporch=%u, hsync=%u, "
6715bc3cb74SMauro Carvalho Chehab 			"hbackporch=%u, vfrontporch=%u, "
6725bc3cb74SMauro Carvalho Chehab 			"vsync=%u, vbackporch=%u, "
6735bc3cb74SMauro Carvalho Chehab 			"il_vfrontporch=%u, il_vsync=%u, "
6745bc3cb74SMauro Carvalho Chehab 			"il_vbackporch=%u, standards=0x%x, flags=0x%x\n",
6755bc3cb74SMauro Carvalho Chehab 				p->bt.interlaced, p->bt.pixelclock,
6765bc3cb74SMauro Carvalho Chehab 				p->bt.width, p->bt.height,
6775bc3cb74SMauro Carvalho Chehab 				p->bt.polarities, p->bt.hfrontporch,
6785bc3cb74SMauro Carvalho Chehab 				p->bt.hsync, p->bt.hbackporch,
6795bc3cb74SMauro Carvalho Chehab 				p->bt.vfrontporch, p->bt.vsync,
6805bc3cb74SMauro Carvalho Chehab 				p->bt.vbackporch, p->bt.il_vfrontporch,
6815bc3cb74SMauro Carvalho Chehab 				p->bt.il_vsync, p->bt.il_vbackporch,
6825bc3cb74SMauro Carvalho Chehab 				p->bt.standards, p->bt.flags);
6835bc3cb74SMauro Carvalho Chehab 		break;
6845bc3cb74SMauro Carvalho Chehab 	default:
6855bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%d\n", p->type);
6865bc3cb74SMauro Carvalho Chehab 		break;
6875bc3cb74SMauro Carvalho Chehab 	}
6885bc3cb74SMauro Carvalho Chehab }
6895bc3cb74SMauro Carvalho Chehab 
6905bc3cb74SMauro Carvalho Chehab static void v4l_print_enum_dv_timings(const void *arg, bool write_only)
6915bc3cb74SMauro Carvalho Chehab {
6925bc3cb74SMauro Carvalho Chehab 	const struct v4l2_enum_dv_timings *p = arg;
6935bc3cb74SMauro Carvalho Chehab 
6945bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, ", p->index);
6955bc3cb74SMauro Carvalho Chehab 	v4l_print_dv_timings(&p->timings, write_only);
6965bc3cb74SMauro Carvalho Chehab }
6975bc3cb74SMauro Carvalho Chehab 
6985bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings_cap(const void *arg, bool write_only)
6995bc3cb74SMauro Carvalho Chehab {
7005bc3cb74SMauro Carvalho Chehab 	const struct v4l2_dv_timings_cap *p = arg;
7015bc3cb74SMauro Carvalho Chehab 
7025bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7035bc3cb74SMauro Carvalho Chehab 	case V4L2_DV_BT_656_1120:
7045bc3cb74SMauro Carvalho Chehab 		pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, "
7055bc3cb74SMauro Carvalho Chehab 			"pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n",
7065bc3cb74SMauro Carvalho Chehab 			p->bt.min_width, p->bt.max_width,
7075bc3cb74SMauro Carvalho Chehab 			p->bt.min_height, p->bt.max_height,
7085bc3cb74SMauro Carvalho Chehab 			p->bt.min_pixelclock, p->bt.max_pixelclock,
7095bc3cb74SMauro Carvalho Chehab 			p->bt.standards, p->bt.capabilities);
7105bc3cb74SMauro Carvalho Chehab 		break;
7115bc3cb74SMauro Carvalho Chehab 	default:
7125bc3cb74SMauro Carvalho Chehab 		pr_cont("type=%u\n", p->type);
7135bc3cb74SMauro Carvalho Chehab 		break;
7145bc3cb74SMauro Carvalho Chehab 	}
7155bc3cb74SMauro Carvalho Chehab }
7165bc3cb74SMauro Carvalho Chehab 
7175bc3cb74SMauro Carvalho Chehab static void v4l_print_frmsizeenum(const void *arg, bool write_only)
7185bc3cb74SMauro Carvalho Chehab {
7195bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmsizeenum *p = arg;
7205bc3cb74SMauro Carvalho Chehab 
7215bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u",
7225bc3cb74SMauro Carvalho Chehab 			p->index,
7235bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7245bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7255bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7265bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7275bc3cb74SMauro Carvalho Chehab 			p->type);
7285bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7295bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_DISCRETE:
730560dde24SHans Verkuil 		pr_cont(", wxh=%ux%u\n",
7315bc3cb74SMauro Carvalho Chehab 			p->discrete.width, p->discrete.height);
7325bc3cb74SMauro Carvalho Chehab 		break;
7335bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_STEPWISE:
734560dde24SHans Verkuil 		pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n",
7355bc3cb74SMauro Carvalho Chehab 				p->stepwise.min_width,  p->stepwise.min_height,
7365bc3cb74SMauro Carvalho Chehab 				p->stepwise.step_width, p->stepwise.step_height,
7375bc3cb74SMauro Carvalho Chehab 				p->stepwise.max_width,  p->stepwise.max_height);
7385bc3cb74SMauro Carvalho Chehab 		break;
7395bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMSIZE_TYPE_CONTINUOUS:
7405bc3cb74SMauro Carvalho Chehab 		/* fall through */
7415bc3cb74SMauro Carvalho Chehab 	default:
7425bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7435bc3cb74SMauro Carvalho Chehab 		break;
7445bc3cb74SMauro Carvalho Chehab 	}
7455bc3cb74SMauro Carvalho Chehab }
7465bc3cb74SMauro Carvalho Chehab 
7475bc3cb74SMauro Carvalho Chehab static void v4l_print_frmivalenum(const void *arg, bool write_only)
7485bc3cb74SMauro Carvalho Chehab {
7495bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frmivalenum *p = arg;
7505bc3cb74SMauro Carvalho Chehab 
7515bc3cb74SMauro Carvalho Chehab 	pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u",
7525bc3cb74SMauro Carvalho Chehab 			p->index,
7535bc3cb74SMauro Carvalho Chehab 			(p->pixel_format & 0xff),
7545bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >>  8) & 0xff,
7555bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 16) & 0xff,
7565bc3cb74SMauro Carvalho Chehab 			(p->pixel_format >> 24) & 0xff,
7575bc3cb74SMauro Carvalho Chehab 			p->width, p->height, p->type);
7585bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7595bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_DISCRETE:
760560dde24SHans Verkuil 		pr_cont(", fps=%d/%d\n",
7615bc3cb74SMauro Carvalho Chehab 				p->discrete.numerator,
7625bc3cb74SMauro Carvalho Chehab 				p->discrete.denominator);
7635bc3cb74SMauro Carvalho Chehab 		break;
7645bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_STEPWISE:
765560dde24SHans Verkuil 		pr_cont(", min=%d/%d, max=%d/%d, step=%d/%d\n",
7665bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.numerator,
7675bc3cb74SMauro Carvalho Chehab 				p->stepwise.min.denominator,
7685bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.numerator,
7695bc3cb74SMauro Carvalho Chehab 				p->stepwise.max.denominator,
7705bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.numerator,
7715bc3cb74SMauro Carvalho Chehab 				p->stepwise.step.denominator);
7725bc3cb74SMauro Carvalho Chehab 		break;
7735bc3cb74SMauro Carvalho Chehab 	case V4L2_FRMIVAL_TYPE_CONTINUOUS:
7745bc3cb74SMauro Carvalho Chehab 		/* fall through */
7755bc3cb74SMauro Carvalho Chehab 	default:
7765bc3cb74SMauro Carvalho Chehab 		pr_cont("\n");
7775bc3cb74SMauro Carvalho Chehab 		break;
7785bc3cb74SMauro Carvalho Chehab 	}
7795bc3cb74SMauro Carvalho Chehab }
7805bc3cb74SMauro Carvalho Chehab 
7815bc3cb74SMauro Carvalho Chehab static void v4l_print_event(const void *arg, bool write_only)
7825bc3cb74SMauro Carvalho Chehab {
7835bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event *p = arg;
7845bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_ctrl *c;
7855bc3cb74SMauro Carvalho Chehab 
7865bc3cb74SMauro Carvalho Chehab 	pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, "
7875bc3cb74SMauro Carvalho Chehab 		"timestamp=%lu.%9.9lu\n",
7885bc3cb74SMauro Carvalho Chehab 			p->type, p->pending, p->sequence, p->id,
7895bc3cb74SMauro Carvalho Chehab 			p->timestamp.tv_sec, p->timestamp.tv_nsec);
7905bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
7915bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_VSYNC:
7925bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "field=%s\n",
7935bc3cb74SMauro Carvalho Chehab 			prt_names(p->u.vsync.field, v4l2_field_names));
7945bc3cb74SMauro Carvalho Chehab 		break;
7955bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_CTRL:
7965bc3cb74SMauro Carvalho Chehab 		c = &p->u.ctrl;
7975bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "changes=0x%x, type=%u, ",
7985bc3cb74SMauro Carvalho Chehab 			c->changes, c->type);
7995bc3cb74SMauro Carvalho Chehab 		if (c->type == V4L2_CTRL_TYPE_INTEGER64)
8005bc3cb74SMauro Carvalho Chehab 			pr_cont("value64=%lld, ", c->value64);
8015bc3cb74SMauro Carvalho Chehab 		else
8025bc3cb74SMauro Carvalho Chehab 			pr_cont("value=%d, ", c->value);
8035bc3cb74SMauro Carvalho Chehab 		pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, "
8045bc3cb74SMauro Carvalho Chehab 			"default_value=%d\n",
8055bc3cb74SMauro Carvalho Chehab 			c->flags, c->minimum, c->maximum,
8065bc3cb74SMauro Carvalho Chehab 			c->step, c->default_value);
8075bc3cb74SMauro Carvalho Chehab 		break;
8085bc3cb74SMauro Carvalho Chehab 	case V4L2_EVENT_FRAME_SYNC:
8095bc3cb74SMauro Carvalho Chehab 		pr_cont("frame_sequence=%u\n",
8105bc3cb74SMauro Carvalho Chehab 			p->u.frame_sync.frame_sequence);
8115bc3cb74SMauro Carvalho Chehab 		break;
8125bc3cb74SMauro Carvalho Chehab 	}
8135bc3cb74SMauro Carvalho Chehab }
8145bc3cb74SMauro Carvalho Chehab 
8155bc3cb74SMauro Carvalho Chehab static void v4l_print_event_subscription(const void *arg, bool write_only)
8165bc3cb74SMauro Carvalho Chehab {
8175bc3cb74SMauro Carvalho Chehab 	const struct v4l2_event_subscription *p = arg;
8185bc3cb74SMauro Carvalho Chehab 
8195bc3cb74SMauro Carvalho Chehab 	pr_cont("type=0x%x, id=0x%x, flags=0x%x\n",
8205bc3cb74SMauro Carvalho Chehab 			p->type, p->id, p->flags);
8215bc3cb74SMauro Carvalho Chehab }
8225bc3cb74SMauro Carvalho Chehab 
8235bc3cb74SMauro Carvalho Chehab static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only)
8245bc3cb74SMauro Carvalho Chehab {
8255bc3cb74SMauro Carvalho Chehab 	const struct v4l2_sliced_vbi_cap *p = arg;
8265bc3cb74SMauro Carvalho Chehab 	int i;
8275bc3cb74SMauro Carvalho Chehab 
8285bc3cb74SMauro Carvalho Chehab 	pr_cont("type=%s, service_set=0x%08x\n",
8295bc3cb74SMauro Carvalho Chehab 			prt_names(p->type, v4l2_type_names), p->service_set);
8305bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < 24; i++)
8315bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i,
8325bc3cb74SMauro Carvalho Chehab 				p->service_lines[0][i],
8335bc3cb74SMauro Carvalho Chehab 				p->service_lines[1][i]);
8345bc3cb74SMauro Carvalho Chehab }
8355bc3cb74SMauro Carvalho Chehab 
8365bc3cb74SMauro Carvalho Chehab static void v4l_print_freq_band(const void *arg, bool write_only)
8375bc3cb74SMauro Carvalho Chehab {
8385bc3cb74SMauro Carvalho Chehab 	const struct v4l2_frequency_band *p = arg;
8395bc3cb74SMauro Carvalho Chehab 
8405bc3cb74SMauro Carvalho Chehab 	pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, "
8415bc3cb74SMauro Carvalho Chehab 		"rangelow=%u, rangehigh=%u, modulation=0x%x\n",
8425bc3cb74SMauro Carvalho Chehab 			p->tuner, p->type, p->index,
8435bc3cb74SMauro Carvalho Chehab 			p->capability, p->rangelow,
8445bc3cb74SMauro Carvalho Chehab 			p->rangehigh, p->modulation);
8455bc3cb74SMauro Carvalho Chehab }
8465bc3cb74SMauro Carvalho Chehab 
847dd519bb3SHans Verkuil static void v4l_print_edid(const void *arg, bool write_only)
848dd519bb3SHans Verkuil {
849dd519bb3SHans Verkuil 	const struct v4l2_edid *p = arg;
850dd519bb3SHans Verkuil 
851dd519bb3SHans Verkuil 	pr_cont("pad=%u, start_block=%u, blocks=%u\n",
852dd519bb3SHans Verkuil 		p->pad, p->start_block, p->blocks);
853dd519bb3SHans Verkuil }
854dd519bb3SHans Verkuil 
8555bc3cb74SMauro Carvalho Chehab static void v4l_print_u32(const void *arg, bool write_only)
8565bc3cb74SMauro Carvalho Chehab {
8575bc3cb74SMauro Carvalho Chehab 	pr_cont("value=%u\n", *(const u32 *)arg);
8585bc3cb74SMauro Carvalho Chehab }
8595bc3cb74SMauro Carvalho Chehab 
8605bc3cb74SMauro Carvalho Chehab static void v4l_print_newline(const void *arg, bool write_only)
8615bc3cb74SMauro Carvalho Chehab {
8625bc3cb74SMauro Carvalho Chehab 	pr_cont("\n");
8635bc3cb74SMauro Carvalho Chehab }
8645bc3cb74SMauro Carvalho Chehab 
8655bc3cb74SMauro Carvalho Chehab static void v4l_print_default(const void *arg, bool write_only)
8665bc3cb74SMauro Carvalho Chehab {
8675bc3cb74SMauro Carvalho Chehab 	pr_cont("driver-specific ioctl\n");
8685bc3cb74SMauro Carvalho Chehab }
8695bc3cb74SMauro Carvalho Chehab 
8705bc3cb74SMauro Carvalho Chehab static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
8715bc3cb74SMauro Carvalho Chehab {
8725bc3cb74SMauro Carvalho Chehab 	__u32 i;
8735bc3cb74SMauro Carvalho Chehab 
8745bc3cb74SMauro Carvalho Chehab 	/* zero the reserved fields */
8755bc3cb74SMauro Carvalho Chehab 	c->reserved[0] = c->reserved[1] = 0;
8765bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++)
8775bc3cb74SMauro Carvalho Chehab 		c->controls[i].reserved2[0] = 0;
8785bc3cb74SMauro Carvalho Chehab 
8795bc3cb74SMauro Carvalho Chehab 	/* V4L2_CID_PRIVATE_BASE cannot be used as control class
8805bc3cb74SMauro Carvalho Chehab 	   when using extended controls.
8815bc3cb74SMauro Carvalho Chehab 	   Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL
8825bc3cb74SMauro Carvalho Chehab 	   is it allowed for backwards compatibility.
8835bc3cb74SMauro Carvalho Chehab 	 */
8845bc3cb74SMauro Carvalho Chehab 	if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE)
8855bc3cb74SMauro Carvalho Chehab 		return 0;
8865bc3cb74SMauro Carvalho Chehab 	/* Check that all controls are from the same control class. */
8875bc3cb74SMauro Carvalho Chehab 	for (i = 0; i < c->count; i++) {
8885bc3cb74SMauro Carvalho Chehab 		if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) {
8895bc3cb74SMauro Carvalho Chehab 			c->error_idx = i;
8905bc3cb74SMauro Carvalho Chehab 			return 0;
8915bc3cb74SMauro Carvalho Chehab 		}
8925bc3cb74SMauro Carvalho Chehab 	}
8935bc3cb74SMauro Carvalho Chehab 	return 1;
8945bc3cb74SMauro Carvalho Chehab }
8955bc3cb74SMauro Carvalho Chehab 
8964b20259fSHans Verkuil static int check_fmt(struct file *file, enum v4l2_buf_type type)
8975bc3cb74SMauro Carvalho Chehab {
8984b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
8994b20259fSHans Verkuil 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
9004b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
9014b20259fSHans Verkuil 	bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
902582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
9034b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
9044b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
9054b20259fSHans Verkuil 
9065bc3cb74SMauro Carvalho Chehab 	if (ops == NULL)
9075bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
9085bc3cb74SMauro Carvalho Chehab 
9095bc3cb74SMauro Carvalho Chehab 	switch (type) {
9105bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
9114b20259fSHans Verkuil 		if (is_vid && is_rx &&
9124b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane))
9135bc3cb74SMauro Carvalho Chehab 			return 0;
9145bc3cb74SMauro Carvalho Chehab 		break;
9155bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
9164b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane)
9175bc3cb74SMauro Carvalho Chehab 			return 0;
9185bc3cb74SMauro Carvalho Chehab 		break;
9195bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
9204b20259fSHans Verkuil 		if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay)
9215bc3cb74SMauro Carvalho Chehab 			return 0;
9225bc3cb74SMauro Carvalho Chehab 		break;
9235bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
9244b20259fSHans Verkuil 		if (is_vid && is_tx &&
9254b20259fSHans Verkuil 		    (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane))
9265bc3cb74SMauro Carvalho Chehab 			return 0;
9275bc3cb74SMauro Carvalho Chehab 		break;
9285bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
9294b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane)
9305bc3cb74SMauro Carvalho Chehab 			return 0;
9315bc3cb74SMauro Carvalho Chehab 		break;
9325bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
9334b20259fSHans Verkuil 		if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay)
9345bc3cb74SMauro Carvalho Chehab 			return 0;
9355bc3cb74SMauro Carvalho Chehab 		break;
9365bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_CAPTURE:
9374b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap)
9385bc3cb74SMauro Carvalho Chehab 			return 0;
9395bc3cb74SMauro Carvalho Chehab 		break;
9405bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
9414b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out)
9425bc3cb74SMauro Carvalho Chehab 			return 0;
9435bc3cb74SMauro Carvalho Chehab 		break;
9445bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
9454b20259fSHans Verkuil 		if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap)
9465bc3cb74SMauro Carvalho Chehab 			return 0;
9475bc3cb74SMauro Carvalho Chehab 		break;
9485bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
9494b20259fSHans Verkuil 		if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
9505bc3cb74SMauro Carvalho Chehab 			return 0;
9515bc3cb74SMauro Carvalho Chehab 		break;
952582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
953582c52cbSAntti Palosaari 		if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap)
954582c52cbSAntti Palosaari 			return 0;
955582c52cbSAntti Palosaari 		break;
956633c98e5SHans Verkuil 	default:
9575bc3cb74SMauro Carvalho Chehab 		break;
9585bc3cb74SMauro Carvalho Chehab 	}
9595bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
9605bc3cb74SMauro Carvalho Chehab }
9615bc3cb74SMauro Carvalho Chehab 
9625bc3cb74SMauro Carvalho Chehab static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
9635bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9645bc3cb74SMauro Carvalho Chehab {
9655bc3cb74SMauro Carvalho Chehab 	struct v4l2_capability *cap = (struct v4l2_capability *)arg;
9665bc3cb74SMauro Carvalho Chehab 
9675bc3cb74SMauro Carvalho Chehab 	cap->version = LINUX_VERSION_CODE;
9685bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_querycap(file, fh, cap);
9695bc3cb74SMauro Carvalho Chehab }
9705bc3cb74SMauro Carvalho Chehab 
9715bc3cb74SMauro Carvalho Chehab static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
9725bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9735bc3cb74SMauro Carvalho Chehab {
9745bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_input(file, fh, *(unsigned int *)arg);
9755bc3cb74SMauro Carvalho Chehab }
9765bc3cb74SMauro Carvalho Chehab 
9775bc3cb74SMauro Carvalho Chehab static int v4l_s_output(const struct v4l2_ioctl_ops *ops,
9785bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9795bc3cb74SMauro Carvalho Chehab {
9805bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_output(file, fh, *(unsigned int *)arg);
9815bc3cb74SMauro Carvalho Chehab }
9825bc3cb74SMauro Carvalho Chehab 
9835bc3cb74SMauro Carvalho Chehab static int v4l_g_priority(const struct v4l2_ioctl_ops *ops,
9845bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9855bc3cb74SMauro Carvalho Chehab {
9865bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
9875bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
9885bc3cb74SMauro Carvalho Chehab 
9895bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_priority)
9905bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_priority(file, fh, arg);
9915bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
9925bc3cb74SMauro Carvalho Chehab 	*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
9935bc3cb74SMauro Carvalho Chehab 	return 0;
9945bc3cb74SMauro Carvalho Chehab }
9955bc3cb74SMauro Carvalho Chehab 
9965bc3cb74SMauro Carvalho Chehab static int v4l_s_priority(const struct v4l2_ioctl_ops *ops,
9975bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
9985bc3cb74SMauro Carvalho Chehab {
9995bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd;
10005bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh;
10015bc3cb74SMauro Carvalho Chehab 	u32 *p = arg;
10025bc3cb74SMauro Carvalho Chehab 
10035bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_priority)
10045bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_priority(file, fh, *p);
10055bc3cb74SMauro Carvalho Chehab 	vfd = video_devdata(file);
10065bc3cb74SMauro Carvalho Chehab 	vfh = file->private_data;
10075bc3cb74SMauro Carvalho Chehab 	return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
10085bc3cb74SMauro Carvalho Chehab }
10095bc3cb74SMauro Carvalho Chehab 
10105bc3cb74SMauro Carvalho Chehab static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
10115bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10125bc3cb74SMauro Carvalho Chehab {
101373f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10145bc3cb74SMauro Carvalho Chehab 	struct v4l2_input *p = arg;
10155bc3cb74SMauro Carvalho Chehab 
10165bc3cb74SMauro Carvalho Chehab 	/*
101702fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10185bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10195bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10205bc3cb74SMauro Carvalho Chehab 	 * for a specific input, it must override these flags.
10215bc3cb74SMauro Carvalho Chehab 	 */
102273f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10235bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_IN_CAP_STD;
10245bc3cb74SMauro Carvalho Chehab 
10255bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_input(file, fh, p);
10265bc3cb74SMauro Carvalho Chehab }
10275bc3cb74SMauro Carvalho Chehab 
10285bc3cb74SMauro Carvalho Chehab static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
10295bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10305bc3cb74SMauro Carvalho Chehab {
103173f35418SHans Verkuil 	struct video_device *vfd = video_devdata(file);
10325bc3cb74SMauro Carvalho Chehab 	struct v4l2_output *p = arg;
10335bc3cb74SMauro Carvalho Chehab 
10345bc3cb74SMauro Carvalho Chehab 	/*
103502fa6282SHans Verkuil 	 * We set the flags for CAP_DV_TIMINGS &
10365bc3cb74SMauro Carvalho Chehab 	 * CAP_STD here based on ioctl handler provided by the
10375bc3cb74SMauro Carvalho Chehab 	 * driver. If the driver doesn't support these
10385bc3cb74SMauro Carvalho Chehab 	 * for a specific output, it must override these flags.
10395bc3cb74SMauro Carvalho Chehab 	 */
104073f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_S_STD))
10415bc3cb74SMauro Carvalho Chehab 		p->capabilities |= V4L2_OUT_CAP_STD;
10425bc3cb74SMauro Carvalho Chehab 
10435bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_enum_output(file, fh, p);
10445bc3cb74SMauro Carvalho Chehab }
10455bc3cb74SMauro Carvalho Chehab 
10465bc3cb74SMauro Carvalho Chehab static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
10475bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10485bc3cb74SMauro Carvalho Chehab {
10495bc3cb74SMauro Carvalho Chehab 	struct v4l2_fmtdesc *p = arg;
10504b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
10514b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
10524b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
10535bc3cb74SMauro Carvalho Chehab 
10545bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
10555bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
10564b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap))
10575bc3cb74SMauro Carvalho Chehab 			break;
10585bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
10595bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
10604b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane))
10615bc3cb74SMauro Carvalho Chehab 			break;
10625bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
10635bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
10644b20259fSHans Verkuil 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay))
10655bc3cb74SMauro Carvalho Chehab 			break;
10665bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
10675bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
10684b20259fSHans Verkuil 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out))
10695bc3cb74SMauro Carvalho Chehab 			break;
10705bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
10715bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
10724b20259fSHans Verkuil 		if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
10735bc3cb74SMauro Carvalho Chehab 			break;
10745bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
1075582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1076582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
1077582c52cbSAntti Palosaari 			break;
1078582c52cbSAntti Palosaari 		return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
10795bc3cb74SMauro Carvalho Chehab 	}
10805bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
10815bc3cb74SMauro Carvalho Chehab }
10825bc3cb74SMauro Carvalho Chehab 
10835bc3cb74SMauro Carvalho Chehab static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
10845bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
10855bc3cb74SMauro Carvalho Chehab {
10865bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
10874b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
10884b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1089582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
10904b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
10914b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
10925bc3cb74SMauro Carvalho Chehab 
10935bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
10945bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
10954b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
10965bc3cb74SMauro Carvalho Chehab 			break;
10975bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
10985bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
10994b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
11005bc3cb74SMauro Carvalho Chehab 			break;
11015bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
11025bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
11034b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay))
11045bc3cb74SMauro Carvalho Chehab 			break;
11055bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_overlay(file, fh, arg);
11064b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
11074b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap))
11084b20259fSHans Verkuil 			break;
11094b20259fSHans Verkuil 		return ops->vidioc_g_fmt_vbi_cap(file, fh, arg);
11104b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
11114b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap))
11124b20259fSHans Verkuil 			break;
11134b20259fSHans Verkuil 		return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg);
11145bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
11154b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
11165bc3cb74SMauro Carvalho Chehab 			break;
11175bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out(file, fh, arg);
11185bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
11194b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
11205bc3cb74SMauro Carvalho Chehab 			break;
11215bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg);
11225bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
11234b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay))
11245bc3cb74SMauro Carvalho Chehab 			break;
11255bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg);
11265bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
11274b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out))
11285bc3cb74SMauro Carvalho Chehab 			break;
11295bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_vbi_out(file, fh, arg);
11305bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
11314b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
11325bc3cb74SMauro Carvalho Chehab 			break;
11335bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
1134582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1135582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap))
1136582c52cbSAntti Palosaari 			break;
1137582c52cbSAntti Palosaari 		return ops->vidioc_g_fmt_sdr_cap(file, fh, arg);
11385bc3cb74SMauro Carvalho Chehab 	}
11395bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
11405bc3cb74SMauro Carvalho Chehab }
11415bc3cb74SMauro Carvalho Chehab 
11425bc3cb74SMauro Carvalho Chehab static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
11435bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
11445bc3cb74SMauro Carvalho Chehab {
11455bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
11464b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
11474b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1148582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
11494b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
11504b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
11515bc3cb74SMauro Carvalho Chehab 
11525bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
11535bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
11544b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
11555bc3cb74SMauro Carvalho Chehab 			break;
11565bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
11575bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_cap(file, fh, arg);
11585bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
11594b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
11605bc3cb74SMauro Carvalho Chehab 			break;
11615bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
11625bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
11635bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
11644b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay))
11655bc3cb74SMauro Carvalho Chehab 			break;
11665bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
11675bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_overlay(file, fh, arg);
11684b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
11694b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap))
11704b20259fSHans Verkuil 			break;
11714b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
11724b20259fSHans Verkuil 		return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
11734b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
11744b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap))
11754b20259fSHans Verkuil 			break;
11764b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
11774b20259fSHans Verkuil 		return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
11785bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
11794b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
11805bc3cb74SMauro Carvalho Chehab 			break;
11815bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
11825bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out(file, fh, arg);
11835bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
11844b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
11855bc3cb74SMauro Carvalho Chehab 			break;
11865bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
11875bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
11885bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
11894b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay))
11905bc3cb74SMauro Carvalho Chehab 			break;
11915bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
11925bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg);
11935bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
11944b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out))
11955bc3cb74SMauro Carvalho Chehab 			break;
11965bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
11975bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_vbi_out(file, fh, arg);
11985bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
11994b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out))
12005bc3cb74SMauro Carvalho Chehab 			break;
12015bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
12025bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
1203582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1204582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap))
1205582c52cbSAntti Palosaari 			break;
1206582c52cbSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
1207582c52cbSAntti Palosaari 		return ops->vidioc_s_fmt_sdr_cap(file, fh, arg);
12085bc3cb74SMauro Carvalho Chehab 	}
12095bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
12105bc3cb74SMauro Carvalho Chehab }
12115bc3cb74SMauro Carvalho Chehab 
12125bc3cb74SMauro Carvalho Chehab static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
12135bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12145bc3cb74SMauro Carvalho Chehab {
12155bc3cb74SMauro Carvalho Chehab 	struct v4l2_format *p = arg;
12164b20259fSHans Verkuil 	struct video_device *vfd = video_devdata(file);
12174b20259fSHans Verkuil 	bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
1218582c52cbSAntti Palosaari 	bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
12194b20259fSHans Verkuil 	bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
12204b20259fSHans Verkuil 	bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
12215bc3cb74SMauro Carvalho Chehab 
12225bc3cb74SMauro Carvalho Chehab 	switch (p->type) {
12235bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
12244b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
12255bc3cb74SMauro Carvalho Chehab 			break;
12265bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
12275bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_cap(file, fh, arg);
12285bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
12294b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
12305bc3cb74SMauro Carvalho Chehab 			break;
12315bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
12325bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
12335bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
12344b20259fSHans Verkuil 		if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay))
12355bc3cb74SMauro Carvalho Chehab 			break;
12365bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
12375bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_overlay(file, fh, arg);
12384b20259fSHans Verkuil 	case V4L2_BUF_TYPE_VBI_CAPTURE:
12394b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap))
12404b20259fSHans Verkuil 			break;
12414b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.vbi);
12424b20259fSHans Verkuil 		return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
12434b20259fSHans Verkuil 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
12444b20259fSHans Verkuil 		if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap))
12454b20259fSHans Verkuil 			break;
12464b20259fSHans Verkuil 		CLEAR_AFTER_FIELD(p, fmt.sliced);
12474b20259fSHans Verkuil 		return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
12485bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
12494b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
12505bc3cb74SMauro Carvalho Chehab 			break;
12515bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix);
12525bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out(file, fh, arg);
12535bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
12544b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
12555bc3cb74SMauro Carvalho Chehab 			break;
12565bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.pix_mp);
12575bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
12585bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
12594b20259fSHans Verkuil 		if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay))
12605bc3cb74SMauro Carvalho Chehab 			break;
12615bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.win);
12625bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg);
12635bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_VBI_OUTPUT:
12644b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out))
12655bc3cb74SMauro Carvalho Chehab 			break;
12665bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.vbi);
12675bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_vbi_out(file, fh, arg);
12685bc3cb74SMauro Carvalho Chehab 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
12694b20259fSHans Verkuil 		if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out))
12705bc3cb74SMauro Carvalho Chehab 			break;
12715bc3cb74SMauro Carvalho Chehab 		CLEAR_AFTER_FIELD(p, fmt.sliced);
12725bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
1273582c52cbSAntti Palosaari 	case V4L2_BUF_TYPE_SDR_CAPTURE:
1274582c52cbSAntti Palosaari 		if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap))
1275582c52cbSAntti Palosaari 			break;
1276582c52cbSAntti Palosaari 		CLEAR_AFTER_FIELD(p, fmt.sdr);
1277582c52cbSAntti Palosaari 		return ops->vidioc_try_fmt_sdr_cap(file, fh, arg);
12785bc3cb74SMauro Carvalho Chehab 	}
12795bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
12805bc3cb74SMauro Carvalho Chehab }
12815bc3cb74SMauro Carvalho Chehab 
12825bc3cb74SMauro Carvalho Chehab static int v4l_streamon(const struct v4l2_ioctl_ops *ops,
12835bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12845bc3cb74SMauro Carvalho Chehab {
12855bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamon(file, fh, *(unsigned int *)arg);
12865bc3cb74SMauro Carvalho Chehab }
12875bc3cb74SMauro Carvalho Chehab 
12885bc3cb74SMauro Carvalho Chehab static int v4l_streamoff(const struct v4l2_ioctl_ops *ops,
12895bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12905bc3cb74SMauro Carvalho Chehab {
12915bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg);
12925bc3cb74SMauro Carvalho Chehab }
12935bc3cb74SMauro Carvalho Chehab 
12945bc3cb74SMauro Carvalho Chehab static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops,
12955bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
12965bc3cb74SMauro Carvalho Chehab {
12975bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
12985bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
12995bc3cb74SMauro Carvalho Chehab 	int err;
13005bc3cb74SMauro Carvalho Chehab 
13015bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13025bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
13035bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_tuner(file, fh, p);
13045bc3cb74SMauro Carvalho Chehab 	if (!err)
13055bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
13065bc3cb74SMauro Carvalho Chehab 	return err;
13075bc3cb74SMauro Carvalho Chehab }
13085bc3cb74SMauro Carvalho Chehab 
13095bc3cb74SMauro Carvalho Chehab static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops,
13105bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13115bc3cb74SMauro Carvalho Chehab {
13125bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13135bc3cb74SMauro Carvalho Chehab 	struct v4l2_tuner *p = arg;
13145bc3cb74SMauro Carvalho Chehab 
13155bc3cb74SMauro Carvalho Chehab 	p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13165bc3cb74SMauro Carvalho Chehab 			V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
13175bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_tuner(file, fh, p);
13185bc3cb74SMauro Carvalho Chehab }
13195bc3cb74SMauro Carvalho Chehab 
13205bc3cb74SMauro Carvalho Chehab static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops,
13215bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13225bc3cb74SMauro Carvalho Chehab {
13235bc3cb74SMauro Carvalho Chehab 	struct v4l2_modulator *p = arg;
13245bc3cb74SMauro Carvalho Chehab 	int err;
13255bc3cb74SMauro Carvalho Chehab 
13265bc3cb74SMauro Carvalho Chehab 	err = ops->vidioc_g_modulator(file, fh, p);
13275bc3cb74SMauro Carvalho Chehab 	if (!err)
13285bc3cb74SMauro Carvalho Chehab 		p->capability |= V4L2_TUNER_CAP_FREQ_BANDS;
13295bc3cb74SMauro Carvalho Chehab 	return err;
13305bc3cb74SMauro Carvalho Chehab }
13315bc3cb74SMauro Carvalho Chehab 
13325bc3cb74SMauro Carvalho Chehab static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops,
13335bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13345bc3cb74SMauro Carvalho Chehab {
13355bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13365bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency *p = arg;
13375bc3cb74SMauro Carvalho Chehab 
133884099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR)
133984099a28SAntti Palosaari 		p->type = V4L2_TUNER_ADC;
134084099a28SAntti Palosaari 	else
13415bc3cb74SMauro Carvalho Chehab 		p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13425bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
13435bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_frequency(file, fh, p);
13445bc3cb74SMauro Carvalho Chehab }
13455bc3cb74SMauro Carvalho Chehab 
13465bc3cb74SMauro Carvalho Chehab static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops,
13475bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13485bc3cb74SMauro Carvalho Chehab {
13495bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1350b530a447SHans Verkuil 	const struct v4l2_frequency *p = arg;
13515bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
13525bc3cb74SMauro Carvalho Chehab 
135384099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR) {
135484099a28SAntti Palosaari 		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
135584099a28SAntti Palosaari 			return -EINVAL;
135684099a28SAntti Palosaari 	} else {
13575bc3cb74SMauro Carvalho Chehab 		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
13585bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
135984099a28SAntti Palosaari 		if (type != p->type)
13605bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
136184099a28SAntti Palosaari 	}
13625bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_frequency(file, fh, p);
13635bc3cb74SMauro Carvalho Chehab }
13645bc3cb74SMauro Carvalho Chehab 
13655bc3cb74SMauro Carvalho Chehab static int v4l_enumstd(const struct v4l2_ioctl_ops *ops,
13665bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
13675bc3cb74SMauro Carvalho Chehab {
13685bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
13695bc3cb74SMauro Carvalho Chehab 	struct v4l2_standard *p = arg;
13705bc3cb74SMauro Carvalho Chehab 	v4l2_std_id id = vfd->tvnorms, curr_id = 0;
13715bc3cb74SMauro Carvalho Chehab 	unsigned int index = p->index, i, j = 0;
13725bc3cb74SMauro Carvalho Chehab 	const char *descr = "";
13735bc3cb74SMauro Carvalho Chehab 
1374a5338190SHans Verkuil 	/* Return -ENODATA if the tvnorms for the current input
1375a5338190SHans Verkuil 	   or output is 0, meaning that it doesn't support this API. */
1376a5338190SHans Verkuil 	if (id == 0)
1377a5338190SHans Verkuil 		return -ENODATA;
1378a5338190SHans Verkuil 
13795bc3cb74SMauro Carvalho Chehab 	/* Return norm array in a canonical way */
13805bc3cb74SMauro Carvalho Chehab 	for (i = 0; i <= index && id; i++) {
13815bc3cb74SMauro Carvalho Chehab 		/* last std value in the standards array is 0, so this
13825bc3cb74SMauro Carvalho Chehab 		   while always ends there since (id & 0) == 0. */
13835bc3cb74SMauro Carvalho Chehab 		while ((id & standards[j].std) != standards[j].std)
13845bc3cb74SMauro Carvalho Chehab 			j++;
13855bc3cb74SMauro Carvalho Chehab 		curr_id = standards[j].std;
13865bc3cb74SMauro Carvalho Chehab 		descr = standards[j].descr;
13875bc3cb74SMauro Carvalho Chehab 		j++;
13885bc3cb74SMauro Carvalho Chehab 		if (curr_id == 0)
13895bc3cb74SMauro Carvalho Chehab 			break;
13905bc3cb74SMauro Carvalho Chehab 		if (curr_id != V4L2_STD_PAL &&
13915bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_SECAM &&
13925bc3cb74SMauro Carvalho Chehab 				curr_id != V4L2_STD_NTSC)
13935bc3cb74SMauro Carvalho Chehab 			id &= ~curr_id;
13945bc3cb74SMauro Carvalho Chehab 	}
13955bc3cb74SMauro Carvalho Chehab 	if (i <= index)
13965bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
13975bc3cb74SMauro Carvalho Chehab 
13985bc3cb74SMauro Carvalho Chehab 	v4l2_video_std_construct(p, curr_id, descr);
13995bc3cb74SMauro Carvalho Chehab 	return 0;
14005bc3cb74SMauro Carvalho Chehab }
14015bc3cb74SMauro Carvalho Chehab 
14025bc3cb74SMauro Carvalho Chehab static int v4l_s_std(const struct v4l2_ioctl_ops *ops,
14035bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14045bc3cb74SMauro Carvalho Chehab {
14055bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
1406314527acSHans Verkuil 	v4l2_std_id id = *(v4l2_std_id *)arg, norm;
14075bc3cb74SMauro Carvalho Chehab 
1408314527acSHans Verkuil 	norm = id & vfd->tvnorms;
14095bc3cb74SMauro Carvalho Chehab 	if (vfd->tvnorms && !norm)	/* Check if std is supported */
14105bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
14115bc3cb74SMauro Carvalho Chehab 
14125bc3cb74SMauro Carvalho Chehab 	/* Calls the specific handler */
1413ca371575SHans Verkuil 	return ops->vidioc_s_std(file, fh, norm);
14145bc3cb74SMauro Carvalho Chehab }
14155bc3cb74SMauro Carvalho Chehab 
14165bc3cb74SMauro Carvalho Chehab static int v4l_querystd(const struct v4l2_ioctl_ops *ops,
14175bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14185bc3cb74SMauro Carvalho Chehab {
14195bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
14205bc3cb74SMauro Carvalho Chehab 	v4l2_std_id *p = arg;
14215bc3cb74SMauro Carvalho Chehab 
14225bc3cb74SMauro Carvalho Chehab 	/*
14231a2c6866SHans Verkuil 	 * If no signal is detected, then the driver should return
14241a2c6866SHans Verkuil 	 * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with
14251a2c6866SHans Verkuil 	 * any standards that do not apply removed.
14261a2c6866SHans Verkuil 	 *
14275bc3cb74SMauro Carvalho Chehab 	 * This means that tuners, audio and video decoders can join
14285bc3cb74SMauro Carvalho Chehab 	 * their efforts to improve the standards detection.
14295bc3cb74SMauro Carvalho Chehab 	 */
14305bc3cb74SMauro Carvalho Chehab 	*p = vfd->tvnorms;
14315bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_querystd(file, fh, arg);
14325bc3cb74SMauro Carvalho Chehab }
14335bc3cb74SMauro Carvalho Chehab 
14345bc3cb74SMauro Carvalho Chehab static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
14355bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14365bc3cb74SMauro Carvalho Chehab {
14375bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
14385bc3cb74SMauro Carvalho Chehab 	struct v4l2_hw_freq_seek *p = arg;
14395bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
14405bc3cb74SMauro Carvalho Chehab 
144184099a28SAntti Palosaari 	/* s_hw_freq_seek is not supported for SDR for now */
144284099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR)
144384099a28SAntti Palosaari 		return -EINVAL;
144484099a28SAntti Palosaari 
14455bc3cb74SMauro Carvalho Chehab 	type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
14465bc3cb74SMauro Carvalho Chehab 		V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
14475bc3cb74SMauro Carvalho Chehab 	if (p->type != type)
14485bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
14495bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_hw_freq_seek(file, fh, p);
14505bc3cb74SMauro Carvalho Chehab }
14515bc3cb74SMauro Carvalho Chehab 
1452737c097bSHans Verkuil static int v4l_overlay(const struct v4l2_ioctl_ops *ops,
1453737c097bSHans Verkuil 				struct file *file, void *fh, void *arg)
1454737c097bSHans Verkuil {
1455737c097bSHans Verkuil 	return ops->vidioc_overlay(file, fh, *(unsigned int *)arg);
1456737c097bSHans Verkuil }
1457737c097bSHans Verkuil 
14585bc3cb74SMauro Carvalho Chehab static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
14595bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14605bc3cb74SMauro Carvalho Chehab {
14615bc3cb74SMauro Carvalho Chehab 	struct v4l2_requestbuffers *p = arg;
14624b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14635bc3cb74SMauro Carvalho Chehab 
14645bc3cb74SMauro Carvalho Chehab 	if (ret)
14655bc3cb74SMauro Carvalho Chehab 		return ret;
14665bc3cb74SMauro Carvalho Chehab 
14675bc3cb74SMauro Carvalho Chehab 	CLEAR_AFTER_FIELD(p, memory);
14685bc3cb74SMauro Carvalho Chehab 
14695bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_reqbufs(file, fh, p);
14705bc3cb74SMauro Carvalho Chehab }
14715bc3cb74SMauro Carvalho Chehab 
14725bc3cb74SMauro Carvalho Chehab static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,
14735bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14745bc3cb74SMauro Carvalho Chehab {
14755bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14764b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14775bc3cb74SMauro Carvalho Chehab 
14785bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_querybuf(file, fh, p);
14795bc3cb74SMauro Carvalho Chehab }
14805bc3cb74SMauro Carvalho Chehab 
14815bc3cb74SMauro Carvalho Chehab static int v4l_qbuf(const struct v4l2_ioctl_ops *ops,
14825bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14835bc3cb74SMauro Carvalho Chehab {
14845bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14854b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14865bc3cb74SMauro Carvalho Chehab 
14875bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_qbuf(file, fh, p);
14885bc3cb74SMauro Carvalho Chehab }
14895bc3cb74SMauro Carvalho Chehab 
14905bc3cb74SMauro Carvalho Chehab static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,
14915bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
14925bc3cb74SMauro Carvalho Chehab {
14935bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *p = arg;
14944b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
14955bc3cb74SMauro Carvalho Chehab 
14965bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
14975bc3cb74SMauro Carvalho Chehab }
14985bc3cb74SMauro Carvalho Chehab 
14995bc3cb74SMauro Carvalho Chehab static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
15005bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15015bc3cb74SMauro Carvalho Chehab {
15025bc3cb74SMauro Carvalho Chehab 	struct v4l2_create_buffers *create = arg;
15034b20259fSHans Verkuil 	int ret = check_fmt(file, create->format.type);
15045bc3cb74SMauro Carvalho Chehab 
15055bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
15065bc3cb74SMauro Carvalho Chehab }
15075bc3cb74SMauro Carvalho Chehab 
15085bc3cb74SMauro Carvalho Chehab static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
15095bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15105bc3cb74SMauro Carvalho Chehab {
15115bc3cb74SMauro Carvalho Chehab 	struct v4l2_buffer *b = arg;
15124b20259fSHans Verkuil 	int ret = check_fmt(file, b->type);
15135bc3cb74SMauro Carvalho Chehab 
15145bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
15155bc3cb74SMauro Carvalho Chehab }
15165bc3cb74SMauro Carvalho Chehab 
15175bc3cb74SMauro Carvalho Chehab static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
15185bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15195bc3cb74SMauro Carvalho Chehab {
15205bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
15215bc3cb74SMauro Carvalho Chehab 	v4l2_std_id std;
15224b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
15235bc3cb74SMauro Carvalho Chehab 
15245bc3cb74SMauro Carvalho Chehab 	if (ret)
15255bc3cb74SMauro Carvalho Chehab 		return ret;
15265bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_parm)
15275bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_parm(file, fh, p);
15285bc3cb74SMauro Carvalho Chehab 	if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
15295bc3cb74SMauro Carvalho Chehab 	    p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
15305bc3cb74SMauro Carvalho Chehab 		return -EINVAL;
15315bc3cb74SMauro Carvalho Chehab 	p->parm.capture.readbuffers = 2;
15325bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_std(file, fh, &std);
15335bc3cb74SMauro Carvalho Chehab 	if (ret == 0)
1534ca371575SHans Verkuil 		v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe);
15355bc3cb74SMauro Carvalho Chehab 	return ret;
15365bc3cb74SMauro Carvalho Chehab }
15375bc3cb74SMauro Carvalho Chehab 
15385bc3cb74SMauro Carvalho Chehab static int v4l_s_parm(const struct v4l2_ioctl_ops *ops,
15395bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15405bc3cb74SMauro Carvalho Chehab {
15415bc3cb74SMauro Carvalho Chehab 	struct v4l2_streamparm *p = arg;
15424b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
15435bc3cb74SMauro Carvalho Chehab 
15445bc3cb74SMauro Carvalho Chehab 	return ret ? ret : ops->vidioc_s_parm(file, fh, p);
15455bc3cb74SMauro Carvalho Chehab }
15465bc3cb74SMauro Carvalho Chehab 
15475bc3cb74SMauro Carvalho Chehab static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
15485bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15495bc3cb74SMauro Carvalho Chehab {
15505bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15515bc3cb74SMauro Carvalho Chehab 	struct v4l2_queryctrl *p = arg;
15525bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15535bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15545bc3cb74SMauro Carvalho Chehab 
15555bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15565bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfh->ctrl_handler, p);
15575bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15585bc3cb74SMauro Carvalho Chehab 		return v4l2_queryctrl(vfd->ctrl_handler, p);
15595bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_queryctrl)
15605bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_queryctrl(file, fh, p);
15615bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
15625bc3cb74SMauro Carvalho Chehab }
15635bc3cb74SMauro Carvalho Chehab 
15645bc3cb74SMauro Carvalho Chehab static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
15655bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15665bc3cb74SMauro Carvalho Chehab {
15675bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15685bc3cb74SMauro Carvalho Chehab 	struct v4l2_querymenu *p = arg;
15695bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15705bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15715bc3cb74SMauro Carvalho Chehab 
15725bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15735bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfh->ctrl_handler, p);
15745bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15755bc3cb74SMauro Carvalho Chehab 		return v4l2_querymenu(vfd->ctrl_handler, p);
15765bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_querymenu)
15775bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_querymenu(file, fh, p);
15785bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
15795bc3cb74SMauro Carvalho Chehab }
15805bc3cb74SMauro Carvalho Chehab 
15815bc3cb74SMauro Carvalho Chehab static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops,
15825bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
15835bc3cb74SMauro Carvalho Chehab {
15845bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
15855bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
15865bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
15875bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
15885bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
15895bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
15905bc3cb74SMauro Carvalho Chehab 
15915bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
15925bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfh->ctrl_handler, p);
15935bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
15945bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ctrl(vfd->ctrl_handler, p);
15955bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ctrl)
15965bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_ctrl(file, fh, p);
15975bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
15985bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
15995bc3cb74SMauro Carvalho Chehab 
16005bc3cb74SMauro Carvalho Chehab 	ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
16015bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
16025bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
16035bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
16045bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
16055bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1)) {
16065bc3cb74SMauro Carvalho Chehab 		int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls);
16075bc3cb74SMauro Carvalho Chehab 
16085bc3cb74SMauro Carvalho Chehab 		if (ret == 0)
16095bc3cb74SMauro Carvalho Chehab 			p->value = ctrl.value;
16105bc3cb74SMauro Carvalho Chehab 		return ret;
16115bc3cb74SMauro Carvalho Chehab 	}
16125bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
16135bc3cb74SMauro Carvalho Chehab }
16145bc3cb74SMauro Carvalho Chehab 
16155bc3cb74SMauro Carvalho Chehab static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops,
16165bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16175bc3cb74SMauro Carvalho Chehab {
16185bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16195bc3cb74SMauro Carvalho Chehab 	struct v4l2_control *p = arg;
16205bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16215bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16225bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls ctrls;
16235bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_control ctrl;
16245bc3cb74SMauro Carvalho Chehab 
16255bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16265bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p);
16275bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16285bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p);
16295bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ctrl)
16305bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ctrl(file, fh, p);
16315bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
16325bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16335bc3cb74SMauro Carvalho Chehab 
16345bc3cb74SMauro Carvalho Chehab 	ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id);
16355bc3cb74SMauro Carvalho Chehab 	ctrls.count = 1;
16365bc3cb74SMauro Carvalho Chehab 	ctrls.controls = &ctrl;
16375bc3cb74SMauro Carvalho Chehab 	ctrl.id = p->id;
16385bc3cb74SMauro Carvalho Chehab 	ctrl.value = p->value;
16395bc3cb74SMauro Carvalho Chehab 	if (check_ext_ctrls(&ctrls, 1))
16405bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_ext_ctrls(file, fh, &ctrls);
16415bc3cb74SMauro Carvalho Chehab 	return -EINVAL;
16425bc3cb74SMauro Carvalho Chehab }
16435bc3cb74SMauro Carvalho Chehab 
16445bc3cb74SMauro Carvalho Chehab static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16455bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16465bc3cb74SMauro Carvalho Chehab {
16475bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16485bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16495bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16505bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16515bc3cb74SMauro Carvalho Chehab 
16525bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16535bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16545bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfh->ctrl_handler, p);
16555bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16565bc3cb74SMauro Carvalho Chehab 		return v4l2_g_ext_ctrls(vfd->ctrl_handler, p);
16575bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_ext_ctrls == NULL)
16585bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16595bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) :
16605bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16615bc3cb74SMauro Carvalho Chehab }
16625bc3cb74SMauro Carvalho Chehab 
16635bc3cb74SMauro Carvalho Chehab static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16645bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16655bc3cb74SMauro Carvalho Chehab {
16665bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16675bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16685bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16695bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16705bc3cb74SMauro Carvalho Chehab 
16715bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16725bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16735bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p);
16745bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16755bc3cb74SMauro Carvalho Chehab 		return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p);
16765bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_ext_ctrls == NULL)
16775bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16785bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) :
16795bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16805bc3cb74SMauro Carvalho Chehab }
16815bc3cb74SMauro Carvalho Chehab 
16825bc3cb74SMauro Carvalho Chehab static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops,
16835bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
16845bc3cb74SMauro Carvalho Chehab {
16855bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
16865bc3cb74SMauro Carvalho Chehab 	struct v4l2_ext_controls *p = arg;
16875bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh =
16885bc3cb74SMauro Carvalho Chehab 		test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
16895bc3cb74SMauro Carvalho Chehab 
16905bc3cb74SMauro Carvalho Chehab 	p->error_idx = p->count;
16915bc3cb74SMauro Carvalho Chehab 	if (vfh && vfh->ctrl_handler)
16925bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfh->ctrl_handler, p);
16935bc3cb74SMauro Carvalho Chehab 	if (vfd->ctrl_handler)
16945bc3cb74SMauro Carvalho Chehab 		return v4l2_try_ext_ctrls(vfd->ctrl_handler, p);
16955bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_try_ext_ctrls == NULL)
16965bc3cb74SMauro Carvalho Chehab 		return -ENOTTY;
16975bc3cb74SMauro Carvalho Chehab 	return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) :
16985bc3cb74SMauro Carvalho Chehab 					-EINVAL;
16995bc3cb74SMauro Carvalho Chehab }
17005bc3cb74SMauro Carvalho Chehab 
17015bc3cb74SMauro Carvalho Chehab static int v4l_g_crop(const struct v4l2_ioctl_ops *ops,
17025bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17035bc3cb74SMauro Carvalho Chehab {
17045bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
17055bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
17065bc3cb74SMauro Carvalho Chehab 		.type = p->type,
17075bc3cb74SMauro Carvalho Chehab 	};
17085bc3cb74SMauro Carvalho Chehab 	int ret;
17095bc3cb74SMauro Carvalho Chehab 
17105bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_g_crop)
17115bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_crop(file, fh, p);
17125bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
17135bc3cb74SMauro Carvalho Chehab 
17145bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
17155bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17165bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
17175bc3cb74SMauro Carvalho Chehab 	else
17185bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
17195bc3cb74SMauro Carvalho Chehab 
17205bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17215bc3cb74SMauro Carvalho Chehab 
17225bc3cb74SMauro Carvalho Chehab 	/* copying results to old structure on success */
17235bc3cb74SMauro Carvalho Chehab 	if (!ret)
17245bc3cb74SMauro Carvalho Chehab 		p->c = s.r;
17255bc3cb74SMauro Carvalho Chehab 	return ret;
17265bc3cb74SMauro Carvalho Chehab }
17275bc3cb74SMauro Carvalho Chehab 
17285bc3cb74SMauro Carvalho Chehab static int v4l_s_crop(const struct v4l2_ioctl_ops *ops,
17295bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17305bc3cb74SMauro Carvalho Chehab {
17315bc3cb74SMauro Carvalho Chehab 	struct v4l2_crop *p = arg;
17325bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = {
17335bc3cb74SMauro Carvalho Chehab 		.type = p->type,
17345bc3cb74SMauro Carvalho Chehab 		.r = p->c,
17355bc3cb74SMauro Carvalho Chehab 	};
17365bc3cb74SMauro Carvalho Chehab 
17375bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_s_crop)
17385bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_s_crop(file, fh, p);
17395bc3cb74SMauro Carvalho Chehab 	/* simulate capture crop using selection api */
17405bc3cb74SMauro Carvalho Chehab 
17415bc3cb74SMauro Carvalho Chehab 	/* crop means compose for output devices */
17425bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17435bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE;
17445bc3cb74SMauro Carvalho Chehab 	else
17455bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_ACTIVE;
17465bc3cb74SMauro Carvalho Chehab 
17475bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_s_selection(file, fh, &s);
17485bc3cb74SMauro Carvalho Chehab }
17495bc3cb74SMauro Carvalho Chehab 
17505bc3cb74SMauro Carvalho Chehab static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
17515bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17525bc3cb74SMauro Carvalho Chehab {
17535bc3cb74SMauro Carvalho Chehab 	struct v4l2_cropcap *p = arg;
17545bc3cb74SMauro Carvalho Chehab 	struct v4l2_selection s = { .type = p->type };
17555bc3cb74SMauro Carvalho Chehab 	int ret;
17565bc3cb74SMauro Carvalho Chehab 
17575bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_cropcap)
17585bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_cropcap(file, fh, p);
17595bc3cb74SMauro Carvalho Chehab 
17605bc3cb74SMauro Carvalho Chehab 	/* obtaining bounds */
17615bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17625bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
17635bc3cb74SMauro Carvalho Chehab 	else
17645bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_BOUNDS;
17655bc3cb74SMauro Carvalho Chehab 
17665bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17675bc3cb74SMauro Carvalho Chehab 	if (ret)
17685bc3cb74SMauro Carvalho Chehab 		return ret;
17695bc3cb74SMauro Carvalho Chehab 	p->bounds = s.r;
17705bc3cb74SMauro Carvalho Chehab 
17715bc3cb74SMauro Carvalho Chehab 	/* obtaining defrect */
17725bc3cb74SMauro Carvalho Chehab 	if (V4L2_TYPE_IS_OUTPUT(p->type))
17735bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
17745bc3cb74SMauro Carvalho Chehab 	else
17755bc3cb74SMauro Carvalho Chehab 		s.target = V4L2_SEL_TGT_CROP_DEFAULT;
17765bc3cb74SMauro Carvalho Chehab 
17775bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_g_selection(file, fh, &s);
17785bc3cb74SMauro Carvalho Chehab 	if (ret)
17795bc3cb74SMauro Carvalho Chehab 		return ret;
17805bc3cb74SMauro Carvalho Chehab 	p->defrect = s.r;
17815bc3cb74SMauro Carvalho Chehab 
17825bc3cb74SMauro Carvalho Chehab 	/* setting trivial pixelaspect */
17835bc3cb74SMauro Carvalho Chehab 	p->pixelaspect.numerator = 1;
17845bc3cb74SMauro Carvalho Chehab 	p->pixelaspect.denominator = 1;
17855bc3cb74SMauro Carvalho Chehab 	return 0;
17865bc3cb74SMauro Carvalho Chehab }
17875bc3cb74SMauro Carvalho Chehab 
17885bc3cb74SMauro Carvalho Chehab static int v4l_log_status(const struct v4l2_ioctl_ops *ops,
17895bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
17905bc3cb74SMauro Carvalho Chehab {
17915bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
17925bc3cb74SMauro Carvalho Chehab 	int ret;
17935bc3cb74SMauro Carvalho Chehab 
17945bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
17955bc3cb74SMauro Carvalho Chehab 		pr_info("%s: =================  START STATUS  =================\n",
17965bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
17975bc3cb74SMauro Carvalho Chehab 	ret = ops->vidioc_log_status(file, fh);
17985bc3cb74SMauro Carvalho Chehab 	if (vfd->v4l2_dev)
17995bc3cb74SMauro Carvalho Chehab 		pr_info("%s: ==================  END STATUS  ==================\n",
18005bc3cb74SMauro Carvalho Chehab 			vfd->v4l2_dev->name);
18015bc3cb74SMauro Carvalho Chehab 	return ret;
18025bc3cb74SMauro Carvalho Chehab }
18035bc3cb74SMauro Carvalho Chehab 
18045bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops,
18055bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18065bc3cb74SMauro Carvalho Chehab {
18075bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
18085bc3cb74SMauro Carvalho Chehab 	struct v4l2_dbg_register *p = arg;
180979b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
181079b0c640SHans Verkuil 	struct v4l2_subdev *sd;
181179b0c640SHans Verkuil 	int idx = 0;
18125bc3cb74SMauro Carvalho Chehab 
18135bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
18145bc3cb74SMauro Carvalho Chehab 		return -EPERM;
18153eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) {
181679b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
181779b0c640SHans Verkuil 			return -EINVAL;
18183eef2510SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev)
18193eef2510SHans Verkuil 			if (p->match.addr == idx++)
182079b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, g_register, p);
182179b0c640SHans Verkuil 		return -EINVAL;
182279b0c640SHans Verkuil 	}
1823191b79b0SHans Verkuil 	if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE &&
1824191b79b0SHans Verkuil 	    (ops->vidioc_g_chip_info || p->match.addr == 0))
18255bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_g_register(file, fh, p);
182679b0c640SHans Verkuil 	return -EINVAL;
18275bc3cb74SMauro Carvalho Chehab #else
18285bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
18295bc3cb74SMauro Carvalho Chehab #endif
18305bc3cb74SMauro Carvalho Chehab }
18315bc3cb74SMauro Carvalho Chehab 
18325bc3cb74SMauro Carvalho Chehab static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops,
18335bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
18345bc3cb74SMauro Carvalho Chehab {
18355bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG
1836977ba3b1SHans Verkuil 	const struct v4l2_dbg_register *p = arg;
183779b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
183879b0c640SHans Verkuil 	struct v4l2_subdev *sd;
183979b0c640SHans Verkuil 	int idx = 0;
18405bc3cb74SMauro Carvalho Chehab 
18415bc3cb74SMauro Carvalho Chehab 	if (!capable(CAP_SYS_ADMIN))
18425bc3cb74SMauro Carvalho Chehab 		return -EPERM;
18433eef2510SHans Verkuil 	if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) {
184479b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
184579b0c640SHans Verkuil 			return -EINVAL;
18463eef2510SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev)
18473eef2510SHans Verkuil 			if (p->match.addr == idx++)
184879b0c640SHans Verkuil 				return v4l2_subdev_call(sd, core, s_register, p);
184979b0c640SHans Verkuil 		return -EINVAL;
185079b0c640SHans Verkuil 	}
1851191b79b0SHans Verkuil 	if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE &&
1852191b79b0SHans Verkuil 	    (ops->vidioc_g_chip_info || p->match.addr == 0))
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 
186096b03d2aSHans Verkuil static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops,
186179b0c640SHans Verkuil 				struct file *file, void *fh, void *arg)
186279b0c640SHans Verkuil {
1863cd634f1bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG
186479b0c640SHans Verkuil 	struct video_device *vfd = video_devdata(file);
186596b03d2aSHans Verkuil 	struct v4l2_dbg_chip_info *p = arg;
186679b0c640SHans Verkuil 	struct v4l2_subdev *sd;
186779b0c640SHans Verkuil 	int idx = 0;
186879b0c640SHans Verkuil 
186979b0c640SHans Verkuil 	switch (p->match.type) {
187079b0c640SHans Verkuil 	case V4L2_CHIP_MATCH_BRIDGE:
187179b0c640SHans Verkuil 		if (ops->vidioc_s_register)
187279b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_WRITABLE;
187379b0c640SHans Verkuil 		if (ops->vidioc_g_register)
187479b0c640SHans Verkuil 			p->flags |= V4L2_CHIP_FL_READABLE;
187579b0c640SHans Verkuil 		strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name));
187696b03d2aSHans Verkuil 		if (ops->vidioc_g_chip_info)
187796b03d2aSHans Verkuil 			return ops->vidioc_g_chip_info(file, fh, arg);
18780f0fe4b9SHans Verkuil 		if (p->match.addr)
18790f0fe4b9SHans Verkuil 			return -EINVAL;
188079b0c640SHans Verkuil 		return 0;
188179b0c640SHans Verkuil 
18823eef2510SHans Verkuil 	case V4L2_CHIP_MATCH_SUBDEV:
188379b0c640SHans Verkuil 		if (vfd->v4l2_dev == NULL)
188479b0c640SHans Verkuil 			break;
188579b0c640SHans Verkuil 		v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) {
18863eef2510SHans Verkuil 			if (p->match.addr != idx++)
18873eef2510SHans Verkuil 				continue;
188879b0c640SHans Verkuil 			if (sd->ops->core && sd->ops->core->s_register)
188979b0c640SHans Verkuil 				p->flags |= V4L2_CHIP_FL_WRITABLE;
189079b0c640SHans Verkuil 			if (sd->ops->core && sd->ops->core->g_register)
189179b0c640SHans Verkuil 				p->flags |= V4L2_CHIP_FL_READABLE;
189279b0c640SHans Verkuil 			strlcpy(p->name, sd->name, sizeof(p->name));
189379b0c640SHans Verkuil 			return 0;
189479b0c640SHans Verkuil 		}
189579b0c640SHans Verkuil 		break;
189679b0c640SHans Verkuil 	}
189779b0c640SHans Verkuil 	return -EINVAL;
1898cd634f1bSHans Verkuil #else
1899cd634f1bSHans Verkuil 	return -ENOTTY;
1900cd634f1bSHans Verkuil #endif
190179b0c640SHans Verkuil }
190279b0c640SHans Verkuil 
19035bc3cb74SMauro Carvalho Chehab static int v4l_dqevent(const struct v4l2_ioctl_ops *ops,
19045bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19055bc3cb74SMauro Carvalho Chehab {
19065bc3cb74SMauro Carvalho Chehab 	return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK);
19075bc3cb74SMauro Carvalho Chehab }
19085bc3cb74SMauro Carvalho Chehab 
19095bc3cb74SMauro Carvalho Chehab static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops,
19105bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19115bc3cb74SMauro Carvalho Chehab {
19125bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_subscribe_event(fh, arg);
19135bc3cb74SMauro Carvalho Chehab }
19145bc3cb74SMauro Carvalho Chehab 
19155bc3cb74SMauro Carvalho Chehab static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops,
19165bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19175bc3cb74SMauro Carvalho Chehab {
19185bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_unsubscribe_event(fh, arg);
19195bc3cb74SMauro Carvalho Chehab }
19205bc3cb74SMauro Carvalho Chehab 
19215bc3cb74SMauro Carvalho Chehab static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops,
19225bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19235bc3cb74SMauro Carvalho Chehab {
19245bc3cb74SMauro Carvalho Chehab 	struct v4l2_sliced_vbi_cap *p = arg;
19254b20259fSHans Verkuil 	int ret = check_fmt(file, p->type);
19264b20259fSHans Verkuil 
19274b20259fSHans Verkuil 	if (ret)
19284b20259fSHans Verkuil 		return ret;
19295bc3cb74SMauro Carvalho Chehab 
19305bc3cb74SMauro Carvalho Chehab 	/* Clear up to type, everything after type is zeroed already */
19315bc3cb74SMauro Carvalho Chehab 	memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
19325bc3cb74SMauro Carvalho Chehab 
19335bc3cb74SMauro Carvalho Chehab 	return ops->vidioc_g_sliced_vbi_cap(file, fh, p);
19345bc3cb74SMauro Carvalho Chehab }
19355bc3cb74SMauro Carvalho Chehab 
19365bc3cb74SMauro Carvalho Chehab static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
19375bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *arg)
19385bc3cb74SMauro Carvalho Chehab {
19395bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
19405bc3cb74SMauro Carvalho Chehab 	struct v4l2_frequency_band *p = arg;
19415bc3cb74SMauro Carvalho Chehab 	enum v4l2_tuner_type type;
19425bc3cb74SMauro Carvalho Chehab 	int err;
19435bc3cb74SMauro Carvalho Chehab 
194484099a28SAntti Palosaari 	if (vfd->vfl_type == VFL_TYPE_SDR) {
194584099a28SAntti Palosaari 		if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF)
194684099a28SAntti Palosaari 			return -EINVAL;
194784099a28SAntti Palosaari 		type = p->type;
194884099a28SAntti Palosaari 	} else {
19495bc3cb74SMauro Carvalho Chehab 		type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
19505bc3cb74SMauro Carvalho Chehab 				V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
19515bc3cb74SMauro Carvalho Chehab 		if (type != p->type)
19525bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
195384099a28SAntti Palosaari 	}
19545bc3cb74SMauro Carvalho Chehab 	if (ops->vidioc_enum_freq_bands)
19555bc3cb74SMauro Carvalho Chehab 		return ops->vidioc_enum_freq_bands(file, fh, p);
195673f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
19575bc3cb74SMauro Carvalho Chehab 		struct v4l2_tuner t = {
19585bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
19595bc3cb74SMauro Carvalho Chehab 			.type = type,
19605bc3cb74SMauro Carvalho Chehab 		};
19615bc3cb74SMauro Carvalho Chehab 
196279e8c7beSMauro Carvalho Chehab 		if (p->index)
196379e8c7beSMauro Carvalho Chehab 			return -EINVAL;
19645bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_tuner(file, fh, &t);
19655bc3cb74SMauro Carvalho Chehab 		if (err)
19665bc3cb74SMauro Carvalho Chehab 			return err;
19675bc3cb74SMauro Carvalho Chehab 		p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS;
19685bc3cb74SMauro Carvalho Chehab 		p->rangelow = t.rangelow;
19695bc3cb74SMauro Carvalho Chehab 		p->rangehigh = t.rangehigh;
19705bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
19715bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
19725bc3cb74SMauro Carvalho Chehab 		return 0;
19735bc3cb74SMauro Carvalho Chehab 	}
197473f35418SHans Verkuil 	if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) {
19755bc3cb74SMauro Carvalho Chehab 		struct v4l2_modulator m = {
19765bc3cb74SMauro Carvalho Chehab 			.index = p->tuner,
19775bc3cb74SMauro Carvalho Chehab 		};
19785bc3cb74SMauro Carvalho Chehab 
19795bc3cb74SMauro Carvalho Chehab 		if (type != V4L2_TUNER_RADIO)
19805bc3cb74SMauro Carvalho Chehab 			return -EINVAL;
198179e8c7beSMauro Carvalho Chehab 		if (p->index)
198279e8c7beSMauro Carvalho Chehab 			return -EINVAL;
19835bc3cb74SMauro Carvalho Chehab 		err = ops->vidioc_g_modulator(file, fh, &m);
19845bc3cb74SMauro Carvalho Chehab 		if (err)
19855bc3cb74SMauro Carvalho Chehab 			return err;
19865bc3cb74SMauro Carvalho Chehab 		p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS;
19875bc3cb74SMauro Carvalho Chehab 		p->rangelow = m.rangelow;
19885bc3cb74SMauro Carvalho Chehab 		p->rangehigh = m.rangehigh;
19895bc3cb74SMauro Carvalho Chehab 		p->modulation = (type == V4L2_TUNER_RADIO) ?
19905bc3cb74SMauro Carvalho Chehab 			V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB;
19915bc3cb74SMauro Carvalho Chehab 		return 0;
19925bc3cb74SMauro Carvalho Chehab 	}
19935bc3cb74SMauro Carvalho Chehab 	return -ENOTTY;
19945bc3cb74SMauro Carvalho Chehab }
19955bc3cb74SMauro Carvalho Chehab 
19965bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info {
19975bc3cb74SMauro Carvalho Chehab 	unsigned int ioctl;
19985bc3cb74SMauro Carvalho Chehab 	u32 flags;
19995bc3cb74SMauro Carvalho Chehab 	const char * const name;
20005bc3cb74SMauro Carvalho Chehab 	union {
20015bc3cb74SMauro Carvalho Chehab 		u32 offset;
20025bc3cb74SMauro Carvalho Chehab 		int (*func)(const struct v4l2_ioctl_ops *ops,
20035bc3cb74SMauro Carvalho Chehab 				struct file *file, void *fh, void *p);
20045bc3cb74SMauro Carvalho Chehab 	} u;
20055bc3cb74SMauro Carvalho Chehab 	void (*debug)(const void *arg, bool write_only);
20065bc3cb74SMauro Carvalho Chehab };
20075bc3cb74SMauro Carvalho Chehab 
20085bc3cb74SMauro Carvalho Chehab /* This control needs a priority check */
20095bc3cb74SMauro Carvalho Chehab #define INFO_FL_PRIO	(1 << 0)
20105bc3cb74SMauro Carvalho Chehab /* This control can be valid if the filehandle passes a control handler. */
20115bc3cb74SMauro Carvalho Chehab #define INFO_FL_CTRL	(1 << 1)
20125bc3cb74SMauro Carvalho Chehab /* This is a standard ioctl, no need for special code */
20135bc3cb74SMauro Carvalho Chehab #define INFO_FL_STD	(1 << 2)
20145bc3cb74SMauro Carvalho Chehab /* This is ioctl has its own function */
20155bc3cb74SMauro Carvalho Chehab #define INFO_FL_FUNC	(1 << 3)
20165bc3cb74SMauro Carvalho Chehab /* Queuing ioctl */
20175bc3cb74SMauro Carvalho Chehab #define INFO_FL_QUEUE	(1 << 4)
20185bc3cb74SMauro Carvalho Chehab /* Zero struct from after the field to the end */
20195bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR(v4l2_struct, field)			\
20205bc3cb74SMauro Carvalho Chehab 	((offsetof(struct v4l2_struct, field) +			\
20215bc3cb74SMauro Carvalho Chehab 	  sizeof(((struct v4l2_struct *)0)->field)) << 16)
20225bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16)
20235bc3cb74SMauro Carvalho Chehab 
20245bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags)			\
20255bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
20265bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
20275bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_STD,				\
20285bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
20295bc3cb74SMauro Carvalho Chehab 		.u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc),	\
20305bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
20315bc3cb74SMauro Carvalho Chehab 	}
20325bc3cb74SMauro Carvalho Chehab 
20335bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags)			\
20345bc3cb74SMauro Carvalho Chehab 	[_IOC_NR(_ioctl)] = {						\
20355bc3cb74SMauro Carvalho Chehab 		.ioctl = _ioctl,					\
20365bc3cb74SMauro Carvalho Chehab 		.flags = _flags | INFO_FL_FUNC,				\
20375bc3cb74SMauro Carvalho Chehab 		.name = #_ioctl,					\
20385bc3cb74SMauro Carvalho Chehab 		.u.func = _func,					\
20395bc3cb74SMauro Carvalho Chehab 		.debug = _debug,					\
20405bc3cb74SMauro Carvalho Chehab 	}
20415bc3cb74SMauro Carvalho Chehab 
20425bc3cb74SMauro Carvalho Chehab static struct v4l2_ioctl_info v4l2_ioctls[] = {
20435bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
20445bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
20455bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)),
20465bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
20475bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
20485bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
20495bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0),
20505bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
2051737c097bSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
20525bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
2053b799d09aSTomasz Stanislawski 	IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)),
20545bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
20555bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
20565bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
20575bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)),
20585bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO),
2059ca371575SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0),
20605bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO),
20615bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)),
20625bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)),
20635bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)),
20645bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL),
20655bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)),
20665bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO),
20675bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0),
20685bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO),
20695bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)),
20705bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
20715bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
20725bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
2073dd519bb3SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)),
2074dd519bb3SHans Verkuil 	IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)),
20755bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
20765bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
20775bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
20785bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0),
20795bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO),
20805bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)),
20815bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO),
20825bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)),
20835bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO),
20845bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
20855bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
20865bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
20875bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0),
20885bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO),
20895bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
20905bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
20915bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
20925bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0),
20935bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)),
20945bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)),
20955bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0),
20965bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO),
20975bc3cb74SMauro 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)),
20985bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0),
20995bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
21005bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL),
21015bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL),
21025bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)),
21035bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)),
21045bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0),
21055bc3cb74SMauro 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)),
21065bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)),
21075bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO),
21085bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0),
21095bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0),
21105bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0),
21115bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO),
21125bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO),
21135bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0),
21145bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0),
21155bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0),
21165bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0),
21175bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE),
21185bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE),
21195bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0),
21205bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0),
21215bc3cb74SMauro 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)),
21225bc3cb74SMauro Carvalho Chehab 	IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
212396b03d2aSHans Verkuil 	IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
21245bc3cb74SMauro Carvalho Chehab };
21255bc3cb74SMauro Carvalho Chehab #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
21265bc3cb74SMauro Carvalho Chehab 
21275bc3cb74SMauro Carvalho Chehab bool v4l2_is_known_ioctl(unsigned int cmd)
21285bc3cb74SMauro Carvalho Chehab {
21295bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
21305bc3cb74SMauro Carvalho Chehab 		return false;
21315bc3cb74SMauro Carvalho Chehab 	return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd;
21325bc3cb74SMauro Carvalho Chehab }
21335bc3cb74SMauro Carvalho Chehab 
21345bc3cb74SMauro Carvalho Chehab struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd)
21355bc3cb74SMauro Carvalho Chehab {
21365bc3cb74SMauro Carvalho Chehab 	if (_IOC_NR(cmd) >= V4L2_IOCTLS)
21375bc3cb74SMauro Carvalho Chehab 		return vdev->lock;
21385bc3cb74SMauro Carvalho Chehab 	if (test_bit(_IOC_NR(cmd), vdev->disable_locking))
21395bc3cb74SMauro Carvalho Chehab 		return NULL;
21405bc3cb74SMauro Carvalho Chehab 	if (vdev->queue && vdev->queue->lock &&
21415bc3cb74SMauro Carvalho Chehab 			(v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE))
21425bc3cb74SMauro Carvalho Chehab 		return vdev->queue->lock;
21435bc3cb74SMauro Carvalho Chehab 	return vdev->lock;
21445bc3cb74SMauro Carvalho Chehab }
21455bc3cb74SMauro Carvalho Chehab 
21465bc3cb74SMauro Carvalho Chehab /* Common ioctl debug function. This function can be used by
21475bc3cb74SMauro Carvalho Chehab    external ioctl messages as well as internal V4L ioctl */
21485bc3cb74SMauro Carvalho Chehab void v4l_printk_ioctl(const char *prefix, unsigned int cmd)
21495bc3cb74SMauro Carvalho Chehab {
21505bc3cb74SMauro Carvalho Chehab 	const char *dir, *type;
21515bc3cb74SMauro Carvalho Chehab 
21525bc3cb74SMauro Carvalho Chehab 	if (prefix)
21535bc3cb74SMauro Carvalho Chehab 		printk(KERN_DEBUG "%s: ", prefix);
21545bc3cb74SMauro Carvalho Chehab 
21555bc3cb74SMauro Carvalho Chehab 	switch (_IOC_TYPE(cmd)) {
21565bc3cb74SMauro Carvalho Chehab 	case 'd':
21575bc3cb74SMauro Carvalho Chehab 		type = "v4l2_int";
21585bc3cb74SMauro Carvalho Chehab 		break;
21595bc3cb74SMauro Carvalho Chehab 	case 'V':
21605bc3cb74SMauro Carvalho Chehab 		if (_IOC_NR(cmd) >= V4L2_IOCTLS) {
21615bc3cb74SMauro Carvalho Chehab 			type = "v4l2";
21625bc3cb74SMauro Carvalho Chehab 			break;
21635bc3cb74SMauro Carvalho Chehab 		}
21645bc3cb74SMauro Carvalho Chehab 		pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name);
21655bc3cb74SMauro Carvalho Chehab 		return;
21665bc3cb74SMauro Carvalho Chehab 	default:
21675bc3cb74SMauro Carvalho Chehab 		type = "unknown";
21685bc3cb74SMauro Carvalho Chehab 		break;
21695bc3cb74SMauro Carvalho Chehab 	}
21705bc3cb74SMauro Carvalho Chehab 
21715bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
21725bc3cb74SMauro Carvalho Chehab 	case _IOC_NONE:              dir = "--"; break;
21735bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:              dir = "r-"; break;
21745bc3cb74SMauro Carvalho Chehab 	case _IOC_WRITE:             dir = "-w"; break;
21755bc3cb74SMauro Carvalho Chehab 	case _IOC_READ | _IOC_WRITE: dir = "rw"; break;
21765bc3cb74SMauro Carvalho Chehab 	default:                     dir = "*ERR*"; break;
21775bc3cb74SMauro Carvalho Chehab 	}
21785bc3cb74SMauro Carvalho Chehab 	pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)",
21795bc3cb74SMauro Carvalho Chehab 		type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd);
21805bc3cb74SMauro Carvalho Chehab }
21815bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l_printk_ioctl);
21825bc3cb74SMauro Carvalho Chehab 
21835bc3cb74SMauro Carvalho Chehab static long __video_do_ioctl(struct file *file,
21845bc3cb74SMauro Carvalho Chehab 		unsigned int cmd, void *arg)
21855bc3cb74SMauro Carvalho Chehab {
21865bc3cb74SMauro Carvalho Chehab 	struct video_device *vfd = video_devdata(file);
21875bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
21885bc3cb74SMauro Carvalho Chehab 	bool write_only = false;
21895bc3cb74SMauro Carvalho Chehab 	struct v4l2_ioctl_info default_info;
21905bc3cb74SMauro Carvalho Chehab 	const struct v4l2_ioctl_info *info;
21915bc3cb74SMauro Carvalho Chehab 	void *fh = file->private_data;
21925bc3cb74SMauro Carvalho Chehab 	struct v4l2_fh *vfh = NULL;
21935bc3cb74SMauro Carvalho Chehab 	int use_fh_prio = 0;
21945bc3cb74SMauro Carvalho Chehab 	int debug = vfd->debug;
21955bc3cb74SMauro Carvalho Chehab 	long ret = -ENOTTY;
21965bc3cb74SMauro Carvalho Chehab 
21975bc3cb74SMauro Carvalho Chehab 	if (ops == NULL) {
21985bc3cb74SMauro Carvalho Chehab 		pr_warn("%s: has no ioctl_ops.\n",
21995bc3cb74SMauro Carvalho Chehab 				video_device_node_name(vfd));
22005bc3cb74SMauro Carvalho Chehab 		return ret;
22015bc3cb74SMauro Carvalho Chehab 	}
22025bc3cb74SMauro Carvalho Chehab 
22035bc3cb74SMauro Carvalho Chehab 	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
22045bc3cb74SMauro Carvalho Chehab 		vfh = file->private_data;
22055bc3cb74SMauro Carvalho Chehab 		use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
22065bc3cb74SMauro Carvalho Chehab 	}
22075bc3cb74SMauro Carvalho Chehab 
22085bc3cb74SMauro Carvalho Chehab 	if (v4l2_is_known_ioctl(cmd)) {
22095bc3cb74SMauro Carvalho Chehab 		info = &v4l2_ioctls[_IOC_NR(cmd)];
22105bc3cb74SMauro Carvalho Chehab 
22115bc3cb74SMauro Carvalho Chehab 	        if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
22125bc3cb74SMauro Carvalho Chehab 		    !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
22135bc3cb74SMauro Carvalho Chehab 			goto done;
22145bc3cb74SMauro Carvalho Chehab 
22155bc3cb74SMauro Carvalho Chehab 		if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
22165bc3cb74SMauro Carvalho Chehab 			ret = v4l2_prio_check(vfd->prio, vfh->prio);
22175bc3cb74SMauro Carvalho Chehab 			if (ret)
22185bc3cb74SMauro Carvalho Chehab 				goto done;
22195bc3cb74SMauro Carvalho Chehab 		}
22205bc3cb74SMauro Carvalho Chehab 	} else {
22215bc3cb74SMauro Carvalho Chehab 		default_info.ioctl = cmd;
22225bc3cb74SMauro Carvalho Chehab 		default_info.flags = 0;
22235bc3cb74SMauro Carvalho Chehab 		default_info.debug = v4l_print_default;
22245bc3cb74SMauro Carvalho Chehab 		info = &default_info;
22255bc3cb74SMauro Carvalho Chehab 	}
22265bc3cb74SMauro Carvalho Chehab 
22275bc3cb74SMauro Carvalho Chehab 	write_only = _IOC_DIR(cmd) == _IOC_WRITE;
22285bc3cb74SMauro Carvalho Chehab 	if (info->flags & INFO_FL_STD) {
22295bc3cb74SMauro Carvalho Chehab 		typedef int (*vidioc_op)(struct file *file, void *fh, void *p);
22305bc3cb74SMauro Carvalho Chehab 		const void *p = vfd->ioctl_ops;
22315bc3cb74SMauro Carvalho Chehab 		const vidioc_op *vidioc = p + info->u.offset;
22325bc3cb74SMauro Carvalho Chehab 
22335bc3cb74SMauro Carvalho Chehab 		ret = (*vidioc)(file, fh, arg);
22345bc3cb74SMauro Carvalho Chehab 	} else if (info->flags & INFO_FL_FUNC) {
22355bc3cb74SMauro Carvalho Chehab 		ret = info->u.func(ops, file, fh, arg);
22365bc3cb74SMauro Carvalho Chehab 	} else if (!ops->vidioc_default) {
22375bc3cb74SMauro Carvalho Chehab 		ret = -ENOTTY;
22385bc3cb74SMauro Carvalho Chehab 	} else {
22395bc3cb74SMauro Carvalho Chehab 		ret = ops->vidioc_default(file, fh,
22405bc3cb74SMauro Carvalho Chehab 			use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
22415bc3cb74SMauro Carvalho Chehab 			cmd, arg);
22425bc3cb74SMauro Carvalho Chehab 	}
22435bc3cb74SMauro Carvalho Chehab 
22445bc3cb74SMauro Carvalho Chehab done:
22455bc3cb74SMauro Carvalho Chehab 	if (debug) {
22465bc3cb74SMauro Carvalho Chehab 		v4l_printk_ioctl(video_device_node_name(vfd), cmd);
22475bc3cb74SMauro Carvalho Chehab 		if (ret < 0)
2248505d04bdSHans Verkuil 			pr_cont(": error %ld", ret);
2249505d04bdSHans Verkuil 		if (debug == V4L2_DEBUG_IOCTL)
22505bc3cb74SMauro Carvalho Chehab 			pr_cont("\n");
22515bc3cb74SMauro Carvalho Chehab 		else if (_IOC_DIR(cmd) == _IOC_NONE)
22525bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
22535bc3cb74SMauro Carvalho Chehab 		else {
22545bc3cb74SMauro Carvalho Chehab 			pr_cont(": ");
22555bc3cb74SMauro Carvalho Chehab 			info->debug(arg, write_only);
22565bc3cb74SMauro Carvalho Chehab 		}
22575bc3cb74SMauro Carvalho Chehab 	}
22585bc3cb74SMauro Carvalho Chehab 
22595bc3cb74SMauro Carvalho Chehab 	return ret;
22605bc3cb74SMauro Carvalho Chehab }
22615bc3cb74SMauro Carvalho Chehab 
22625bc3cb74SMauro Carvalho Chehab static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
22635bc3cb74SMauro Carvalho Chehab 			    void * __user *user_ptr, void ***kernel_ptr)
22645bc3cb74SMauro Carvalho Chehab {
22655bc3cb74SMauro Carvalho Chehab 	int ret = 0;
22665bc3cb74SMauro Carvalho Chehab 
22675bc3cb74SMauro Carvalho Chehab 	switch (cmd) {
226896b1a702SHans Verkuil 	case VIDIOC_PREPARE_BUF:
22695bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QUERYBUF:
22705bc3cb74SMauro Carvalho Chehab 	case VIDIOC_QBUF:
22715bc3cb74SMauro Carvalho Chehab 	case VIDIOC_DQBUF: {
22725bc3cb74SMauro Carvalho Chehab 		struct v4l2_buffer *buf = parg;
22735bc3cb74SMauro Carvalho Chehab 
22745bc3cb74SMauro Carvalho Chehab 		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
22755bc3cb74SMauro Carvalho Chehab 			if (buf->length > VIDEO_MAX_PLANES) {
22765bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
22775bc3cb74SMauro Carvalho Chehab 				break;
22785bc3cb74SMauro Carvalho Chehab 			}
22795bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)buf->m.planes;
22805bc3cb74SMauro Carvalho Chehab 			*kernel_ptr = (void *)&buf->m.planes;
22815bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_plane) * buf->length;
22825bc3cb74SMauro Carvalho Chehab 			ret = 1;
22835bc3cb74SMauro Carvalho Chehab 		}
22845bc3cb74SMauro Carvalho Chehab 		break;
22855bc3cb74SMauro Carvalho Chehab 	}
22865bc3cb74SMauro Carvalho Chehab 
2287dd519bb3SHans Verkuil 	case VIDIOC_G_EDID:
2288dd519bb3SHans Verkuil 	case VIDIOC_S_EDID: {
2289dd519bb3SHans Verkuil 		struct v4l2_edid *edid = parg;
2290ed45ce2cSHans Verkuil 
2291ed45ce2cSHans Verkuil 		if (edid->blocks) {
22921b8b10ccSHans Verkuil 			if (edid->blocks > 256) {
22931b8b10ccSHans Verkuil 				ret = -EINVAL;
22941b8b10ccSHans Verkuil 				break;
22951b8b10ccSHans Verkuil 			}
2296ed45ce2cSHans Verkuil 			*user_ptr = (void __user *)edid->edid;
2297ed45ce2cSHans Verkuil 			*kernel_ptr = (void *)&edid->edid;
2298ed45ce2cSHans Verkuil 			*array_size = edid->blocks * 128;
2299ed45ce2cSHans Verkuil 			ret = 1;
2300ed45ce2cSHans Verkuil 		}
2301ed45ce2cSHans Verkuil 		break;
2302ed45ce2cSHans Verkuil 	}
2303ed45ce2cSHans Verkuil 
23045bc3cb74SMauro Carvalho Chehab 	case VIDIOC_S_EXT_CTRLS:
23055bc3cb74SMauro Carvalho Chehab 	case VIDIOC_G_EXT_CTRLS:
23065bc3cb74SMauro Carvalho Chehab 	case VIDIOC_TRY_EXT_CTRLS: {
23075bc3cb74SMauro Carvalho Chehab 		struct v4l2_ext_controls *ctrls = parg;
23085bc3cb74SMauro Carvalho Chehab 
23095bc3cb74SMauro Carvalho Chehab 		if (ctrls->count != 0) {
23105bc3cb74SMauro Carvalho Chehab 			if (ctrls->count > V4L2_CID_MAX_CTRLS) {
23115bc3cb74SMauro Carvalho Chehab 				ret = -EINVAL;
23125bc3cb74SMauro Carvalho Chehab 				break;
23135bc3cb74SMauro Carvalho Chehab 			}
23145bc3cb74SMauro Carvalho Chehab 			*user_ptr = (void __user *)ctrls->controls;
23155bc3cb74SMauro Carvalho Chehab 			*kernel_ptr = (void *)&ctrls->controls;
23165bc3cb74SMauro Carvalho Chehab 			*array_size = sizeof(struct v4l2_ext_control)
23175bc3cb74SMauro Carvalho Chehab 				    * ctrls->count;
23185bc3cb74SMauro Carvalho Chehab 			ret = 1;
23195bc3cb74SMauro Carvalho Chehab 		}
23205bc3cb74SMauro Carvalho Chehab 		break;
23215bc3cb74SMauro Carvalho Chehab 	}
23225bc3cb74SMauro Carvalho Chehab 	}
23235bc3cb74SMauro Carvalho Chehab 
23245bc3cb74SMauro Carvalho Chehab 	return ret;
23255bc3cb74SMauro Carvalho Chehab }
23265bc3cb74SMauro Carvalho Chehab 
23275bc3cb74SMauro Carvalho Chehab long
23285bc3cb74SMauro Carvalho Chehab video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
23295bc3cb74SMauro Carvalho Chehab 	       v4l2_kioctl func)
23305bc3cb74SMauro Carvalho Chehab {
23315bc3cb74SMauro Carvalho Chehab 	char	sbuf[128];
23325bc3cb74SMauro Carvalho Chehab 	void    *mbuf = NULL;
23335bc3cb74SMauro Carvalho Chehab 	void	*parg = (void *)arg;
23345bc3cb74SMauro Carvalho Chehab 	long	err  = -EINVAL;
23355bc3cb74SMauro Carvalho Chehab 	bool	has_array_args;
23365bc3cb74SMauro Carvalho Chehab 	size_t  array_size = 0;
23375bc3cb74SMauro Carvalho Chehab 	void __user *user_ptr = NULL;
23385bc3cb74SMauro Carvalho Chehab 	void	**kernel_ptr = NULL;
23395bc3cb74SMauro Carvalho Chehab 
23405bc3cb74SMauro Carvalho Chehab 	/*  Copy arguments into temp kernel buffer  */
23415bc3cb74SMauro Carvalho Chehab 	if (_IOC_DIR(cmd) != _IOC_NONE) {
23425bc3cb74SMauro Carvalho Chehab 		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
23435bc3cb74SMauro Carvalho Chehab 			parg = sbuf;
23445bc3cb74SMauro Carvalho Chehab 		} else {
23455bc3cb74SMauro Carvalho Chehab 			/* too big to allocate from stack */
23465bc3cb74SMauro Carvalho Chehab 			mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
23475bc3cb74SMauro Carvalho Chehab 			if (NULL == mbuf)
23485bc3cb74SMauro Carvalho Chehab 				return -ENOMEM;
23495bc3cb74SMauro Carvalho Chehab 			parg = mbuf;
23505bc3cb74SMauro Carvalho Chehab 		}
23515bc3cb74SMauro Carvalho Chehab 
23525bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
23535bc3cb74SMauro Carvalho Chehab 		if (_IOC_DIR(cmd) & _IOC_WRITE) {
23545bc3cb74SMauro Carvalho Chehab 			unsigned int n = _IOC_SIZE(cmd);
23555bc3cb74SMauro Carvalho Chehab 
23565bc3cb74SMauro Carvalho Chehab 			/*
23575bc3cb74SMauro Carvalho Chehab 			 * In some cases, only a few fields are used as input,
23585bc3cb74SMauro Carvalho Chehab 			 * i.e. when the app sets "index" and then the driver
23595bc3cb74SMauro Carvalho Chehab 			 * fills in the rest of the structure for the thing
23605bc3cb74SMauro Carvalho Chehab 			 * with that index.  We only need to copy up the first
23615bc3cb74SMauro Carvalho Chehab 			 * non-input field.
23625bc3cb74SMauro Carvalho Chehab 			 */
23635bc3cb74SMauro Carvalho Chehab 			if (v4l2_is_known_ioctl(cmd)) {
23645bc3cb74SMauro Carvalho Chehab 				u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;
23655bc3cb74SMauro Carvalho Chehab 				if (flags & INFO_FL_CLEAR_MASK)
23665bc3cb74SMauro Carvalho Chehab 					n = (flags & INFO_FL_CLEAR_MASK) >> 16;
23675bc3cb74SMauro Carvalho Chehab 			}
23685bc3cb74SMauro Carvalho Chehab 
23695bc3cb74SMauro Carvalho Chehab 			if (copy_from_user(parg, (void __user *)arg, n))
23705bc3cb74SMauro Carvalho Chehab 				goto out;
23715bc3cb74SMauro Carvalho Chehab 
23725bc3cb74SMauro Carvalho Chehab 			/* zero out anything we don't copy from userspace */
23735bc3cb74SMauro Carvalho Chehab 			if (n < _IOC_SIZE(cmd))
23745bc3cb74SMauro Carvalho Chehab 				memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n);
23755bc3cb74SMauro Carvalho Chehab 		} else {
23765bc3cb74SMauro Carvalho Chehab 			/* read-only ioctl */
23775bc3cb74SMauro Carvalho Chehab 			memset(parg, 0, _IOC_SIZE(cmd));
23785bc3cb74SMauro Carvalho Chehab 		}
23795bc3cb74SMauro Carvalho Chehab 	}
23805bc3cb74SMauro Carvalho Chehab 
23815bc3cb74SMauro Carvalho Chehab 	err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
23825bc3cb74SMauro Carvalho Chehab 	if (err < 0)
23835bc3cb74SMauro Carvalho Chehab 		goto out;
23845bc3cb74SMauro Carvalho Chehab 	has_array_args = err;
23855bc3cb74SMauro Carvalho Chehab 
23865bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
23875bc3cb74SMauro Carvalho Chehab 		/*
23885bc3cb74SMauro Carvalho Chehab 		 * When adding new types of array args, make sure that the
23895bc3cb74SMauro Carvalho Chehab 		 * parent argument to ioctl (which contains the pointer to the
23905bc3cb74SMauro Carvalho Chehab 		 * array) fits into sbuf (so that mbuf will still remain
23915bc3cb74SMauro Carvalho Chehab 		 * unused up to here).
23925bc3cb74SMauro Carvalho Chehab 		 */
23935bc3cb74SMauro Carvalho Chehab 		mbuf = kmalloc(array_size, GFP_KERNEL);
23945bc3cb74SMauro Carvalho Chehab 		err = -ENOMEM;
23955bc3cb74SMauro Carvalho Chehab 		if (NULL == mbuf)
23965bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
23975bc3cb74SMauro Carvalho Chehab 		err = -EFAULT;
23985bc3cb74SMauro Carvalho Chehab 		if (copy_from_user(mbuf, user_ptr, array_size))
23995bc3cb74SMauro Carvalho Chehab 			goto out_array_args;
24005bc3cb74SMauro Carvalho Chehab 		*kernel_ptr = mbuf;
24015bc3cb74SMauro Carvalho Chehab 	}
24025bc3cb74SMauro Carvalho Chehab 
24035bc3cb74SMauro Carvalho Chehab 	/* Handles IOCTL */
24045bc3cb74SMauro Carvalho Chehab 	err = func(file, cmd, parg);
24055bc3cb74SMauro Carvalho Chehab 	if (err == -ENOIOCTLCMD)
24065bc3cb74SMauro Carvalho Chehab 		err = -ENOTTY;
2407aa32f4c0SHans Verkuil 	if (err == 0) {
2408aa32f4c0SHans Verkuil 		if (cmd == VIDIOC_DQBUF)
2409aa32f4c0SHans Verkuil 			trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
2410aa32f4c0SHans Verkuil 		else if (cmd == VIDIOC_QBUF)
2411aa32f4c0SHans Verkuil 			trace_v4l2_qbuf(video_devdata(file)->minor, parg);
2412aa32f4c0SHans Verkuil 	}
24135bc3cb74SMauro Carvalho Chehab 
24145bc3cb74SMauro Carvalho Chehab 	if (has_array_args) {
24155bc3cb74SMauro Carvalho Chehab 		*kernel_ptr = user_ptr;
24165bc3cb74SMauro Carvalho Chehab 		if (copy_to_user(user_ptr, mbuf, array_size))
24175bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
24185bc3cb74SMauro Carvalho Chehab 		goto out_array_args;
24195bc3cb74SMauro Carvalho Chehab 	}
24205bc3cb74SMauro Carvalho Chehab 	/* VIDIOC_QUERY_DV_TIMINGS can return an error, but still have valid
24215bc3cb74SMauro Carvalho Chehab 	   results that must be returned. */
24225bc3cb74SMauro Carvalho Chehab 	if (err < 0 && cmd != VIDIOC_QUERY_DV_TIMINGS)
24235bc3cb74SMauro Carvalho Chehab 		goto out;
24245bc3cb74SMauro Carvalho Chehab 
24255bc3cb74SMauro Carvalho Chehab out_array_args:
24265bc3cb74SMauro Carvalho Chehab 	/*  Copy results into user buffer  */
24275bc3cb74SMauro Carvalho Chehab 	switch (_IOC_DIR(cmd)) {
24285bc3cb74SMauro Carvalho Chehab 	case _IOC_READ:
24295bc3cb74SMauro Carvalho Chehab 	case (_IOC_WRITE | _IOC_READ):
24305bc3cb74SMauro Carvalho Chehab 		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
24315bc3cb74SMauro Carvalho Chehab 			err = -EFAULT;
24325bc3cb74SMauro Carvalho Chehab 		break;
24335bc3cb74SMauro Carvalho Chehab 	}
24345bc3cb74SMauro Carvalho Chehab 
24355bc3cb74SMauro Carvalho Chehab out:
24365bc3cb74SMauro Carvalho Chehab 	kfree(mbuf);
24375bc3cb74SMauro Carvalho Chehab 	return err;
24385bc3cb74SMauro Carvalho Chehab }
24395bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_usercopy);
24405bc3cb74SMauro Carvalho Chehab 
24415bc3cb74SMauro Carvalho Chehab long video_ioctl2(struct file *file,
24425bc3cb74SMauro Carvalho Chehab 	       unsigned int cmd, unsigned long arg)
24435bc3cb74SMauro Carvalho Chehab {
24445bc3cb74SMauro Carvalho Chehab 	return video_usercopy(file, cmd, arg, __video_do_ioctl);
24455bc3cb74SMauro Carvalho Chehab }
24465bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_ioctl2);
2447