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; 24987185c95SAntti Palosaari const struct v4l2_sdr_format *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, " 259c96fd46aSLaurent Pinchart "bytesperline=%u, sizeimage=%u, colorspace=%d, " 260c96fd46aSLaurent Pinchart "flags %u\n", 2615bc3cb74SMauro Carvalho Chehab pix->width, pix->height, 2625bc3cb74SMauro Carvalho Chehab (pix->pixelformat & 0xff), 2635bc3cb74SMauro Carvalho Chehab (pix->pixelformat >> 8) & 0xff, 2645bc3cb74SMauro Carvalho Chehab (pix->pixelformat >> 16) & 0xff, 2655bc3cb74SMauro Carvalho Chehab (pix->pixelformat >> 24) & 0xff, 2665bc3cb74SMauro Carvalho Chehab prt_names(pix->field, v4l2_field_names), 2675bc3cb74SMauro Carvalho Chehab pix->bytesperline, pix->sizeimage, 268c96fd46aSLaurent Pinchart pix->colorspace, pix->flags); 2695bc3cb74SMauro Carvalho Chehab break; 2705bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 2715bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 2725bc3cb74SMauro Carvalho Chehab mp = &p->fmt.pix_mp; 2735bc3cb74SMauro Carvalho Chehab pr_cont(", width=%u, height=%u, " 2745bc3cb74SMauro Carvalho Chehab "format=%c%c%c%c, field=%s, " 2755bc3cb74SMauro Carvalho Chehab "colorspace=%d, num_planes=%u\n", 2765bc3cb74SMauro Carvalho Chehab mp->width, mp->height, 2775bc3cb74SMauro Carvalho Chehab (mp->pixelformat & 0xff), 2785bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 8) & 0xff, 2795bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 16) & 0xff, 2805bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 24) & 0xff, 2815bc3cb74SMauro Carvalho Chehab prt_names(mp->field, v4l2_field_names), 2825bc3cb74SMauro Carvalho Chehab mp->colorspace, mp->num_planes); 2835bc3cb74SMauro Carvalho Chehab for (i = 0; i < mp->num_planes; i++) 2845bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i, 2855bc3cb74SMauro Carvalho Chehab mp->plane_fmt[i].bytesperline, 2865bc3cb74SMauro Carvalho Chehab mp->plane_fmt[i].sizeimage); 2875bc3cb74SMauro Carvalho Chehab break; 2885bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 2895bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 2905bc3cb74SMauro Carvalho Chehab win = &p->fmt.win; 291560dde24SHans Verkuil /* Note: we can't print the clip list here since the clips 292560dde24SHans Verkuil * pointer is a userspace pointer, not a kernelspace 293560dde24SHans Verkuil * pointer. */ 294560dde24SHans 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", 295560dde24SHans Verkuil win->w.width, win->w.height, win->w.left, win->w.top, 2965bc3cb74SMauro Carvalho Chehab prt_names(win->field, v4l2_field_names), 297560dde24SHans Verkuil win->chromakey, win->clipcount, win->clips, 298560dde24SHans Verkuil win->bitmap, win->global_alpha); 2995bc3cb74SMauro Carvalho Chehab break; 3005bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_CAPTURE: 3015bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 3025bc3cb74SMauro Carvalho Chehab vbi = &p->fmt.vbi; 3035bc3cb74SMauro Carvalho Chehab pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, " 3045bc3cb74SMauro Carvalho Chehab "sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n", 3055bc3cb74SMauro Carvalho Chehab vbi->sampling_rate, vbi->offset, 3065bc3cb74SMauro Carvalho Chehab vbi->samples_per_line, 3075bc3cb74SMauro Carvalho Chehab (vbi->sample_format & 0xff), 3085bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 8) & 0xff, 3095bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 16) & 0xff, 3105bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 24) & 0xff, 3115bc3cb74SMauro Carvalho Chehab vbi->start[0], vbi->start[1], 3125bc3cb74SMauro Carvalho Chehab vbi->count[0], vbi->count[1]); 3135bc3cb74SMauro Carvalho Chehab break; 3145bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 3155bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 3165bc3cb74SMauro Carvalho Chehab sliced = &p->fmt.sliced; 3175bc3cb74SMauro Carvalho Chehab pr_cont(", service_set=0x%08x, io_size=%d\n", 3185bc3cb74SMauro Carvalho Chehab sliced->service_set, sliced->io_size); 3195bc3cb74SMauro Carvalho Chehab for (i = 0; i < 24; i++) 3205bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, 3215bc3cb74SMauro Carvalho Chehab sliced->service_lines[0][i], 3225bc3cb74SMauro Carvalho Chehab sliced->service_lines[1][i]); 3235bc3cb74SMauro Carvalho Chehab break; 324582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 325582c52cbSAntti Palosaari sdr = &p->fmt.sdr; 326582c52cbSAntti Palosaari pr_cont(", pixelformat=%c%c%c%c\n", 327582c52cbSAntti Palosaari (sdr->pixelformat >> 0) & 0xff, 328582c52cbSAntti Palosaari (sdr->pixelformat >> 8) & 0xff, 329582c52cbSAntti Palosaari (sdr->pixelformat >> 16) & 0xff, 330582c52cbSAntti Palosaari (sdr->pixelformat >> 24) & 0xff); 331582c52cbSAntti Palosaari break; 3325bc3cb74SMauro Carvalho Chehab } 3335bc3cb74SMauro Carvalho Chehab } 3345bc3cb74SMauro Carvalho Chehab 3355bc3cb74SMauro Carvalho Chehab static void v4l_print_framebuffer(const void *arg, bool write_only) 3365bc3cb74SMauro Carvalho Chehab { 3375bc3cb74SMauro Carvalho Chehab const struct v4l2_framebuffer *p = arg; 3385bc3cb74SMauro Carvalho Chehab 3395bc3cb74SMauro Carvalho Chehab pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, " 3405bc3cb74SMauro Carvalho Chehab "height=%u, pixelformat=%c%c%c%c, " 341560dde24SHans Verkuil "bytesperline=%u, sizeimage=%u, colorspace=%d\n", 3425bc3cb74SMauro Carvalho Chehab p->capability, p->flags, p->base, 3435bc3cb74SMauro Carvalho Chehab p->fmt.width, p->fmt.height, 3445bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat & 0xff), 3455bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 8) & 0xff, 3465bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 16) & 0xff, 3475bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 24) & 0xff, 3485bc3cb74SMauro Carvalho Chehab p->fmt.bytesperline, p->fmt.sizeimage, 3495bc3cb74SMauro Carvalho Chehab p->fmt.colorspace); 3505bc3cb74SMauro Carvalho Chehab } 3515bc3cb74SMauro Carvalho Chehab 3525bc3cb74SMauro Carvalho Chehab static void v4l_print_buftype(const void *arg, bool write_only) 3535bc3cb74SMauro Carvalho Chehab { 3545bc3cb74SMauro Carvalho Chehab pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names)); 3555bc3cb74SMauro Carvalho Chehab } 3565bc3cb74SMauro Carvalho Chehab 3575bc3cb74SMauro Carvalho Chehab static void v4l_print_modulator(const void *arg, bool write_only) 3585bc3cb74SMauro Carvalho Chehab { 3595bc3cb74SMauro Carvalho Chehab const struct v4l2_modulator *p = arg; 3605bc3cb74SMauro Carvalho Chehab 3615bc3cb74SMauro Carvalho Chehab if (write_only) 362560dde24SHans Verkuil pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans); 3635bc3cb74SMauro Carvalho Chehab else 36427d5a87cSHans Verkuil pr_cont("index=%u, name=%.*s, capability=0x%x, " 3655bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, txsubchans=0x%x\n", 36627d5a87cSHans Verkuil p->index, (int)sizeof(p->name), p->name, p->capability, 3675bc3cb74SMauro Carvalho Chehab p->rangelow, p->rangehigh, p->txsubchans); 3685bc3cb74SMauro Carvalho Chehab } 3695bc3cb74SMauro Carvalho Chehab 3705bc3cb74SMauro Carvalho Chehab static void v4l_print_tuner(const void *arg, bool write_only) 3715bc3cb74SMauro Carvalho Chehab { 3725bc3cb74SMauro Carvalho Chehab const struct v4l2_tuner *p = arg; 3735bc3cb74SMauro Carvalho Chehab 3745bc3cb74SMauro Carvalho Chehab if (write_only) 3755bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, audmode=%u\n", p->index, p->audmode); 3765bc3cb74SMauro Carvalho Chehab else 37727d5a87cSHans Verkuil pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, " 3785bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, signal=%u, afc=%d, " 3795bc3cb74SMauro Carvalho Chehab "rxsubchans=0x%x, audmode=%u\n", 38027d5a87cSHans Verkuil p->index, (int)sizeof(p->name), p->name, p->type, 3815bc3cb74SMauro Carvalho Chehab p->capability, p->rangelow, 3825bc3cb74SMauro Carvalho Chehab p->rangehigh, p->signal, p->afc, 3835bc3cb74SMauro Carvalho Chehab p->rxsubchans, p->audmode); 3845bc3cb74SMauro Carvalho Chehab } 3855bc3cb74SMauro Carvalho Chehab 3865bc3cb74SMauro Carvalho Chehab static void v4l_print_frequency(const void *arg, bool write_only) 3875bc3cb74SMauro Carvalho Chehab { 3885bc3cb74SMauro Carvalho Chehab const struct v4l2_frequency *p = arg; 3895bc3cb74SMauro Carvalho Chehab 3905bc3cb74SMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, frequency=%u\n", 3915bc3cb74SMauro Carvalho Chehab p->tuner, p->type, p->frequency); 3925bc3cb74SMauro Carvalho Chehab } 3935bc3cb74SMauro Carvalho Chehab 3945bc3cb74SMauro Carvalho Chehab static void v4l_print_standard(const void *arg, bool write_only) 3955bc3cb74SMauro Carvalho Chehab { 3965bc3cb74SMauro Carvalho Chehab const struct v4l2_standard *p = arg; 3975bc3cb74SMauro Carvalho Chehab 39827d5a87cSHans Verkuil pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, " 3995bc3cb74SMauro Carvalho Chehab "framelines=%u\n", p->index, 40027d5a87cSHans Verkuil (unsigned long long)p->id, (int)sizeof(p->name), p->name, 4015bc3cb74SMauro Carvalho Chehab p->frameperiod.numerator, 4025bc3cb74SMauro Carvalho Chehab p->frameperiod.denominator, 4035bc3cb74SMauro Carvalho Chehab p->framelines); 4045bc3cb74SMauro Carvalho Chehab } 4055bc3cb74SMauro Carvalho Chehab 4065bc3cb74SMauro Carvalho Chehab static void v4l_print_std(const void *arg, bool write_only) 4075bc3cb74SMauro Carvalho Chehab { 4085bc3cb74SMauro Carvalho Chehab pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg); 4095bc3cb74SMauro Carvalho Chehab } 4105bc3cb74SMauro Carvalho Chehab 4115bc3cb74SMauro Carvalho Chehab static void v4l_print_hw_freq_seek(const void *arg, bool write_only) 4125bc3cb74SMauro Carvalho Chehab { 4135bc3cb74SMauro Carvalho Chehab const struct v4l2_hw_freq_seek *p = arg; 4145bc3cb74SMauro Carvalho Chehab 41579e8c7beSMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " 41679e8c7beSMauro Carvalho Chehab "rangelow=%u, rangehigh=%u\n", 41779e8c7beSMauro Carvalho Chehab p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, 41879e8c7beSMauro Carvalho Chehab p->rangelow, p->rangehigh); 4195bc3cb74SMauro Carvalho Chehab } 4205bc3cb74SMauro Carvalho Chehab 4215bc3cb74SMauro Carvalho Chehab static void v4l_print_requestbuffers(const void *arg, bool write_only) 4225bc3cb74SMauro Carvalho Chehab { 4235bc3cb74SMauro Carvalho Chehab const struct v4l2_requestbuffers *p = arg; 4245bc3cb74SMauro Carvalho Chehab 4255bc3cb74SMauro Carvalho Chehab pr_cont("count=%d, type=%s, memory=%s\n", 4265bc3cb74SMauro Carvalho Chehab p->count, 4275bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 4285bc3cb74SMauro Carvalho Chehab prt_names(p->memory, v4l2_memory_names)); 4295bc3cb74SMauro Carvalho Chehab } 4305bc3cb74SMauro Carvalho Chehab 4315bc3cb74SMauro Carvalho Chehab static void v4l_print_buffer(const void *arg, bool write_only) 4325bc3cb74SMauro Carvalho Chehab { 4335bc3cb74SMauro Carvalho Chehab const struct v4l2_buffer *p = arg; 4345bc3cb74SMauro Carvalho Chehab const struct v4l2_timecode *tc = &p->timecode; 4355bc3cb74SMauro Carvalho Chehab const struct v4l2_plane *plane; 4365bc3cb74SMauro Carvalho Chehab int i; 4375bc3cb74SMauro Carvalho Chehab 4385bc3cb74SMauro Carvalho Chehab pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, " 4395bc3cb74SMauro Carvalho Chehab "flags=0x%08x, field=%s, sequence=%d, memory=%s", 4405bc3cb74SMauro Carvalho Chehab p->timestamp.tv_sec / 3600, 4415bc3cb74SMauro Carvalho Chehab (int)(p->timestamp.tv_sec / 60) % 60, 4425bc3cb74SMauro Carvalho Chehab (int)(p->timestamp.tv_sec % 60), 4435bc3cb74SMauro Carvalho Chehab (long)p->timestamp.tv_usec, 4445bc3cb74SMauro Carvalho Chehab p->index, 4455bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 4465bc3cb74SMauro Carvalho Chehab p->flags, prt_names(p->field, v4l2_field_names), 4475bc3cb74SMauro Carvalho Chehab p->sequence, prt_names(p->memory, v4l2_memory_names)); 4485bc3cb74SMauro Carvalho Chehab 4495bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) { 4505bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 4515bc3cb74SMauro Carvalho Chehab for (i = 0; i < p->length; ++i) { 4525bc3cb74SMauro Carvalho Chehab plane = &p->m.planes[i]; 4535bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG 454560dde24SHans Verkuil "plane %d: bytesused=%d, data_offset=0x%08x, " 4555bc3cb74SMauro Carvalho Chehab "offset/userptr=0x%lx, length=%d\n", 4565bc3cb74SMauro Carvalho Chehab i, plane->bytesused, plane->data_offset, 4575bc3cb74SMauro Carvalho Chehab plane->m.userptr, plane->length); 4585bc3cb74SMauro Carvalho Chehab } 4595bc3cb74SMauro Carvalho Chehab } else { 460560dde24SHans Verkuil pr_cont(", bytesused=%d, offset/userptr=0x%lx, length=%d\n", 4615bc3cb74SMauro Carvalho Chehab p->bytesused, p->m.userptr, p->length); 4625bc3cb74SMauro Carvalho Chehab } 4635bc3cb74SMauro Carvalho Chehab 4645bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, " 4655bc3cb74SMauro Carvalho Chehab "flags=0x%08x, frames=%d, userbits=0x%08x\n", 4665bc3cb74SMauro Carvalho Chehab tc->hours, tc->minutes, tc->seconds, 4675bc3cb74SMauro Carvalho Chehab tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits); 4685bc3cb74SMauro Carvalho Chehab } 4695bc3cb74SMauro Carvalho Chehab 470b799d09aSTomasz Stanislawski static void v4l_print_exportbuffer(const void *arg, bool write_only) 471b799d09aSTomasz Stanislawski { 472b799d09aSTomasz Stanislawski const struct v4l2_exportbuffer *p = arg; 473b799d09aSTomasz Stanislawski 474b799d09aSTomasz Stanislawski pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n", 475b799d09aSTomasz Stanislawski p->fd, prt_names(p->type, v4l2_type_names), 476b799d09aSTomasz Stanislawski p->index, p->plane, p->flags); 477b799d09aSTomasz Stanislawski } 478b799d09aSTomasz Stanislawski 4795bc3cb74SMauro Carvalho Chehab static void v4l_print_create_buffers(const void *arg, bool write_only) 4805bc3cb74SMauro Carvalho Chehab { 4815bc3cb74SMauro Carvalho Chehab const struct v4l2_create_buffers *p = arg; 4825bc3cb74SMauro Carvalho Chehab 4835bc3cb74SMauro Carvalho Chehab pr_cont("index=%d, count=%d, memory=%s, ", 4845bc3cb74SMauro Carvalho Chehab p->index, p->count, 4855bc3cb74SMauro Carvalho Chehab prt_names(p->memory, v4l2_memory_names)); 4865bc3cb74SMauro Carvalho Chehab v4l_print_format(&p->format, write_only); 4875bc3cb74SMauro Carvalho Chehab } 4885bc3cb74SMauro Carvalho Chehab 4895bc3cb74SMauro Carvalho Chehab static void v4l_print_streamparm(const void *arg, bool write_only) 4905bc3cb74SMauro Carvalho Chehab { 4915bc3cb74SMauro Carvalho Chehab const struct v4l2_streamparm *p = arg; 4925bc3cb74SMauro Carvalho Chehab 4935bc3cb74SMauro Carvalho Chehab pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); 4945bc3cb74SMauro Carvalho Chehab 4955bc3cb74SMauro Carvalho Chehab if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || 4965bc3cb74SMauro Carvalho Chehab p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 4975bc3cb74SMauro Carvalho Chehab const struct v4l2_captureparm *c = &p->parm.capture; 4985bc3cb74SMauro Carvalho Chehab 4995bc3cb74SMauro Carvalho Chehab pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, " 5005bc3cb74SMauro Carvalho Chehab "extendedmode=%d, readbuffers=%d\n", 5015bc3cb74SMauro Carvalho Chehab c->capability, c->capturemode, 5025bc3cb74SMauro Carvalho Chehab c->timeperframe.numerator, c->timeperframe.denominator, 5035bc3cb74SMauro Carvalho Chehab c->extendedmode, c->readbuffers); 5045bc3cb74SMauro Carvalho Chehab } else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || 5055bc3cb74SMauro Carvalho Chehab p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 5065bc3cb74SMauro Carvalho Chehab const struct v4l2_outputparm *c = &p->parm.output; 5075bc3cb74SMauro Carvalho Chehab 5085bc3cb74SMauro Carvalho Chehab pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, " 5095bc3cb74SMauro Carvalho Chehab "extendedmode=%d, writebuffers=%d\n", 5105bc3cb74SMauro Carvalho Chehab c->capability, c->outputmode, 5115bc3cb74SMauro Carvalho Chehab c->timeperframe.numerator, c->timeperframe.denominator, 5125bc3cb74SMauro Carvalho Chehab c->extendedmode, c->writebuffers); 513560dde24SHans Verkuil } else { 514560dde24SHans Verkuil pr_cont("\n"); 5155bc3cb74SMauro Carvalho Chehab } 5165bc3cb74SMauro Carvalho Chehab } 5175bc3cb74SMauro Carvalho Chehab 5185bc3cb74SMauro Carvalho Chehab static void v4l_print_queryctrl(const void *arg, bool write_only) 5195bc3cb74SMauro Carvalho Chehab { 5205bc3cb74SMauro Carvalho Chehab const struct v4l2_queryctrl *p = arg; 5215bc3cb74SMauro Carvalho Chehab 52227d5a87cSHans Verkuil pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, " 5235bc3cb74SMauro Carvalho Chehab "step=%d, default=%d, flags=0x%08x\n", 52427d5a87cSHans Verkuil p->id, p->type, (int)sizeof(p->name), p->name, 5255bc3cb74SMauro Carvalho Chehab p->minimum, p->maximum, 5265bc3cb74SMauro Carvalho Chehab p->step, p->default_value, p->flags); 5275bc3cb74SMauro Carvalho Chehab } 5285bc3cb74SMauro Carvalho Chehab 529e6bee368SHans Verkuil static void v4l_print_query_ext_ctrl(const void *arg, bool write_only) 530e6bee368SHans Verkuil { 531e6bee368SHans Verkuil const struct v4l2_query_ext_ctrl *p = arg; 532e6bee368SHans Verkuil 533e6bee368SHans Verkuil pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, " 534e6bee368SHans Verkuil "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, " 5350176077aSHans Verkuil "nr_of_dims=%u, dims=%u,%u,%u,%u\n", 536e6bee368SHans Verkuil p->id, p->type, (int)sizeof(p->name), p->name, 537e6bee368SHans Verkuil p->minimum, p->maximum, 538e6bee368SHans Verkuil p->step, p->default_value, p->flags, 539e6bee368SHans Verkuil p->elem_size, p->elems, p->nr_of_dims, 5400176077aSHans Verkuil p->dims[0], p->dims[1], p->dims[2], p->dims[3]); 541e6bee368SHans Verkuil } 542e6bee368SHans Verkuil 5435bc3cb74SMauro Carvalho Chehab static void v4l_print_querymenu(const void *arg, bool write_only) 5445bc3cb74SMauro Carvalho Chehab { 5455bc3cb74SMauro Carvalho Chehab const struct v4l2_querymenu *p = arg; 5465bc3cb74SMauro Carvalho Chehab 5475bc3cb74SMauro Carvalho Chehab pr_cont("id=0x%x, index=%d\n", p->id, p->index); 5485bc3cb74SMauro Carvalho Chehab } 5495bc3cb74SMauro Carvalho Chehab 5505bc3cb74SMauro Carvalho Chehab static void v4l_print_control(const void *arg, bool write_only) 5515bc3cb74SMauro Carvalho Chehab { 5525bc3cb74SMauro Carvalho Chehab const struct v4l2_control *p = arg; 5535bc3cb74SMauro Carvalho Chehab 5545bc3cb74SMauro Carvalho Chehab pr_cont("id=0x%x, value=%d\n", p->id, p->value); 5555bc3cb74SMauro Carvalho Chehab } 5565bc3cb74SMauro Carvalho Chehab 5575bc3cb74SMauro Carvalho Chehab static void v4l_print_ext_controls(const void *arg, bool write_only) 5585bc3cb74SMauro Carvalho Chehab { 5595bc3cb74SMauro Carvalho Chehab const struct v4l2_ext_controls *p = arg; 5605bc3cb74SMauro Carvalho Chehab int i; 5615bc3cb74SMauro Carvalho Chehab 5625bc3cb74SMauro Carvalho Chehab pr_cont("class=0x%x, count=%d, error_idx=%d", 5635bc3cb74SMauro Carvalho Chehab p->ctrl_class, p->count, p->error_idx); 5645bc3cb74SMauro Carvalho Chehab for (i = 0; i < p->count; i++) { 5655bc3cb74SMauro Carvalho Chehab if (p->controls[i].size) 5665bc3cb74SMauro Carvalho Chehab pr_cont(", id/val=0x%x/0x%x", 5675bc3cb74SMauro Carvalho Chehab p->controls[i].id, p->controls[i].value); 5685bc3cb74SMauro Carvalho Chehab else 5695bc3cb74SMauro Carvalho Chehab pr_cont(", id/size=0x%x/%u", 5705bc3cb74SMauro Carvalho Chehab p->controls[i].id, p->controls[i].size); 5715bc3cb74SMauro Carvalho Chehab } 5725bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 5735bc3cb74SMauro Carvalho Chehab } 5745bc3cb74SMauro Carvalho Chehab 5755bc3cb74SMauro Carvalho Chehab static void v4l_print_cropcap(const void *arg, bool write_only) 5765bc3cb74SMauro Carvalho Chehab { 5775bc3cb74SMauro Carvalho Chehab const struct v4l2_cropcap *p = arg; 5785bc3cb74SMauro Carvalho Chehab 5795bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, " 580a112fbafSHans Verkuil "defrect wxh=%dx%d, x,y=%d,%d, " 5815bc3cb74SMauro Carvalho Chehab "pixelaspect %d/%d\n", 5825bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 5835bc3cb74SMauro Carvalho Chehab p->bounds.width, p->bounds.height, 5845bc3cb74SMauro Carvalho Chehab p->bounds.left, p->bounds.top, 5855bc3cb74SMauro Carvalho Chehab p->defrect.width, p->defrect.height, 5865bc3cb74SMauro Carvalho Chehab p->defrect.left, p->defrect.top, 5875bc3cb74SMauro Carvalho Chehab p->pixelaspect.numerator, p->pixelaspect.denominator); 5885bc3cb74SMauro Carvalho Chehab } 5895bc3cb74SMauro Carvalho Chehab 5905bc3cb74SMauro Carvalho Chehab static void v4l_print_crop(const void *arg, bool write_only) 5915bc3cb74SMauro Carvalho Chehab { 5925bc3cb74SMauro Carvalho Chehab const struct v4l2_crop *p = arg; 5935bc3cb74SMauro Carvalho Chehab 5945bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n", 5955bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 5965bc3cb74SMauro Carvalho Chehab p->c.width, p->c.height, 5975bc3cb74SMauro Carvalho Chehab p->c.left, p->c.top); 5985bc3cb74SMauro Carvalho Chehab } 5995bc3cb74SMauro Carvalho Chehab 6005bc3cb74SMauro Carvalho Chehab static void v4l_print_selection(const void *arg, bool write_only) 6015bc3cb74SMauro Carvalho Chehab { 6025bc3cb74SMauro Carvalho Chehab const struct v4l2_selection *p = arg; 6035bc3cb74SMauro Carvalho Chehab 6045bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n", 6055bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 6065bc3cb74SMauro Carvalho Chehab p->target, p->flags, 6075bc3cb74SMauro Carvalho Chehab p->r.width, p->r.height, p->r.left, p->r.top); 6085bc3cb74SMauro Carvalho Chehab } 6095bc3cb74SMauro Carvalho Chehab 6105bc3cb74SMauro Carvalho Chehab static void v4l_print_jpegcompression(const void *arg, bool write_only) 6115bc3cb74SMauro Carvalho Chehab { 6125bc3cb74SMauro Carvalho Chehab const struct v4l2_jpegcompression *p = arg; 6135bc3cb74SMauro Carvalho Chehab 6145bc3cb74SMauro Carvalho Chehab pr_cont("quality=%d, APPn=%d, APP_len=%d, " 6155bc3cb74SMauro Carvalho Chehab "COM_len=%d, jpeg_markers=0x%x\n", 6165bc3cb74SMauro Carvalho Chehab p->quality, p->APPn, p->APP_len, 6175bc3cb74SMauro Carvalho Chehab p->COM_len, p->jpeg_markers); 6185bc3cb74SMauro Carvalho Chehab } 6195bc3cb74SMauro Carvalho Chehab 6205bc3cb74SMauro Carvalho Chehab static void v4l_print_enc_idx(const void *arg, bool write_only) 6215bc3cb74SMauro Carvalho Chehab { 6225bc3cb74SMauro Carvalho Chehab const struct v4l2_enc_idx *p = arg; 6235bc3cb74SMauro Carvalho Chehab 6245bc3cb74SMauro Carvalho Chehab pr_cont("entries=%d, entries_cap=%d\n", 6255bc3cb74SMauro Carvalho Chehab p->entries, p->entries_cap); 6265bc3cb74SMauro Carvalho Chehab } 6275bc3cb74SMauro Carvalho Chehab 6285bc3cb74SMauro Carvalho Chehab static void v4l_print_encoder_cmd(const void *arg, bool write_only) 6295bc3cb74SMauro Carvalho Chehab { 6305bc3cb74SMauro Carvalho Chehab const struct v4l2_encoder_cmd *p = arg; 6315bc3cb74SMauro Carvalho Chehab 6325bc3cb74SMauro Carvalho Chehab pr_cont("cmd=%d, flags=0x%x\n", 6335bc3cb74SMauro Carvalho Chehab p->cmd, p->flags); 6345bc3cb74SMauro Carvalho Chehab } 6355bc3cb74SMauro Carvalho Chehab 6365bc3cb74SMauro Carvalho Chehab static void v4l_print_decoder_cmd(const void *arg, bool write_only) 6375bc3cb74SMauro Carvalho Chehab { 6385bc3cb74SMauro Carvalho Chehab const struct v4l2_decoder_cmd *p = arg; 6395bc3cb74SMauro Carvalho Chehab 6405bc3cb74SMauro Carvalho Chehab pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags); 6415bc3cb74SMauro Carvalho Chehab 6425bc3cb74SMauro Carvalho Chehab if (p->cmd == V4L2_DEC_CMD_START) 6435bc3cb74SMauro Carvalho Chehab pr_info("speed=%d, format=%u\n", 6445bc3cb74SMauro Carvalho Chehab p->start.speed, p->start.format); 6455bc3cb74SMauro Carvalho Chehab else if (p->cmd == V4L2_DEC_CMD_STOP) 6465bc3cb74SMauro Carvalho Chehab pr_info("pts=%llu\n", p->stop.pts); 6475bc3cb74SMauro Carvalho Chehab } 6485bc3cb74SMauro Carvalho Chehab 64996b03d2aSHans Verkuil static void v4l_print_dbg_chip_info(const void *arg, bool write_only) 65079b0c640SHans Verkuil { 65196b03d2aSHans Verkuil const struct v4l2_dbg_chip_info *p = arg; 65279b0c640SHans Verkuil 65379b0c640SHans Verkuil pr_cont("type=%u, ", p->match.type); 6543eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) 65579b0c640SHans Verkuil pr_cont("name=%.*s, ", 65679b0c640SHans Verkuil (int)sizeof(p->match.name), p->match.name); 65779b0c640SHans Verkuil else 65879b0c640SHans Verkuil pr_cont("addr=%u, ", p->match.addr); 65979b0c640SHans Verkuil pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name); 66079b0c640SHans Verkuil } 66179b0c640SHans Verkuil 6625bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_register(const void *arg, bool write_only) 6635bc3cb74SMauro Carvalho Chehab { 6645bc3cb74SMauro Carvalho Chehab const struct v4l2_dbg_register *p = arg; 6655bc3cb74SMauro Carvalho Chehab 6665bc3cb74SMauro Carvalho Chehab pr_cont("type=%u, ", p->match.type); 6673eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) 66827d5a87cSHans Verkuil pr_cont("name=%.*s, ", 66927d5a87cSHans Verkuil (int)sizeof(p->match.name), p->match.name); 6705bc3cb74SMauro Carvalho Chehab else 6715bc3cb74SMauro Carvalho Chehab pr_cont("addr=%u, ", p->match.addr); 6725bc3cb74SMauro Carvalho Chehab pr_cont("reg=0x%llx, val=0x%llx\n", 6735bc3cb74SMauro Carvalho Chehab p->reg, p->val); 6745bc3cb74SMauro Carvalho Chehab } 6755bc3cb74SMauro Carvalho Chehab 6765bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings(const void *arg, bool write_only) 6775bc3cb74SMauro Carvalho Chehab { 6785bc3cb74SMauro Carvalho Chehab const struct v4l2_dv_timings *p = arg; 6795bc3cb74SMauro Carvalho Chehab 6805bc3cb74SMauro Carvalho Chehab switch (p->type) { 6815bc3cb74SMauro Carvalho Chehab case V4L2_DV_BT_656_1120: 6825bc3cb74SMauro Carvalho Chehab pr_cont("type=bt-656/1120, interlaced=%u, " 6835bc3cb74SMauro Carvalho Chehab "pixelclock=%llu, " 6845bc3cb74SMauro Carvalho Chehab "width=%u, height=%u, polarities=0x%x, " 6855bc3cb74SMauro Carvalho Chehab "hfrontporch=%u, hsync=%u, " 6865bc3cb74SMauro Carvalho Chehab "hbackporch=%u, vfrontporch=%u, " 6875bc3cb74SMauro Carvalho Chehab "vsync=%u, vbackporch=%u, " 6885bc3cb74SMauro Carvalho Chehab "il_vfrontporch=%u, il_vsync=%u, " 6895bc3cb74SMauro Carvalho Chehab "il_vbackporch=%u, standards=0x%x, flags=0x%x\n", 6905bc3cb74SMauro Carvalho Chehab p->bt.interlaced, p->bt.pixelclock, 6915bc3cb74SMauro Carvalho Chehab p->bt.width, p->bt.height, 6925bc3cb74SMauro Carvalho Chehab p->bt.polarities, p->bt.hfrontporch, 6935bc3cb74SMauro Carvalho Chehab p->bt.hsync, p->bt.hbackporch, 6945bc3cb74SMauro Carvalho Chehab p->bt.vfrontporch, p->bt.vsync, 6955bc3cb74SMauro Carvalho Chehab p->bt.vbackporch, p->bt.il_vfrontporch, 6965bc3cb74SMauro Carvalho Chehab p->bt.il_vsync, p->bt.il_vbackporch, 6975bc3cb74SMauro Carvalho Chehab p->bt.standards, p->bt.flags); 6985bc3cb74SMauro Carvalho Chehab break; 6995bc3cb74SMauro Carvalho Chehab default: 7005bc3cb74SMauro Carvalho Chehab pr_cont("type=%d\n", p->type); 7015bc3cb74SMauro Carvalho Chehab break; 7025bc3cb74SMauro Carvalho Chehab } 7035bc3cb74SMauro Carvalho Chehab } 7045bc3cb74SMauro Carvalho Chehab 7055bc3cb74SMauro Carvalho Chehab static void v4l_print_enum_dv_timings(const void *arg, bool write_only) 7065bc3cb74SMauro Carvalho Chehab { 7075bc3cb74SMauro Carvalho Chehab const struct v4l2_enum_dv_timings *p = arg; 7085bc3cb74SMauro Carvalho Chehab 7095bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, ", p->index); 7105bc3cb74SMauro Carvalho Chehab v4l_print_dv_timings(&p->timings, write_only); 7115bc3cb74SMauro Carvalho Chehab } 7125bc3cb74SMauro Carvalho Chehab 7135bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings_cap(const void *arg, bool write_only) 7145bc3cb74SMauro Carvalho Chehab { 7155bc3cb74SMauro Carvalho Chehab const struct v4l2_dv_timings_cap *p = arg; 7165bc3cb74SMauro Carvalho Chehab 7175bc3cb74SMauro Carvalho Chehab switch (p->type) { 7185bc3cb74SMauro Carvalho Chehab case V4L2_DV_BT_656_1120: 7195bc3cb74SMauro Carvalho Chehab pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, " 7205bc3cb74SMauro Carvalho Chehab "pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n", 7215bc3cb74SMauro Carvalho Chehab p->bt.min_width, p->bt.max_width, 7225bc3cb74SMauro Carvalho Chehab p->bt.min_height, p->bt.max_height, 7235bc3cb74SMauro Carvalho Chehab p->bt.min_pixelclock, p->bt.max_pixelclock, 7245bc3cb74SMauro Carvalho Chehab p->bt.standards, p->bt.capabilities); 7255bc3cb74SMauro Carvalho Chehab break; 7265bc3cb74SMauro Carvalho Chehab default: 7275bc3cb74SMauro Carvalho Chehab pr_cont("type=%u\n", p->type); 7285bc3cb74SMauro Carvalho Chehab break; 7295bc3cb74SMauro Carvalho Chehab } 7305bc3cb74SMauro Carvalho Chehab } 7315bc3cb74SMauro Carvalho Chehab 7325bc3cb74SMauro Carvalho Chehab static void v4l_print_frmsizeenum(const void *arg, bool write_only) 7335bc3cb74SMauro Carvalho Chehab { 7345bc3cb74SMauro Carvalho Chehab const struct v4l2_frmsizeenum *p = arg; 7355bc3cb74SMauro Carvalho Chehab 7365bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u", 7375bc3cb74SMauro Carvalho Chehab p->index, 7385bc3cb74SMauro Carvalho Chehab (p->pixel_format & 0xff), 7395bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 8) & 0xff, 7405bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 16) & 0xff, 7415bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 24) & 0xff, 7425bc3cb74SMauro Carvalho Chehab p->type); 7435bc3cb74SMauro Carvalho Chehab switch (p->type) { 7445bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_DISCRETE: 745560dde24SHans Verkuil pr_cont(", wxh=%ux%u\n", 7465bc3cb74SMauro Carvalho Chehab p->discrete.width, p->discrete.height); 7475bc3cb74SMauro Carvalho Chehab break; 7485bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_STEPWISE: 749560dde24SHans Verkuil pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n", 7505bc3cb74SMauro Carvalho Chehab p->stepwise.min_width, p->stepwise.min_height, 7515bc3cb74SMauro Carvalho Chehab p->stepwise.step_width, p->stepwise.step_height, 7525bc3cb74SMauro Carvalho Chehab p->stepwise.max_width, p->stepwise.max_height); 7535bc3cb74SMauro Carvalho Chehab break; 7545bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_CONTINUOUS: 7555bc3cb74SMauro Carvalho Chehab /* fall through */ 7565bc3cb74SMauro Carvalho Chehab default: 7575bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 7585bc3cb74SMauro Carvalho Chehab break; 7595bc3cb74SMauro Carvalho Chehab } 7605bc3cb74SMauro Carvalho Chehab } 7615bc3cb74SMauro Carvalho Chehab 7625bc3cb74SMauro Carvalho Chehab static void v4l_print_frmivalenum(const void *arg, bool write_only) 7635bc3cb74SMauro Carvalho Chehab { 7645bc3cb74SMauro Carvalho Chehab const struct v4l2_frmivalenum *p = arg; 7655bc3cb74SMauro Carvalho Chehab 7665bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u", 7675bc3cb74SMauro Carvalho Chehab p->index, 7685bc3cb74SMauro Carvalho Chehab (p->pixel_format & 0xff), 7695bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 8) & 0xff, 7705bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 16) & 0xff, 7715bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 24) & 0xff, 7725bc3cb74SMauro Carvalho Chehab p->width, p->height, p->type); 7735bc3cb74SMauro Carvalho Chehab switch (p->type) { 7745bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_DISCRETE: 775560dde24SHans Verkuil pr_cont(", fps=%d/%d\n", 7765bc3cb74SMauro Carvalho Chehab p->discrete.numerator, 7775bc3cb74SMauro Carvalho Chehab p->discrete.denominator); 7785bc3cb74SMauro Carvalho Chehab break; 7795bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_STEPWISE: 780560dde24SHans Verkuil pr_cont(", min=%d/%d, max=%d/%d, step=%d/%d\n", 7815bc3cb74SMauro Carvalho Chehab p->stepwise.min.numerator, 7825bc3cb74SMauro Carvalho Chehab p->stepwise.min.denominator, 7835bc3cb74SMauro Carvalho Chehab p->stepwise.max.numerator, 7845bc3cb74SMauro Carvalho Chehab p->stepwise.max.denominator, 7855bc3cb74SMauro Carvalho Chehab p->stepwise.step.numerator, 7865bc3cb74SMauro Carvalho Chehab p->stepwise.step.denominator); 7875bc3cb74SMauro Carvalho Chehab break; 7885bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_CONTINUOUS: 7895bc3cb74SMauro Carvalho Chehab /* fall through */ 7905bc3cb74SMauro Carvalho Chehab default: 7915bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 7925bc3cb74SMauro Carvalho Chehab break; 7935bc3cb74SMauro Carvalho Chehab } 7945bc3cb74SMauro Carvalho Chehab } 7955bc3cb74SMauro Carvalho Chehab 7965bc3cb74SMauro Carvalho Chehab static void v4l_print_event(const void *arg, bool write_only) 7975bc3cb74SMauro Carvalho Chehab { 7985bc3cb74SMauro Carvalho Chehab const struct v4l2_event *p = arg; 7995bc3cb74SMauro Carvalho Chehab const struct v4l2_event_ctrl *c; 8005bc3cb74SMauro Carvalho Chehab 8015bc3cb74SMauro Carvalho Chehab pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, " 8025bc3cb74SMauro Carvalho Chehab "timestamp=%lu.%9.9lu\n", 8035bc3cb74SMauro Carvalho Chehab p->type, p->pending, p->sequence, p->id, 8045bc3cb74SMauro Carvalho Chehab p->timestamp.tv_sec, p->timestamp.tv_nsec); 8055bc3cb74SMauro Carvalho Chehab switch (p->type) { 8065bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_VSYNC: 8075bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "field=%s\n", 8085bc3cb74SMauro Carvalho Chehab prt_names(p->u.vsync.field, v4l2_field_names)); 8095bc3cb74SMauro Carvalho Chehab break; 8105bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_CTRL: 8115bc3cb74SMauro Carvalho Chehab c = &p->u.ctrl; 8125bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "changes=0x%x, type=%u, ", 8135bc3cb74SMauro Carvalho Chehab c->changes, c->type); 8145bc3cb74SMauro Carvalho Chehab if (c->type == V4L2_CTRL_TYPE_INTEGER64) 8155bc3cb74SMauro Carvalho Chehab pr_cont("value64=%lld, ", c->value64); 8165bc3cb74SMauro Carvalho Chehab else 8175bc3cb74SMauro Carvalho Chehab pr_cont("value=%d, ", c->value); 8185bc3cb74SMauro Carvalho Chehab pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, " 8195bc3cb74SMauro Carvalho Chehab "default_value=%d\n", 8205bc3cb74SMauro Carvalho Chehab c->flags, c->minimum, c->maximum, 8215bc3cb74SMauro Carvalho Chehab c->step, c->default_value); 8225bc3cb74SMauro Carvalho Chehab break; 8235bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_FRAME_SYNC: 8245bc3cb74SMauro Carvalho Chehab pr_cont("frame_sequence=%u\n", 8255bc3cb74SMauro Carvalho Chehab p->u.frame_sync.frame_sequence); 8265bc3cb74SMauro Carvalho Chehab break; 8275bc3cb74SMauro Carvalho Chehab } 8285bc3cb74SMauro Carvalho Chehab } 8295bc3cb74SMauro Carvalho Chehab 8305bc3cb74SMauro Carvalho Chehab static void v4l_print_event_subscription(const void *arg, bool write_only) 8315bc3cb74SMauro Carvalho Chehab { 8325bc3cb74SMauro Carvalho Chehab const struct v4l2_event_subscription *p = arg; 8335bc3cb74SMauro Carvalho Chehab 8345bc3cb74SMauro Carvalho Chehab pr_cont("type=0x%x, id=0x%x, flags=0x%x\n", 8355bc3cb74SMauro Carvalho Chehab p->type, p->id, p->flags); 8365bc3cb74SMauro Carvalho Chehab } 8375bc3cb74SMauro Carvalho Chehab 8385bc3cb74SMauro Carvalho Chehab static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only) 8395bc3cb74SMauro Carvalho Chehab { 8405bc3cb74SMauro Carvalho Chehab const struct v4l2_sliced_vbi_cap *p = arg; 8415bc3cb74SMauro Carvalho Chehab int i; 8425bc3cb74SMauro Carvalho Chehab 8435bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, service_set=0x%08x\n", 8445bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), p->service_set); 8455bc3cb74SMauro Carvalho Chehab for (i = 0; i < 24; i++) 8465bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, 8475bc3cb74SMauro Carvalho Chehab p->service_lines[0][i], 8485bc3cb74SMauro Carvalho Chehab p->service_lines[1][i]); 8495bc3cb74SMauro Carvalho Chehab } 8505bc3cb74SMauro Carvalho Chehab 8515bc3cb74SMauro Carvalho Chehab static void v4l_print_freq_band(const void *arg, bool write_only) 8525bc3cb74SMauro Carvalho Chehab { 8535bc3cb74SMauro Carvalho Chehab const struct v4l2_frequency_band *p = arg; 8545bc3cb74SMauro Carvalho Chehab 8555bc3cb74SMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, " 8565bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, modulation=0x%x\n", 8575bc3cb74SMauro Carvalho Chehab p->tuner, p->type, p->index, 8585bc3cb74SMauro Carvalho Chehab p->capability, p->rangelow, 8595bc3cb74SMauro Carvalho Chehab p->rangehigh, p->modulation); 8605bc3cb74SMauro Carvalho Chehab } 8615bc3cb74SMauro Carvalho Chehab 862dd519bb3SHans Verkuil static void v4l_print_edid(const void *arg, bool write_only) 863dd519bb3SHans Verkuil { 864dd519bb3SHans Verkuil const struct v4l2_edid *p = arg; 865dd519bb3SHans Verkuil 866dd519bb3SHans Verkuil pr_cont("pad=%u, start_block=%u, blocks=%u\n", 867dd519bb3SHans Verkuil p->pad, p->start_block, p->blocks); 868dd519bb3SHans Verkuil } 869dd519bb3SHans Verkuil 8705bc3cb74SMauro Carvalho Chehab static void v4l_print_u32(const void *arg, bool write_only) 8715bc3cb74SMauro Carvalho Chehab { 8725bc3cb74SMauro Carvalho Chehab pr_cont("value=%u\n", *(const u32 *)arg); 8735bc3cb74SMauro Carvalho Chehab } 8745bc3cb74SMauro Carvalho Chehab 8755bc3cb74SMauro Carvalho Chehab static void v4l_print_newline(const void *arg, bool write_only) 8765bc3cb74SMauro Carvalho Chehab { 8775bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 8785bc3cb74SMauro Carvalho Chehab } 8795bc3cb74SMauro Carvalho Chehab 8805bc3cb74SMauro Carvalho Chehab static void v4l_print_default(const void *arg, bool write_only) 8815bc3cb74SMauro Carvalho Chehab { 8825bc3cb74SMauro Carvalho Chehab pr_cont("driver-specific ioctl\n"); 8835bc3cb74SMauro Carvalho Chehab } 8845bc3cb74SMauro Carvalho Chehab 8855bc3cb74SMauro Carvalho Chehab static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) 8865bc3cb74SMauro Carvalho Chehab { 8875bc3cb74SMauro Carvalho Chehab __u32 i; 8885bc3cb74SMauro Carvalho Chehab 8895bc3cb74SMauro Carvalho Chehab /* zero the reserved fields */ 8905bc3cb74SMauro Carvalho Chehab c->reserved[0] = c->reserved[1] = 0; 8915bc3cb74SMauro Carvalho Chehab for (i = 0; i < c->count; i++) 8925bc3cb74SMauro Carvalho Chehab c->controls[i].reserved2[0] = 0; 8935bc3cb74SMauro Carvalho Chehab 8945bc3cb74SMauro Carvalho Chehab /* V4L2_CID_PRIVATE_BASE cannot be used as control class 8955bc3cb74SMauro Carvalho Chehab when using extended controls. 8965bc3cb74SMauro Carvalho Chehab Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL 8975bc3cb74SMauro Carvalho Chehab is it allowed for backwards compatibility. 8985bc3cb74SMauro Carvalho Chehab */ 8995bc3cb74SMauro Carvalho Chehab if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE) 9005bc3cb74SMauro Carvalho Chehab return 0; 9015bc3cb74SMauro Carvalho Chehab /* Check that all controls are from the same control class. */ 9025bc3cb74SMauro Carvalho Chehab for (i = 0; i < c->count; i++) { 9035bc3cb74SMauro Carvalho Chehab if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) { 9045bc3cb74SMauro Carvalho Chehab c->error_idx = i; 9055bc3cb74SMauro Carvalho Chehab return 0; 9065bc3cb74SMauro Carvalho Chehab } 9075bc3cb74SMauro Carvalho Chehab } 9085bc3cb74SMauro Carvalho Chehab return 1; 9095bc3cb74SMauro Carvalho Chehab } 9105bc3cb74SMauro Carvalho Chehab 9114b20259fSHans Verkuil static int check_fmt(struct file *file, enum v4l2_buf_type type) 9125bc3cb74SMauro Carvalho Chehab { 9134b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 9144b20259fSHans Verkuil const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 9154b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 9164b20259fSHans Verkuil bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI; 917582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 9184b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 9194b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 9204b20259fSHans Verkuil 9215bc3cb74SMauro Carvalho Chehab if (ops == NULL) 9225bc3cb74SMauro Carvalho Chehab return -EINVAL; 9235bc3cb74SMauro Carvalho Chehab 9245bc3cb74SMauro Carvalho Chehab switch (type) { 9255bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 9264b20259fSHans Verkuil if (is_vid && is_rx && 9274b20259fSHans Verkuil (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane)) 9285bc3cb74SMauro Carvalho Chehab return 0; 9295bc3cb74SMauro Carvalho Chehab break; 9305bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 9314b20259fSHans Verkuil if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) 9325bc3cb74SMauro Carvalho Chehab return 0; 9335bc3cb74SMauro Carvalho Chehab break; 9345bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 9354b20259fSHans Verkuil if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay) 9365bc3cb74SMauro Carvalho Chehab return 0; 9375bc3cb74SMauro Carvalho Chehab break; 9385bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 9394b20259fSHans Verkuil if (is_vid && is_tx && 9404b20259fSHans Verkuil (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane)) 9415bc3cb74SMauro Carvalho Chehab return 0; 9425bc3cb74SMauro Carvalho Chehab break; 9435bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 9444b20259fSHans Verkuil if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane) 9455bc3cb74SMauro Carvalho Chehab return 0; 9465bc3cb74SMauro Carvalho Chehab break; 9475bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 9484b20259fSHans Verkuil if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay) 9495bc3cb74SMauro Carvalho Chehab return 0; 9505bc3cb74SMauro Carvalho Chehab break; 9515bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_CAPTURE: 9524b20259fSHans Verkuil if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap) 9535bc3cb74SMauro Carvalho Chehab return 0; 9545bc3cb74SMauro Carvalho Chehab break; 9555bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 9564b20259fSHans Verkuil if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out) 9575bc3cb74SMauro Carvalho Chehab return 0; 9585bc3cb74SMauro Carvalho Chehab break; 9595bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 9604b20259fSHans Verkuil if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap) 9615bc3cb74SMauro Carvalho Chehab return 0; 9625bc3cb74SMauro Carvalho Chehab break; 9635bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 9644b20259fSHans Verkuil if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out) 9655bc3cb74SMauro Carvalho Chehab return 0; 9665bc3cb74SMauro Carvalho Chehab break; 967582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 968582c52cbSAntti Palosaari if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap) 969582c52cbSAntti Palosaari return 0; 970582c52cbSAntti Palosaari break; 971633c98e5SHans Verkuil default: 9725bc3cb74SMauro Carvalho Chehab break; 9735bc3cb74SMauro Carvalho Chehab } 9745bc3cb74SMauro Carvalho Chehab return -EINVAL; 9755bc3cb74SMauro Carvalho Chehab } 9765bc3cb74SMauro Carvalho Chehab 977d52e2381SLaurent Pinchart static void v4l_sanitize_format(struct v4l2_format *fmt) 978d52e2381SLaurent Pinchart { 979d52e2381SLaurent Pinchart unsigned int offset; 980d52e2381SLaurent Pinchart 981d52e2381SLaurent Pinchart /* 982d52e2381SLaurent Pinchart * The v4l2_pix_format structure has been extended with fields that were 983d52e2381SLaurent Pinchart * not previously required to be set to zero by applications. The priv 984d52e2381SLaurent Pinchart * field, when set to a magic value, indicates the the extended fields 985d52e2381SLaurent Pinchart * are valid. Otherwise they will contain undefined values. To simplify 986d52e2381SLaurent Pinchart * the API towards drivers zero the extended fields and set the priv 987d52e2381SLaurent Pinchart * field to the magic value when the extended pixel format structure 988d52e2381SLaurent Pinchart * isn't used by applications. 989d52e2381SLaurent Pinchart */ 990d52e2381SLaurent Pinchart 991d52e2381SLaurent Pinchart if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 992d52e2381SLaurent Pinchart fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 993d52e2381SLaurent Pinchart return; 994d52e2381SLaurent Pinchart 995d52e2381SLaurent Pinchart if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) 996d52e2381SLaurent Pinchart return; 997d52e2381SLaurent Pinchart 998d52e2381SLaurent Pinchart fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 999d52e2381SLaurent Pinchart 1000d52e2381SLaurent Pinchart offset = offsetof(struct v4l2_pix_format, priv) 1001d52e2381SLaurent Pinchart + sizeof(fmt->fmt.pix.priv); 1002d52e2381SLaurent Pinchart memset(((void *)&fmt->fmt.pix) + offset, 0, 1003d52e2381SLaurent Pinchart sizeof(fmt->fmt.pix) - offset); 1004d52e2381SLaurent Pinchart } 1005d52e2381SLaurent Pinchart 10065bc3cb74SMauro Carvalho Chehab static int v4l_querycap(const struct v4l2_ioctl_ops *ops, 10075bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10085bc3cb74SMauro Carvalho Chehab { 10095bc3cb74SMauro Carvalho Chehab struct v4l2_capability *cap = (struct v4l2_capability *)arg; 1010d52e2381SLaurent Pinchart int ret; 10115bc3cb74SMauro Carvalho Chehab 10125bc3cb74SMauro Carvalho Chehab cap->version = LINUX_VERSION_CODE; 1013d52e2381SLaurent Pinchart 1014d52e2381SLaurent Pinchart ret = ops->vidioc_querycap(file, fh, cap); 1015d52e2381SLaurent Pinchart 1016d52e2381SLaurent Pinchart cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; 1017796a2bd2SHans Verkuil cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; 1018d52e2381SLaurent Pinchart 1019d52e2381SLaurent Pinchart return ret; 10205bc3cb74SMauro Carvalho Chehab } 10215bc3cb74SMauro Carvalho Chehab 10225bc3cb74SMauro Carvalho Chehab static int v4l_s_input(const struct v4l2_ioctl_ops *ops, 10235bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10245bc3cb74SMauro Carvalho Chehab { 10255bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); 10265bc3cb74SMauro Carvalho Chehab } 10275bc3cb74SMauro Carvalho Chehab 10285bc3cb74SMauro Carvalho Chehab static int v4l_s_output(const struct v4l2_ioctl_ops *ops, 10295bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10305bc3cb74SMauro Carvalho Chehab { 10315bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); 10325bc3cb74SMauro Carvalho Chehab } 10335bc3cb74SMauro Carvalho Chehab 10345bc3cb74SMauro Carvalho Chehab static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, 10355bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10365bc3cb74SMauro Carvalho Chehab { 10375bc3cb74SMauro Carvalho Chehab struct video_device *vfd; 10385bc3cb74SMauro Carvalho Chehab u32 *p = arg; 10395bc3cb74SMauro Carvalho Chehab 10405bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_priority) 10415bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_priority(file, fh, arg); 10425bc3cb74SMauro Carvalho Chehab vfd = video_devdata(file); 10435bc3cb74SMauro Carvalho Chehab *p = v4l2_prio_max(&vfd->v4l2_dev->prio); 10445bc3cb74SMauro Carvalho Chehab return 0; 10455bc3cb74SMauro Carvalho Chehab } 10465bc3cb74SMauro Carvalho Chehab 10475bc3cb74SMauro Carvalho Chehab static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, 10485bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10495bc3cb74SMauro Carvalho Chehab { 10505bc3cb74SMauro Carvalho Chehab struct video_device *vfd; 10515bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh; 10525bc3cb74SMauro Carvalho Chehab u32 *p = arg; 10535bc3cb74SMauro Carvalho Chehab 10545bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_priority) 10555bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_priority(file, fh, *p); 10565bc3cb74SMauro Carvalho Chehab vfd = video_devdata(file); 10575bc3cb74SMauro Carvalho Chehab vfh = file->private_data; 10585bc3cb74SMauro Carvalho Chehab return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p); 10595bc3cb74SMauro Carvalho Chehab } 10605bc3cb74SMauro Carvalho Chehab 10615bc3cb74SMauro Carvalho Chehab static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, 10625bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10635bc3cb74SMauro Carvalho Chehab { 106473f35418SHans Verkuil struct video_device *vfd = video_devdata(file); 10655bc3cb74SMauro Carvalho Chehab struct v4l2_input *p = arg; 10665bc3cb74SMauro Carvalho Chehab 10675bc3cb74SMauro Carvalho Chehab /* 106802fa6282SHans Verkuil * We set the flags for CAP_DV_TIMINGS & 10695bc3cb74SMauro Carvalho Chehab * CAP_STD here based on ioctl handler provided by the 10705bc3cb74SMauro Carvalho Chehab * driver. If the driver doesn't support these 10715bc3cb74SMauro Carvalho Chehab * for a specific input, it must override these flags. 10725bc3cb74SMauro Carvalho Chehab */ 107373f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_S_STD)) 10745bc3cb74SMauro Carvalho Chehab p->capabilities |= V4L2_IN_CAP_STD; 10755bc3cb74SMauro Carvalho Chehab 10765bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_input(file, fh, p); 10775bc3cb74SMauro Carvalho Chehab } 10785bc3cb74SMauro Carvalho Chehab 10795bc3cb74SMauro Carvalho Chehab static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, 10805bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10815bc3cb74SMauro Carvalho Chehab { 108273f35418SHans Verkuil struct video_device *vfd = video_devdata(file); 10835bc3cb74SMauro Carvalho Chehab struct v4l2_output *p = arg; 10845bc3cb74SMauro Carvalho Chehab 10855bc3cb74SMauro Carvalho Chehab /* 108602fa6282SHans Verkuil * We set the flags for CAP_DV_TIMINGS & 10875bc3cb74SMauro Carvalho Chehab * CAP_STD here based on ioctl handler provided by the 10885bc3cb74SMauro Carvalho Chehab * driver. If the driver doesn't support these 10895bc3cb74SMauro Carvalho Chehab * for a specific output, it must override these flags. 10905bc3cb74SMauro Carvalho Chehab */ 109173f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_S_STD)) 10925bc3cb74SMauro Carvalho Chehab p->capabilities |= V4L2_OUT_CAP_STD; 10935bc3cb74SMauro Carvalho Chehab 10945bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_output(file, fh, p); 10955bc3cb74SMauro Carvalho Chehab } 10965bc3cb74SMauro Carvalho Chehab 10975bc3cb74SMauro Carvalho Chehab static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, 10985bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10995bc3cb74SMauro Carvalho Chehab { 11005bc3cb74SMauro Carvalho Chehab struct v4l2_fmtdesc *p = arg; 11014b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 1102ce71bbc9SHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1103ce71bbc9SHans Verkuil bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 11044b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 11054b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 11065bc3cb74SMauro Carvalho Chehab 11075bc3cb74SMauro Carvalho Chehab switch (p->type) { 11085bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1109ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap)) 11105bc3cb74SMauro Carvalho Chehab break; 11115bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_fmt_vid_cap(file, fh, arg); 11125bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 1113ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane)) 11145bc3cb74SMauro Carvalho Chehab break; 11155bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); 11165bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1117ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay)) 11185bc3cb74SMauro Carvalho Chehab break; 11195bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); 11205bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1121ce71bbc9SHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out)) 11225bc3cb74SMauro Carvalho Chehab break; 11235bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_fmt_vid_out(file, fh, arg); 11245bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 1125ce71bbc9SHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane)) 11265bc3cb74SMauro Carvalho Chehab break; 11275bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); 1128582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1129ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap)) 1130582c52cbSAntti Palosaari break; 1131582c52cbSAntti Palosaari return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); 11325bc3cb74SMauro Carvalho Chehab } 11335bc3cb74SMauro Carvalho Chehab return -EINVAL; 11345bc3cb74SMauro Carvalho Chehab } 11355bc3cb74SMauro Carvalho Chehab 11365bc3cb74SMauro Carvalho Chehab static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, 11375bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 11385bc3cb74SMauro Carvalho Chehab { 11395bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 11404b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 11414b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1142582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 11434b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 11444b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1145d52e2381SLaurent Pinchart int ret; 1146d52e2381SLaurent Pinchart 1147e5ce558aSHans Verkuil /* 1148e5ce558aSHans Verkuil * fmt can't be cleared for these overlay types due to the 'clips' 1149e5ce558aSHans Verkuil * 'clipcount' and 'bitmap' pointers in struct v4l2_window. 1150e5ce558aSHans Verkuil * Those are provided by the user. So handle these two overlay types 1151e5ce558aSHans Verkuil * first, and then just do a simple memset for the other types. 1152e5ce558aSHans Verkuil */ 1153e5ce558aSHans Verkuil switch (p->type) { 1154e5ce558aSHans Verkuil case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1155e5ce558aSHans Verkuil case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { 11564d1afa51SHans Verkuil struct v4l2_clip __user *clips = p->fmt.win.clips; 1157e5ce558aSHans Verkuil u32 clipcount = p->fmt.win.clipcount; 11584d1afa51SHans Verkuil void __user *bitmap = p->fmt.win.bitmap; 1159e5ce558aSHans Verkuil 1160e5ce558aSHans Verkuil memset(&p->fmt, 0, sizeof(p->fmt)); 1161e5ce558aSHans Verkuil p->fmt.win.clips = clips; 1162e5ce558aSHans Verkuil p->fmt.win.clipcount = clipcount; 1163e5ce558aSHans Verkuil p->fmt.win.bitmap = bitmap; 1164e5ce558aSHans Verkuil break; 1165e5ce558aSHans Verkuil } 1166e5ce558aSHans Verkuil default: 1167e5ce558aSHans Verkuil memset(&p->fmt, 0, sizeof(p->fmt)); 1168e5ce558aSHans Verkuil break; 1169e5ce558aSHans Verkuil } 1170e5ce558aSHans Verkuil 11715bc3cb74SMauro Carvalho Chehab switch (p->type) { 11725bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 11734b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) 11745bc3cb74SMauro Carvalho Chehab break; 117548f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1176d52e2381SLaurent Pinchart ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); 117748f2650aSHans Verkuil /* just in case the driver zeroed it again */ 1178d52e2381SLaurent Pinchart p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1179d52e2381SLaurent Pinchart return ret; 11805bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 11814b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) 11825bc3cb74SMauro Carvalho Chehab break; 11835bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); 11845bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 11854b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay)) 11865bc3cb74SMauro Carvalho Chehab break; 11875bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); 11884b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 11894b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap)) 11904b20259fSHans Verkuil break; 11914b20259fSHans Verkuil return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); 11924b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 11934b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap)) 11944b20259fSHans Verkuil break; 11954b20259fSHans Verkuil return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); 11965bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 11974b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) 11985bc3cb74SMauro Carvalho Chehab break; 119948f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1200d52e2381SLaurent Pinchart ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); 120148f2650aSHans Verkuil /* just in case the driver zeroed it again */ 1202d52e2381SLaurent Pinchart p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1203d52e2381SLaurent Pinchart return ret; 12045bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 12054b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) 12065bc3cb74SMauro Carvalho Chehab break; 12075bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); 12085bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 12094b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay)) 12105bc3cb74SMauro Carvalho Chehab break; 12115bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); 12125bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 12134b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out)) 12145bc3cb74SMauro Carvalho Chehab break; 12155bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vbi_out(file, fh, arg); 12165bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 12174b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out)) 12185bc3cb74SMauro Carvalho Chehab break; 12195bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); 1220582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1221582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap)) 1222582c52cbSAntti Palosaari break; 1223582c52cbSAntti Palosaari return ops->vidioc_g_fmt_sdr_cap(file, fh, arg); 12245bc3cb74SMauro Carvalho Chehab } 12255bc3cb74SMauro Carvalho Chehab return -EINVAL; 12265bc3cb74SMauro Carvalho Chehab } 12275bc3cb74SMauro Carvalho Chehab 12285bc3cb74SMauro Carvalho Chehab static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, 12295bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 12305bc3cb74SMauro Carvalho Chehab { 12315bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 12324b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 12334b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1234582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 12354b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 12364b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 123748f2650aSHans Verkuil int ret; 12385bc3cb74SMauro Carvalho Chehab 1239d52e2381SLaurent Pinchart v4l_sanitize_format(p); 1240d52e2381SLaurent Pinchart 12415bc3cb74SMauro Carvalho Chehab switch (p->type) { 12425bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 12434b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) 12445bc3cb74SMauro Carvalho Chehab break; 12455bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 124648f2650aSHans Verkuil ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); 124748f2650aSHans Verkuil /* just in case the driver zeroed it again */ 124848f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 124948f2650aSHans Verkuil return ret; 12505bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 12514b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) 12525bc3cb74SMauro Carvalho Chehab break; 12535bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 12545bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); 12555bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 12564b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay)) 12575bc3cb74SMauro Carvalho Chehab break; 12585bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 12595bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); 12604b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 12614b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap)) 12624b20259fSHans Verkuil break; 12634b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.vbi); 12644b20259fSHans Verkuil return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); 12654b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 12664b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap)) 12674b20259fSHans Verkuil break; 12684b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.sliced); 12694b20259fSHans Verkuil return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); 12705bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 12714b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out)) 12725bc3cb74SMauro Carvalho Chehab break; 12735bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 127448f2650aSHans Verkuil ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); 127548f2650aSHans Verkuil /* just in case the driver zeroed it again */ 127648f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 127748f2650aSHans Verkuil return ret; 12785bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 12794b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane)) 12805bc3cb74SMauro Carvalho Chehab break; 12815bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 12825bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); 12835bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 12844b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay)) 12855bc3cb74SMauro Carvalho Chehab break; 12865bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 12875bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); 12885bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 12894b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out)) 12905bc3cb74SMauro Carvalho Chehab break; 12915bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.vbi); 12925bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vbi_out(file, fh, arg); 12935bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 12944b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out)) 12955bc3cb74SMauro Carvalho Chehab break; 12965bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.sliced); 12975bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); 1298582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1299582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap)) 1300582c52cbSAntti Palosaari break; 1301582c52cbSAntti Palosaari CLEAR_AFTER_FIELD(p, fmt.sdr); 1302582c52cbSAntti Palosaari return ops->vidioc_s_fmt_sdr_cap(file, fh, arg); 13035bc3cb74SMauro Carvalho Chehab } 13045bc3cb74SMauro Carvalho Chehab return -EINVAL; 13055bc3cb74SMauro Carvalho Chehab } 13065bc3cb74SMauro Carvalho Chehab 13075bc3cb74SMauro Carvalho Chehab static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, 13085bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 13095bc3cb74SMauro Carvalho Chehab { 13105bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 13114b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 13124b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1313582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 13144b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 13154b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 131648f2650aSHans Verkuil int ret; 13175bc3cb74SMauro Carvalho Chehab 1318d52e2381SLaurent Pinchart v4l_sanitize_format(p); 1319d52e2381SLaurent Pinchart 13205bc3cb74SMauro Carvalho Chehab switch (p->type) { 13215bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 13224b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) 13235bc3cb74SMauro Carvalho Chehab break; 13245bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 132548f2650aSHans Verkuil ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); 132648f2650aSHans Verkuil /* just in case the driver zeroed it again */ 132748f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 132848f2650aSHans Verkuil return ret; 13295bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 13304b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane)) 13315bc3cb74SMauro Carvalho Chehab break; 13325bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 13335bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); 13345bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 13354b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay)) 13365bc3cb74SMauro Carvalho Chehab break; 13375bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 13385bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); 13394b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 13404b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap)) 13414b20259fSHans Verkuil break; 13424b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.vbi); 13434b20259fSHans Verkuil return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); 13444b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 13454b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap)) 13464b20259fSHans Verkuil break; 13474b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.sliced); 13484b20259fSHans Verkuil return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); 13495bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 13504b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out)) 13515bc3cb74SMauro Carvalho Chehab break; 13525bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 135348f2650aSHans Verkuil ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); 135448f2650aSHans Verkuil /* just in case the driver zeroed it again */ 135548f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 135648f2650aSHans Verkuil return ret; 13575bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 13584b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane)) 13595bc3cb74SMauro Carvalho Chehab break; 13605bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 13615bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); 13625bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 13634b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay)) 13645bc3cb74SMauro Carvalho Chehab break; 13655bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 13665bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); 13675bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 13684b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out)) 13695bc3cb74SMauro Carvalho Chehab break; 13705bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.vbi); 13715bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vbi_out(file, fh, arg); 13725bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 13734b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out)) 13745bc3cb74SMauro Carvalho Chehab break; 13755bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.sliced); 13765bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); 1377582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1378582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap)) 1379582c52cbSAntti Palosaari break; 1380582c52cbSAntti Palosaari CLEAR_AFTER_FIELD(p, fmt.sdr); 1381582c52cbSAntti Palosaari return ops->vidioc_try_fmt_sdr_cap(file, fh, arg); 13825bc3cb74SMauro Carvalho Chehab } 13835bc3cb74SMauro Carvalho Chehab return -EINVAL; 13845bc3cb74SMauro Carvalho Chehab } 13855bc3cb74SMauro Carvalho Chehab 13865bc3cb74SMauro Carvalho Chehab static int v4l_streamon(const struct v4l2_ioctl_ops *ops, 13875bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 13885bc3cb74SMauro Carvalho Chehab { 13895bc3cb74SMauro Carvalho Chehab return ops->vidioc_streamon(file, fh, *(unsigned int *)arg); 13905bc3cb74SMauro Carvalho Chehab } 13915bc3cb74SMauro Carvalho Chehab 13925bc3cb74SMauro Carvalho Chehab static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, 13935bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 13945bc3cb74SMauro Carvalho Chehab { 13955bc3cb74SMauro Carvalho Chehab return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); 13965bc3cb74SMauro Carvalho Chehab } 13975bc3cb74SMauro Carvalho Chehab 13985bc3cb74SMauro Carvalho Chehab static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, 13995bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14005bc3cb74SMauro Carvalho Chehab { 14015bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 14025bc3cb74SMauro Carvalho Chehab struct v4l2_tuner *p = arg; 14035bc3cb74SMauro Carvalho Chehab int err; 14045bc3cb74SMauro Carvalho Chehab 14055bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 14065bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 14075bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_tuner(file, fh, p); 14085bc3cb74SMauro Carvalho Chehab if (!err) 14095bc3cb74SMauro Carvalho Chehab p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; 14105bc3cb74SMauro Carvalho Chehab return err; 14115bc3cb74SMauro Carvalho Chehab } 14125bc3cb74SMauro Carvalho Chehab 14135bc3cb74SMauro Carvalho Chehab static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, 14145bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14155bc3cb74SMauro Carvalho Chehab { 14165bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 14175bc3cb74SMauro Carvalho Chehab struct v4l2_tuner *p = arg; 14185bc3cb74SMauro Carvalho Chehab 14195bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 14205bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 14215bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_tuner(file, fh, p); 14225bc3cb74SMauro Carvalho Chehab } 14235bc3cb74SMauro Carvalho Chehab 14245bc3cb74SMauro Carvalho Chehab static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, 14255bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14265bc3cb74SMauro Carvalho Chehab { 14275bc3cb74SMauro Carvalho Chehab struct v4l2_modulator *p = arg; 14285bc3cb74SMauro Carvalho Chehab int err; 14295bc3cb74SMauro Carvalho Chehab 14305bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_modulator(file, fh, p); 14315bc3cb74SMauro Carvalho Chehab if (!err) 14325bc3cb74SMauro Carvalho Chehab p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; 14335bc3cb74SMauro Carvalho Chehab return err; 14345bc3cb74SMauro Carvalho Chehab } 14355bc3cb74SMauro Carvalho Chehab 14365bc3cb74SMauro Carvalho Chehab static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, 14375bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14385bc3cb74SMauro Carvalho Chehab { 14395bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 14405bc3cb74SMauro Carvalho Chehab struct v4l2_frequency *p = arg; 14415bc3cb74SMauro Carvalho Chehab 144284099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) 144384099a28SAntti Palosaari p->type = V4L2_TUNER_ADC; 144484099a28SAntti Palosaari else 14455bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 14465bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 14475bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_frequency(file, fh, p); 14485bc3cb74SMauro Carvalho Chehab } 14495bc3cb74SMauro Carvalho Chehab 14505bc3cb74SMauro Carvalho Chehab static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, 14515bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14525bc3cb74SMauro Carvalho Chehab { 14535bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 1454b530a447SHans Verkuil const struct v4l2_frequency *p = arg; 14555bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 14565bc3cb74SMauro Carvalho Chehab 145784099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) { 145884099a28SAntti Palosaari if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) 145984099a28SAntti Palosaari return -EINVAL; 146084099a28SAntti Palosaari } else { 14615bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 14625bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 146384099a28SAntti Palosaari if (type != p->type) 14645bc3cb74SMauro Carvalho Chehab return -EINVAL; 146584099a28SAntti Palosaari } 14665bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_frequency(file, fh, p); 14675bc3cb74SMauro Carvalho Chehab } 14685bc3cb74SMauro Carvalho Chehab 14695bc3cb74SMauro Carvalho Chehab static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, 14705bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14715bc3cb74SMauro Carvalho Chehab { 14725bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 14735bc3cb74SMauro Carvalho Chehab struct v4l2_standard *p = arg; 14745bc3cb74SMauro Carvalho Chehab v4l2_std_id id = vfd->tvnorms, curr_id = 0; 14755bc3cb74SMauro Carvalho Chehab unsigned int index = p->index, i, j = 0; 14765bc3cb74SMauro Carvalho Chehab const char *descr = ""; 14775bc3cb74SMauro Carvalho Chehab 1478a5338190SHans Verkuil /* Return -ENODATA if the tvnorms for the current input 1479a5338190SHans Verkuil or output is 0, meaning that it doesn't support this API. */ 1480a5338190SHans Verkuil if (id == 0) 1481a5338190SHans Verkuil return -ENODATA; 1482a5338190SHans Verkuil 14835bc3cb74SMauro Carvalho Chehab /* Return norm array in a canonical way */ 14845bc3cb74SMauro Carvalho Chehab for (i = 0; i <= index && id; i++) { 14855bc3cb74SMauro Carvalho Chehab /* last std value in the standards array is 0, so this 14865bc3cb74SMauro Carvalho Chehab while always ends there since (id & 0) == 0. */ 14875bc3cb74SMauro Carvalho Chehab while ((id & standards[j].std) != standards[j].std) 14885bc3cb74SMauro Carvalho Chehab j++; 14895bc3cb74SMauro Carvalho Chehab curr_id = standards[j].std; 14905bc3cb74SMauro Carvalho Chehab descr = standards[j].descr; 14915bc3cb74SMauro Carvalho Chehab j++; 14925bc3cb74SMauro Carvalho Chehab if (curr_id == 0) 14935bc3cb74SMauro Carvalho Chehab break; 14945bc3cb74SMauro Carvalho Chehab if (curr_id != V4L2_STD_PAL && 14955bc3cb74SMauro Carvalho Chehab curr_id != V4L2_STD_SECAM && 14965bc3cb74SMauro Carvalho Chehab curr_id != V4L2_STD_NTSC) 14975bc3cb74SMauro Carvalho Chehab id &= ~curr_id; 14985bc3cb74SMauro Carvalho Chehab } 14995bc3cb74SMauro Carvalho Chehab if (i <= index) 15005bc3cb74SMauro Carvalho Chehab return -EINVAL; 15015bc3cb74SMauro Carvalho Chehab 15025bc3cb74SMauro Carvalho Chehab v4l2_video_std_construct(p, curr_id, descr); 15035bc3cb74SMauro Carvalho Chehab return 0; 15045bc3cb74SMauro Carvalho Chehab } 15055bc3cb74SMauro Carvalho Chehab 15065bc3cb74SMauro Carvalho Chehab static int v4l_s_std(const struct v4l2_ioctl_ops *ops, 15075bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15085bc3cb74SMauro Carvalho Chehab { 15095bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 1510314527acSHans Verkuil v4l2_std_id id = *(v4l2_std_id *)arg, norm; 15115bc3cb74SMauro Carvalho Chehab 1512314527acSHans Verkuil norm = id & vfd->tvnorms; 15135bc3cb74SMauro Carvalho Chehab if (vfd->tvnorms && !norm) /* Check if std is supported */ 15145bc3cb74SMauro Carvalho Chehab return -EINVAL; 15155bc3cb74SMauro Carvalho Chehab 15165bc3cb74SMauro Carvalho Chehab /* Calls the specific handler */ 1517ca371575SHans Verkuil return ops->vidioc_s_std(file, fh, norm); 15185bc3cb74SMauro Carvalho Chehab } 15195bc3cb74SMauro Carvalho Chehab 15205bc3cb74SMauro Carvalho Chehab static int v4l_querystd(const struct v4l2_ioctl_ops *ops, 15215bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15225bc3cb74SMauro Carvalho Chehab { 15235bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 15245bc3cb74SMauro Carvalho Chehab v4l2_std_id *p = arg; 15255bc3cb74SMauro Carvalho Chehab 15265bc3cb74SMauro Carvalho Chehab /* 15271a2c6866SHans Verkuil * If no signal is detected, then the driver should return 15281a2c6866SHans Verkuil * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with 15291a2c6866SHans Verkuil * any standards that do not apply removed. 15301a2c6866SHans Verkuil * 15315bc3cb74SMauro Carvalho Chehab * This means that tuners, audio and video decoders can join 15325bc3cb74SMauro Carvalho Chehab * their efforts to improve the standards detection. 15335bc3cb74SMauro Carvalho Chehab */ 15345bc3cb74SMauro Carvalho Chehab *p = vfd->tvnorms; 15355bc3cb74SMauro Carvalho Chehab return ops->vidioc_querystd(file, fh, arg); 15365bc3cb74SMauro Carvalho Chehab } 15375bc3cb74SMauro Carvalho Chehab 15385bc3cb74SMauro Carvalho Chehab static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, 15395bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15405bc3cb74SMauro Carvalho Chehab { 15415bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 15425bc3cb74SMauro Carvalho Chehab struct v4l2_hw_freq_seek *p = arg; 15435bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 15445bc3cb74SMauro Carvalho Chehab 154584099a28SAntti Palosaari /* s_hw_freq_seek is not supported for SDR for now */ 154684099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) 154784099a28SAntti Palosaari return -EINVAL; 154884099a28SAntti Palosaari 15495bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 15505bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 15515bc3cb74SMauro Carvalho Chehab if (p->type != type) 15525bc3cb74SMauro Carvalho Chehab return -EINVAL; 15535bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_hw_freq_seek(file, fh, p); 15545bc3cb74SMauro Carvalho Chehab } 15555bc3cb74SMauro Carvalho Chehab 1556737c097bSHans Verkuil static int v4l_overlay(const struct v4l2_ioctl_ops *ops, 1557737c097bSHans Verkuil struct file *file, void *fh, void *arg) 1558737c097bSHans Verkuil { 1559737c097bSHans Verkuil return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); 1560737c097bSHans Verkuil } 1561737c097bSHans Verkuil 15625bc3cb74SMauro Carvalho Chehab static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, 15635bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15645bc3cb74SMauro Carvalho Chehab { 15655bc3cb74SMauro Carvalho Chehab struct v4l2_requestbuffers *p = arg; 15664b20259fSHans Verkuil int ret = check_fmt(file, p->type); 15675bc3cb74SMauro Carvalho Chehab 15685bc3cb74SMauro Carvalho Chehab if (ret) 15695bc3cb74SMauro Carvalho Chehab return ret; 15705bc3cb74SMauro Carvalho Chehab 15715bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, memory); 15725bc3cb74SMauro Carvalho Chehab 15735bc3cb74SMauro Carvalho Chehab return ops->vidioc_reqbufs(file, fh, p); 15745bc3cb74SMauro Carvalho Chehab } 15755bc3cb74SMauro Carvalho Chehab 15765bc3cb74SMauro Carvalho Chehab static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, 15775bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15785bc3cb74SMauro Carvalho Chehab { 15795bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 15804b20259fSHans Verkuil int ret = check_fmt(file, p->type); 15815bc3cb74SMauro Carvalho Chehab 15825bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_querybuf(file, fh, p); 15835bc3cb74SMauro Carvalho Chehab } 15845bc3cb74SMauro Carvalho Chehab 15855bc3cb74SMauro Carvalho Chehab static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, 15865bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15875bc3cb74SMauro Carvalho Chehab { 15885bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 15894b20259fSHans Verkuil int ret = check_fmt(file, p->type); 15905bc3cb74SMauro Carvalho Chehab 15915bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_qbuf(file, fh, p); 15925bc3cb74SMauro Carvalho Chehab } 15935bc3cb74SMauro Carvalho Chehab 15945bc3cb74SMauro Carvalho Chehab static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, 15955bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15965bc3cb74SMauro Carvalho Chehab { 15975bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 15984b20259fSHans Verkuil int ret = check_fmt(file, p->type); 15995bc3cb74SMauro Carvalho Chehab 16005bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_dqbuf(file, fh, p); 16015bc3cb74SMauro Carvalho Chehab } 16025bc3cb74SMauro Carvalho Chehab 16035bc3cb74SMauro Carvalho Chehab static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, 16045bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16055bc3cb74SMauro Carvalho Chehab { 16065bc3cb74SMauro Carvalho Chehab struct v4l2_create_buffers *create = arg; 16074b20259fSHans Verkuil int ret = check_fmt(file, create->format.type); 16085bc3cb74SMauro Carvalho Chehab 1609d52e2381SLaurent Pinchart if (ret) 1610d52e2381SLaurent Pinchart return ret; 1611d52e2381SLaurent Pinchart 1612d52e2381SLaurent Pinchart v4l_sanitize_format(&create->format); 1613d52e2381SLaurent Pinchart 1614d52e2381SLaurent Pinchart ret = ops->vidioc_create_bufs(file, fh, create); 1615d52e2381SLaurent Pinchart 1616d52e2381SLaurent Pinchart if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || 1617d52e2381SLaurent Pinchart create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1618d52e2381SLaurent Pinchart create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1619d52e2381SLaurent Pinchart 1620d52e2381SLaurent Pinchart return ret; 16215bc3cb74SMauro Carvalho Chehab } 16225bc3cb74SMauro Carvalho Chehab 16235bc3cb74SMauro Carvalho Chehab static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, 16245bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16255bc3cb74SMauro Carvalho Chehab { 16265bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *b = arg; 16274b20259fSHans Verkuil int ret = check_fmt(file, b->type); 16285bc3cb74SMauro Carvalho Chehab 16295bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); 16305bc3cb74SMauro Carvalho Chehab } 16315bc3cb74SMauro Carvalho Chehab 16325bc3cb74SMauro Carvalho Chehab static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, 16335bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16345bc3cb74SMauro Carvalho Chehab { 16355bc3cb74SMauro Carvalho Chehab struct v4l2_streamparm *p = arg; 16365bc3cb74SMauro Carvalho Chehab v4l2_std_id std; 16374b20259fSHans Verkuil int ret = check_fmt(file, p->type); 16385bc3cb74SMauro Carvalho Chehab 16395bc3cb74SMauro Carvalho Chehab if (ret) 16405bc3cb74SMauro Carvalho Chehab return ret; 16415bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_parm) 16425bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_parm(file, fh, p); 16435bc3cb74SMauro Carvalho Chehab if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 16445bc3cb74SMauro Carvalho Chehab p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 16455bc3cb74SMauro Carvalho Chehab return -EINVAL; 16465bc3cb74SMauro Carvalho Chehab p->parm.capture.readbuffers = 2; 16475bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_std(file, fh, &std); 16485bc3cb74SMauro Carvalho Chehab if (ret == 0) 1649ca371575SHans Verkuil v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); 16505bc3cb74SMauro Carvalho Chehab return ret; 16515bc3cb74SMauro Carvalho Chehab } 16525bc3cb74SMauro Carvalho Chehab 16535bc3cb74SMauro Carvalho Chehab static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, 16545bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16555bc3cb74SMauro Carvalho Chehab { 16565bc3cb74SMauro Carvalho Chehab struct v4l2_streamparm *p = arg; 16574b20259fSHans Verkuil int ret = check_fmt(file, p->type); 16585bc3cb74SMauro Carvalho Chehab 16595bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_s_parm(file, fh, p); 16605bc3cb74SMauro Carvalho Chehab } 16615bc3cb74SMauro Carvalho Chehab 16625bc3cb74SMauro Carvalho Chehab static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, 16635bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16645bc3cb74SMauro Carvalho Chehab { 16655bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 16665bc3cb74SMauro Carvalho Chehab struct v4l2_queryctrl *p = arg; 16675bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 16685bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 16695bc3cb74SMauro Carvalho Chehab 16705bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 16715bc3cb74SMauro Carvalho Chehab return v4l2_queryctrl(vfh->ctrl_handler, p); 16725bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 16735bc3cb74SMauro Carvalho Chehab return v4l2_queryctrl(vfd->ctrl_handler, p); 16745bc3cb74SMauro Carvalho Chehab if (ops->vidioc_queryctrl) 16755bc3cb74SMauro Carvalho Chehab return ops->vidioc_queryctrl(file, fh, p); 16765bc3cb74SMauro Carvalho Chehab return -ENOTTY; 16775bc3cb74SMauro Carvalho Chehab } 16785bc3cb74SMauro Carvalho Chehab 1679e6bee368SHans Verkuil static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, 1680e6bee368SHans Verkuil struct file *file, void *fh, void *arg) 1681e6bee368SHans Verkuil { 1682e6bee368SHans Verkuil struct video_device *vfd = video_devdata(file); 1683e6bee368SHans Verkuil struct v4l2_query_ext_ctrl *p = arg; 1684e6bee368SHans Verkuil struct v4l2_fh *vfh = 1685e6bee368SHans Verkuil test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 1686e6bee368SHans Verkuil 1687e6bee368SHans Verkuil if (vfh && vfh->ctrl_handler) 1688e6bee368SHans Verkuil return v4l2_query_ext_ctrl(vfh->ctrl_handler, p); 1689e6bee368SHans Verkuil if (vfd->ctrl_handler) 1690e6bee368SHans Verkuil return v4l2_query_ext_ctrl(vfd->ctrl_handler, p); 1691e6bee368SHans Verkuil if (ops->vidioc_query_ext_ctrl) 1692e6bee368SHans Verkuil return ops->vidioc_query_ext_ctrl(file, fh, p); 1693e6bee368SHans Verkuil return -ENOTTY; 1694e6bee368SHans Verkuil } 1695e6bee368SHans Verkuil 16965bc3cb74SMauro Carvalho Chehab static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, 16975bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16985bc3cb74SMauro Carvalho Chehab { 16995bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17005bc3cb74SMauro Carvalho Chehab struct v4l2_querymenu *p = arg; 17015bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 17025bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 17035bc3cb74SMauro Carvalho Chehab 17045bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 17055bc3cb74SMauro Carvalho Chehab return v4l2_querymenu(vfh->ctrl_handler, p); 17065bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 17075bc3cb74SMauro Carvalho Chehab return v4l2_querymenu(vfd->ctrl_handler, p); 17085bc3cb74SMauro Carvalho Chehab if (ops->vidioc_querymenu) 17095bc3cb74SMauro Carvalho Chehab return ops->vidioc_querymenu(file, fh, p); 17105bc3cb74SMauro Carvalho Chehab return -ENOTTY; 17115bc3cb74SMauro Carvalho Chehab } 17125bc3cb74SMauro Carvalho Chehab 17135bc3cb74SMauro Carvalho Chehab static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, 17145bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17155bc3cb74SMauro Carvalho Chehab { 17165bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17175bc3cb74SMauro Carvalho Chehab struct v4l2_control *p = arg; 17185bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 17195bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 17205bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls ctrls; 17215bc3cb74SMauro Carvalho Chehab struct v4l2_ext_control ctrl; 17225bc3cb74SMauro Carvalho Chehab 17235bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 17245bc3cb74SMauro Carvalho Chehab return v4l2_g_ctrl(vfh->ctrl_handler, p); 17255bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 17265bc3cb74SMauro Carvalho Chehab return v4l2_g_ctrl(vfd->ctrl_handler, p); 17275bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ctrl) 17285bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_ctrl(file, fh, p); 17295bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ext_ctrls == NULL) 17305bc3cb74SMauro Carvalho Chehab return -ENOTTY; 17315bc3cb74SMauro Carvalho Chehab 17325bc3cb74SMauro Carvalho Chehab ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); 17335bc3cb74SMauro Carvalho Chehab ctrls.count = 1; 17345bc3cb74SMauro Carvalho Chehab ctrls.controls = &ctrl; 17355bc3cb74SMauro Carvalho Chehab ctrl.id = p->id; 17365bc3cb74SMauro Carvalho Chehab ctrl.value = p->value; 17375bc3cb74SMauro Carvalho Chehab if (check_ext_ctrls(&ctrls, 1)) { 17385bc3cb74SMauro Carvalho Chehab int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); 17395bc3cb74SMauro Carvalho Chehab 17405bc3cb74SMauro Carvalho Chehab if (ret == 0) 17415bc3cb74SMauro Carvalho Chehab p->value = ctrl.value; 17425bc3cb74SMauro Carvalho Chehab return ret; 17435bc3cb74SMauro Carvalho Chehab } 17445bc3cb74SMauro Carvalho Chehab return -EINVAL; 17455bc3cb74SMauro Carvalho Chehab } 17465bc3cb74SMauro Carvalho Chehab 17475bc3cb74SMauro Carvalho Chehab static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, 17485bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17495bc3cb74SMauro Carvalho Chehab { 17505bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17515bc3cb74SMauro Carvalho Chehab struct v4l2_control *p = arg; 17525bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 17535bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 17545bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls ctrls; 17555bc3cb74SMauro Carvalho Chehab struct v4l2_ext_control ctrl; 17565bc3cb74SMauro Carvalho Chehab 17575bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 17585bc3cb74SMauro Carvalho Chehab return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); 17595bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 17605bc3cb74SMauro Carvalho Chehab return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); 17615bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ctrl) 17625bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_ctrl(file, fh, p); 17635bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ext_ctrls == NULL) 17645bc3cb74SMauro Carvalho Chehab return -ENOTTY; 17655bc3cb74SMauro Carvalho Chehab 17665bc3cb74SMauro Carvalho Chehab ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); 17675bc3cb74SMauro Carvalho Chehab ctrls.count = 1; 17685bc3cb74SMauro Carvalho Chehab ctrls.controls = &ctrl; 17695bc3cb74SMauro Carvalho Chehab ctrl.id = p->id; 17705bc3cb74SMauro Carvalho Chehab ctrl.value = p->value; 17715bc3cb74SMauro Carvalho Chehab if (check_ext_ctrls(&ctrls, 1)) 17725bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); 17735bc3cb74SMauro Carvalho Chehab return -EINVAL; 17745bc3cb74SMauro Carvalho Chehab } 17755bc3cb74SMauro Carvalho Chehab 17765bc3cb74SMauro Carvalho Chehab static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, 17775bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17785bc3cb74SMauro Carvalho Chehab { 17795bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17805bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 17815bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 17825bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 17835bc3cb74SMauro Carvalho Chehab 17845bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 17855bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 17865bc3cb74SMauro Carvalho Chehab return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); 17875bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 17885bc3cb74SMauro Carvalho Chehab return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); 17895bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ext_ctrls == NULL) 17905bc3cb74SMauro Carvalho Chehab return -ENOTTY; 17915bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : 17925bc3cb74SMauro Carvalho Chehab -EINVAL; 17935bc3cb74SMauro Carvalho Chehab } 17945bc3cb74SMauro Carvalho Chehab 17955bc3cb74SMauro Carvalho Chehab static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, 17965bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17975bc3cb74SMauro Carvalho Chehab { 17985bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17995bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 18005bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 18015bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 18025bc3cb74SMauro Carvalho Chehab 18035bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 18045bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 18055bc3cb74SMauro Carvalho Chehab return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); 18065bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 18075bc3cb74SMauro Carvalho Chehab return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); 18085bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ext_ctrls == NULL) 18095bc3cb74SMauro Carvalho Chehab return -ENOTTY; 18105bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : 18115bc3cb74SMauro Carvalho Chehab -EINVAL; 18125bc3cb74SMauro Carvalho Chehab } 18135bc3cb74SMauro Carvalho Chehab 18145bc3cb74SMauro Carvalho Chehab static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, 18155bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18165bc3cb74SMauro Carvalho Chehab { 18175bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 18185bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 18195bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 18205bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 18215bc3cb74SMauro Carvalho Chehab 18225bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 18235bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 18245bc3cb74SMauro Carvalho Chehab return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); 18255bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 18265bc3cb74SMauro Carvalho Chehab return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); 18275bc3cb74SMauro Carvalho Chehab if (ops->vidioc_try_ext_ctrls == NULL) 18285bc3cb74SMauro Carvalho Chehab return -ENOTTY; 18295bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : 18305bc3cb74SMauro Carvalho Chehab -EINVAL; 18315bc3cb74SMauro Carvalho Chehab } 18325bc3cb74SMauro Carvalho Chehab 18335bc3cb74SMauro Carvalho Chehab static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, 18345bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18355bc3cb74SMauro Carvalho Chehab { 18365bc3cb74SMauro Carvalho Chehab struct v4l2_crop *p = arg; 18375bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { 18385bc3cb74SMauro Carvalho Chehab .type = p->type, 18395bc3cb74SMauro Carvalho Chehab }; 18405bc3cb74SMauro Carvalho Chehab int ret; 18415bc3cb74SMauro Carvalho Chehab 18425bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_crop) 18435bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_crop(file, fh, p); 18445bc3cb74SMauro Carvalho Chehab /* simulate capture crop using selection api */ 18455bc3cb74SMauro Carvalho Chehab 18465bc3cb74SMauro Carvalho Chehab /* crop means compose for output devices */ 18475bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 18485bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; 18495bc3cb74SMauro Carvalho Chehab else 18505bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_ACTIVE; 18515bc3cb74SMauro Carvalho Chehab 18525bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 18535bc3cb74SMauro Carvalho Chehab 18545bc3cb74SMauro Carvalho Chehab /* copying results to old structure on success */ 18555bc3cb74SMauro Carvalho Chehab if (!ret) 18565bc3cb74SMauro Carvalho Chehab p->c = s.r; 18575bc3cb74SMauro Carvalho Chehab return ret; 18585bc3cb74SMauro Carvalho Chehab } 18595bc3cb74SMauro Carvalho Chehab 18605bc3cb74SMauro Carvalho Chehab static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, 18615bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18625bc3cb74SMauro Carvalho Chehab { 18635bc3cb74SMauro Carvalho Chehab struct v4l2_crop *p = arg; 18645bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { 18655bc3cb74SMauro Carvalho Chehab .type = p->type, 18665bc3cb74SMauro Carvalho Chehab .r = p->c, 18675bc3cb74SMauro Carvalho Chehab }; 18685bc3cb74SMauro Carvalho Chehab 18695bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_crop) 18705bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_crop(file, fh, p); 18715bc3cb74SMauro Carvalho Chehab /* simulate capture crop using selection api */ 18725bc3cb74SMauro Carvalho Chehab 18735bc3cb74SMauro Carvalho Chehab /* crop means compose for output devices */ 18745bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 18755bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; 18765bc3cb74SMauro Carvalho Chehab else 18775bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_ACTIVE; 18785bc3cb74SMauro Carvalho Chehab 18795bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_selection(file, fh, &s); 18805bc3cb74SMauro Carvalho Chehab } 18815bc3cb74SMauro Carvalho Chehab 18825bc3cb74SMauro Carvalho Chehab static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, 18835bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18845bc3cb74SMauro Carvalho Chehab { 18855bc3cb74SMauro Carvalho Chehab struct v4l2_cropcap *p = arg; 18869409945cSHans Verkuil 18879409945cSHans Verkuil if (ops->vidioc_g_selection) { 18885bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { .type = p->type }; 18895bc3cb74SMauro Carvalho Chehab int ret; 18905bc3cb74SMauro Carvalho Chehab 18915bc3cb74SMauro Carvalho Chehab /* obtaining bounds */ 18925bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 18935bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; 18945bc3cb74SMauro Carvalho Chehab else 18955bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_BOUNDS; 18965bc3cb74SMauro Carvalho Chehab 18975bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 18985bc3cb74SMauro Carvalho Chehab if (ret) 18995bc3cb74SMauro Carvalho Chehab return ret; 19005bc3cb74SMauro Carvalho Chehab p->bounds = s.r; 19015bc3cb74SMauro Carvalho Chehab 19025bc3cb74SMauro Carvalho Chehab /* obtaining defrect */ 19035bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 19045bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; 19055bc3cb74SMauro Carvalho Chehab else 19065bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_DEFAULT; 19075bc3cb74SMauro Carvalho Chehab 19085bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 19095bc3cb74SMauro Carvalho Chehab if (ret) 19105bc3cb74SMauro Carvalho Chehab return ret; 19115bc3cb74SMauro Carvalho Chehab p->defrect = s.r; 19129409945cSHans Verkuil } 19135bc3cb74SMauro Carvalho Chehab 19145bc3cb74SMauro Carvalho Chehab /* setting trivial pixelaspect */ 19155bc3cb74SMauro Carvalho Chehab p->pixelaspect.numerator = 1; 19165bc3cb74SMauro Carvalho Chehab p->pixelaspect.denominator = 1; 19179409945cSHans Verkuil 19189409945cSHans Verkuil if (ops->vidioc_cropcap) 19199409945cSHans Verkuil return ops->vidioc_cropcap(file, fh, p); 19209409945cSHans Verkuil 19215bc3cb74SMauro Carvalho Chehab return 0; 19225bc3cb74SMauro Carvalho Chehab } 19235bc3cb74SMauro Carvalho Chehab 19245bc3cb74SMauro Carvalho Chehab static int v4l_log_status(const struct v4l2_ioctl_ops *ops, 19255bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19265bc3cb74SMauro Carvalho Chehab { 19275bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 19285bc3cb74SMauro Carvalho Chehab int ret; 19295bc3cb74SMauro Carvalho Chehab 19305bc3cb74SMauro Carvalho Chehab if (vfd->v4l2_dev) 19315bc3cb74SMauro Carvalho Chehab pr_info("%s: ================= START STATUS =================\n", 19325bc3cb74SMauro Carvalho Chehab vfd->v4l2_dev->name); 19335bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_log_status(file, fh); 19345bc3cb74SMauro Carvalho Chehab if (vfd->v4l2_dev) 19355bc3cb74SMauro Carvalho Chehab pr_info("%s: ================== END STATUS ==================\n", 19365bc3cb74SMauro Carvalho Chehab vfd->v4l2_dev->name); 19375bc3cb74SMauro Carvalho Chehab return ret; 19385bc3cb74SMauro Carvalho Chehab } 19395bc3cb74SMauro Carvalho Chehab 19405bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, 19415bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19425bc3cb74SMauro Carvalho Chehab { 19435bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 19445bc3cb74SMauro Carvalho Chehab struct v4l2_dbg_register *p = arg; 194579b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 194679b0c640SHans Verkuil struct v4l2_subdev *sd; 194779b0c640SHans Verkuil int idx = 0; 19485bc3cb74SMauro Carvalho Chehab 19495bc3cb74SMauro Carvalho Chehab if (!capable(CAP_SYS_ADMIN)) 19505bc3cb74SMauro Carvalho Chehab return -EPERM; 19513eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) { 195279b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 195379b0c640SHans Verkuil return -EINVAL; 19543eef2510SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) 19553eef2510SHans Verkuil if (p->match.addr == idx++) 195679b0c640SHans Verkuil return v4l2_subdev_call(sd, core, g_register, p); 195779b0c640SHans Verkuil return -EINVAL; 195879b0c640SHans Verkuil } 1959191b79b0SHans Verkuil if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && 1960191b79b0SHans Verkuil (ops->vidioc_g_chip_info || p->match.addr == 0)) 19615bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_register(file, fh, p); 196279b0c640SHans Verkuil return -EINVAL; 19635bc3cb74SMauro Carvalho Chehab #else 19645bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19655bc3cb74SMauro Carvalho Chehab #endif 19665bc3cb74SMauro Carvalho Chehab } 19675bc3cb74SMauro Carvalho Chehab 19685bc3cb74SMauro Carvalho Chehab static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, 19695bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19705bc3cb74SMauro Carvalho Chehab { 19715bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 1972977ba3b1SHans Verkuil const struct v4l2_dbg_register *p = arg; 197379b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 197479b0c640SHans Verkuil struct v4l2_subdev *sd; 197579b0c640SHans Verkuil int idx = 0; 19765bc3cb74SMauro Carvalho Chehab 19775bc3cb74SMauro Carvalho Chehab if (!capable(CAP_SYS_ADMIN)) 19785bc3cb74SMauro Carvalho Chehab return -EPERM; 19793eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) { 198079b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 198179b0c640SHans Verkuil return -EINVAL; 19823eef2510SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) 19833eef2510SHans Verkuil if (p->match.addr == idx++) 198479b0c640SHans Verkuil return v4l2_subdev_call(sd, core, s_register, p); 198579b0c640SHans Verkuil return -EINVAL; 198679b0c640SHans Verkuil } 1987191b79b0SHans Verkuil if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && 1988191b79b0SHans Verkuil (ops->vidioc_g_chip_info || p->match.addr == 0)) 19895bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_register(file, fh, p); 199079b0c640SHans Verkuil return -EINVAL; 19915bc3cb74SMauro Carvalho Chehab #else 19925bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19935bc3cb74SMauro Carvalho Chehab #endif 19945bc3cb74SMauro Carvalho Chehab } 19955bc3cb74SMauro Carvalho Chehab 199696b03d2aSHans Verkuil static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, 199779b0c640SHans Verkuil struct file *file, void *fh, void *arg) 199879b0c640SHans Verkuil { 1999cd634f1bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG 200079b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 200196b03d2aSHans Verkuil struct v4l2_dbg_chip_info *p = arg; 200279b0c640SHans Verkuil struct v4l2_subdev *sd; 200379b0c640SHans Verkuil int idx = 0; 200479b0c640SHans Verkuil 200579b0c640SHans Verkuil switch (p->match.type) { 200679b0c640SHans Verkuil case V4L2_CHIP_MATCH_BRIDGE: 200779b0c640SHans Verkuil if (ops->vidioc_s_register) 200879b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_WRITABLE; 200979b0c640SHans Verkuil if (ops->vidioc_g_register) 201079b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_READABLE; 201179b0c640SHans Verkuil strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); 201296b03d2aSHans Verkuil if (ops->vidioc_g_chip_info) 201396b03d2aSHans Verkuil return ops->vidioc_g_chip_info(file, fh, arg); 20140f0fe4b9SHans Verkuil if (p->match.addr) 20150f0fe4b9SHans Verkuil return -EINVAL; 201679b0c640SHans Verkuil return 0; 201779b0c640SHans Verkuil 20183eef2510SHans Verkuil case V4L2_CHIP_MATCH_SUBDEV: 201979b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 202079b0c640SHans Verkuil break; 202179b0c640SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) { 20223eef2510SHans Verkuil if (p->match.addr != idx++) 20233eef2510SHans Verkuil continue; 202479b0c640SHans Verkuil if (sd->ops->core && sd->ops->core->s_register) 202579b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_WRITABLE; 202679b0c640SHans Verkuil if (sd->ops->core && sd->ops->core->g_register) 202779b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_READABLE; 202879b0c640SHans Verkuil strlcpy(p->name, sd->name, sizeof(p->name)); 202979b0c640SHans Verkuil return 0; 203079b0c640SHans Verkuil } 203179b0c640SHans Verkuil break; 203279b0c640SHans Verkuil } 203379b0c640SHans Verkuil return -EINVAL; 2034cd634f1bSHans Verkuil #else 2035cd634f1bSHans Verkuil return -ENOTTY; 2036cd634f1bSHans Verkuil #endif 203779b0c640SHans Verkuil } 203879b0c640SHans Verkuil 20395bc3cb74SMauro Carvalho Chehab static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, 20405bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20415bc3cb74SMauro Carvalho Chehab { 20425bc3cb74SMauro Carvalho Chehab return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); 20435bc3cb74SMauro Carvalho Chehab } 20445bc3cb74SMauro Carvalho Chehab 20455bc3cb74SMauro Carvalho Chehab static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops, 20465bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20475bc3cb74SMauro Carvalho Chehab { 20485bc3cb74SMauro Carvalho Chehab return ops->vidioc_subscribe_event(fh, arg); 20495bc3cb74SMauro Carvalho Chehab } 20505bc3cb74SMauro Carvalho Chehab 20515bc3cb74SMauro Carvalho Chehab static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops, 20525bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20535bc3cb74SMauro Carvalho Chehab { 20545bc3cb74SMauro Carvalho Chehab return ops->vidioc_unsubscribe_event(fh, arg); 20555bc3cb74SMauro Carvalho Chehab } 20565bc3cb74SMauro Carvalho Chehab 20575bc3cb74SMauro Carvalho Chehab static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, 20585bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20595bc3cb74SMauro Carvalho Chehab { 20605bc3cb74SMauro Carvalho Chehab struct v4l2_sliced_vbi_cap *p = arg; 20614b20259fSHans Verkuil int ret = check_fmt(file, p->type); 20624b20259fSHans Verkuil 20634b20259fSHans Verkuil if (ret) 20644b20259fSHans Verkuil return ret; 20655bc3cb74SMauro Carvalho Chehab 20665bc3cb74SMauro Carvalho Chehab /* Clear up to type, everything after type is zeroed already */ 20675bc3cb74SMauro Carvalho Chehab memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); 20685bc3cb74SMauro Carvalho Chehab 20695bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_sliced_vbi_cap(file, fh, p); 20705bc3cb74SMauro Carvalho Chehab } 20715bc3cb74SMauro Carvalho Chehab 20725bc3cb74SMauro Carvalho Chehab static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, 20735bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20745bc3cb74SMauro Carvalho Chehab { 20755bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 20765bc3cb74SMauro Carvalho Chehab struct v4l2_frequency_band *p = arg; 20775bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 20785bc3cb74SMauro Carvalho Chehab int err; 20795bc3cb74SMauro Carvalho Chehab 208084099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) { 208184099a28SAntti Palosaari if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) 208284099a28SAntti Palosaari return -EINVAL; 208384099a28SAntti Palosaari type = p->type; 208484099a28SAntti Palosaari } else { 20855bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 20865bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 20875bc3cb74SMauro Carvalho Chehab if (type != p->type) 20885bc3cb74SMauro Carvalho Chehab return -EINVAL; 208984099a28SAntti Palosaari } 2090a7f404afSHans Verkuil if (ops->vidioc_enum_freq_bands) { 2091a7f404afSHans Verkuil err = ops->vidioc_enum_freq_bands(file, fh, p); 2092a7f404afSHans Verkuil if (err != -ENOTTY) 2093a7f404afSHans Verkuil return err; 2094a7f404afSHans Verkuil } 209573f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) { 20965bc3cb74SMauro Carvalho Chehab struct v4l2_tuner t = { 20975bc3cb74SMauro Carvalho Chehab .index = p->tuner, 20985bc3cb74SMauro Carvalho Chehab .type = type, 20995bc3cb74SMauro Carvalho Chehab }; 21005bc3cb74SMauro Carvalho Chehab 210179e8c7beSMauro Carvalho Chehab if (p->index) 210279e8c7beSMauro Carvalho Chehab return -EINVAL; 21035bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_tuner(file, fh, &t); 21045bc3cb74SMauro Carvalho Chehab if (err) 21055bc3cb74SMauro Carvalho Chehab return err; 21065bc3cb74SMauro Carvalho Chehab p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS; 21075bc3cb74SMauro Carvalho Chehab p->rangelow = t.rangelow; 21085bc3cb74SMauro Carvalho Chehab p->rangehigh = t.rangehigh; 21095bc3cb74SMauro Carvalho Chehab p->modulation = (type == V4L2_TUNER_RADIO) ? 21105bc3cb74SMauro Carvalho Chehab V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; 21115bc3cb74SMauro Carvalho Chehab return 0; 21125bc3cb74SMauro Carvalho Chehab } 211373f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) { 21145bc3cb74SMauro Carvalho Chehab struct v4l2_modulator m = { 21155bc3cb74SMauro Carvalho Chehab .index = p->tuner, 21165bc3cb74SMauro Carvalho Chehab }; 21175bc3cb74SMauro Carvalho Chehab 21185bc3cb74SMauro Carvalho Chehab if (type != V4L2_TUNER_RADIO) 21195bc3cb74SMauro Carvalho Chehab return -EINVAL; 212079e8c7beSMauro Carvalho Chehab if (p->index) 212179e8c7beSMauro Carvalho Chehab return -EINVAL; 21225bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_modulator(file, fh, &m); 21235bc3cb74SMauro Carvalho Chehab if (err) 21245bc3cb74SMauro Carvalho Chehab return err; 21255bc3cb74SMauro Carvalho Chehab p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS; 21265bc3cb74SMauro Carvalho Chehab p->rangelow = m.rangelow; 21275bc3cb74SMauro Carvalho Chehab p->rangehigh = m.rangehigh; 21285bc3cb74SMauro Carvalho Chehab p->modulation = (type == V4L2_TUNER_RADIO) ? 21295bc3cb74SMauro Carvalho Chehab V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; 21305bc3cb74SMauro Carvalho Chehab return 0; 21315bc3cb74SMauro Carvalho Chehab } 21325bc3cb74SMauro Carvalho Chehab return -ENOTTY; 21335bc3cb74SMauro Carvalho Chehab } 21345bc3cb74SMauro Carvalho Chehab 21355bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info { 21365bc3cb74SMauro Carvalho Chehab unsigned int ioctl; 21375bc3cb74SMauro Carvalho Chehab u32 flags; 21385bc3cb74SMauro Carvalho Chehab const char * const name; 21395bc3cb74SMauro Carvalho Chehab union { 21405bc3cb74SMauro Carvalho Chehab u32 offset; 21415bc3cb74SMauro Carvalho Chehab int (*func)(const struct v4l2_ioctl_ops *ops, 21425bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *p); 21435bc3cb74SMauro Carvalho Chehab } u; 21445bc3cb74SMauro Carvalho Chehab void (*debug)(const void *arg, bool write_only); 21455bc3cb74SMauro Carvalho Chehab }; 21465bc3cb74SMauro Carvalho Chehab 21475bc3cb74SMauro Carvalho Chehab /* This control needs a priority check */ 21485bc3cb74SMauro Carvalho Chehab #define INFO_FL_PRIO (1 << 0) 21495bc3cb74SMauro Carvalho Chehab /* This control can be valid if the filehandle passes a control handler. */ 21505bc3cb74SMauro Carvalho Chehab #define INFO_FL_CTRL (1 << 1) 21515bc3cb74SMauro Carvalho Chehab /* This is a standard ioctl, no need for special code */ 21525bc3cb74SMauro Carvalho Chehab #define INFO_FL_STD (1 << 2) 21535bc3cb74SMauro Carvalho Chehab /* This is ioctl has its own function */ 21545bc3cb74SMauro Carvalho Chehab #define INFO_FL_FUNC (1 << 3) 21555bc3cb74SMauro Carvalho Chehab /* Queuing ioctl */ 21565bc3cb74SMauro Carvalho Chehab #define INFO_FL_QUEUE (1 << 4) 21575bc3cb74SMauro Carvalho Chehab /* Zero struct from after the field to the end */ 21585bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR(v4l2_struct, field) \ 21595bc3cb74SMauro Carvalho Chehab ((offsetof(struct v4l2_struct, field) + \ 21605bc3cb74SMauro Carvalho Chehab sizeof(((struct v4l2_struct *)0)->field)) << 16) 21615bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) 21625bc3cb74SMauro Carvalho Chehab 21635bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ 21645bc3cb74SMauro Carvalho Chehab [_IOC_NR(_ioctl)] = { \ 21655bc3cb74SMauro Carvalho Chehab .ioctl = _ioctl, \ 21665bc3cb74SMauro Carvalho Chehab .flags = _flags | INFO_FL_STD, \ 21675bc3cb74SMauro Carvalho Chehab .name = #_ioctl, \ 21685bc3cb74SMauro Carvalho Chehab .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ 21695bc3cb74SMauro Carvalho Chehab .debug = _debug, \ 21705bc3cb74SMauro Carvalho Chehab } 21715bc3cb74SMauro Carvalho Chehab 21725bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ 21735bc3cb74SMauro Carvalho Chehab [_IOC_NR(_ioctl)] = { \ 21745bc3cb74SMauro Carvalho Chehab .ioctl = _ioctl, \ 21755bc3cb74SMauro Carvalho Chehab .flags = _flags | INFO_FL_FUNC, \ 21765bc3cb74SMauro Carvalho Chehab .name = #_ioctl, \ 21775bc3cb74SMauro Carvalho Chehab .u.func = _func, \ 21785bc3cb74SMauro Carvalho Chehab .debug = _debug, \ 21795bc3cb74SMauro Carvalho Chehab } 21805bc3cb74SMauro Carvalho Chehab 21815bc3cb74SMauro Carvalho Chehab static struct v4l2_ioctl_info v4l2_ioctls[] = { 21825bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), 21835bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), 2184e5ce558aSHans Verkuil IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0), 21855bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), 21865bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), 21875bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), 21885bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), 21895bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), 2190737c097bSHans Verkuil IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO), 21915bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), 2192b799d09aSTomasz Stanislawski IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)), 21935bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), 21945bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), 21955bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), 21965bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), 21975bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), 2198ca371575SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0), 21995bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), 22005bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), 22015bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), 22025bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)), 22035bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL), 22045bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)), 22055bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO), 22065bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), 22075bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), 22085bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), 22095bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), 22105bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), 22115bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), 2212f9402a94SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0), 2213f9402a94SHans Verkuil IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO), 22145bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), 22155bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), 22165bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), 22175bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), 22185bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), 22195bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), 22205bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), 22215bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), 22225bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), 22235bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), 22245bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)), 22255bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), 2226865c4642SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)), 2227865c4642SHans Verkuil IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)), 22285bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0), 22295bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO), 22305bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), 22315bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), 22325bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), 22335bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), 22345bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), 22355bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), 22365bc3cb74SMauro 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)), 22375bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), 22385bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), 22395bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), 22405bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), 22415bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), 22425bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)), 22435bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0), 22445bc3cb74SMauro 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)), 22455bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), 22465bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO), 22475bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), 22485bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), 22495bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), 22505bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), 22515bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), 22525bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), 22535bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0), 22545bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0), 22555bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0), 22565bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), 22575bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), 22585bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), 22595bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), 22605bc3cb74SMauro 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)), 22615bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), 226296b03d2aSHans 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)), 2263e6bee368SHans Verkuil IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), 22645bc3cb74SMauro Carvalho Chehab }; 22655bc3cb74SMauro Carvalho Chehab #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) 22665bc3cb74SMauro Carvalho Chehab 22675bc3cb74SMauro Carvalho Chehab bool v4l2_is_known_ioctl(unsigned int cmd) 22685bc3cb74SMauro Carvalho Chehab { 22695bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) 22705bc3cb74SMauro Carvalho Chehab return false; 22715bc3cb74SMauro Carvalho Chehab return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; 22725bc3cb74SMauro Carvalho Chehab } 22735bc3cb74SMauro Carvalho Chehab 22745bc3cb74SMauro Carvalho Chehab struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd) 22755bc3cb74SMauro Carvalho Chehab { 22765bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) 22775bc3cb74SMauro Carvalho Chehab return vdev->lock; 22785bc3cb74SMauro Carvalho Chehab if (test_bit(_IOC_NR(cmd), vdev->disable_locking)) 22795bc3cb74SMauro Carvalho Chehab return NULL; 22805bc3cb74SMauro Carvalho Chehab if (vdev->queue && vdev->queue->lock && 22815bc3cb74SMauro Carvalho Chehab (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) 22825bc3cb74SMauro Carvalho Chehab return vdev->queue->lock; 22835bc3cb74SMauro Carvalho Chehab return vdev->lock; 22845bc3cb74SMauro Carvalho Chehab } 22855bc3cb74SMauro Carvalho Chehab 22865bc3cb74SMauro Carvalho Chehab /* Common ioctl debug function. This function can be used by 22875bc3cb74SMauro Carvalho Chehab external ioctl messages as well as internal V4L ioctl */ 22885bc3cb74SMauro Carvalho Chehab void v4l_printk_ioctl(const char *prefix, unsigned int cmd) 22895bc3cb74SMauro Carvalho Chehab { 22905bc3cb74SMauro Carvalho Chehab const char *dir, *type; 22915bc3cb74SMauro Carvalho Chehab 22925bc3cb74SMauro Carvalho Chehab if (prefix) 22935bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "%s: ", prefix); 22945bc3cb74SMauro Carvalho Chehab 22955bc3cb74SMauro Carvalho Chehab switch (_IOC_TYPE(cmd)) { 22965bc3cb74SMauro Carvalho Chehab case 'd': 22975bc3cb74SMauro Carvalho Chehab type = "v4l2_int"; 22985bc3cb74SMauro Carvalho Chehab break; 22995bc3cb74SMauro Carvalho Chehab case 'V': 23005bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) { 23015bc3cb74SMauro Carvalho Chehab type = "v4l2"; 23025bc3cb74SMauro Carvalho Chehab break; 23035bc3cb74SMauro Carvalho Chehab } 23045bc3cb74SMauro Carvalho Chehab pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name); 23055bc3cb74SMauro Carvalho Chehab return; 23065bc3cb74SMauro Carvalho Chehab default: 23075bc3cb74SMauro Carvalho Chehab type = "unknown"; 23085bc3cb74SMauro Carvalho Chehab break; 23095bc3cb74SMauro Carvalho Chehab } 23105bc3cb74SMauro Carvalho Chehab 23115bc3cb74SMauro Carvalho Chehab switch (_IOC_DIR(cmd)) { 23125bc3cb74SMauro Carvalho Chehab case _IOC_NONE: dir = "--"; break; 23135bc3cb74SMauro Carvalho Chehab case _IOC_READ: dir = "r-"; break; 23145bc3cb74SMauro Carvalho Chehab case _IOC_WRITE: dir = "-w"; break; 23155bc3cb74SMauro Carvalho Chehab case _IOC_READ | _IOC_WRITE: dir = "rw"; break; 23165bc3cb74SMauro Carvalho Chehab default: dir = "*ERR*"; break; 23175bc3cb74SMauro Carvalho Chehab } 23185bc3cb74SMauro Carvalho Chehab pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)", 23195bc3cb74SMauro Carvalho Chehab type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); 23205bc3cb74SMauro Carvalho Chehab } 23215bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l_printk_ioctl); 23225bc3cb74SMauro Carvalho Chehab 23235bc3cb74SMauro Carvalho Chehab static long __video_do_ioctl(struct file *file, 23245bc3cb74SMauro Carvalho Chehab unsigned int cmd, void *arg) 23255bc3cb74SMauro Carvalho Chehab { 23265bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 23275bc3cb74SMauro Carvalho Chehab const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 23285bc3cb74SMauro Carvalho Chehab bool write_only = false; 23295bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info default_info; 23305bc3cb74SMauro Carvalho Chehab const struct v4l2_ioctl_info *info; 23315bc3cb74SMauro Carvalho Chehab void *fh = file->private_data; 23325bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = NULL; 23335bc3cb74SMauro Carvalho Chehab int debug = vfd->debug; 23345bc3cb74SMauro Carvalho Chehab long ret = -ENOTTY; 23355bc3cb74SMauro Carvalho Chehab 23365bc3cb74SMauro Carvalho Chehab if (ops == NULL) { 23375bc3cb74SMauro Carvalho Chehab pr_warn("%s: has no ioctl_ops.\n", 23385bc3cb74SMauro Carvalho Chehab video_device_node_name(vfd)); 23395bc3cb74SMauro Carvalho Chehab return ret; 23405bc3cb74SMauro Carvalho Chehab } 23415bc3cb74SMauro Carvalho Chehab 2342b7284bb0SRamakrishnan Muthukrishnan if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) 23435bc3cb74SMauro Carvalho Chehab vfh = file->private_data; 23445bc3cb74SMauro Carvalho Chehab 23455bc3cb74SMauro Carvalho Chehab if (v4l2_is_known_ioctl(cmd)) { 23465bc3cb74SMauro Carvalho Chehab info = &v4l2_ioctls[_IOC_NR(cmd)]; 23475bc3cb74SMauro Carvalho Chehab 23485bc3cb74SMauro Carvalho Chehab if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) && 23495bc3cb74SMauro Carvalho Chehab !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) 23505bc3cb74SMauro Carvalho Chehab goto done; 23515bc3cb74SMauro Carvalho Chehab 2352b7284bb0SRamakrishnan Muthukrishnan if (vfh && (info->flags & INFO_FL_PRIO)) { 23535bc3cb74SMauro Carvalho Chehab ret = v4l2_prio_check(vfd->prio, vfh->prio); 23545bc3cb74SMauro Carvalho Chehab if (ret) 23555bc3cb74SMauro Carvalho Chehab goto done; 23565bc3cb74SMauro Carvalho Chehab } 23575bc3cb74SMauro Carvalho Chehab } else { 23585bc3cb74SMauro Carvalho Chehab default_info.ioctl = cmd; 23595bc3cb74SMauro Carvalho Chehab default_info.flags = 0; 23605bc3cb74SMauro Carvalho Chehab default_info.debug = v4l_print_default; 23615bc3cb74SMauro Carvalho Chehab info = &default_info; 23625bc3cb74SMauro Carvalho Chehab } 23635bc3cb74SMauro Carvalho Chehab 23645bc3cb74SMauro Carvalho Chehab write_only = _IOC_DIR(cmd) == _IOC_WRITE; 23655bc3cb74SMauro Carvalho Chehab if (info->flags & INFO_FL_STD) { 23665bc3cb74SMauro Carvalho Chehab typedef int (*vidioc_op)(struct file *file, void *fh, void *p); 23675bc3cb74SMauro Carvalho Chehab const void *p = vfd->ioctl_ops; 23685bc3cb74SMauro Carvalho Chehab const vidioc_op *vidioc = p + info->u.offset; 23695bc3cb74SMauro Carvalho Chehab 23705bc3cb74SMauro Carvalho Chehab ret = (*vidioc)(file, fh, arg); 23715bc3cb74SMauro Carvalho Chehab } else if (info->flags & INFO_FL_FUNC) { 23725bc3cb74SMauro Carvalho Chehab ret = info->u.func(ops, file, fh, arg); 23735bc3cb74SMauro Carvalho Chehab } else if (!ops->vidioc_default) { 23745bc3cb74SMauro Carvalho Chehab ret = -ENOTTY; 23755bc3cb74SMauro Carvalho Chehab } else { 23765bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_default(file, fh, 2377b7284bb0SRamakrishnan Muthukrishnan vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, 23785bc3cb74SMauro Carvalho Chehab cmd, arg); 23795bc3cb74SMauro Carvalho Chehab } 23805bc3cb74SMauro Carvalho Chehab 23815bc3cb74SMauro Carvalho Chehab done: 23825bc3cb74SMauro Carvalho Chehab if (debug) { 23835bc3cb74SMauro Carvalho Chehab v4l_printk_ioctl(video_device_node_name(vfd), cmd); 23845bc3cb74SMauro Carvalho Chehab if (ret < 0) 2385505d04bdSHans Verkuil pr_cont(": error %ld", ret); 2386505d04bdSHans Verkuil if (debug == V4L2_DEBUG_IOCTL) 23875bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 23885bc3cb74SMauro Carvalho Chehab else if (_IOC_DIR(cmd) == _IOC_NONE) 23895bc3cb74SMauro Carvalho Chehab info->debug(arg, write_only); 23905bc3cb74SMauro Carvalho Chehab else { 23915bc3cb74SMauro Carvalho Chehab pr_cont(": "); 23925bc3cb74SMauro Carvalho Chehab info->debug(arg, write_only); 23935bc3cb74SMauro Carvalho Chehab } 23945bc3cb74SMauro Carvalho Chehab } 23955bc3cb74SMauro Carvalho Chehab 23965bc3cb74SMauro Carvalho Chehab return ret; 23975bc3cb74SMauro Carvalho Chehab } 23985bc3cb74SMauro Carvalho Chehab 23995bc3cb74SMauro Carvalho Chehab static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, 2400ba2d35c1SHans Verkuil void __user **user_ptr, void ***kernel_ptr) 24015bc3cb74SMauro Carvalho Chehab { 24025bc3cb74SMauro Carvalho Chehab int ret = 0; 24035bc3cb74SMauro Carvalho Chehab 24045bc3cb74SMauro Carvalho Chehab switch (cmd) { 240596b1a702SHans Verkuil case VIDIOC_PREPARE_BUF: 24065bc3cb74SMauro Carvalho Chehab case VIDIOC_QUERYBUF: 24075bc3cb74SMauro Carvalho Chehab case VIDIOC_QBUF: 24085bc3cb74SMauro Carvalho Chehab case VIDIOC_DQBUF: { 24095bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *buf = parg; 24105bc3cb74SMauro Carvalho Chehab 24115bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) { 24125bc3cb74SMauro Carvalho Chehab if (buf->length > VIDEO_MAX_PLANES) { 24135bc3cb74SMauro Carvalho Chehab ret = -EINVAL; 24145bc3cb74SMauro Carvalho Chehab break; 24155bc3cb74SMauro Carvalho Chehab } 24165bc3cb74SMauro Carvalho Chehab *user_ptr = (void __user *)buf->m.planes; 2417ba2d35c1SHans Verkuil *kernel_ptr = (void **)&buf->m.planes; 24185bc3cb74SMauro Carvalho Chehab *array_size = sizeof(struct v4l2_plane) * buf->length; 24195bc3cb74SMauro Carvalho Chehab ret = 1; 24205bc3cb74SMauro Carvalho Chehab } 24215bc3cb74SMauro Carvalho Chehab break; 24225bc3cb74SMauro Carvalho Chehab } 24235bc3cb74SMauro Carvalho Chehab 2424dd519bb3SHans Verkuil case VIDIOC_G_EDID: 2425dd519bb3SHans Verkuil case VIDIOC_S_EDID: { 2426dd519bb3SHans Verkuil struct v4l2_edid *edid = parg; 2427ed45ce2cSHans Verkuil 2428ed45ce2cSHans Verkuil if (edid->blocks) { 24291b8b10ccSHans Verkuil if (edid->blocks > 256) { 24301b8b10ccSHans Verkuil ret = -EINVAL; 24311b8b10ccSHans Verkuil break; 24321b8b10ccSHans Verkuil } 2433ed45ce2cSHans Verkuil *user_ptr = (void __user *)edid->edid; 2434ba2d35c1SHans Verkuil *kernel_ptr = (void **)&edid->edid; 2435ed45ce2cSHans Verkuil *array_size = edid->blocks * 128; 2436ed45ce2cSHans Verkuil ret = 1; 2437ed45ce2cSHans Verkuil } 2438ed45ce2cSHans Verkuil break; 2439ed45ce2cSHans Verkuil } 2440ed45ce2cSHans Verkuil 24415bc3cb74SMauro Carvalho Chehab case VIDIOC_S_EXT_CTRLS: 24425bc3cb74SMauro Carvalho Chehab case VIDIOC_G_EXT_CTRLS: 24435bc3cb74SMauro Carvalho Chehab case VIDIOC_TRY_EXT_CTRLS: { 24445bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *ctrls = parg; 24455bc3cb74SMauro Carvalho Chehab 24465bc3cb74SMauro Carvalho Chehab if (ctrls->count != 0) { 24475bc3cb74SMauro Carvalho Chehab if (ctrls->count > V4L2_CID_MAX_CTRLS) { 24485bc3cb74SMauro Carvalho Chehab ret = -EINVAL; 24495bc3cb74SMauro Carvalho Chehab break; 24505bc3cb74SMauro Carvalho Chehab } 24515bc3cb74SMauro Carvalho Chehab *user_ptr = (void __user *)ctrls->controls; 2452ba2d35c1SHans Verkuil *kernel_ptr = (void **)&ctrls->controls; 24535bc3cb74SMauro Carvalho Chehab *array_size = sizeof(struct v4l2_ext_control) 24545bc3cb74SMauro Carvalho Chehab * ctrls->count; 24555bc3cb74SMauro Carvalho Chehab ret = 1; 24565bc3cb74SMauro Carvalho Chehab } 24575bc3cb74SMauro Carvalho Chehab break; 24585bc3cb74SMauro Carvalho Chehab } 24595bc3cb74SMauro Carvalho Chehab } 24605bc3cb74SMauro Carvalho Chehab 24615bc3cb74SMauro Carvalho Chehab return ret; 24625bc3cb74SMauro Carvalho Chehab } 24635bc3cb74SMauro Carvalho Chehab 24645bc3cb74SMauro Carvalho Chehab long 24655bc3cb74SMauro Carvalho Chehab video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, 24665bc3cb74SMauro Carvalho Chehab v4l2_kioctl func) 24675bc3cb74SMauro Carvalho Chehab { 24685bc3cb74SMauro Carvalho Chehab char sbuf[128]; 24695bc3cb74SMauro Carvalho Chehab void *mbuf = NULL; 24705bc3cb74SMauro Carvalho Chehab void *parg = (void *)arg; 24715bc3cb74SMauro Carvalho Chehab long err = -EINVAL; 24725bc3cb74SMauro Carvalho Chehab bool has_array_args; 24735bc3cb74SMauro Carvalho Chehab size_t array_size = 0; 24745bc3cb74SMauro Carvalho Chehab void __user *user_ptr = NULL; 24755bc3cb74SMauro Carvalho Chehab void **kernel_ptr = NULL; 24765bc3cb74SMauro Carvalho Chehab 24775bc3cb74SMauro Carvalho Chehab /* Copy arguments into temp kernel buffer */ 24785bc3cb74SMauro Carvalho Chehab if (_IOC_DIR(cmd) != _IOC_NONE) { 24795bc3cb74SMauro Carvalho Chehab if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { 24805bc3cb74SMauro Carvalho Chehab parg = sbuf; 24815bc3cb74SMauro Carvalho Chehab } else { 24825bc3cb74SMauro Carvalho Chehab /* too big to allocate from stack */ 24835bc3cb74SMauro Carvalho Chehab mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); 24845bc3cb74SMauro Carvalho Chehab if (NULL == mbuf) 24855bc3cb74SMauro Carvalho Chehab return -ENOMEM; 24865bc3cb74SMauro Carvalho Chehab parg = mbuf; 24875bc3cb74SMauro Carvalho Chehab } 24885bc3cb74SMauro Carvalho Chehab 24895bc3cb74SMauro Carvalho Chehab err = -EFAULT; 24905bc3cb74SMauro Carvalho Chehab if (_IOC_DIR(cmd) & _IOC_WRITE) { 24915bc3cb74SMauro Carvalho Chehab unsigned int n = _IOC_SIZE(cmd); 24925bc3cb74SMauro Carvalho Chehab 24935bc3cb74SMauro Carvalho Chehab /* 24945bc3cb74SMauro Carvalho Chehab * In some cases, only a few fields are used as input, 24955bc3cb74SMauro Carvalho Chehab * i.e. when the app sets "index" and then the driver 24965bc3cb74SMauro Carvalho Chehab * fills in the rest of the structure for the thing 24975bc3cb74SMauro Carvalho Chehab * with that index. We only need to copy up the first 24985bc3cb74SMauro Carvalho Chehab * non-input field. 24995bc3cb74SMauro Carvalho Chehab */ 25005bc3cb74SMauro Carvalho Chehab if (v4l2_is_known_ioctl(cmd)) { 25015bc3cb74SMauro Carvalho Chehab u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; 25025bc3cb74SMauro Carvalho Chehab if (flags & INFO_FL_CLEAR_MASK) 25035bc3cb74SMauro Carvalho Chehab n = (flags & INFO_FL_CLEAR_MASK) >> 16; 25045bc3cb74SMauro Carvalho Chehab } 25055bc3cb74SMauro Carvalho Chehab 25065bc3cb74SMauro Carvalho Chehab if (copy_from_user(parg, (void __user *)arg, n)) 25075bc3cb74SMauro Carvalho Chehab goto out; 25085bc3cb74SMauro Carvalho Chehab 25095bc3cb74SMauro Carvalho Chehab /* zero out anything we don't copy from userspace */ 25105bc3cb74SMauro Carvalho Chehab if (n < _IOC_SIZE(cmd)) 25115bc3cb74SMauro Carvalho Chehab memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); 25125bc3cb74SMauro Carvalho Chehab } else { 25135bc3cb74SMauro Carvalho Chehab /* read-only ioctl */ 25145bc3cb74SMauro Carvalho Chehab memset(parg, 0, _IOC_SIZE(cmd)); 25155bc3cb74SMauro Carvalho Chehab } 25165bc3cb74SMauro Carvalho Chehab } 25175bc3cb74SMauro Carvalho Chehab 25185bc3cb74SMauro Carvalho Chehab err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr); 25195bc3cb74SMauro Carvalho Chehab if (err < 0) 25205bc3cb74SMauro Carvalho Chehab goto out; 25215bc3cb74SMauro Carvalho Chehab has_array_args = err; 25225bc3cb74SMauro Carvalho Chehab 25235bc3cb74SMauro Carvalho Chehab if (has_array_args) { 25245bc3cb74SMauro Carvalho Chehab /* 25255bc3cb74SMauro Carvalho Chehab * When adding new types of array args, make sure that the 25265bc3cb74SMauro Carvalho Chehab * parent argument to ioctl (which contains the pointer to the 25275bc3cb74SMauro Carvalho Chehab * array) fits into sbuf (so that mbuf will still remain 25285bc3cb74SMauro Carvalho Chehab * unused up to here). 25295bc3cb74SMauro Carvalho Chehab */ 25305bc3cb74SMauro Carvalho Chehab mbuf = kmalloc(array_size, GFP_KERNEL); 25315bc3cb74SMauro Carvalho Chehab err = -ENOMEM; 25325bc3cb74SMauro Carvalho Chehab if (NULL == mbuf) 25335bc3cb74SMauro Carvalho Chehab goto out_array_args; 25345bc3cb74SMauro Carvalho Chehab err = -EFAULT; 25355bc3cb74SMauro Carvalho Chehab if (copy_from_user(mbuf, user_ptr, array_size)) 25365bc3cb74SMauro Carvalho Chehab goto out_array_args; 25375bc3cb74SMauro Carvalho Chehab *kernel_ptr = mbuf; 25385bc3cb74SMauro Carvalho Chehab } 25395bc3cb74SMauro Carvalho Chehab 25405bc3cb74SMauro Carvalho Chehab /* Handles IOCTL */ 25415bc3cb74SMauro Carvalho Chehab err = func(file, cmd, parg); 25425bc3cb74SMauro Carvalho Chehab if (err == -ENOIOCTLCMD) 25435bc3cb74SMauro Carvalho Chehab err = -ENOTTY; 2544aa32f4c0SHans Verkuil if (err == 0) { 2545aa32f4c0SHans Verkuil if (cmd == VIDIOC_DQBUF) 2546aa32f4c0SHans Verkuil trace_v4l2_dqbuf(video_devdata(file)->minor, parg); 2547aa32f4c0SHans Verkuil else if (cmd == VIDIOC_QBUF) 2548aa32f4c0SHans Verkuil trace_v4l2_qbuf(video_devdata(file)->minor, parg); 2549aa32f4c0SHans Verkuil } 25505bc3cb74SMauro Carvalho Chehab 25515bc3cb74SMauro Carvalho Chehab if (has_array_args) { 2552ba2d35c1SHans Verkuil *kernel_ptr = (void __force *)user_ptr; 25535bc3cb74SMauro Carvalho Chehab if (copy_to_user(user_ptr, mbuf, array_size)) 25545bc3cb74SMauro Carvalho Chehab err = -EFAULT; 25555bc3cb74SMauro Carvalho Chehab goto out_array_args; 25565bc3cb74SMauro Carvalho Chehab } 25575bc3cb74SMauro Carvalho Chehab /* VIDIOC_QUERY_DV_TIMINGS can return an error, but still have valid 25585bc3cb74SMauro Carvalho Chehab results that must be returned. */ 25595bc3cb74SMauro Carvalho Chehab if (err < 0 && cmd != VIDIOC_QUERY_DV_TIMINGS) 25605bc3cb74SMauro Carvalho Chehab goto out; 25615bc3cb74SMauro Carvalho Chehab 25625bc3cb74SMauro Carvalho Chehab out_array_args: 25635bc3cb74SMauro Carvalho Chehab /* Copy results into user buffer */ 25645bc3cb74SMauro Carvalho Chehab switch (_IOC_DIR(cmd)) { 25655bc3cb74SMauro Carvalho Chehab case _IOC_READ: 25665bc3cb74SMauro Carvalho Chehab case (_IOC_WRITE | _IOC_READ): 25675bc3cb74SMauro Carvalho Chehab if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) 25685bc3cb74SMauro Carvalho Chehab err = -EFAULT; 25695bc3cb74SMauro Carvalho Chehab break; 25705bc3cb74SMauro Carvalho Chehab } 25715bc3cb74SMauro Carvalho Chehab 25725bc3cb74SMauro Carvalho Chehab out: 25735bc3cb74SMauro Carvalho Chehab kfree(mbuf); 25745bc3cb74SMauro Carvalho Chehab return err; 25755bc3cb74SMauro Carvalho Chehab } 25765bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_usercopy); 25775bc3cb74SMauro Carvalho Chehab 25785bc3cb74SMauro Carvalho Chehab long video_ioctl2(struct file *file, 25795bc3cb74SMauro Carvalho Chehab unsigned int cmd, unsigned long arg) 25805bc3cb74SMauro Carvalho Chehab { 25815bc3cb74SMauro Carvalho Chehab return video_usercopy(file, cmd, arg, __video_do_ioctl); 25825bc3cb74SMauro Carvalho Chehab } 25835bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_ioctl2); 2584