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, " 2601e8faa59SHans Verkuil "flags=0x%x, ycbcr_enc=%u, quantization=%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, 268736d96b5SHans Verkuil pix->colorspace, pix->flags, pix->ycbcr_enc, 269736d96b5SHans Verkuil pix->quantization); 2705bc3cb74SMauro Carvalho Chehab break; 2715bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 2725bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 2735bc3cb74SMauro Carvalho Chehab mp = &p->fmt.pix_mp; 2745bc3cb74SMauro Carvalho Chehab pr_cont(", width=%u, height=%u, " 2755bc3cb74SMauro Carvalho Chehab "format=%c%c%c%c, field=%s, " 2761e8faa59SHans Verkuil "colorspace=%d, num_planes=%u, flags=0x%x, " 277736d96b5SHans Verkuil "ycbcr_enc=%u, quantization=%u\n", 2785bc3cb74SMauro Carvalho Chehab mp->width, mp->height, 2795bc3cb74SMauro Carvalho Chehab (mp->pixelformat & 0xff), 2805bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 8) & 0xff, 2815bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 16) & 0xff, 2825bc3cb74SMauro Carvalho Chehab (mp->pixelformat >> 24) & 0xff, 2835bc3cb74SMauro Carvalho Chehab prt_names(mp->field, v4l2_field_names), 284736d96b5SHans Verkuil mp->colorspace, mp->num_planes, mp->flags, 285736d96b5SHans Verkuil mp->ycbcr_enc, mp->quantization); 2865bc3cb74SMauro Carvalho Chehab for (i = 0; i < mp->num_planes; i++) 2875bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i, 2885bc3cb74SMauro Carvalho Chehab mp->plane_fmt[i].bytesperline, 2895bc3cb74SMauro Carvalho Chehab mp->plane_fmt[i].sizeimage); 2905bc3cb74SMauro Carvalho Chehab break; 2915bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 2925bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 2935bc3cb74SMauro Carvalho Chehab win = &p->fmt.win; 294560dde24SHans Verkuil /* Note: we can't print the clip list here since the clips 295560dde24SHans Verkuil * pointer is a userspace pointer, not a kernelspace 296560dde24SHans Verkuil * pointer. */ 297560dde24SHans 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", 298560dde24SHans Verkuil win->w.width, win->w.height, win->w.left, win->w.top, 2995bc3cb74SMauro Carvalho Chehab prt_names(win->field, v4l2_field_names), 300560dde24SHans Verkuil win->chromakey, win->clipcount, win->clips, 301560dde24SHans Verkuil win->bitmap, win->global_alpha); 3025bc3cb74SMauro Carvalho Chehab break; 3035bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_CAPTURE: 3045bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 3055bc3cb74SMauro Carvalho Chehab vbi = &p->fmt.vbi; 3065bc3cb74SMauro Carvalho Chehab pr_cont(", sampling_rate=%u, offset=%u, samples_per_line=%u, " 3075bc3cb74SMauro Carvalho Chehab "sample_format=%c%c%c%c, start=%u,%u, count=%u,%u\n", 3085bc3cb74SMauro Carvalho Chehab vbi->sampling_rate, vbi->offset, 3095bc3cb74SMauro Carvalho Chehab vbi->samples_per_line, 3105bc3cb74SMauro Carvalho Chehab (vbi->sample_format & 0xff), 3115bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 8) & 0xff, 3125bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 16) & 0xff, 3135bc3cb74SMauro Carvalho Chehab (vbi->sample_format >> 24) & 0xff, 3145bc3cb74SMauro Carvalho Chehab vbi->start[0], vbi->start[1], 3155bc3cb74SMauro Carvalho Chehab vbi->count[0], vbi->count[1]); 3165bc3cb74SMauro Carvalho Chehab break; 3175bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 3185bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 3195bc3cb74SMauro Carvalho Chehab sliced = &p->fmt.sliced; 3205bc3cb74SMauro Carvalho Chehab pr_cont(", service_set=0x%08x, io_size=%d\n", 3215bc3cb74SMauro Carvalho Chehab sliced->service_set, sliced->io_size); 3225bc3cb74SMauro Carvalho Chehab for (i = 0; i < 24; i++) 3235bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, 3245bc3cb74SMauro Carvalho Chehab sliced->service_lines[0][i], 3255bc3cb74SMauro Carvalho Chehab sliced->service_lines[1][i]); 3265bc3cb74SMauro Carvalho Chehab break; 327582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 328582c52cbSAntti Palosaari sdr = &p->fmt.sdr; 329582c52cbSAntti Palosaari pr_cont(", pixelformat=%c%c%c%c\n", 330582c52cbSAntti Palosaari (sdr->pixelformat >> 0) & 0xff, 331582c52cbSAntti Palosaari (sdr->pixelformat >> 8) & 0xff, 332582c52cbSAntti Palosaari (sdr->pixelformat >> 16) & 0xff, 333582c52cbSAntti Palosaari (sdr->pixelformat >> 24) & 0xff); 334582c52cbSAntti Palosaari break; 3355bc3cb74SMauro Carvalho Chehab } 3365bc3cb74SMauro Carvalho Chehab } 3375bc3cb74SMauro Carvalho Chehab 3385bc3cb74SMauro Carvalho Chehab static void v4l_print_framebuffer(const void *arg, bool write_only) 3395bc3cb74SMauro Carvalho Chehab { 3405bc3cb74SMauro Carvalho Chehab const struct v4l2_framebuffer *p = arg; 3415bc3cb74SMauro Carvalho Chehab 3425bc3cb74SMauro Carvalho Chehab pr_cont("capability=0x%x, flags=0x%x, base=0x%p, width=%u, " 3435bc3cb74SMauro Carvalho Chehab "height=%u, pixelformat=%c%c%c%c, " 344560dde24SHans Verkuil "bytesperline=%u, sizeimage=%u, colorspace=%d\n", 3455bc3cb74SMauro Carvalho Chehab p->capability, p->flags, p->base, 3465bc3cb74SMauro Carvalho Chehab p->fmt.width, p->fmt.height, 3475bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat & 0xff), 3485bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 8) & 0xff, 3495bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 16) & 0xff, 3505bc3cb74SMauro Carvalho Chehab (p->fmt.pixelformat >> 24) & 0xff, 3515bc3cb74SMauro Carvalho Chehab p->fmt.bytesperline, p->fmt.sizeimage, 3525bc3cb74SMauro Carvalho Chehab p->fmt.colorspace); 3535bc3cb74SMauro Carvalho Chehab } 3545bc3cb74SMauro Carvalho Chehab 3555bc3cb74SMauro Carvalho Chehab static void v4l_print_buftype(const void *arg, bool write_only) 3565bc3cb74SMauro Carvalho Chehab { 3575bc3cb74SMauro Carvalho Chehab pr_cont("type=%s\n", prt_names(*(u32 *)arg, v4l2_type_names)); 3585bc3cb74SMauro Carvalho Chehab } 3595bc3cb74SMauro Carvalho Chehab 3605bc3cb74SMauro Carvalho Chehab static void v4l_print_modulator(const void *arg, bool write_only) 3615bc3cb74SMauro Carvalho Chehab { 3625bc3cb74SMauro Carvalho Chehab const struct v4l2_modulator *p = arg; 3635bc3cb74SMauro Carvalho Chehab 3645bc3cb74SMauro Carvalho Chehab if (write_only) 365560dde24SHans Verkuil pr_cont("index=%u, txsubchans=0x%x\n", p->index, p->txsubchans); 3665bc3cb74SMauro Carvalho Chehab else 36727d5a87cSHans Verkuil pr_cont("index=%u, name=%.*s, capability=0x%x, " 3685bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, txsubchans=0x%x\n", 36927d5a87cSHans Verkuil p->index, (int)sizeof(p->name), p->name, p->capability, 3705bc3cb74SMauro Carvalho Chehab p->rangelow, p->rangehigh, p->txsubchans); 3715bc3cb74SMauro Carvalho Chehab } 3725bc3cb74SMauro Carvalho Chehab 3735bc3cb74SMauro Carvalho Chehab static void v4l_print_tuner(const void *arg, bool write_only) 3745bc3cb74SMauro Carvalho Chehab { 3755bc3cb74SMauro Carvalho Chehab const struct v4l2_tuner *p = arg; 3765bc3cb74SMauro Carvalho Chehab 3775bc3cb74SMauro Carvalho Chehab if (write_only) 3785bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, audmode=%u\n", p->index, p->audmode); 3795bc3cb74SMauro Carvalho Chehab else 38027d5a87cSHans Verkuil pr_cont("index=%u, name=%.*s, type=%u, capability=0x%x, " 3815bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, signal=%u, afc=%d, " 3825bc3cb74SMauro Carvalho Chehab "rxsubchans=0x%x, audmode=%u\n", 38327d5a87cSHans Verkuil p->index, (int)sizeof(p->name), p->name, p->type, 3845bc3cb74SMauro Carvalho Chehab p->capability, p->rangelow, 3855bc3cb74SMauro Carvalho Chehab p->rangehigh, p->signal, p->afc, 3865bc3cb74SMauro Carvalho Chehab p->rxsubchans, p->audmode); 3875bc3cb74SMauro Carvalho Chehab } 3885bc3cb74SMauro Carvalho Chehab 3895bc3cb74SMauro Carvalho Chehab static void v4l_print_frequency(const void *arg, bool write_only) 3905bc3cb74SMauro Carvalho Chehab { 3915bc3cb74SMauro Carvalho Chehab const struct v4l2_frequency *p = arg; 3925bc3cb74SMauro Carvalho Chehab 3935bc3cb74SMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, frequency=%u\n", 3945bc3cb74SMauro Carvalho Chehab p->tuner, p->type, p->frequency); 3955bc3cb74SMauro Carvalho Chehab } 3965bc3cb74SMauro Carvalho Chehab 3975bc3cb74SMauro Carvalho Chehab static void v4l_print_standard(const void *arg, bool write_only) 3985bc3cb74SMauro Carvalho Chehab { 3995bc3cb74SMauro Carvalho Chehab const struct v4l2_standard *p = arg; 4005bc3cb74SMauro Carvalho Chehab 40127d5a87cSHans Verkuil pr_cont("index=%u, id=0x%Lx, name=%.*s, fps=%u/%u, " 4025bc3cb74SMauro Carvalho Chehab "framelines=%u\n", p->index, 40327d5a87cSHans Verkuil (unsigned long long)p->id, (int)sizeof(p->name), p->name, 4045bc3cb74SMauro Carvalho Chehab p->frameperiod.numerator, 4055bc3cb74SMauro Carvalho Chehab p->frameperiod.denominator, 4065bc3cb74SMauro Carvalho Chehab p->framelines); 4075bc3cb74SMauro Carvalho Chehab } 4085bc3cb74SMauro Carvalho Chehab 4095bc3cb74SMauro Carvalho Chehab static void v4l_print_std(const void *arg, bool write_only) 4105bc3cb74SMauro Carvalho Chehab { 4115bc3cb74SMauro Carvalho Chehab pr_cont("std=0x%08Lx\n", *(const long long unsigned *)arg); 4125bc3cb74SMauro Carvalho Chehab } 4135bc3cb74SMauro Carvalho Chehab 4145bc3cb74SMauro Carvalho Chehab static void v4l_print_hw_freq_seek(const void *arg, bool write_only) 4155bc3cb74SMauro Carvalho Chehab { 4165bc3cb74SMauro Carvalho Chehab const struct v4l2_hw_freq_seek *p = arg; 4175bc3cb74SMauro Carvalho Chehab 41879e8c7beSMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, seek_upward=%u, wrap_around=%u, spacing=%u, " 41979e8c7beSMauro Carvalho Chehab "rangelow=%u, rangehigh=%u\n", 42079e8c7beSMauro Carvalho Chehab p->tuner, p->type, p->seek_upward, p->wrap_around, p->spacing, 42179e8c7beSMauro Carvalho Chehab p->rangelow, p->rangehigh); 4225bc3cb74SMauro Carvalho Chehab } 4235bc3cb74SMauro Carvalho Chehab 4245bc3cb74SMauro Carvalho Chehab static void v4l_print_requestbuffers(const void *arg, bool write_only) 4255bc3cb74SMauro Carvalho Chehab { 4265bc3cb74SMauro Carvalho Chehab const struct v4l2_requestbuffers *p = arg; 4275bc3cb74SMauro Carvalho Chehab 4285bc3cb74SMauro Carvalho Chehab pr_cont("count=%d, type=%s, memory=%s\n", 4295bc3cb74SMauro Carvalho Chehab p->count, 4305bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 4315bc3cb74SMauro Carvalho Chehab prt_names(p->memory, v4l2_memory_names)); 4325bc3cb74SMauro Carvalho Chehab } 4335bc3cb74SMauro Carvalho Chehab 4345bc3cb74SMauro Carvalho Chehab static void v4l_print_buffer(const void *arg, bool write_only) 4355bc3cb74SMauro Carvalho Chehab { 4365bc3cb74SMauro Carvalho Chehab const struct v4l2_buffer *p = arg; 4375bc3cb74SMauro Carvalho Chehab const struct v4l2_timecode *tc = &p->timecode; 4385bc3cb74SMauro Carvalho Chehab const struct v4l2_plane *plane; 4395bc3cb74SMauro Carvalho Chehab int i; 4405bc3cb74SMauro Carvalho Chehab 4415bc3cb74SMauro Carvalho Chehab pr_cont("%02ld:%02d:%02d.%08ld index=%d, type=%s, " 4425bc3cb74SMauro Carvalho Chehab "flags=0x%08x, field=%s, sequence=%d, memory=%s", 4435bc3cb74SMauro Carvalho Chehab p->timestamp.tv_sec / 3600, 4445bc3cb74SMauro Carvalho Chehab (int)(p->timestamp.tv_sec / 60) % 60, 4455bc3cb74SMauro Carvalho Chehab (int)(p->timestamp.tv_sec % 60), 4465bc3cb74SMauro Carvalho Chehab (long)p->timestamp.tv_usec, 4475bc3cb74SMauro Carvalho Chehab p->index, 4485bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 4495bc3cb74SMauro Carvalho Chehab p->flags, prt_names(p->field, v4l2_field_names), 4505bc3cb74SMauro Carvalho Chehab p->sequence, prt_names(p->memory, v4l2_memory_names)); 4515bc3cb74SMauro Carvalho Chehab 4525bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) { 4535bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 4545bc3cb74SMauro Carvalho Chehab for (i = 0; i < p->length; ++i) { 4555bc3cb74SMauro Carvalho Chehab plane = &p->m.planes[i]; 4565bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG 457560dde24SHans Verkuil "plane %d: bytesused=%d, data_offset=0x%08x, " 4585bc3cb74SMauro Carvalho Chehab "offset/userptr=0x%lx, length=%d\n", 4595bc3cb74SMauro Carvalho Chehab i, plane->bytesused, plane->data_offset, 4605bc3cb74SMauro Carvalho Chehab plane->m.userptr, plane->length); 4615bc3cb74SMauro Carvalho Chehab } 4625bc3cb74SMauro Carvalho Chehab } else { 463560dde24SHans Verkuil pr_cont(", bytesused=%d, offset/userptr=0x%lx, length=%d\n", 4645bc3cb74SMauro Carvalho Chehab p->bytesused, p->m.userptr, p->length); 4655bc3cb74SMauro Carvalho Chehab } 4665bc3cb74SMauro Carvalho Chehab 4675bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "timecode=%02d:%02d:%02d type=%d, " 4685bc3cb74SMauro Carvalho Chehab "flags=0x%08x, frames=%d, userbits=0x%08x\n", 4695bc3cb74SMauro Carvalho Chehab tc->hours, tc->minutes, tc->seconds, 4705bc3cb74SMauro Carvalho Chehab tc->type, tc->flags, tc->frames, *(__u32 *)tc->userbits); 4715bc3cb74SMauro Carvalho Chehab } 4725bc3cb74SMauro Carvalho Chehab 473b799d09aSTomasz Stanislawski static void v4l_print_exportbuffer(const void *arg, bool write_only) 474b799d09aSTomasz Stanislawski { 475b799d09aSTomasz Stanislawski const struct v4l2_exportbuffer *p = arg; 476b799d09aSTomasz Stanislawski 477b799d09aSTomasz Stanislawski pr_cont("fd=%d, type=%s, index=%u, plane=%u, flags=0x%08x\n", 478b799d09aSTomasz Stanislawski p->fd, prt_names(p->type, v4l2_type_names), 479b799d09aSTomasz Stanislawski p->index, p->plane, p->flags); 480b799d09aSTomasz Stanislawski } 481b799d09aSTomasz Stanislawski 4825bc3cb74SMauro Carvalho Chehab static void v4l_print_create_buffers(const void *arg, bool write_only) 4835bc3cb74SMauro Carvalho Chehab { 4845bc3cb74SMauro Carvalho Chehab const struct v4l2_create_buffers *p = arg; 4855bc3cb74SMauro Carvalho Chehab 4865bc3cb74SMauro Carvalho Chehab pr_cont("index=%d, count=%d, memory=%s, ", 4875bc3cb74SMauro Carvalho Chehab p->index, p->count, 4885bc3cb74SMauro Carvalho Chehab prt_names(p->memory, v4l2_memory_names)); 4895bc3cb74SMauro Carvalho Chehab v4l_print_format(&p->format, write_only); 4905bc3cb74SMauro Carvalho Chehab } 4915bc3cb74SMauro Carvalho Chehab 4925bc3cb74SMauro Carvalho Chehab static void v4l_print_streamparm(const void *arg, bool write_only) 4935bc3cb74SMauro Carvalho Chehab { 4945bc3cb74SMauro Carvalho Chehab const struct v4l2_streamparm *p = arg; 4955bc3cb74SMauro Carvalho Chehab 4965bc3cb74SMauro Carvalho Chehab pr_cont("type=%s", prt_names(p->type, v4l2_type_names)); 4975bc3cb74SMauro Carvalho Chehab 4985bc3cb74SMauro Carvalho Chehab if (p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE || 4995bc3cb74SMauro Carvalho Chehab p->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { 5005bc3cb74SMauro Carvalho Chehab const struct v4l2_captureparm *c = &p->parm.capture; 5015bc3cb74SMauro Carvalho Chehab 5025bc3cb74SMauro Carvalho Chehab pr_cont(", capability=0x%x, capturemode=0x%x, timeperframe=%d/%d, " 5035bc3cb74SMauro Carvalho Chehab "extendedmode=%d, readbuffers=%d\n", 5045bc3cb74SMauro Carvalho Chehab c->capability, c->capturemode, 5055bc3cb74SMauro Carvalho Chehab c->timeperframe.numerator, c->timeperframe.denominator, 5065bc3cb74SMauro Carvalho Chehab c->extendedmode, c->readbuffers); 5075bc3cb74SMauro Carvalho Chehab } else if (p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT || 5085bc3cb74SMauro Carvalho Chehab p->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { 5095bc3cb74SMauro Carvalho Chehab const struct v4l2_outputparm *c = &p->parm.output; 5105bc3cb74SMauro Carvalho Chehab 5115bc3cb74SMauro Carvalho Chehab pr_cont(", capability=0x%x, outputmode=0x%x, timeperframe=%d/%d, " 5125bc3cb74SMauro Carvalho Chehab "extendedmode=%d, writebuffers=%d\n", 5135bc3cb74SMauro Carvalho Chehab c->capability, c->outputmode, 5145bc3cb74SMauro Carvalho Chehab c->timeperframe.numerator, c->timeperframe.denominator, 5155bc3cb74SMauro Carvalho Chehab c->extendedmode, c->writebuffers); 516560dde24SHans Verkuil } else { 517560dde24SHans Verkuil pr_cont("\n"); 5185bc3cb74SMauro Carvalho Chehab } 5195bc3cb74SMauro Carvalho Chehab } 5205bc3cb74SMauro Carvalho Chehab 5215bc3cb74SMauro Carvalho Chehab static void v4l_print_queryctrl(const void *arg, bool write_only) 5225bc3cb74SMauro Carvalho Chehab { 5235bc3cb74SMauro Carvalho Chehab const struct v4l2_queryctrl *p = arg; 5245bc3cb74SMauro Carvalho Chehab 52527d5a87cSHans Verkuil pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%d/%d, " 5265bc3cb74SMauro Carvalho Chehab "step=%d, default=%d, flags=0x%08x\n", 52727d5a87cSHans Verkuil p->id, p->type, (int)sizeof(p->name), p->name, 5285bc3cb74SMauro Carvalho Chehab p->minimum, p->maximum, 5295bc3cb74SMauro Carvalho Chehab p->step, p->default_value, p->flags); 5305bc3cb74SMauro Carvalho Chehab } 5315bc3cb74SMauro Carvalho Chehab 532e6bee368SHans Verkuil static void v4l_print_query_ext_ctrl(const void *arg, bool write_only) 533e6bee368SHans Verkuil { 534e6bee368SHans Verkuil const struct v4l2_query_ext_ctrl *p = arg; 535e6bee368SHans Verkuil 536e6bee368SHans Verkuil pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, " 537e6bee368SHans Verkuil "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, " 5380176077aSHans Verkuil "nr_of_dims=%u, dims=%u,%u,%u,%u\n", 539e6bee368SHans Verkuil p->id, p->type, (int)sizeof(p->name), p->name, 540e6bee368SHans Verkuil p->minimum, p->maximum, 541e6bee368SHans Verkuil p->step, p->default_value, p->flags, 542e6bee368SHans Verkuil p->elem_size, p->elems, p->nr_of_dims, 5430176077aSHans Verkuil p->dims[0], p->dims[1], p->dims[2], p->dims[3]); 544e6bee368SHans Verkuil } 545e6bee368SHans Verkuil 5465bc3cb74SMauro Carvalho Chehab static void v4l_print_querymenu(const void *arg, bool write_only) 5475bc3cb74SMauro Carvalho Chehab { 5485bc3cb74SMauro Carvalho Chehab const struct v4l2_querymenu *p = arg; 5495bc3cb74SMauro Carvalho Chehab 5505bc3cb74SMauro Carvalho Chehab pr_cont("id=0x%x, index=%d\n", p->id, p->index); 5515bc3cb74SMauro Carvalho Chehab } 5525bc3cb74SMauro Carvalho Chehab 5535bc3cb74SMauro Carvalho Chehab static void v4l_print_control(const void *arg, bool write_only) 5545bc3cb74SMauro Carvalho Chehab { 5555bc3cb74SMauro Carvalho Chehab const struct v4l2_control *p = arg; 5565bc3cb74SMauro Carvalho Chehab 5575bc3cb74SMauro Carvalho Chehab pr_cont("id=0x%x, value=%d\n", p->id, p->value); 5585bc3cb74SMauro Carvalho Chehab } 5595bc3cb74SMauro Carvalho Chehab 5605bc3cb74SMauro Carvalho Chehab static void v4l_print_ext_controls(const void *arg, bool write_only) 5615bc3cb74SMauro Carvalho Chehab { 5625bc3cb74SMauro Carvalho Chehab const struct v4l2_ext_controls *p = arg; 5635bc3cb74SMauro Carvalho Chehab int i; 5645bc3cb74SMauro Carvalho Chehab 5655bc3cb74SMauro Carvalho Chehab pr_cont("class=0x%x, count=%d, error_idx=%d", 5665bc3cb74SMauro Carvalho Chehab p->ctrl_class, p->count, p->error_idx); 5675bc3cb74SMauro Carvalho Chehab for (i = 0; i < p->count; i++) { 568017ab36aSHans Verkuil if (!p->controls[i].size) 5695bc3cb74SMauro Carvalho Chehab pr_cont(", id/val=0x%x/0x%x", 5705bc3cb74SMauro Carvalho Chehab p->controls[i].id, p->controls[i].value); 5715bc3cb74SMauro Carvalho Chehab else 5725bc3cb74SMauro Carvalho Chehab pr_cont(", id/size=0x%x/%u", 5735bc3cb74SMauro Carvalho Chehab p->controls[i].id, p->controls[i].size); 5745bc3cb74SMauro Carvalho Chehab } 5755bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 5765bc3cb74SMauro Carvalho Chehab } 5775bc3cb74SMauro Carvalho Chehab 5785bc3cb74SMauro Carvalho Chehab static void v4l_print_cropcap(const void *arg, bool write_only) 5795bc3cb74SMauro Carvalho Chehab { 5805bc3cb74SMauro Carvalho Chehab const struct v4l2_cropcap *p = arg; 5815bc3cb74SMauro Carvalho Chehab 5825bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, " 583a112fbafSHans Verkuil "defrect wxh=%dx%d, x,y=%d,%d, " 5845bc3cb74SMauro Carvalho Chehab "pixelaspect %d/%d\n", 5855bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 5865bc3cb74SMauro Carvalho Chehab p->bounds.width, p->bounds.height, 5875bc3cb74SMauro Carvalho Chehab p->bounds.left, p->bounds.top, 5885bc3cb74SMauro Carvalho Chehab p->defrect.width, p->defrect.height, 5895bc3cb74SMauro Carvalho Chehab p->defrect.left, p->defrect.top, 5905bc3cb74SMauro Carvalho Chehab p->pixelaspect.numerator, p->pixelaspect.denominator); 5915bc3cb74SMauro Carvalho Chehab } 5925bc3cb74SMauro Carvalho Chehab 5935bc3cb74SMauro Carvalho Chehab static void v4l_print_crop(const void *arg, bool write_only) 5945bc3cb74SMauro Carvalho Chehab { 5955bc3cb74SMauro Carvalho Chehab const struct v4l2_crop *p = arg; 5965bc3cb74SMauro Carvalho Chehab 5975bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n", 5985bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 5995bc3cb74SMauro Carvalho Chehab p->c.width, p->c.height, 6005bc3cb74SMauro Carvalho Chehab p->c.left, p->c.top); 6015bc3cb74SMauro Carvalho Chehab } 6025bc3cb74SMauro Carvalho Chehab 6035bc3cb74SMauro Carvalho Chehab static void v4l_print_selection(const void *arg, bool write_only) 6045bc3cb74SMauro Carvalho Chehab { 6055bc3cb74SMauro Carvalho Chehab const struct v4l2_selection *p = arg; 6065bc3cb74SMauro Carvalho Chehab 6075bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n", 6085bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), 6095bc3cb74SMauro Carvalho Chehab p->target, p->flags, 6105bc3cb74SMauro Carvalho Chehab p->r.width, p->r.height, p->r.left, p->r.top); 6115bc3cb74SMauro Carvalho Chehab } 6125bc3cb74SMauro Carvalho Chehab 6135bc3cb74SMauro Carvalho Chehab static void v4l_print_jpegcompression(const void *arg, bool write_only) 6145bc3cb74SMauro Carvalho Chehab { 6155bc3cb74SMauro Carvalho Chehab const struct v4l2_jpegcompression *p = arg; 6165bc3cb74SMauro Carvalho Chehab 6175bc3cb74SMauro Carvalho Chehab pr_cont("quality=%d, APPn=%d, APP_len=%d, " 6185bc3cb74SMauro Carvalho Chehab "COM_len=%d, jpeg_markers=0x%x\n", 6195bc3cb74SMauro Carvalho Chehab p->quality, p->APPn, p->APP_len, 6205bc3cb74SMauro Carvalho Chehab p->COM_len, p->jpeg_markers); 6215bc3cb74SMauro Carvalho Chehab } 6225bc3cb74SMauro Carvalho Chehab 6235bc3cb74SMauro Carvalho Chehab static void v4l_print_enc_idx(const void *arg, bool write_only) 6245bc3cb74SMauro Carvalho Chehab { 6255bc3cb74SMauro Carvalho Chehab const struct v4l2_enc_idx *p = arg; 6265bc3cb74SMauro Carvalho Chehab 6275bc3cb74SMauro Carvalho Chehab pr_cont("entries=%d, entries_cap=%d\n", 6285bc3cb74SMauro Carvalho Chehab p->entries, p->entries_cap); 6295bc3cb74SMauro Carvalho Chehab } 6305bc3cb74SMauro Carvalho Chehab 6315bc3cb74SMauro Carvalho Chehab static void v4l_print_encoder_cmd(const void *arg, bool write_only) 6325bc3cb74SMauro Carvalho Chehab { 6335bc3cb74SMauro Carvalho Chehab const struct v4l2_encoder_cmd *p = arg; 6345bc3cb74SMauro Carvalho Chehab 6355bc3cb74SMauro Carvalho Chehab pr_cont("cmd=%d, flags=0x%x\n", 6365bc3cb74SMauro Carvalho Chehab p->cmd, p->flags); 6375bc3cb74SMauro Carvalho Chehab } 6385bc3cb74SMauro Carvalho Chehab 6395bc3cb74SMauro Carvalho Chehab static void v4l_print_decoder_cmd(const void *arg, bool write_only) 6405bc3cb74SMauro Carvalho Chehab { 6415bc3cb74SMauro Carvalho Chehab const struct v4l2_decoder_cmd *p = arg; 6425bc3cb74SMauro Carvalho Chehab 6435bc3cb74SMauro Carvalho Chehab pr_cont("cmd=%d, flags=0x%x\n", p->cmd, p->flags); 6445bc3cb74SMauro Carvalho Chehab 6455bc3cb74SMauro Carvalho Chehab if (p->cmd == V4L2_DEC_CMD_START) 6465bc3cb74SMauro Carvalho Chehab pr_info("speed=%d, format=%u\n", 6475bc3cb74SMauro Carvalho Chehab p->start.speed, p->start.format); 6485bc3cb74SMauro Carvalho Chehab else if (p->cmd == V4L2_DEC_CMD_STOP) 6495bc3cb74SMauro Carvalho Chehab pr_info("pts=%llu\n", p->stop.pts); 6505bc3cb74SMauro Carvalho Chehab } 6515bc3cb74SMauro Carvalho Chehab 65296b03d2aSHans Verkuil static void v4l_print_dbg_chip_info(const void *arg, bool write_only) 65379b0c640SHans Verkuil { 65496b03d2aSHans Verkuil const struct v4l2_dbg_chip_info *p = arg; 65579b0c640SHans Verkuil 65679b0c640SHans Verkuil pr_cont("type=%u, ", p->match.type); 6573eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) 65879b0c640SHans Verkuil pr_cont("name=%.*s, ", 65979b0c640SHans Verkuil (int)sizeof(p->match.name), p->match.name); 66079b0c640SHans Verkuil else 66179b0c640SHans Verkuil pr_cont("addr=%u, ", p->match.addr); 66279b0c640SHans Verkuil pr_cont("name=%.*s\n", (int)sizeof(p->name), p->name); 66379b0c640SHans Verkuil } 66479b0c640SHans Verkuil 6655bc3cb74SMauro Carvalho Chehab static void v4l_print_dbg_register(const void *arg, bool write_only) 6665bc3cb74SMauro Carvalho Chehab { 6675bc3cb74SMauro Carvalho Chehab const struct v4l2_dbg_register *p = arg; 6685bc3cb74SMauro Carvalho Chehab 6695bc3cb74SMauro Carvalho Chehab pr_cont("type=%u, ", p->match.type); 6703eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_I2C_DRIVER) 67127d5a87cSHans Verkuil pr_cont("name=%.*s, ", 67227d5a87cSHans Verkuil (int)sizeof(p->match.name), p->match.name); 6735bc3cb74SMauro Carvalho Chehab else 6745bc3cb74SMauro Carvalho Chehab pr_cont("addr=%u, ", p->match.addr); 6755bc3cb74SMauro Carvalho Chehab pr_cont("reg=0x%llx, val=0x%llx\n", 6765bc3cb74SMauro Carvalho Chehab p->reg, p->val); 6775bc3cb74SMauro Carvalho Chehab } 6785bc3cb74SMauro Carvalho Chehab 6795bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings(const void *arg, bool write_only) 6805bc3cb74SMauro Carvalho Chehab { 6815bc3cb74SMauro Carvalho Chehab const struct v4l2_dv_timings *p = arg; 6825bc3cb74SMauro Carvalho Chehab 6835bc3cb74SMauro Carvalho Chehab switch (p->type) { 6845bc3cb74SMauro Carvalho Chehab case V4L2_DV_BT_656_1120: 6855bc3cb74SMauro Carvalho Chehab pr_cont("type=bt-656/1120, interlaced=%u, " 6865bc3cb74SMauro Carvalho Chehab "pixelclock=%llu, " 6875bc3cb74SMauro Carvalho Chehab "width=%u, height=%u, polarities=0x%x, " 6885bc3cb74SMauro Carvalho Chehab "hfrontporch=%u, hsync=%u, " 6895bc3cb74SMauro Carvalho Chehab "hbackporch=%u, vfrontporch=%u, " 6905bc3cb74SMauro Carvalho Chehab "vsync=%u, vbackporch=%u, " 6915bc3cb74SMauro Carvalho Chehab "il_vfrontporch=%u, il_vsync=%u, " 6925bc3cb74SMauro Carvalho Chehab "il_vbackporch=%u, standards=0x%x, flags=0x%x\n", 6935bc3cb74SMauro Carvalho Chehab p->bt.interlaced, p->bt.pixelclock, 6945bc3cb74SMauro Carvalho Chehab p->bt.width, p->bt.height, 6955bc3cb74SMauro Carvalho Chehab p->bt.polarities, p->bt.hfrontporch, 6965bc3cb74SMauro Carvalho Chehab p->bt.hsync, p->bt.hbackporch, 6975bc3cb74SMauro Carvalho Chehab p->bt.vfrontporch, p->bt.vsync, 6985bc3cb74SMauro Carvalho Chehab p->bt.vbackporch, p->bt.il_vfrontporch, 6995bc3cb74SMauro Carvalho Chehab p->bt.il_vsync, p->bt.il_vbackporch, 7005bc3cb74SMauro Carvalho Chehab p->bt.standards, p->bt.flags); 7015bc3cb74SMauro Carvalho Chehab break; 7025bc3cb74SMauro Carvalho Chehab default: 7035bc3cb74SMauro Carvalho Chehab pr_cont("type=%d\n", p->type); 7045bc3cb74SMauro Carvalho Chehab break; 7055bc3cb74SMauro Carvalho Chehab } 7065bc3cb74SMauro Carvalho Chehab } 7075bc3cb74SMauro Carvalho Chehab 7085bc3cb74SMauro Carvalho Chehab static void v4l_print_enum_dv_timings(const void *arg, bool write_only) 7095bc3cb74SMauro Carvalho Chehab { 7105bc3cb74SMauro Carvalho Chehab const struct v4l2_enum_dv_timings *p = arg; 7115bc3cb74SMauro Carvalho Chehab 7125bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, ", p->index); 7135bc3cb74SMauro Carvalho Chehab v4l_print_dv_timings(&p->timings, write_only); 7145bc3cb74SMauro Carvalho Chehab } 7155bc3cb74SMauro Carvalho Chehab 7165bc3cb74SMauro Carvalho Chehab static void v4l_print_dv_timings_cap(const void *arg, bool write_only) 7175bc3cb74SMauro Carvalho Chehab { 7185bc3cb74SMauro Carvalho Chehab const struct v4l2_dv_timings_cap *p = arg; 7195bc3cb74SMauro Carvalho Chehab 7205bc3cb74SMauro Carvalho Chehab switch (p->type) { 7215bc3cb74SMauro Carvalho Chehab case V4L2_DV_BT_656_1120: 7225bc3cb74SMauro Carvalho Chehab pr_cont("type=bt-656/1120, width=%u-%u, height=%u-%u, " 7235bc3cb74SMauro Carvalho Chehab "pixelclock=%llu-%llu, standards=0x%x, capabilities=0x%x\n", 7245bc3cb74SMauro Carvalho Chehab p->bt.min_width, p->bt.max_width, 7255bc3cb74SMauro Carvalho Chehab p->bt.min_height, p->bt.max_height, 7265bc3cb74SMauro Carvalho Chehab p->bt.min_pixelclock, p->bt.max_pixelclock, 7275bc3cb74SMauro Carvalho Chehab p->bt.standards, p->bt.capabilities); 7285bc3cb74SMauro Carvalho Chehab break; 7295bc3cb74SMauro Carvalho Chehab default: 7305bc3cb74SMauro Carvalho Chehab pr_cont("type=%u\n", p->type); 7315bc3cb74SMauro Carvalho Chehab break; 7325bc3cb74SMauro Carvalho Chehab } 7335bc3cb74SMauro Carvalho Chehab } 7345bc3cb74SMauro Carvalho Chehab 7355bc3cb74SMauro Carvalho Chehab static void v4l_print_frmsizeenum(const void *arg, bool write_only) 7365bc3cb74SMauro Carvalho Chehab { 7375bc3cb74SMauro Carvalho Chehab const struct v4l2_frmsizeenum *p = arg; 7385bc3cb74SMauro Carvalho Chehab 7395bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, pixelformat=%c%c%c%c, type=%u", 7405bc3cb74SMauro Carvalho Chehab p->index, 7415bc3cb74SMauro Carvalho Chehab (p->pixel_format & 0xff), 7425bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 8) & 0xff, 7435bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 16) & 0xff, 7445bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 24) & 0xff, 7455bc3cb74SMauro Carvalho Chehab p->type); 7465bc3cb74SMauro Carvalho Chehab switch (p->type) { 7475bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_DISCRETE: 748560dde24SHans Verkuil pr_cont(", wxh=%ux%u\n", 7495bc3cb74SMauro Carvalho Chehab p->discrete.width, p->discrete.height); 7505bc3cb74SMauro Carvalho Chehab break; 7515bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_STEPWISE: 752560dde24SHans Verkuil pr_cont(", min=%ux%u, max=%ux%u, step=%ux%u\n", 7535bc3cb74SMauro Carvalho Chehab p->stepwise.min_width, p->stepwise.min_height, 7545bc3cb74SMauro Carvalho Chehab p->stepwise.step_width, p->stepwise.step_height, 7555bc3cb74SMauro Carvalho Chehab p->stepwise.max_width, p->stepwise.max_height); 7565bc3cb74SMauro Carvalho Chehab break; 7575bc3cb74SMauro Carvalho Chehab case V4L2_FRMSIZE_TYPE_CONTINUOUS: 7585bc3cb74SMauro Carvalho Chehab /* fall through */ 7595bc3cb74SMauro Carvalho Chehab default: 7605bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 7615bc3cb74SMauro Carvalho Chehab break; 7625bc3cb74SMauro Carvalho Chehab } 7635bc3cb74SMauro Carvalho Chehab } 7645bc3cb74SMauro Carvalho Chehab 7655bc3cb74SMauro Carvalho Chehab static void v4l_print_frmivalenum(const void *arg, bool write_only) 7665bc3cb74SMauro Carvalho Chehab { 7675bc3cb74SMauro Carvalho Chehab const struct v4l2_frmivalenum *p = arg; 7685bc3cb74SMauro Carvalho Chehab 7695bc3cb74SMauro Carvalho Chehab pr_cont("index=%u, pixelformat=%c%c%c%c, wxh=%ux%u, type=%u", 7705bc3cb74SMauro Carvalho Chehab p->index, 7715bc3cb74SMauro Carvalho Chehab (p->pixel_format & 0xff), 7725bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 8) & 0xff, 7735bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 16) & 0xff, 7745bc3cb74SMauro Carvalho Chehab (p->pixel_format >> 24) & 0xff, 7755bc3cb74SMauro Carvalho Chehab p->width, p->height, p->type); 7765bc3cb74SMauro Carvalho Chehab switch (p->type) { 7775bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_DISCRETE: 778560dde24SHans Verkuil pr_cont(", fps=%d/%d\n", 7795bc3cb74SMauro Carvalho Chehab p->discrete.numerator, 7805bc3cb74SMauro Carvalho Chehab p->discrete.denominator); 7815bc3cb74SMauro Carvalho Chehab break; 7825bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_STEPWISE: 783560dde24SHans Verkuil pr_cont(", min=%d/%d, max=%d/%d, step=%d/%d\n", 7845bc3cb74SMauro Carvalho Chehab p->stepwise.min.numerator, 7855bc3cb74SMauro Carvalho Chehab p->stepwise.min.denominator, 7865bc3cb74SMauro Carvalho Chehab p->stepwise.max.numerator, 7875bc3cb74SMauro Carvalho Chehab p->stepwise.max.denominator, 7885bc3cb74SMauro Carvalho Chehab p->stepwise.step.numerator, 7895bc3cb74SMauro Carvalho Chehab p->stepwise.step.denominator); 7905bc3cb74SMauro Carvalho Chehab break; 7915bc3cb74SMauro Carvalho Chehab case V4L2_FRMIVAL_TYPE_CONTINUOUS: 7925bc3cb74SMauro Carvalho Chehab /* fall through */ 7935bc3cb74SMauro Carvalho Chehab default: 7945bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 7955bc3cb74SMauro Carvalho Chehab break; 7965bc3cb74SMauro Carvalho Chehab } 7975bc3cb74SMauro Carvalho Chehab } 7985bc3cb74SMauro Carvalho Chehab 7995bc3cb74SMauro Carvalho Chehab static void v4l_print_event(const void *arg, bool write_only) 8005bc3cb74SMauro Carvalho Chehab { 8015bc3cb74SMauro Carvalho Chehab const struct v4l2_event *p = arg; 8025bc3cb74SMauro Carvalho Chehab const struct v4l2_event_ctrl *c; 8035bc3cb74SMauro Carvalho Chehab 8045bc3cb74SMauro Carvalho Chehab pr_cont("type=0x%x, pending=%u, sequence=%u, id=%u, " 8055bc3cb74SMauro Carvalho Chehab "timestamp=%lu.%9.9lu\n", 8065bc3cb74SMauro Carvalho Chehab p->type, p->pending, p->sequence, p->id, 8075bc3cb74SMauro Carvalho Chehab p->timestamp.tv_sec, p->timestamp.tv_nsec); 8085bc3cb74SMauro Carvalho Chehab switch (p->type) { 8095bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_VSYNC: 8105bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "field=%s\n", 8115bc3cb74SMauro Carvalho Chehab prt_names(p->u.vsync.field, v4l2_field_names)); 8125bc3cb74SMauro Carvalho Chehab break; 8135bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_CTRL: 8145bc3cb74SMauro Carvalho Chehab c = &p->u.ctrl; 8155bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "changes=0x%x, type=%u, ", 8165bc3cb74SMauro Carvalho Chehab c->changes, c->type); 8175bc3cb74SMauro Carvalho Chehab if (c->type == V4L2_CTRL_TYPE_INTEGER64) 8185bc3cb74SMauro Carvalho Chehab pr_cont("value64=%lld, ", c->value64); 8195bc3cb74SMauro Carvalho Chehab else 8205bc3cb74SMauro Carvalho Chehab pr_cont("value=%d, ", c->value); 8215bc3cb74SMauro Carvalho Chehab pr_cont("flags=0x%x, minimum=%d, maximum=%d, step=%d, " 8225bc3cb74SMauro Carvalho Chehab "default_value=%d\n", 8235bc3cb74SMauro Carvalho Chehab c->flags, c->minimum, c->maximum, 8245bc3cb74SMauro Carvalho Chehab c->step, c->default_value); 8255bc3cb74SMauro Carvalho Chehab break; 8265bc3cb74SMauro Carvalho Chehab case V4L2_EVENT_FRAME_SYNC: 8275bc3cb74SMauro Carvalho Chehab pr_cont("frame_sequence=%u\n", 8285bc3cb74SMauro Carvalho Chehab p->u.frame_sync.frame_sequence); 8295bc3cb74SMauro Carvalho Chehab break; 8305bc3cb74SMauro Carvalho Chehab } 8315bc3cb74SMauro Carvalho Chehab } 8325bc3cb74SMauro Carvalho Chehab 8335bc3cb74SMauro Carvalho Chehab static void v4l_print_event_subscription(const void *arg, bool write_only) 8345bc3cb74SMauro Carvalho Chehab { 8355bc3cb74SMauro Carvalho Chehab const struct v4l2_event_subscription *p = arg; 8365bc3cb74SMauro Carvalho Chehab 8375bc3cb74SMauro Carvalho Chehab pr_cont("type=0x%x, id=0x%x, flags=0x%x\n", 8385bc3cb74SMauro Carvalho Chehab p->type, p->id, p->flags); 8395bc3cb74SMauro Carvalho Chehab } 8405bc3cb74SMauro Carvalho Chehab 8415bc3cb74SMauro Carvalho Chehab static void v4l_print_sliced_vbi_cap(const void *arg, bool write_only) 8425bc3cb74SMauro Carvalho Chehab { 8435bc3cb74SMauro Carvalho Chehab const struct v4l2_sliced_vbi_cap *p = arg; 8445bc3cb74SMauro Carvalho Chehab int i; 8455bc3cb74SMauro Carvalho Chehab 8465bc3cb74SMauro Carvalho Chehab pr_cont("type=%s, service_set=0x%08x\n", 8475bc3cb74SMauro Carvalho Chehab prt_names(p->type, v4l2_type_names), p->service_set); 8485bc3cb74SMauro Carvalho Chehab for (i = 0; i < 24; i++) 8495bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "line[%02u]=0x%04x, 0x%04x\n", i, 8505bc3cb74SMauro Carvalho Chehab p->service_lines[0][i], 8515bc3cb74SMauro Carvalho Chehab p->service_lines[1][i]); 8525bc3cb74SMauro Carvalho Chehab } 8535bc3cb74SMauro Carvalho Chehab 8545bc3cb74SMauro Carvalho Chehab static void v4l_print_freq_band(const void *arg, bool write_only) 8555bc3cb74SMauro Carvalho Chehab { 8565bc3cb74SMauro Carvalho Chehab const struct v4l2_frequency_band *p = arg; 8575bc3cb74SMauro Carvalho Chehab 8585bc3cb74SMauro Carvalho Chehab pr_cont("tuner=%u, type=%u, index=%u, capability=0x%x, " 8595bc3cb74SMauro Carvalho Chehab "rangelow=%u, rangehigh=%u, modulation=0x%x\n", 8605bc3cb74SMauro Carvalho Chehab p->tuner, p->type, p->index, 8615bc3cb74SMauro Carvalho Chehab p->capability, p->rangelow, 8625bc3cb74SMauro Carvalho Chehab p->rangehigh, p->modulation); 8635bc3cb74SMauro Carvalho Chehab } 8645bc3cb74SMauro Carvalho Chehab 865dd519bb3SHans Verkuil static void v4l_print_edid(const void *arg, bool write_only) 866dd519bb3SHans Verkuil { 867dd519bb3SHans Verkuil const struct v4l2_edid *p = arg; 868dd519bb3SHans Verkuil 869dd519bb3SHans Verkuil pr_cont("pad=%u, start_block=%u, blocks=%u\n", 870dd519bb3SHans Verkuil p->pad, p->start_block, p->blocks); 871dd519bb3SHans Verkuil } 872dd519bb3SHans Verkuil 8735bc3cb74SMauro Carvalho Chehab static void v4l_print_u32(const void *arg, bool write_only) 8745bc3cb74SMauro Carvalho Chehab { 8755bc3cb74SMauro Carvalho Chehab pr_cont("value=%u\n", *(const u32 *)arg); 8765bc3cb74SMauro Carvalho Chehab } 8775bc3cb74SMauro Carvalho Chehab 8785bc3cb74SMauro Carvalho Chehab static void v4l_print_newline(const void *arg, bool write_only) 8795bc3cb74SMauro Carvalho Chehab { 8805bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 8815bc3cb74SMauro Carvalho Chehab } 8825bc3cb74SMauro Carvalho Chehab 8835bc3cb74SMauro Carvalho Chehab static void v4l_print_default(const void *arg, bool write_only) 8845bc3cb74SMauro Carvalho Chehab { 8855bc3cb74SMauro Carvalho Chehab pr_cont("driver-specific ioctl\n"); 8865bc3cb74SMauro Carvalho Chehab } 8875bc3cb74SMauro Carvalho Chehab 8885bc3cb74SMauro Carvalho Chehab static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv) 8895bc3cb74SMauro Carvalho Chehab { 8905bc3cb74SMauro Carvalho Chehab __u32 i; 8915bc3cb74SMauro Carvalho Chehab 8925bc3cb74SMauro Carvalho Chehab /* zero the reserved fields */ 8935bc3cb74SMauro Carvalho Chehab c->reserved[0] = c->reserved[1] = 0; 8945bc3cb74SMauro Carvalho Chehab for (i = 0; i < c->count; i++) 8955bc3cb74SMauro Carvalho Chehab c->controls[i].reserved2[0] = 0; 8965bc3cb74SMauro Carvalho Chehab 8975bc3cb74SMauro Carvalho Chehab /* V4L2_CID_PRIVATE_BASE cannot be used as control class 8985bc3cb74SMauro Carvalho Chehab when using extended controls. 8995bc3cb74SMauro Carvalho Chehab Only when passed in through VIDIOC_G_CTRL and VIDIOC_S_CTRL 9005bc3cb74SMauro Carvalho Chehab is it allowed for backwards compatibility. 9015bc3cb74SMauro Carvalho Chehab */ 9025bc3cb74SMauro Carvalho Chehab if (!allow_priv && c->ctrl_class == V4L2_CID_PRIVATE_BASE) 9035bc3cb74SMauro Carvalho Chehab return 0; 9049b239b22SHans Verkuil if (c->ctrl_class == 0) 9059b239b22SHans Verkuil return 1; 9065bc3cb74SMauro Carvalho Chehab /* Check that all controls are from the same control class. */ 9075bc3cb74SMauro Carvalho Chehab for (i = 0; i < c->count; i++) { 9085bc3cb74SMauro Carvalho Chehab if (V4L2_CTRL_ID2CLASS(c->controls[i].id) != c->ctrl_class) { 9095bc3cb74SMauro Carvalho Chehab c->error_idx = i; 9105bc3cb74SMauro Carvalho Chehab return 0; 9115bc3cb74SMauro Carvalho Chehab } 9125bc3cb74SMauro Carvalho Chehab } 9135bc3cb74SMauro Carvalho Chehab return 1; 9145bc3cb74SMauro Carvalho Chehab } 9155bc3cb74SMauro Carvalho Chehab 9164b20259fSHans Verkuil static int check_fmt(struct file *file, enum v4l2_buf_type type) 9175bc3cb74SMauro Carvalho Chehab { 9184b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 9194b20259fSHans Verkuil const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 9204b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 9214b20259fSHans Verkuil bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI; 922582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 9234b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 9244b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 9254b20259fSHans Verkuil 9265bc3cb74SMauro Carvalho Chehab if (ops == NULL) 9275bc3cb74SMauro Carvalho Chehab return -EINVAL; 9285bc3cb74SMauro Carvalho Chehab 9295bc3cb74SMauro Carvalho Chehab switch (type) { 9305bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 9314b20259fSHans Verkuil if (is_vid && is_rx && 9324b20259fSHans Verkuil (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane)) 9335bc3cb74SMauro Carvalho Chehab return 0; 9345bc3cb74SMauro Carvalho Chehab break; 9355bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 9364b20259fSHans Verkuil if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane) 9375bc3cb74SMauro Carvalho Chehab return 0; 9385bc3cb74SMauro Carvalho Chehab break; 9395bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 9404b20259fSHans Verkuil if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay) 9415bc3cb74SMauro Carvalho Chehab return 0; 9425bc3cb74SMauro Carvalho Chehab break; 9435bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 9444b20259fSHans Verkuil if (is_vid && is_tx && 9454b20259fSHans Verkuil (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane)) 9465bc3cb74SMauro Carvalho Chehab return 0; 9475bc3cb74SMauro Carvalho Chehab break; 9485bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 9494b20259fSHans Verkuil if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane) 9505bc3cb74SMauro Carvalho Chehab return 0; 9515bc3cb74SMauro Carvalho Chehab break; 9525bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 9534b20259fSHans Verkuil if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay) 9545bc3cb74SMauro Carvalho Chehab return 0; 9555bc3cb74SMauro Carvalho Chehab break; 9565bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_CAPTURE: 9574b20259fSHans Verkuil if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap) 9585bc3cb74SMauro Carvalho Chehab return 0; 9595bc3cb74SMauro Carvalho Chehab break; 9605bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 9614b20259fSHans Verkuil if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out) 9625bc3cb74SMauro Carvalho Chehab return 0; 9635bc3cb74SMauro Carvalho Chehab break; 9645bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 9654b20259fSHans Verkuil if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap) 9665bc3cb74SMauro Carvalho Chehab return 0; 9675bc3cb74SMauro Carvalho Chehab break; 9685bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 9694b20259fSHans Verkuil if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out) 9705bc3cb74SMauro Carvalho Chehab return 0; 9715bc3cb74SMauro Carvalho Chehab break; 972582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 973582c52cbSAntti Palosaari if (is_sdr && is_rx && ops->vidioc_g_fmt_sdr_cap) 974582c52cbSAntti Palosaari return 0; 975582c52cbSAntti Palosaari break; 976633c98e5SHans Verkuil default: 9775bc3cb74SMauro Carvalho Chehab break; 9785bc3cb74SMauro Carvalho Chehab } 9795bc3cb74SMauro Carvalho Chehab return -EINVAL; 9805bc3cb74SMauro Carvalho Chehab } 9815bc3cb74SMauro Carvalho Chehab 982d52e2381SLaurent Pinchart static void v4l_sanitize_format(struct v4l2_format *fmt) 983d52e2381SLaurent Pinchart { 984d52e2381SLaurent Pinchart unsigned int offset; 985d52e2381SLaurent Pinchart 986d52e2381SLaurent Pinchart /* 987d52e2381SLaurent Pinchart * The v4l2_pix_format structure has been extended with fields that were 988d52e2381SLaurent Pinchart * not previously required to be set to zero by applications. The priv 989d52e2381SLaurent Pinchart * field, when set to a magic value, indicates the the extended fields 990d52e2381SLaurent Pinchart * are valid. Otherwise they will contain undefined values. To simplify 991d52e2381SLaurent Pinchart * the API towards drivers zero the extended fields and set the priv 992d52e2381SLaurent Pinchart * field to the magic value when the extended pixel format structure 993d52e2381SLaurent Pinchart * isn't used by applications. 994d52e2381SLaurent Pinchart */ 995d52e2381SLaurent Pinchart 996d52e2381SLaurent Pinchart if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 997d52e2381SLaurent Pinchart fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) 998d52e2381SLaurent Pinchart return; 999d52e2381SLaurent Pinchart 1000d52e2381SLaurent Pinchart if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC) 1001d52e2381SLaurent Pinchart return; 1002d52e2381SLaurent Pinchart 1003d52e2381SLaurent Pinchart fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1004d52e2381SLaurent Pinchart 1005d52e2381SLaurent Pinchart offset = offsetof(struct v4l2_pix_format, priv) 1006d52e2381SLaurent Pinchart + sizeof(fmt->fmt.pix.priv); 1007d52e2381SLaurent Pinchart memset(((void *)&fmt->fmt.pix) + offset, 0, 1008d52e2381SLaurent Pinchart sizeof(fmt->fmt.pix) - offset); 1009d52e2381SLaurent Pinchart } 1010d52e2381SLaurent Pinchart 10115bc3cb74SMauro Carvalho Chehab static int v4l_querycap(const struct v4l2_ioctl_ops *ops, 10125bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10135bc3cb74SMauro Carvalho Chehab { 10145bc3cb74SMauro Carvalho Chehab struct v4l2_capability *cap = (struct v4l2_capability *)arg; 1015d52e2381SLaurent Pinchart int ret; 10165bc3cb74SMauro Carvalho Chehab 10175bc3cb74SMauro Carvalho Chehab cap->version = LINUX_VERSION_CODE; 1018d52e2381SLaurent Pinchart 1019d52e2381SLaurent Pinchart ret = ops->vidioc_querycap(file, fh, cap); 1020d52e2381SLaurent Pinchart 1021d52e2381SLaurent Pinchart cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT; 1022454a4e72SHans Verkuil /* 1023454a4e72SHans Verkuil * Drivers MUST fill in device_caps, so check for this and 1024454a4e72SHans Verkuil * warn if it was forgotten. 1025454a4e72SHans Verkuil */ 1026454a4e72SHans Verkuil WARN_ON(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) || 1027454a4e72SHans Verkuil !cap->device_caps); 1028796a2bd2SHans Verkuil cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT; 1029d52e2381SLaurent Pinchart 1030d52e2381SLaurent Pinchart return ret; 10315bc3cb74SMauro Carvalho Chehab } 10325bc3cb74SMauro Carvalho Chehab 10335bc3cb74SMauro Carvalho Chehab static int v4l_s_input(const struct v4l2_ioctl_ops *ops, 10345bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10355bc3cb74SMauro Carvalho Chehab { 10365bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_input(file, fh, *(unsigned int *)arg); 10375bc3cb74SMauro Carvalho Chehab } 10385bc3cb74SMauro Carvalho Chehab 10395bc3cb74SMauro Carvalho Chehab static int v4l_s_output(const struct v4l2_ioctl_ops *ops, 10405bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10415bc3cb74SMauro Carvalho Chehab { 10425bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_output(file, fh, *(unsigned int *)arg); 10435bc3cb74SMauro Carvalho Chehab } 10445bc3cb74SMauro Carvalho Chehab 10455bc3cb74SMauro Carvalho Chehab static int v4l_g_priority(const struct v4l2_ioctl_ops *ops, 10465bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10475bc3cb74SMauro Carvalho Chehab { 10485bc3cb74SMauro Carvalho Chehab struct video_device *vfd; 10495bc3cb74SMauro Carvalho Chehab u32 *p = arg; 10505bc3cb74SMauro Carvalho Chehab 10515bc3cb74SMauro Carvalho Chehab vfd = video_devdata(file); 105259b702eaSLaurent Pinchart *p = v4l2_prio_max(vfd->prio); 10535bc3cb74SMauro Carvalho Chehab return 0; 10545bc3cb74SMauro Carvalho Chehab } 10555bc3cb74SMauro Carvalho Chehab 10565bc3cb74SMauro Carvalho Chehab static int v4l_s_priority(const struct v4l2_ioctl_ops *ops, 10575bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10585bc3cb74SMauro Carvalho Chehab { 10595bc3cb74SMauro Carvalho Chehab struct video_device *vfd; 10605bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh; 10615bc3cb74SMauro Carvalho Chehab u32 *p = arg; 10625bc3cb74SMauro Carvalho Chehab 10635bc3cb74SMauro Carvalho Chehab vfd = video_devdata(file); 10642438e78aSHans Verkuil if (!test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) 10652438e78aSHans Verkuil return -ENOTTY; 10665bc3cb74SMauro Carvalho Chehab vfh = file->private_data; 106759b702eaSLaurent Pinchart return v4l2_prio_change(vfd->prio, &vfh->prio, *p); 10685bc3cb74SMauro Carvalho Chehab } 10695bc3cb74SMauro Carvalho Chehab 10705bc3cb74SMauro Carvalho Chehab static int v4l_enuminput(const struct v4l2_ioctl_ops *ops, 10715bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10725bc3cb74SMauro Carvalho Chehab { 107373f35418SHans Verkuil struct video_device *vfd = video_devdata(file); 10745bc3cb74SMauro Carvalho Chehab struct v4l2_input *p = arg; 10755bc3cb74SMauro Carvalho Chehab 10765bc3cb74SMauro Carvalho Chehab /* 107702fa6282SHans Verkuil * We set the flags for CAP_DV_TIMINGS & 10785bc3cb74SMauro Carvalho Chehab * CAP_STD here based on ioctl handler provided by the 10795bc3cb74SMauro Carvalho Chehab * driver. If the driver doesn't support these 10805bc3cb74SMauro Carvalho Chehab * for a specific input, it must override these flags. 10815bc3cb74SMauro Carvalho Chehab */ 108273f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_S_STD)) 10835bc3cb74SMauro Carvalho Chehab p->capabilities |= V4L2_IN_CAP_STD; 10845bc3cb74SMauro Carvalho Chehab 10855bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_input(file, fh, p); 10865bc3cb74SMauro Carvalho Chehab } 10875bc3cb74SMauro Carvalho Chehab 10885bc3cb74SMauro Carvalho Chehab static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops, 10895bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 10905bc3cb74SMauro Carvalho Chehab { 109173f35418SHans Verkuil struct video_device *vfd = video_devdata(file); 10925bc3cb74SMauro Carvalho Chehab struct v4l2_output *p = arg; 10935bc3cb74SMauro Carvalho Chehab 10945bc3cb74SMauro Carvalho Chehab /* 109502fa6282SHans Verkuil * We set the flags for CAP_DV_TIMINGS & 10965bc3cb74SMauro Carvalho Chehab * CAP_STD here based on ioctl handler provided by the 10975bc3cb74SMauro Carvalho Chehab * driver. If the driver doesn't support these 10985bc3cb74SMauro Carvalho Chehab * for a specific output, it must override these flags. 10995bc3cb74SMauro Carvalho Chehab */ 110073f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_S_STD)) 11015bc3cb74SMauro Carvalho Chehab p->capabilities |= V4L2_OUT_CAP_STD; 11025bc3cb74SMauro Carvalho Chehab 11035bc3cb74SMauro Carvalho Chehab return ops->vidioc_enum_output(file, fh, p); 11045bc3cb74SMauro Carvalho Chehab } 11055bc3cb74SMauro Carvalho Chehab 1106ba300204SHans Verkuil static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) 1107ba300204SHans Verkuil { 1108ba300204SHans Verkuil const unsigned sz = sizeof(fmt->description); 1109ba300204SHans Verkuil const char *descr = NULL; 1110ba300204SHans Verkuil u32 flags = 0; 1111ba300204SHans Verkuil 1112ba300204SHans Verkuil /* 1113ba300204SHans Verkuil * We depart from the normal coding style here since the descriptions 1114ba300204SHans Verkuil * should be aligned so it is easy to see which descriptions will be 1115ba300204SHans Verkuil * longer than 31 characters (the max length for a description). 1116ba300204SHans Verkuil * And frankly, this is easier to read anyway. 1117ba300204SHans Verkuil * 1118ba300204SHans Verkuil * Note that gcc will use O(log N) comparisons to find the right case. 1119ba300204SHans Verkuil */ 1120ba300204SHans Verkuil switch (fmt->pixelformat) { 1121ba300204SHans Verkuil /* Max description length mask: descr = "0123456789012345678901234567890" */ 1122ba300204SHans Verkuil case V4L2_PIX_FMT_RGB332: descr = "8-bit RGB 3-3-2"; break; 1123ba300204SHans Verkuil case V4L2_PIX_FMT_RGB444: descr = "16-bit A/XRGB 4-4-4-4"; break; 1124ba300204SHans Verkuil case V4L2_PIX_FMT_ARGB444: descr = "16-bit ARGB 4-4-4-4"; break; 1125ba300204SHans Verkuil case V4L2_PIX_FMT_XRGB444: descr = "16-bit XRGB 4-4-4-4"; break; 1126ba300204SHans Verkuil case V4L2_PIX_FMT_RGB555: descr = "16-bit A/XRGB 1-5-5-5"; break; 1127ba300204SHans Verkuil case V4L2_PIX_FMT_ARGB555: descr = "16-bit ARGB 1-5-5-5"; break; 1128ba300204SHans Verkuil case V4L2_PIX_FMT_XRGB555: descr = "16-bit XRGB 1-5-5-5"; break; 1129ba300204SHans Verkuil case V4L2_PIX_FMT_RGB565: descr = "16-bit RGB 5-6-5"; break; 1130ba300204SHans Verkuil case V4L2_PIX_FMT_RGB555X: descr = "16-bit A/XRGB 1-5-5-5 BE"; break; 1131ba300204SHans Verkuil case V4L2_PIX_FMT_ARGB555X: descr = "16-bit ARGB 1-5-5-5 BE"; break; 1132ba300204SHans Verkuil case V4L2_PIX_FMT_XRGB555X: descr = "16-bit XRGB 1-5-5-5 BE"; break; 1133ba300204SHans Verkuil case V4L2_PIX_FMT_RGB565X: descr = "16-bit RGB 5-6-5 BE"; break; 1134ba300204SHans Verkuil case V4L2_PIX_FMT_BGR666: descr = "18-bit BGRX 6-6-6-14"; break; 1135ba300204SHans Verkuil case V4L2_PIX_FMT_BGR24: descr = "24-bit BGR 8-8-8"; break; 1136ba300204SHans Verkuil case V4L2_PIX_FMT_RGB24: descr = "24-bit RGB 8-8-8"; break; 1137ba300204SHans Verkuil case V4L2_PIX_FMT_BGR32: descr = "32-bit BGRA/X 8-8-8-8"; break; 1138ba300204SHans Verkuil case V4L2_PIX_FMT_ABGR32: descr = "32-bit BGRA 8-8-8-8"; break; 1139ba300204SHans Verkuil case V4L2_PIX_FMT_XBGR32: descr = "32-bit BGRX 8-8-8-8"; break; 1140ba300204SHans Verkuil case V4L2_PIX_FMT_RGB32: descr = "32-bit A/XRGB 8-8-8-8"; break; 1141ba300204SHans Verkuil case V4L2_PIX_FMT_ARGB32: descr = "32-bit ARGB 8-8-8-8"; break; 1142ba300204SHans Verkuil case V4L2_PIX_FMT_XRGB32: descr = "32-bit XRGB 8-8-8-8"; break; 1143ba300204SHans Verkuil case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; 1144ba300204SHans Verkuil case V4L2_PIX_FMT_Y4: descr = "4-bit Greyscale"; break; 1145ba300204SHans Verkuil case V4L2_PIX_FMT_Y6: descr = "6-bit Greyscale"; break; 1146ba300204SHans Verkuil case V4L2_PIX_FMT_Y10: descr = "10-bit Greyscale"; break; 1147ba300204SHans Verkuil case V4L2_PIX_FMT_Y12: descr = "12-bit Greyscale"; break; 1148ba300204SHans Verkuil case V4L2_PIX_FMT_Y16: descr = "16-bit Greyscale"; break; 1149ba300204SHans Verkuil case V4L2_PIX_FMT_Y10BPACK: descr = "10-bit Greyscale (Packed)"; break; 1150ba300204SHans Verkuil case V4L2_PIX_FMT_PAL8: descr = "8-bit Palette"; break; 1151ba300204SHans Verkuil case V4L2_PIX_FMT_UV8: descr = "8-bit Chrominance UV 4-4"; break; 1152ba300204SHans Verkuil case V4L2_PIX_FMT_YVU410: descr = "Planar YVU 4:1:0"; break; 1153ba300204SHans Verkuil case V4L2_PIX_FMT_YVU420: descr = "Planar YVU 4:2:0"; break; 1154ba300204SHans Verkuil case V4L2_PIX_FMT_YUYV: descr = "YUYV 4:2:2"; break; 1155ba300204SHans Verkuil case V4L2_PIX_FMT_YYUV: descr = "YYUV 4:2:2"; break; 1156ba300204SHans Verkuil case V4L2_PIX_FMT_YVYU: descr = "YVYU 4:2:2"; break; 1157ba300204SHans Verkuil case V4L2_PIX_FMT_UYVY: descr = "UYVY 4:2:2"; break; 1158ba300204SHans Verkuil case V4L2_PIX_FMT_VYUY: descr = "VYUY 4:2:2"; break; 1159ba300204SHans Verkuil case V4L2_PIX_FMT_YUV422P: descr = "Planar YVU 4:2:2"; break; 1160ba300204SHans Verkuil case V4L2_PIX_FMT_YUV411P: descr = "Planar YUV 4:1:1"; break; 1161ba300204SHans Verkuil case V4L2_PIX_FMT_Y41P: descr = "YUV 4:1:1 (Packed)"; break; 1162ba300204SHans Verkuil case V4L2_PIX_FMT_YUV444: descr = "16-bit A/XYUV 4-4-4-4"; break; 1163ba300204SHans Verkuil case V4L2_PIX_FMT_YUV555: descr = "16-bit A/XYUV 1-5-5-5"; break; 1164ba300204SHans Verkuil case V4L2_PIX_FMT_YUV565: descr = "16-bit YUV 5-6-5"; break; 1165ba300204SHans Verkuil case V4L2_PIX_FMT_YUV32: descr = "32-bit A/XYUV 8-8-8-8"; break; 1166ba300204SHans Verkuil case V4L2_PIX_FMT_YUV410: descr = "Planar YUV 4:1:0"; break; 1167ba300204SHans Verkuil case V4L2_PIX_FMT_YUV420: descr = "Planar YUV 4:2:0"; break; 1168ba300204SHans Verkuil case V4L2_PIX_FMT_HI240: descr = "8-bit Dithered RGB (BTTV)"; break; 1169ba300204SHans Verkuil case V4L2_PIX_FMT_HM12: descr = "YUV 4:2:0 (16x16 Macroblocks)"; break; 1170ba300204SHans Verkuil case V4L2_PIX_FMT_M420: descr = "YUV 4:2:0 (M420)"; break; 1171ba300204SHans Verkuil case V4L2_PIX_FMT_NV12: descr = "Y/CbCr 4:2:0"; break; 1172ba300204SHans Verkuil case V4L2_PIX_FMT_NV21: descr = "Y/CrCb 4:2:0"; break; 1173ba300204SHans Verkuil case V4L2_PIX_FMT_NV16: descr = "Y/CbCr 4:2:2"; break; 1174ba300204SHans Verkuil case V4L2_PIX_FMT_NV61: descr = "Y/CrCb 4:2:2"; break; 1175ba300204SHans Verkuil case V4L2_PIX_FMT_NV24: descr = "Y/CbCr 4:4:4"; break; 1176ba300204SHans Verkuil case V4L2_PIX_FMT_NV42: descr = "Y/CrCb 4:4:4"; break; 1177ba300204SHans Verkuil case V4L2_PIX_FMT_NV12M: descr = "Y/CbCr 4:2:0 (N-C)"; break; 1178ba300204SHans Verkuil case V4L2_PIX_FMT_NV21M: descr = "Y/CrCb 4:2:0 (N-C)"; break; 1179ba300204SHans Verkuil case V4L2_PIX_FMT_NV16M: descr = "Y/CbCr 4:2:2 (N-C)"; break; 1180ba300204SHans Verkuil case V4L2_PIX_FMT_NV61M: descr = "Y/CrCb 4:2:2 (N-C)"; break; 1181ba300204SHans Verkuil case V4L2_PIX_FMT_NV12MT: descr = "Y/CbCr 4:2:0 (64x32 MB, N-C)"; break; 1182ba300204SHans Verkuil case V4L2_PIX_FMT_NV12MT_16X16: descr = "Y/CbCr 4:2:0 (16x16 MB, N-C)"; break; 1183ba300204SHans Verkuil case V4L2_PIX_FMT_YUV420M: descr = "Planar YUV 4:2:0 (N-C)"; break; 1184ba300204SHans Verkuil case V4L2_PIX_FMT_YVU420M: descr = "Planar YVU 4:2:0 (N-C)"; break; 1185ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR8: descr = "8-bit Bayer BGBG/GRGR"; break; 1186ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG8: descr = "8-bit Bayer GBGB/RGRG"; break; 1187ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG8: descr = "8-bit Bayer GRGR/BGBG"; break; 1188ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB8: descr = "8-bit Bayer RGRG/GBGB"; break; 1189ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR10: descr = "10-bit Bayer BGBG/GRGR"; break; 1190ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG10: descr = "10-bit Bayer GBGB/RGRG"; break; 1191ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG10: descr = "10-bit Bayer GRGR/BGBG"; break; 1192ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB10: descr = "10-bit Bayer RGRG/GBGB"; break; 1193ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR12: descr = "12-bit Bayer BGBG/GRGR"; break; 1194ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG12: descr = "12-bit Bayer GBGB/RGRG"; break; 1195ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG12: descr = "12-bit Bayer GRGR/BGBG"; break; 1196ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB12: descr = "12-bit Bayer RGRG/GBGB"; break; 1197ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR10P: descr = "10-bit Bayer BGBG/GRGR Packed"; break; 1198ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG10P: descr = "10-bit Bayer GBGB/RGRG Packed"; break; 1199ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG10P: descr = "10-bit Bayer GRGR/BGBG Packed"; break; 1200ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB10P: descr = "10-bit Bayer RGRG/GBGB Packed"; break; 1201ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR10ALAW8: descr = "8-bit Bayer BGBG/GRGR (A-law)"; break; 1202ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG10ALAW8: descr = "8-bit Bayer GBGB/RGRG (A-law)"; break; 1203ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG10ALAW8: descr = "8-bit Bayer GRGR/BGBG (A-law)"; break; 1204ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB10ALAW8: descr = "8-bit Bayer RGRG/GBGB (A-law)"; break; 1205ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR10DPCM8: descr = "8-bit Bayer BGBG/GRGR (DPCM)"; break; 1206ba300204SHans Verkuil case V4L2_PIX_FMT_SGBRG10DPCM8: descr = "8-bit Bayer GBGB/RGRG (DPCM)"; break; 1207ba300204SHans Verkuil case V4L2_PIX_FMT_SGRBG10DPCM8: descr = "8-bit Bayer GRGR/BGBG (DPCM)"; break; 1208ba300204SHans Verkuil case V4L2_PIX_FMT_SRGGB10DPCM8: descr = "8-bit Bayer RGRG/GBGB (DPCM)"; break; 1209ba300204SHans Verkuil case V4L2_PIX_FMT_SBGGR16: descr = "16-bit Bayer BGBG/GRGR (Exp.)"; break; 121099b74277SMauro Carvalho Chehab case V4L2_PIX_FMT_SN9C20X_I420: descr = "GSPCA SN9C20X I420"; break; 1211ba300204SHans Verkuil case V4L2_PIX_FMT_SPCA501: descr = "GSPCA SPCA501"; break; 1212ba300204SHans Verkuil case V4L2_PIX_FMT_SPCA505: descr = "GSPCA SPCA505"; break; 1213ba300204SHans Verkuil case V4L2_PIX_FMT_SPCA508: descr = "GSPCA SPCA508"; break; 1214ba300204SHans Verkuil case V4L2_PIX_FMT_STV0680: descr = "GSPCA STV0680"; break; 1215ba300204SHans Verkuil case V4L2_PIX_FMT_TM6000: descr = "A/V + VBI Mux Packet"; break; 1216ba300204SHans Verkuil case V4L2_PIX_FMT_CIT_YYVYUY: descr = "GSPCA CIT YYVYUY"; break; 1217ba300204SHans Verkuil case V4L2_PIX_FMT_KONICA420: descr = "GSPCA KONICA420"; break; 1218ba300204SHans Verkuil case V4L2_SDR_FMT_CU8: descr = "Complex U8 (Emulated)"; break; 1219ba300204SHans Verkuil case V4L2_SDR_FMT_CU16LE: descr = "Complex U16LE (Emulated)"; break; 1220ba300204SHans Verkuil case V4L2_SDR_FMT_CS8: descr = "Complex S8"; break; 1221ba300204SHans Verkuil case V4L2_SDR_FMT_CS14LE: descr = "Complex S14LE"; break; 1222ba300204SHans Verkuil case V4L2_SDR_FMT_RU12LE: descr = "Real U12LE"; break; 1223ba300204SHans Verkuil 1224ba300204SHans Verkuil default: 1225ba300204SHans Verkuil /* Compressed formats */ 1226ba300204SHans Verkuil flags = V4L2_FMT_FLAG_COMPRESSED; 1227ba300204SHans Verkuil switch (fmt->pixelformat) { 1228ba300204SHans Verkuil /* Max description length mask: descr = "0123456789012345678901234567890" */ 1229ba300204SHans Verkuil case V4L2_PIX_FMT_MJPEG: descr = "Motion-JPEG"; break; 1230ba300204SHans Verkuil case V4L2_PIX_FMT_JPEG: descr = "JFIF JPEG"; break; 1231ba300204SHans Verkuil case V4L2_PIX_FMT_DV: descr = "1394"; break; 1232ba300204SHans Verkuil case V4L2_PIX_FMT_MPEG: descr = "MPEG-1/2/4"; break; 1233ba300204SHans Verkuil case V4L2_PIX_FMT_H264: descr = "H.264"; break; 1234ba300204SHans Verkuil case V4L2_PIX_FMT_H264_NO_SC: descr = "H.264 (No Start Codes)"; break; 1235ba300204SHans Verkuil case V4L2_PIX_FMT_H264_MVC: descr = "H.264 MVC"; break; 1236ba300204SHans Verkuil case V4L2_PIX_FMT_H263: descr = "H.263"; break; 1237ba300204SHans Verkuil case V4L2_PIX_FMT_MPEG1: descr = "MPEG-1 ES"; break; 1238ba300204SHans Verkuil case V4L2_PIX_FMT_MPEG2: descr = "MPEG-2 ES"; break; 1239ba300204SHans Verkuil case V4L2_PIX_FMT_MPEG4: descr = "MPEG-4 part 2 ES"; break; 1240ba300204SHans Verkuil case V4L2_PIX_FMT_XVID: descr = "Xvid"; break; 1241ba300204SHans Verkuil case V4L2_PIX_FMT_VC1_ANNEX_G: descr = "VC-1 (SMPTE 412M Annex G)"; break; 1242ba300204SHans Verkuil case V4L2_PIX_FMT_VC1_ANNEX_L: descr = "VC-1 (SMPTE 412M Annex L)"; break; 1243ba300204SHans Verkuil case V4L2_PIX_FMT_VP8: descr = "VP8"; break; 1244ba300204SHans Verkuil case V4L2_PIX_FMT_CPIA1: descr = "GSPCA CPiA YUV"; break; 1245ba300204SHans Verkuil case V4L2_PIX_FMT_WNVA: descr = "WNVA"; break; 1246ba300204SHans Verkuil case V4L2_PIX_FMT_SN9C10X: descr = "GSPCA SN9C10X"; break; 1247ba300204SHans Verkuil case V4L2_PIX_FMT_PWC1: descr = "Raw Philips Webcam Type (Old)"; break; 1248ba300204SHans Verkuil case V4L2_PIX_FMT_PWC2: descr = "Raw Philips Webcam Type (New)"; break; 1249ba300204SHans Verkuil case V4L2_PIX_FMT_ET61X251: descr = "GSPCA ET61X251"; break; 1250ba300204SHans Verkuil case V4L2_PIX_FMT_SPCA561: descr = "GSPCA SPCA561"; break; 1251ba300204SHans Verkuil case V4L2_PIX_FMT_PAC207: descr = "GSPCA PAC207"; break; 1252ba300204SHans Verkuil case V4L2_PIX_FMT_MR97310A: descr = "GSPCA MR97310A"; break; 1253ba300204SHans Verkuil case V4L2_PIX_FMT_JL2005BCD: descr = "GSPCA JL2005BCD"; break; 1254ba300204SHans Verkuil case V4L2_PIX_FMT_SN9C2028: descr = "GSPCA SN9C2028"; break; 1255ba300204SHans Verkuil case V4L2_PIX_FMT_SQ905C: descr = "GSPCA SQ905C"; break; 1256ba300204SHans Verkuil case V4L2_PIX_FMT_PJPG: descr = "GSPCA PJPG"; break; 1257ba300204SHans Verkuil case V4L2_PIX_FMT_OV511: descr = "GSPCA OV511"; break; 1258ba300204SHans Verkuil case V4L2_PIX_FMT_OV518: descr = "GSPCA OV518"; break; 1259ba300204SHans Verkuil case V4L2_PIX_FMT_JPGL: descr = "JPEG Lite"; break; 1260ba300204SHans Verkuil case V4L2_PIX_FMT_SE401: descr = "GSPCA SE401"; break; 1261ba300204SHans Verkuil case V4L2_PIX_FMT_S5C_UYVY_JPG: descr = "S5C73MX interleaved UYVY/JPEG"; break; 1262ba300204SHans Verkuil default: 1263ba300204SHans Verkuil WARN(1, "Unknown pixelformat 0x%08x\n", fmt->pixelformat); 1264ba300204SHans Verkuil if (fmt->description[0]) 1265ba300204SHans Verkuil return; 1266ba300204SHans Verkuil flags = 0; 1267ba300204SHans Verkuil snprintf(fmt->description, sz, "%c%c%c%c%s", 1268ba300204SHans Verkuil (char)(fmt->pixelformat & 0x7f), 1269ba300204SHans Verkuil (char)((fmt->pixelformat >> 8) & 0x7f), 1270ba300204SHans Verkuil (char)((fmt->pixelformat >> 16) & 0x7f), 1271ba300204SHans Verkuil (char)((fmt->pixelformat >> 24) & 0x7f), 1272ba300204SHans Verkuil (fmt->pixelformat & (1 << 31)) ? "-BE" : ""); 1273ba300204SHans Verkuil break; 1274ba300204SHans Verkuil } 1275ba300204SHans Verkuil } 1276ba300204SHans Verkuil 1277ba300204SHans Verkuil if (descr) 1278ba300204SHans Verkuil WARN_ON(strlcpy(fmt->description, descr, sz) >= sz); 1279ba300204SHans Verkuil fmt->flags = flags; 1280ba300204SHans Verkuil } 1281ba300204SHans Verkuil 12825bc3cb74SMauro Carvalho Chehab static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops, 12835bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 12845bc3cb74SMauro Carvalho Chehab { 12855bc3cb74SMauro Carvalho Chehab struct v4l2_fmtdesc *p = arg; 12864b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 1287ce71bbc9SHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1288ce71bbc9SHans Verkuil bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 12894b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 12904b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1291ba300204SHans Verkuil int ret = -EINVAL; 12925bc3cb74SMauro Carvalho Chehab 12935bc3cb74SMauro Carvalho Chehab switch (p->type) { 12945bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 1295ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap)) 12965bc3cb74SMauro Carvalho Chehab break; 1297ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_vid_cap(file, fh, arg); 1298ba300204SHans Verkuil break; 12995bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 1300ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane)) 13015bc3cb74SMauro Carvalho Chehab break; 1302ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg); 1303ba300204SHans Verkuil break; 13045bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1305ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay)) 13065bc3cb74SMauro Carvalho Chehab break; 1307ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_vid_overlay(file, fh, arg); 1308ba300204SHans Verkuil break; 13095bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 1310ce71bbc9SHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out)) 13115bc3cb74SMauro Carvalho Chehab break; 1312ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_vid_out(file, fh, arg); 1313ba300204SHans Verkuil break; 13145bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 1315ce71bbc9SHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane)) 13165bc3cb74SMauro Carvalho Chehab break; 1317ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg); 1318ba300204SHans Verkuil break; 1319582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1320ce71bbc9SHans Verkuil if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap)) 1321582c52cbSAntti Palosaari break; 1322ba300204SHans Verkuil ret = ops->vidioc_enum_fmt_sdr_cap(file, fh, arg); 1323ba300204SHans Verkuil break; 13245bc3cb74SMauro Carvalho Chehab } 1325ba300204SHans Verkuil if (ret == 0) 1326ba300204SHans Verkuil v4l_fill_fmtdesc(p); 1327ba300204SHans Verkuil return ret; 13285bc3cb74SMauro Carvalho Chehab } 13295bc3cb74SMauro Carvalho Chehab 13305bc3cb74SMauro Carvalho Chehab static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops, 13315bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 13325bc3cb74SMauro Carvalho Chehab { 13335bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 13344b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 13354b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1336582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 13374b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 13384b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 1339d52e2381SLaurent Pinchart int ret; 1340d52e2381SLaurent Pinchart 1341e5ce558aSHans Verkuil /* 1342e5ce558aSHans Verkuil * fmt can't be cleared for these overlay types due to the 'clips' 1343e5ce558aSHans Verkuil * 'clipcount' and 'bitmap' pointers in struct v4l2_window. 1344e5ce558aSHans Verkuil * Those are provided by the user. So handle these two overlay types 1345e5ce558aSHans Verkuil * first, and then just do a simple memset for the other types. 1346e5ce558aSHans Verkuil */ 1347e5ce558aSHans Verkuil switch (p->type) { 1348e5ce558aSHans Verkuil case V4L2_BUF_TYPE_VIDEO_OVERLAY: 1349e5ce558aSHans Verkuil case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: { 13504d1afa51SHans Verkuil struct v4l2_clip __user *clips = p->fmt.win.clips; 1351e5ce558aSHans Verkuil u32 clipcount = p->fmt.win.clipcount; 13524d1afa51SHans Verkuil void __user *bitmap = p->fmt.win.bitmap; 1353e5ce558aSHans Verkuil 1354e5ce558aSHans Verkuil memset(&p->fmt, 0, sizeof(p->fmt)); 1355e5ce558aSHans Verkuil p->fmt.win.clips = clips; 1356e5ce558aSHans Verkuil p->fmt.win.clipcount = clipcount; 1357e5ce558aSHans Verkuil p->fmt.win.bitmap = bitmap; 1358e5ce558aSHans Verkuil break; 1359e5ce558aSHans Verkuil } 1360e5ce558aSHans Verkuil default: 1361e5ce558aSHans Verkuil memset(&p->fmt, 0, sizeof(p->fmt)); 1362e5ce558aSHans Verkuil break; 1363e5ce558aSHans Verkuil } 1364e5ce558aSHans Verkuil 13655bc3cb74SMauro Carvalho Chehab switch (p->type) { 13665bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 13674b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap)) 13685bc3cb74SMauro Carvalho Chehab break; 136948f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1370d52e2381SLaurent Pinchart ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg); 137148f2650aSHans Verkuil /* just in case the driver zeroed it again */ 1372d52e2381SLaurent Pinchart p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1373d52e2381SLaurent Pinchart return ret; 13745bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 13754b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane)) 13765bc3cb74SMauro Carvalho Chehab break; 13775bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg); 13785bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 13794b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay)) 13805bc3cb74SMauro Carvalho Chehab break; 13815bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_overlay(file, fh, arg); 13824b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 13834b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap)) 13844b20259fSHans Verkuil break; 13854b20259fSHans Verkuil return ops->vidioc_g_fmt_vbi_cap(file, fh, arg); 13864b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 13874b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap)) 13884b20259fSHans Verkuil break; 13894b20259fSHans Verkuil return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg); 13905bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 13914b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out)) 13925bc3cb74SMauro Carvalho Chehab break; 139348f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1394d52e2381SLaurent Pinchart ret = ops->vidioc_g_fmt_vid_out(file, fh, arg); 139548f2650aSHans Verkuil /* just in case the driver zeroed it again */ 1396d52e2381SLaurent Pinchart p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1397d52e2381SLaurent Pinchart return ret; 13985bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 13994b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane)) 14005bc3cb74SMauro Carvalho Chehab break; 14015bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg); 14025bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 14034b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay)) 14045bc3cb74SMauro Carvalho Chehab break; 14055bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg); 14065bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 14074b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out)) 14085bc3cb74SMauro Carvalho Chehab break; 14095bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_vbi_out(file, fh, arg); 14105bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 14114b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out)) 14125bc3cb74SMauro Carvalho Chehab break; 14135bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg); 1414582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1415582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_g_fmt_sdr_cap)) 1416582c52cbSAntti Palosaari break; 1417582c52cbSAntti Palosaari return ops->vidioc_g_fmt_sdr_cap(file, fh, arg); 14185bc3cb74SMauro Carvalho Chehab } 14195bc3cb74SMauro Carvalho Chehab return -EINVAL; 14205bc3cb74SMauro Carvalho Chehab } 14215bc3cb74SMauro Carvalho Chehab 14225bc3cb74SMauro Carvalho Chehab static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops, 14235bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 14245bc3cb74SMauro Carvalho Chehab { 14255bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 14264b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 14274b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1428582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 14294b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 14304b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 143148f2650aSHans Verkuil int ret; 14325bc3cb74SMauro Carvalho Chehab 1433d52e2381SLaurent Pinchart v4l_sanitize_format(p); 1434d52e2381SLaurent Pinchart 14355bc3cb74SMauro Carvalho Chehab switch (p->type) { 14365bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 14374b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap)) 14385bc3cb74SMauro Carvalho Chehab break; 14395bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 144048f2650aSHans Verkuil ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg); 144148f2650aSHans Verkuil /* just in case the driver zeroed it again */ 144248f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 144348f2650aSHans Verkuil return ret; 14445bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 14454b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane)) 14465bc3cb74SMauro Carvalho Chehab break; 14475bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 14485bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg); 14495bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 14504b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay)) 14515bc3cb74SMauro Carvalho Chehab break; 14525bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 14535bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_overlay(file, fh, arg); 14544b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 14554b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap)) 14564b20259fSHans Verkuil break; 14574b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.vbi); 14584b20259fSHans Verkuil return ops->vidioc_s_fmt_vbi_cap(file, fh, arg); 14594b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 14604b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap)) 14614b20259fSHans Verkuil break; 14624b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.sliced); 14634b20259fSHans Verkuil return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg); 14645bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 14654b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out)) 14665bc3cb74SMauro Carvalho Chehab break; 14675bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 146848f2650aSHans Verkuil ret = ops->vidioc_s_fmt_vid_out(file, fh, arg); 146948f2650aSHans Verkuil /* just in case the driver zeroed it again */ 147048f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 147148f2650aSHans Verkuil return ret; 14725bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 14734b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane)) 14745bc3cb74SMauro Carvalho Chehab break; 14755bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 14765bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg); 14775bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 14784b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay)) 14795bc3cb74SMauro Carvalho Chehab break; 14805bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 14815bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg); 14825bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 14834b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out)) 14845bc3cb74SMauro Carvalho Chehab break; 14855bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.vbi); 14865bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_vbi_out(file, fh, arg); 14875bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 14884b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out)) 14895bc3cb74SMauro Carvalho Chehab break; 14905bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.sliced); 14915bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg); 1492582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1493582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_s_fmt_sdr_cap)) 1494582c52cbSAntti Palosaari break; 1495582c52cbSAntti Palosaari CLEAR_AFTER_FIELD(p, fmt.sdr); 1496582c52cbSAntti Palosaari return ops->vidioc_s_fmt_sdr_cap(file, fh, arg); 14975bc3cb74SMauro Carvalho Chehab } 14985bc3cb74SMauro Carvalho Chehab return -EINVAL; 14995bc3cb74SMauro Carvalho Chehab } 15005bc3cb74SMauro Carvalho Chehab 15015bc3cb74SMauro Carvalho Chehab static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops, 15025bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15035bc3cb74SMauro Carvalho Chehab { 15045bc3cb74SMauro Carvalho Chehab struct v4l2_format *p = arg; 15054b20259fSHans Verkuil struct video_device *vfd = video_devdata(file); 15064b20259fSHans Verkuil bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER; 1507582c52cbSAntti Palosaari bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR; 15084b20259fSHans Verkuil bool is_rx = vfd->vfl_dir != VFL_DIR_TX; 15094b20259fSHans Verkuil bool is_tx = vfd->vfl_dir != VFL_DIR_RX; 151048f2650aSHans Verkuil int ret; 15115bc3cb74SMauro Carvalho Chehab 1512d52e2381SLaurent Pinchart v4l_sanitize_format(p); 1513d52e2381SLaurent Pinchart 15145bc3cb74SMauro Carvalho Chehab switch (p->type) { 15155bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE: 15164b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap)) 15175bc3cb74SMauro Carvalho Chehab break; 15185bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 151948f2650aSHans Verkuil ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg); 152048f2650aSHans Verkuil /* just in case the driver zeroed it again */ 152148f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 152248f2650aSHans Verkuil return ret; 15235bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: 15244b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane)) 15255bc3cb74SMauro Carvalho Chehab break; 15265bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 15275bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg); 15285bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OVERLAY: 15294b20259fSHans Verkuil if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay)) 15305bc3cb74SMauro Carvalho Chehab break; 15315bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 15325bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_overlay(file, fh, arg); 15334b20259fSHans Verkuil case V4L2_BUF_TYPE_VBI_CAPTURE: 15344b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap)) 15354b20259fSHans Verkuil break; 15364b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.vbi); 15374b20259fSHans Verkuil return ops->vidioc_try_fmt_vbi_cap(file, fh, arg); 15384b20259fSHans Verkuil case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 15394b20259fSHans Verkuil if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap)) 15404b20259fSHans Verkuil break; 15414b20259fSHans Verkuil CLEAR_AFTER_FIELD(p, fmt.sliced); 15424b20259fSHans Verkuil return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg); 15435bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT: 15444b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out)) 15455bc3cb74SMauro Carvalho Chehab break; 15465bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix); 154748f2650aSHans Verkuil ret = ops->vidioc_try_fmt_vid_out(file, fh, arg); 154848f2650aSHans Verkuil /* just in case the driver zeroed it again */ 154948f2650aSHans Verkuil p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 155048f2650aSHans Verkuil return ret; 15515bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: 15524b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane)) 15535bc3cb74SMauro Carvalho Chehab break; 15545bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.pix_mp); 15555bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg); 15565bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: 15574b20259fSHans Verkuil if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay)) 15585bc3cb74SMauro Carvalho Chehab break; 15595bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.win); 15605bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg); 15615bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_VBI_OUTPUT: 15624b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out)) 15635bc3cb74SMauro Carvalho Chehab break; 15645bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.vbi); 15655bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_vbi_out(file, fh, arg); 15665bc3cb74SMauro Carvalho Chehab case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT: 15674b20259fSHans Verkuil if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out)) 15685bc3cb74SMauro Carvalho Chehab break; 15695bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, fmt.sliced); 15705bc3cb74SMauro Carvalho Chehab return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg); 1571582c52cbSAntti Palosaari case V4L2_BUF_TYPE_SDR_CAPTURE: 1572582c52cbSAntti Palosaari if (unlikely(!is_rx || !is_sdr || !ops->vidioc_try_fmt_sdr_cap)) 1573582c52cbSAntti Palosaari break; 1574582c52cbSAntti Palosaari CLEAR_AFTER_FIELD(p, fmt.sdr); 1575582c52cbSAntti Palosaari return ops->vidioc_try_fmt_sdr_cap(file, fh, arg); 15765bc3cb74SMauro Carvalho Chehab } 15775bc3cb74SMauro Carvalho Chehab return -EINVAL; 15785bc3cb74SMauro Carvalho Chehab } 15795bc3cb74SMauro Carvalho Chehab 15805bc3cb74SMauro Carvalho Chehab static int v4l_streamon(const struct v4l2_ioctl_ops *ops, 15815bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15825bc3cb74SMauro Carvalho Chehab { 15835bc3cb74SMauro Carvalho Chehab return ops->vidioc_streamon(file, fh, *(unsigned int *)arg); 15845bc3cb74SMauro Carvalho Chehab } 15855bc3cb74SMauro Carvalho Chehab 15865bc3cb74SMauro Carvalho Chehab static int v4l_streamoff(const struct v4l2_ioctl_ops *ops, 15875bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15885bc3cb74SMauro Carvalho Chehab { 15895bc3cb74SMauro Carvalho Chehab return ops->vidioc_streamoff(file, fh, *(unsigned int *)arg); 15905bc3cb74SMauro Carvalho Chehab } 15915bc3cb74SMauro Carvalho Chehab 15925bc3cb74SMauro Carvalho Chehab static int v4l_g_tuner(const struct v4l2_ioctl_ops *ops, 15935bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 15945bc3cb74SMauro Carvalho Chehab { 15955bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 15965bc3cb74SMauro Carvalho Chehab struct v4l2_tuner *p = arg; 15975bc3cb74SMauro Carvalho Chehab int err; 15985bc3cb74SMauro Carvalho Chehab 15995bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 16005bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 16015bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_tuner(file, fh, p); 16025bc3cb74SMauro Carvalho Chehab if (!err) 16035bc3cb74SMauro Carvalho Chehab p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; 16045bc3cb74SMauro Carvalho Chehab return err; 16055bc3cb74SMauro Carvalho Chehab } 16065bc3cb74SMauro Carvalho Chehab 16075bc3cb74SMauro Carvalho Chehab static int v4l_s_tuner(const struct v4l2_ioctl_ops *ops, 16085bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16095bc3cb74SMauro Carvalho Chehab { 16105bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 16115bc3cb74SMauro Carvalho Chehab struct v4l2_tuner *p = arg; 16125bc3cb74SMauro Carvalho Chehab 16135bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 16145bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 16155bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_tuner(file, fh, p); 16165bc3cb74SMauro Carvalho Chehab } 16175bc3cb74SMauro Carvalho Chehab 16185bc3cb74SMauro Carvalho Chehab static int v4l_g_modulator(const struct v4l2_ioctl_ops *ops, 16195bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16205bc3cb74SMauro Carvalho Chehab { 16215bc3cb74SMauro Carvalho Chehab struct v4l2_modulator *p = arg; 16225bc3cb74SMauro Carvalho Chehab int err; 16235bc3cb74SMauro Carvalho Chehab 16245bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_modulator(file, fh, p); 16255bc3cb74SMauro Carvalho Chehab if (!err) 16265bc3cb74SMauro Carvalho Chehab p->capability |= V4L2_TUNER_CAP_FREQ_BANDS; 16275bc3cb74SMauro Carvalho Chehab return err; 16285bc3cb74SMauro Carvalho Chehab } 16295bc3cb74SMauro Carvalho Chehab 16305bc3cb74SMauro Carvalho Chehab static int v4l_g_frequency(const struct v4l2_ioctl_ops *ops, 16315bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16325bc3cb74SMauro Carvalho Chehab { 16335bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 16345bc3cb74SMauro Carvalho Chehab struct v4l2_frequency *p = arg; 16355bc3cb74SMauro Carvalho Chehab 163684099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) 163784099a28SAntti Palosaari p->type = V4L2_TUNER_ADC; 163884099a28SAntti Palosaari else 16395bc3cb74SMauro Carvalho Chehab p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 16405bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 16415bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_frequency(file, fh, p); 16425bc3cb74SMauro Carvalho Chehab } 16435bc3cb74SMauro Carvalho Chehab 16445bc3cb74SMauro Carvalho Chehab static int v4l_s_frequency(const struct v4l2_ioctl_ops *ops, 16455bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16465bc3cb74SMauro Carvalho Chehab { 16475bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 1648b530a447SHans Verkuil const struct v4l2_frequency *p = arg; 16495bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 16505bc3cb74SMauro Carvalho Chehab 165184099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) { 165284099a28SAntti Palosaari if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) 165384099a28SAntti Palosaari return -EINVAL; 165484099a28SAntti Palosaari } else { 16555bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 16565bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 165784099a28SAntti Palosaari if (type != p->type) 16585bc3cb74SMauro Carvalho Chehab return -EINVAL; 165984099a28SAntti Palosaari } 16605bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_frequency(file, fh, p); 16615bc3cb74SMauro Carvalho Chehab } 16625bc3cb74SMauro Carvalho Chehab 16635bc3cb74SMauro Carvalho Chehab static int v4l_enumstd(const struct v4l2_ioctl_ops *ops, 16645bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 16655bc3cb74SMauro Carvalho Chehab { 16665bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 16675bc3cb74SMauro Carvalho Chehab struct v4l2_standard *p = arg; 16685bc3cb74SMauro Carvalho Chehab v4l2_std_id id = vfd->tvnorms, curr_id = 0; 16695bc3cb74SMauro Carvalho Chehab unsigned int index = p->index, i, j = 0; 16705bc3cb74SMauro Carvalho Chehab const char *descr = ""; 16715bc3cb74SMauro Carvalho Chehab 1672a5338190SHans Verkuil /* Return -ENODATA if the tvnorms for the current input 1673a5338190SHans Verkuil or output is 0, meaning that it doesn't support this API. */ 1674a5338190SHans Verkuil if (id == 0) 1675a5338190SHans Verkuil return -ENODATA; 1676a5338190SHans Verkuil 16775bc3cb74SMauro Carvalho Chehab /* Return norm array in a canonical way */ 16785bc3cb74SMauro Carvalho Chehab for (i = 0; i <= index && id; i++) { 16795bc3cb74SMauro Carvalho Chehab /* last std value in the standards array is 0, so this 16805bc3cb74SMauro Carvalho Chehab while always ends there since (id & 0) == 0. */ 16815bc3cb74SMauro Carvalho Chehab while ((id & standards[j].std) != standards[j].std) 16825bc3cb74SMauro Carvalho Chehab j++; 16835bc3cb74SMauro Carvalho Chehab curr_id = standards[j].std; 16845bc3cb74SMauro Carvalho Chehab descr = standards[j].descr; 16855bc3cb74SMauro Carvalho Chehab j++; 16865bc3cb74SMauro Carvalho Chehab if (curr_id == 0) 16875bc3cb74SMauro Carvalho Chehab break; 16885bc3cb74SMauro Carvalho Chehab if (curr_id != V4L2_STD_PAL && 16895bc3cb74SMauro Carvalho Chehab curr_id != V4L2_STD_SECAM && 16905bc3cb74SMauro Carvalho Chehab curr_id != V4L2_STD_NTSC) 16915bc3cb74SMauro Carvalho Chehab id &= ~curr_id; 16925bc3cb74SMauro Carvalho Chehab } 16935bc3cb74SMauro Carvalho Chehab if (i <= index) 16945bc3cb74SMauro Carvalho Chehab return -EINVAL; 16955bc3cb74SMauro Carvalho Chehab 16965bc3cb74SMauro Carvalho Chehab v4l2_video_std_construct(p, curr_id, descr); 16975bc3cb74SMauro Carvalho Chehab return 0; 16985bc3cb74SMauro Carvalho Chehab } 16995bc3cb74SMauro Carvalho Chehab 17005bc3cb74SMauro Carvalho Chehab static int v4l_s_std(const struct v4l2_ioctl_ops *ops, 17015bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17025bc3cb74SMauro Carvalho Chehab { 17035bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 1704314527acSHans Verkuil v4l2_std_id id = *(v4l2_std_id *)arg, norm; 17055bc3cb74SMauro Carvalho Chehab 1706314527acSHans Verkuil norm = id & vfd->tvnorms; 17075bc3cb74SMauro Carvalho Chehab if (vfd->tvnorms && !norm) /* Check if std is supported */ 17085bc3cb74SMauro Carvalho Chehab return -EINVAL; 17095bc3cb74SMauro Carvalho Chehab 17105bc3cb74SMauro Carvalho Chehab /* Calls the specific handler */ 1711ca371575SHans Verkuil return ops->vidioc_s_std(file, fh, norm); 17125bc3cb74SMauro Carvalho Chehab } 17135bc3cb74SMauro Carvalho Chehab 17145bc3cb74SMauro Carvalho Chehab static int v4l_querystd(const struct v4l2_ioctl_ops *ops, 17155bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17165bc3cb74SMauro Carvalho Chehab { 17175bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17185bc3cb74SMauro Carvalho Chehab v4l2_std_id *p = arg; 17195bc3cb74SMauro Carvalho Chehab 17205bc3cb74SMauro Carvalho Chehab /* 17211a2c6866SHans Verkuil * If no signal is detected, then the driver should return 17221a2c6866SHans Verkuil * V4L2_STD_UNKNOWN. Otherwise it should return tvnorms with 17231a2c6866SHans Verkuil * any standards that do not apply removed. 17241a2c6866SHans Verkuil * 17255bc3cb74SMauro Carvalho Chehab * This means that tuners, audio and video decoders can join 17265bc3cb74SMauro Carvalho Chehab * their efforts to improve the standards detection. 17275bc3cb74SMauro Carvalho Chehab */ 17285bc3cb74SMauro Carvalho Chehab *p = vfd->tvnorms; 17295bc3cb74SMauro Carvalho Chehab return ops->vidioc_querystd(file, fh, arg); 17305bc3cb74SMauro Carvalho Chehab } 17315bc3cb74SMauro Carvalho Chehab 17325bc3cb74SMauro Carvalho Chehab static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops, 17335bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17345bc3cb74SMauro Carvalho Chehab { 17355bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 17365bc3cb74SMauro Carvalho Chehab struct v4l2_hw_freq_seek *p = arg; 17375bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 17385bc3cb74SMauro Carvalho Chehab 173984099a28SAntti Palosaari /* s_hw_freq_seek is not supported for SDR for now */ 174084099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) 174184099a28SAntti Palosaari return -EINVAL; 174284099a28SAntti Palosaari 17435bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 17445bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 17455bc3cb74SMauro Carvalho Chehab if (p->type != type) 17465bc3cb74SMauro Carvalho Chehab return -EINVAL; 17475bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_hw_freq_seek(file, fh, p); 17485bc3cb74SMauro Carvalho Chehab } 17495bc3cb74SMauro Carvalho Chehab 1750737c097bSHans Verkuil static int v4l_overlay(const struct v4l2_ioctl_ops *ops, 1751737c097bSHans Verkuil struct file *file, void *fh, void *arg) 1752737c097bSHans Verkuil { 1753737c097bSHans Verkuil return ops->vidioc_overlay(file, fh, *(unsigned int *)arg); 1754737c097bSHans Verkuil } 1755737c097bSHans Verkuil 17565bc3cb74SMauro Carvalho Chehab static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, 17575bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17585bc3cb74SMauro Carvalho Chehab { 17595bc3cb74SMauro Carvalho Chehab struct v4l2_requestbuffers *p = arg; 17604b20259fSHans Verkuil int ret = check_fmt(file, p->type); 17615bc3cb74SMauro Carvalho Chehab 17625bc3cb74SMauro Carvalho Chehab if (ret) 17635bc3cb74SMauro Carvalho Chehab return ret; 17645bc3cb74SMauro Carvalho Chehab 17655bc3cb74SMauro Carvalho Chehab CLEAR_AFTER_FIELD(p, memory); 17665bc3cb74SMauro Carvalho Chehab 17675bc3cb74SMauro Carvalho Chehab return ops->vidioc_reqbufs(file, fh, p); 17685bc3cb74SMauro Carvalho Chehab } 17695bc3cb74SMauro Carvalho Chehab 17705bc3cb74SMauro Carvalho Chehab static int v4l_querybuf(const struct v4l2_ioctl_ops *ops, 17715bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17725bc3cb74SMauro Carvalho Chehab { 17735bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 17744b20259fSHans Verkuil int ret = check_fmt(file, p->type); 17755bc3cb74SMauro Carvalho Chehab 17765bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_querybuf(file, fh, p); 17775bc3cb74SMauro Carvalho Chehab } 17785bc3cb74SMauro Carvalho Chehab 17795bc3cb74SMauro Carvalho Chehab static int v4l_qbuf(const struct v4l2_ioctl_ops *ops, 17805bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17815bc3cb74SMauro Carvalho Chehab { 17825bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 17834b20259fSHans Verkuil int ret = check_fmt(file, p->type); 17845bc3cb74SMauro Carvalho Chehab 17855bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_qbuf(file, fh, p); 17865bc3cb74SMauro Carvalho Chehab } 17875bc3cb74SMauro Carvalho Chehab 17885bc3cb74SMauro Carvalho Chehab static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, 17895bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17905bc3cb74SMauro Carvalho Chehab { 17915bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *p = arg; 17924b20259fSHans Verkuil int ret = check_fmt(file, p->type); 17935bc3cb74SMauro Carvalho Chehab 17945bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_dqbuf(file, fh, p); 17955bc3cb74SMauro Carvalho Chehab } 17965bc3cb74SMauro Carvalho Chehab 17975bc3cb74SMauro Carvalho Chehab static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, 17985bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 17995bc3cb74SMauro Carvalho Chehab { 18005bc3cb74SMauro Carvalho Chehab struct v4l2_create_buffers *create = arg; 18014b20259fSHans Verkuil int ret = check_fmt(file, create->format.type); 18025bc3cb74SMauro Carvalho Chehab 1803d52e2381SLaurent Pinchart if (ret) 1804d52e2381SLaurent Pinchart return ret; 1805d52e2381SLaurent Pinchart 1806d52e2381SLaurent Pinchart v4l_sanitize_format(&create->format); 1807d52e2381SLaurent Pinchart 1808d52e2381SLaurent Pinchart ret = ops->vidioc_create_bufs(file, fh, create); 1809d52e2381SLaurent Pinchart 1810d52e2381SLaurent Pinchart if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || 1811d52e2381SLaurent Pinchart create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) 1812d52e2381SLaurent Pinchart create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC; 1813d52e2381SLaurent Pinchart 1814d52e2381SLaurent Pinchart return ret; 18155bc3cb74SMauro Carvalho Chehab } 18165bc3cb74SMauro Carvalho Chehab 18175bc3cb74SMauro Carvalho Chehab static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, 18185bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18195bc3cb74SMauro Carvalho Chehab { 18205bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *b = arg; 18214b20259fSHans Verkuil int ret = check_fmt(file, b->type); 18225bc3cb74SMauro Carvalho Chehab 18235bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); 18245bc3cb74SMauro Carvalho Chehab } 18255bc3cb74SMauro Carvalho Chehab 18265bc3cb74SMauro Carvalho Chehab static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, 18275bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18285bc3cb74SMauro Carvalho Chehab { 18295bc3cb74SMauro Carvalho Chehab struct v4l2_streamparm *p = arg; 18305bc3cb74SMauro Carvalho Chehab v4l2_std_id std; 18314b20259fSHans Verkuil int ret = check_fmt(file, p->type); 18325bc3cb74SMauro Carvalho Chehab 18335bc3cb74SMauro Carvalho Chehab if (ret) 18345bc3cb74SMauro Carvalho Chehab return ret; 18355bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_parm) 18365bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_parm(file, fh, p); 18375bc3cb74SMauro Carvalho Chehab if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE && 18385bc3cb74SMauro Carvalho Chehab p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) 18395bc3cb74SMauro Carvalho Chehab return -EINVAL; 18405bc3cb74SMauro Carvalho Chehab p->parm.capture.readbuffers = 2; 18415bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_std(file, fh, &std); 18425bc3cb74SMauro Carvalho Chehab if (ret == 0) 1843ca371575SHans Verkuil v4l2_video_std_frame_period(std, &p->parm.capture.timeperframe); 18445bc3cb74SMauro Carvalho Chehab return ret; 18455bc3cb74SMauro Carvalho Chehab } 18465bc3cb74SMauro Carvalho Chehab 18475bc3cb74SMauro Carvalho Chehab static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, 18485bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18495bc3cb74SMauro Carvalho Chehab { 18505bc3cb74SMauro Carvalho Chehab struct v4l2_streamparm *p = arg; 18514b20259fSHans Verkuil int ret = check_fmt(file, p->type); 18525bc3cb74SMauro Carvalho Chehab 18535bc3cb74SMauro Carvalho Chehab return ret ? ret : ops->vidioc_s_parm(file, fh, p); 18545bc3cb74SMauro Carvalho Chehab } 18555bc3cb74SMauro Carvalho Chehab 18565bc3cb74SMauro Carvalho Chehab static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, 18575bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18585bc3cb74SMauro Carvalho Chehab { 18595bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 18605bc3cb74SMauro Carvalho Chehab struct v4l2_queryctrl *p = arg; 18615bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 18625bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 18635bc3cb74SMauro Carvalho Chehab 18645bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 18655bc3cb74SMauro Carvalho Chehab return v4l2_queryctrl(vfh->ctrl_handler, p); 18665bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 18675bc3cb74SMauro Carvalho Chehab return v4l2_queryctrl(vfd->ctrl_handler, p); 18685bc3cb74SMauro Carvalho Chehab if (ops->vidioc_queryctrl) 18695bc3cb74SMauro Carvalho Chehab return ops->vidioc_queryctrl(file, fh, p); 18705bc3cb74SMauro Carvalho Chehab return -ENOTTY; 18715bc3cb74SMauro Carvalho Chehab } 18725bc3cb74SMauro Carvalho Chehab 1873e6bee368SHans Verkuil static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, 1874e6bee368SHans Verkuil struct file *file, void *fh, void *arg) 1875e6bee368SHans Verkuil { 1876e6bee368SHans Verkuil struct video_device *vfd = video_devdata(file); 1877e6bee368SHans Verkuil struct v4l2_query_ext_ctrl *p = arg; 1878e6bee368SHans Verkuil struct v4l2_fh *vfh = 1879e6bee368SHans Verkuil test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 1880e6bee368SHans Verkuil 1881e6bee368SHans Verkuil if (vfh && vfh->ctrl_handler) 1882e6bee368SHans Verkuil return v4l2_query_ext_ctrl(vfh->ctrl_handler, p); 1883e6bee368SHans Verkuil if (vfd->ctrl_handler) 1884e6bee368SHans Verkuil return v4l2_query_ext_ctrl(vfd->ctrl_handler, p); 1885e6bee368SHans Verkuil if (ops->vidioc_query_ext_ctrl) 1886e6bee368SHans Verkuil return ops->vidioc_query_ext_ctrl(file, fh, p); 1887e6bee368SHans Verkuil return -ENOTTY; 1888e6bee368SHans Verkuil } 1889e6bee368SHans Verkuil 18905bc3cb74SMauro Carvalho Chehab static int v4l_querymenu(const struct v4l2_ioctl_ops *ops, 18915bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 18925bc3cb74SMauro Carvalho Chehab { 18935bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 18945bc3cb74SMauro Carvalho Chehab struct v4l2_querymenu *p = arg; 18955bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 18965bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 18975bc3cb74SMauro Carvalho Chehab 18985bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 18995bc3cb74SMauro Carvalho Chehab return v4l2_querymenu(vfh->ctrl_handler, p); 19005bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 19015bc3cb74SMauro Carvalho Chehab return v4l2_querymenu(vfd->ctrl_handler, p); 19025bc3cb74SMauro Carvalho Chehab if (ops->vidioc_querymenu) 19035bc3cb74SMauro Carvalho Chehab return ops->vidioc_querymenu(file, fh, p); 19045bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19055bc3cb74SMauro Carvalho Chehab } 19065bc3cb74SMauro Carvalho Chehab 19075bc3cb74SMauro Carvalho Chehab static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, 19085bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19095bc3cb74SMauro Carvalho Chehab { 19105bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 19115bc3cb74SMauro Carvalho Chehab struct v4l2_control *p = arg; 19125bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 19135bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 19145bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls ctrls; 19155bc3cb74SMauro Carvalho Chehab struct v4l2_ext_control ctrl; 19165bc3cb74SMauro Carvalho Chehab 19175bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 19185bc3cb74SMauro Carvalho Chehab return v4l2_g_ctrl(vfh->ctrl_handler, p); 19195bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 19205bc3cb74SMauro Carvalho Chehab return v4l2_g_ctrl(vfd->ctrl_handler, p); 19215bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ctrl) 19225bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_ctrl(file, fh, p); 19235bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ext_ctrls == NULL) 19245bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19255bc3cb74SMauro Carvalho Chehab 19265bc3cb74SMauro Carvalho Chehab ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); 19275bc3cb74SMauro Carvalho Chehab ctrls.count = 1; 19285bc3cb74SMauro Carvalho Chehab ctrls.controls = &ctrl; 19295bc3cb74SMauro Carvalho Chehab ctrl.id = p->id; 19305bc3cb74SMauro Carvalho Chehab ctrl.value = p->value; 19315bc3cb74SMauro Carvalho Chehab if (check_ext_ctrls(&ctrls, 1)) { 19325bc3cb74SMauro Carvalho Chehab int ret = ops->vidioc_g_ext_ctrls(file, fh, &ctrls); 19335bc3cb74SMauro Carvalho Chehab 19345bc3cb74SMauro Carvalho Chehab if (ret == 0) 19355bc3cb74SMauro Carvalho Chehab p->value = ctrl.value; 19365bc3cb74SMauro Carvalho Chehab return ret; 19375bc3cb74SMauro Carvalho Chehab } 19385bc3cb74SMauro Carvalho Chehab return -EINVAL; 19395bc3cb74SMauro Carvalho Chehab } 19405bc3cb74SMauro Carvalho Chehab 19415bc3cb74SMauro Carvalho Chehab static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, 19425bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19435bc3cb74SMauro Carvalho Chehab { 19445bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 19455bc3cb74SMauro Carvalho Chehab struct v4l2_control *p = arg; 19465bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 19475bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 19485bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls ctrls; 19495bc3cb74SMauro Carvalho Chehab struct v4l2_ext_control ctrl; 19505bc3cb74SMauro Carvalho Chehab 19515bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 19525bc3cb74SMauro Carvalho Chehab return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); 19535bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 19545bc3cb74SMauro Carvalho Chehab return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); 19555bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ctrl) 19565bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_ctrl(file, fh, p); 19575bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ext_ctrls == NULL) 19585bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19595bc3cb74SMauro Carvalho Chehab 19605bc3cb74SMauro Carvalho Chehab ctrls.ctrl_class = V4L2_CTRL_ID2CLASS(p->id); 19615bc3cb74SMauro Carvalho Chehab ctrls.count = 1; 19625bc3cb74SMauro Carvalho Chehab ctrls.controls = &ctrl; 19635bc3cb74SMauro Carvalho Chehab ctrl.id = p->id; 19645bc3cb74SMauro Carvalho Chehab ctrl.value = p->value; 19655bc3cb74SMauro Carvalho Chehab if (check_ext_ctrls(&ctrls, 1)) 19665bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_ext_ctrls(file, fh, &ctrls); 19675bc3cb74SMauro Carvalho Chehab return -EINVAL; 19685bc3cb74SMauro Carvalho Chehab } 19695bc3cb74SMauro Carvalho Chehab 19705bc3cb74SMauro Carvalho Chehab static int v4l_g_ext_ctrls(const struct v4l2_ioctl_ops *ops, 19715bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19725bc3cb74SMauro Carvalho Chehab { 19735bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 19745bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 19755bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 19765bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 19775bc3cb74SMauro Carvalho Chehab 19785bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 19795bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 19805bc3cb74SMauro Carvalho Chehab return v4l2_g_ext_ctrls(vfh->ctrl_handler, p); 19815bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 19825bc3cb74SMauro Carvalho Chehab return v4l2_g_ext_ctrls(vfd->ctrl_handler, p); 19835bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_ext_ctrls == NULL) 19845bc3cb74SMauro Carvalho Chehab return -ENOTTY; 19855bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_g_ext_ctrls(file, fh, p) : 19865bc3cb74SMauro Carvalho Chehab -EINVAL; 19875bc3cb74SMauro Carvalho Chehab } 19885bc3cb74SMauro Carvalho Chehab 19895bc3cb74SMauro Carvalho Chehab static int v4l_s_ext_ctrls(const struct v4l2_ioctl_ops *ops, 19905bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 19915bc3cb74SMauro Carvalho Chehab { 19925bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 19935bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 19945bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 19955bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 19965bc3cb74SMauro Carvalho Chehab 19975bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 19985bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 19995bc3cb74SMauro Carvalho Chehab return v4l2_s_ext_ctrls(vfh, vfh->ctrl_handler, p); 20005bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 20015bc3cb74SMauro Carvalho Chehab return v4l2_s_ext_ctrls(NULL, vfd->ctrl_handler, p); 20025bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_ext_ctrls == NULL) 20035bc3cb74SMauro Carvalho Chehab return -ENOTTY; 20045bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_s_ext_ctrls(file, fh, p) : 20055bc3cb74SMauro Carvalho Chehab -EINVAL; 20065bc3cb74SMauro Carvalho Chehab } 20075bc3cb74SMauro Carvalho Chehab 20085bc3cb74SMauro Carvalho Chehab static int v4l_try_ext_ctrls(const struct v4l2_ioctl_ops *ops, 20095bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20105bc3cb74SMauro Carvalho Chehab { 20115bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 20125bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *p = arg; 20135bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = 20145bc3cb74SMauro Carvalho Chehab test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; 20155bc3cb74SMauro Carvalho Chehab 20165bc3cb74SMauro Carvalho Chehab p->error_idx = p->count; 20175bc3cb74SMauro Carvalho Chehab if (vfh && vfh->ctrl_handler) 20185bc3cb74SMauro Carvalho Chehab return v4l2_try_ext_ctrls(vfh->ctrl_handler, p); 20195bc3cb74SMauro Carvalho Chehab if (vfd->ctrl_handler) 20205bc3cb74SMauro Carvalho Chehab return v4l2_try_ext_ctrls(vfd->ctrl_handler, p); 20215bc3cb74SMauro Carvalho Chehab if (ops->vidioc_try_ext_ctrls == NULL) 20225bc3cb74SMauro Carvalho Chehab return -ENOTTY; 20235bc3cb74SMauro Carvalho Chehab return check_ext_ctrls(p, 0) ? ops->vidioc_try_ext_ctrls(file, fh, p) : 20245bc3cb74SMauro Carvalho Chehab -EINVAL; 20255bc3cb74SMauro Carvalho Chehab } 20265bc3cb74SMauro Carvalho Chehab 20275bc3cb74SMauro Carvalho Chehab static int v4l_g_crop(const struct v4l2_ioctl_ops *ops, 20285bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20295bc3cb74SMauro Carvalho Chehab { 20305bc3cb74SMauro Carvalho Chehab struct v4l2_crop *p = arg; 20315bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { 20325bc3cb74SMauro Carvalho Chehab .type = p->type, 20335bc3cb74SMauro Carvalho Chehab }; 20345bc3cb74SMauro Carvalho Chehab int ret; 20355bc3cb74SMauro Carvalho Chehab 20365bc3cb74SMauro Carvalho Chehab if (ops->vidioc_g_crop) 20375bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_crop(file, fh, p); 20385bc3cb74SMauro Carvalho Chehab /* simulate capture crop using selection api */ 20395bc3cb74SMauro Carvalho Chehab 20405bc3cb74SMauro Carvalho Chehab /* crop means compose for output devices */ 20415bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 20425bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; 20435bc3cb74SMauro Carvalho Chehab else 20445bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_ACTIVE; 20455bc3cb74SMauro Carvalho Chehab 20465bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 20475bc3cb74SMauro Carvalho Chehab 20485bc3cb74SMauro Carvalho Chehab /* copying results to old structure on success */ 20495bc3cb74SMauro Carvalho Chehab if (!ret) 20505bc3cb74SMauro Carvalho Chehab p->c = s.r; 20515bc3cb74SMauro Carvalho Chehab return ret; 20525bc3cb74SMauro Carvalho Chehab } 20535bc3cb74SMauro Carvalho Chehab 20545bc3cb74SMauro Carvalho Chehab static int v4l_s_crop(const struct v4l2_ioctl_ops *ops, 20555bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20565bc3cb74SMauro Carvalho Chehab { 20575bc3cb74SMauro Carvalho Chehab struct v4l2_crop *p = arg; 20585bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { 20595bc3cb74SMauro Carvalho Chehab .type = p->type, 20605bc3cb74SMauro Carvalho Chehab .r = p->c, 20615bc3cb74SMauro Carvalho Chehab }; 20625bc3cb74SMauro Carvalho Chehab 20635bc3cb74SMauro Carvalho Chehab if (ops->vidioc_s_crop) 20645bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_crop(file, fh, p); 20655bc3cb74SMauro Carvalho Chehab /* simulate capture crop using selection api */ 20665bc3cb74SMauro Carvalho Chehab 20675bc3cb74SMauro Carvalho Chehab /* crop means compose for output devices */ 20685bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 20695bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; 20705bc3cb74SMauro Carvalho Chehab else 20715bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_ACTIVE; 20725bc3cb74SMauro Carvalho Chehab 20735bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_selection(file, fh, &s); 20745bc3cb74SMauro Carvalho Chehab } 20755bc3cb74SMauro Carvalho Chehab 20765bc3cb74SMauro Carvalho Chehab static int v4l_cropcap(const struct v4l2_ioctl_ops *ops, 20775bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 20785bc3cb74SMauro Carvalho Chehab { 20795bc3cb74SMauro Carvalho Chehab struct v4l2_cropcap *p = arg; 20809409945cSHans Verkuil 20819409945cSHans Verkuil if (ops->vidioc_g_selection) { 20825bc3cb74SMauro Carvalho Chehab struct v4l2_selection s = { .type = p->type }; 20835bc3cb74SMauro Carvalho Chehab int ret; 20845bc3cb74SMauro Carvalho Chehab 20855bc3cb74SMauro Carvalho Chehab /* obtaining bounds */ 20865bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 20875bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; 20885bc3cb74SMauro Carvalho Chehab else 20895bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_BOUNDS; 20905bc3cb74SMauro Carvalho Chehab 20915bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 20925bc3cb74SMauro Carvalho Chehab if (ret) 20935bc3cb74SMauro Carvalho Chehab return ret; 20945bc3cb74SMauro Carvalho Chehab p->bounds = s.r; 20955bc3cb74SMauro Carvalho Chehab 20965bc3cb74SMauro Carvalho Chehab /* obtaining defrect */ 20975bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_OUTPUT(p->type)) 20985bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; 20995bc3cb74SMauro Carvalho Chehab else 21005bc3cb74SMauro Carvalho Chehab s.target = V4L2_SEL_TGT_CROP_DEFAULT; 21015bc3cb74SMauro Carvalho Chehab 21025bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_g_selection(file, fh, &s); 21035bc3cb74SMauro Carvalho Chehab if (ret) 21045bc3cb74SMauro Carvalho Chehab return ret; 21055bc3cb74SMauro Carvalho Chehab p->defrect = s.r; 21069409945cSHans Verkuil } 21075bc3cb74SMauro Carvalho Chehab 21085bc3cb74SMauro Carvalho Chehab /* setting trivial pixelaspect */ 21095bc3cb74SMauro Carvalho Chehab p->pixelaspect.numerator = 1; 21105bc3cb74SMauro Carvalho Chehab p->pixelaspect.denominator = 1; 21119409945cSHans Verkuil 21129409945cSHans Verkuil if (ops->vidioc_cropcap) 21139409945cSHans Verkuil return ops->vidioc_cropcap(file, fh, p); 21149409945cSHans Verkuil 21155bc3cb74SMauro Carvalho Chehab return 0; 21165bc3cb74SMauro Carvalho Chehab } 21175bc3cb74SMauro Carvalho Chehab 21185bc3cb74SMauro Carvalho Chehab static int v4l_log_status(const struct v4l2_ioctl_ops *ops, 21195bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 21205bc3cb74SMauro Carvalho Chehab { 21215bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 21225bc3cb74SMauro Carvalho Chehab int ret; 21235bc3cb74SMauro Carvalho Chehab 21245bc3cb74SMauro Carvalho Chehab if (vfd->v4l2_dev) 21255bc3cb74SMauro Carvalho Chehab pr_info("%s: ================= START STATUS =================\n", 21265bc3cb74SMauro Carvalho Chehab vfd->v4l2_dev->name); 21275bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_log_status(file, fh); 21285bc3cb74SMauro Carvalho Chehab if (vfd->v4l2_dev) 21295bc3cb74SMauro Carvalho Chehab pr_info("%s: ================== END STATUS ==================\n", 21305bc3cb74SMauro Carvalho Chehab vfd->v4l2_dev->name); 21315bc3cb74SMauro Carvalho Chehab return ret; 21325bc3cb74SMauro Carvalho Chehab } 21335bc3cb74SMauro Carvalho Chehab 21345bc3cb74SMauro Carvalho Chehab static int v4l_dbg_g_register(const struct v4l2_ioctl_ops *ops, 21355bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 21365bc3cb74SMauro Carvalho Chehab { 21375bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 21385bc3cb74SMauro Carvalho Chehab struct v4l2_dbg_register *p = arg; 213979b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 214079b0c640SHans Verkuil struct v4l2_subdev *sd; 214179b0c640SHans Verkuil int idx = 0; 21425bc3cb74SMauro Carvalho Chehab 21435bc3cb74SMauro Carvalho Chehab if (!capable(CAP_SYS_ADMIN)) 21445bc3cb74SMauro Carvalho Chehab return -EPERM; 21453eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) { 214679b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 214779b0c640SHans Verkuil return -EINVAL; 21483eef2510SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) 21493eef2510SHans Verkuil if (p->match.addr == idx++) 215079b0c640SHans Verkuil return v4l2_subdev_call(sd, core, g_register, p); 215179b0c640SHans Verkuil return -EINVAL; 215279b0c640SHans Verkuil } 2153191b79b0SHans Verkuil if (ops->vidioc_g_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && 2154191b79b0SHans Verkuil (ops->vidioc_g_chip_info || p->match.addr == 0)) 21555bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_register(file, fh, p); 215679b0c640SHans Verkuil return -EINVAL; 21575bc3cb74SMauro Carvalho Chehab #else 21585bc3cb74SMauro Carvalho Chehab return -ENOTTY; 21595bc3cb74SMauro Carvalho Chehab #endif 21605bc3cb74SMauro Carvalho Chehab } 21615bc3cb74SMauro Carvalho Chehab 21625bc3cb74SMauro Carvalho Chehab static int v4l_dbg_s_register(const struct v4l2_ioctl_ops *ops, 21635bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 21645bc3cb74SMauro Carvalho Chehab { 21655bc3cb74SMauro Carvalho Chehab #ifdef CONFIG_VIDEO_ADV_DEBUG 2166977ba3b1SHans Verkuil const struct v4l2_dbg_register *p = arg; 216779b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 216879b0c640SHans Verkuil struct v4l2_subdev *sd; 216979b0c640SHans Verkuil int idx = 0; 21705bc3cb74SMauro Carvalho Chehab 21715bc3cb74SMauro Carvalho Chehab if (!capable(CAP_SYS_ADMIN)) 21725bc3cb74SMauro Carvalho Chehab return -EPERM; 21733eef2510SHans Verkuil if (p->match.type == V4L2_CHIP_MATCH_SUBDEV) { 217479b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 217579b0c640SHans Verkuil return -EINVAL; 21763eef2510SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) 21773eef2510SHans Verkuil if (p->match.addr == idx++) 217879b0c640SHans Verkuil return v4l2_subdev_call(sd, core, s_register, p); 217979b0c640SHans Verkuil return -EINVAL; 218079b0c640SHans Verkuil } 2181191b79b0SHans Verkuil if (ops->vidioc_s_register && p->match.type == V4L2_CHIP_MATCH_BRIDGE && 2182191b79b0SHans Verkuil (ops->vidioc_g_chip_info || p->match.addr == 0)) 21835bc3cb74SMauro Carvalho Chehab return ops->vidioc_s_register(file, fh, p); 218479b0c640SHans Verkuil return -EINVAL; 21855bc3cb74SMauro Carvalho Chehab #else 21865bc3cb74SMauro Carvalho Chehab return -ENOTTY; 21875bc3cb74SMauro Carvalho Chehab #endif 21885bc3cb74SMauro Carvalho Chehab } 21895bc3cb74SMauro Carvalho Chehab 219096b03d2aSHans Verkuil static int v4l_dbg_g_chip_info(const struct v4l2_ioctl_ops *ops, 219179b0c640SHans Verkuil struct file *file, void *fh, void *arg) 219279b0c640SHans Verkuil { 2193cd634f1bSHans Verkuil #ifdef CONFIG_VIDEO_ADV_DEBUG 219479b0c640SHans Verkuil struct video_device *vfd = video_devdata(file); 219596b03d2aSHans Verkuil struct v4l2_dbg_chip_info *p = arg; 219679b0c640SHans Verkuil struct v4l2_subdev *sd; 219779b0c640SHans Verkuil int idx = 0; 219879b0c640SHans Verkuil 219979b0c640SHans Verkuil switch (p->match.type) { 220079b0c640SHans Verkuil case V4L2_CHIP_MATCH_BRIDGE: 220179b0c640SHans Verkuil if (ops->vidioc_s_register) 220279b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_WRITABLE; 220379b0c640SHans Verkuil if (ops->vidioc_g_register) 220479b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_READABLE; 220579b0c640SHans Verkuil strlcpy(p->name, vfd->v4l2_dev->name, sizeof(p->name)); 220696b03d2aSHans Verkuil if (ops->vidioc_g_chip_info) 220796b03d2aSHans Verkuil return ops->vidioc_g_chip_info(file, fh, arg); 22080f0fe4b9SHans Verkuil if (p->match.addr) 22090f0fe4b9SHans Verkuil return -EINVAL; 221079b0c640SHans Verkuil return 0; 221179b0c640SHans Verkuil 22123eef2510SHans Verkuil case V4L2_CHIP_MATCH_SUBDEV: 221379b0c640SHans Verkuil if (vfd->v4l2_dev == NULL) 221479b0c640SHans Verkuil break; 221579b0c640SHans Verkuil v4l2_device_for_each_subdev(sd, vfd->v4l2_dev) { 22163eef2510SHans Verkuil if (p->match.addr != idx++) 22173eef2510SHans Verkuil continue; 221879b0c640SHans Verkuil if (sd->ops->core && sd->ops->core->s_register) 221979b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_WRITABLE; 222079b0c640SHans Verkuil if (sd->ops->core && sd->ops->core->g_register) 222179b0c640SHans Verkuil p->flags |= V4L2_CHIP_FL_READABLE; 222279b0c640SHans Verkuil strlcpy(p->name, sd->name, sizeof(p->name)); 222379b0c640SHans Verkuil return 0; 222479b0c640SHans Verkuil } 222579b0c640SHans Verkuil break; 222679b0c640SHans Verkuil } 222779b0c640SHans Verkuil return -EINVAL; 2228cd634f1bSHans Verkuil #else 2229cd634f1bSHans Verkuil return -ENOTTY; 2230cd634f1bSHans Verkuil #endif 223179b0c640SHans Verkuil } 223279b0c640SHans Verkuil 22335bc3cb74SMauro Carvalho Chehab static int v4l_dqevent(const struct v4l2_ioctl_ops *ops, 22345bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 22355bc3cb74SMauro Carvalho Chehab { 22365bc3cb74SMauro Carvalho Chehab return v4l2_event_dequeue(fh, arg, file->f_flags & O_NONBLOCK); 22375bc3cb74SMauro Carvalho Chehab } 22385bc3cb74SMauro Carvalho Chehab 22395bc3cb74SMauro Carvalho Chehab static int v4l_subscribe_event(const struct v4l2_ioctl_ops *ops, 22405bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 22415bc3cb74SMauro Carvalho Chehab { 22425bc3cb74SMauro Carvalho Chehab return ops->vidioc_subscribe_event(fh, arg); 22435bc3cb74SMauro Carvalho Chehab } 22445bc3cb74SMauro Carvalho Chehab 22455bc3cb74SMauro Carvalho Chehab static int v4l_unsubscribe_event(const struct v4l2_ioctl_ops *ops, 22465bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 22475bc3cb74SMauro Carvalho Chehab { 22485bc3cb74SMauro Carvalho Chehab return ops->vidioc_unsubscribe_event(fh, arg); 22495bc3cb74SMauro Carvalho Chehab } 22505bc3cb74SMauro Carvalho Chehab 22515bc3cb74SMauro Carvalho Chehab static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops, 22525bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 22535bc3cb74SMauro Carvalho Chehab { 22545bc3cb74SMauro Carvalho Chehab struct v4l2_sliced_vbi_cap *p = arg; 22554b20259fSHans Verkuil int ret = check_fmt(file, p->type); 22564b20259fSHans Verkuil 22574b20259fSHans Verkuil if (ret) 22584b20259fSHans Verkuil return ret; 22595bc3cb74SMauro Carvalho Chehab 22605bc3cb74SMauro Carvalho Chehab /* Clear up to type, everything after type is zeroed already */ 22615bc3cb74SMauro Carvalho Chehab memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type)); 22625bc3cb74SMauro Carvalho Chehab 22635bc3cb74SMauro Carvalho Chehab return ops->vidioc_g_sliced_vbi_cap(file, fh, p); 22645bc3cb74SMauro Carvalho Chehab } 22655bc3cb74SMauro Carvalho Chehab 22665bc3cb74SMauro Carvalho Chehab static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, 22675bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *arg) 22685bc3cb74SMauro Carvalho Chehab { 22695bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 22705bc3cb74SMauro Carvalho Chehab struct v4l2_frequency_band *p = arg; 22715bc3cb74SMauro Carvalho Chehab enum v4l2_tuner_type type; 22725bc3cb74SMauro Carvalho Chehab int err; 22735bc3cb74SMauro Carvalho Chehab 227484099a28SAntti Palosaari if (vfd->vfl_type == VFL_TYPE_SDR) { 227584099a28SAntti Palosaari if (p->type != V4L2_TUNER_ADC && p->type != V4L2_TUNER_RF) 227684099a28SAntti Palosaari return -EINVAL; 227784099a28SAntti Palosaari type = p->type; 227884099a28SAntti Palosaari } else { 22795bc3cb74SMauro Carvalho Chehab type = (vfd->vfl_type == VFL_TYPE_RADIO) ? 22805bc3cb74SMauro Carvalho Chehab V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV; 22815bc3cb74SMauro Carvalho Chehab if (type != p->type) 22825bc3cb74SMauro Carvalho Chehab return -EINVAL; 228384099a28SAntti Palosaari } 2284a7f404afSHans Verkuil if (ops->vidioc_enum_freq_bands) { 2285a7f404afSHans Verkuil err = ops->vidioc_enum_freq_bands(file, fh, p); 2286a7f404afSHans Verkuil if (err != -ENOTTY) 2287a7f404afSHans Verkuil return err; 2288a7f404afSHans Verkuil } 228973f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) { 22905bc3cb74SMauro Carvalho Chehab struct v4l2_tuner t = { 22915bc3cb74SMauro Carvalho Chehab .index = p->tuner, 22925bc3cb74SMauro Carvalho Chehab .type = type, 22935bc3cb74SMauro Carvalho Chehab }; 22945bc3cb74SMauro Carvalho Chehab 229579e8c7beSMauro Carvalho Chehab if (p->index) 229679e8c7beSMauro Carvalho Chehab return -EINVAL; 22975bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_tuner(file, fh, &t); 22985bc3cb74SMauro Carvalho Chehab if (err) 22995bc3cb74SMauro Carvalho Chehab return err; 23005bc3cb74SMauro Carvalho Chehab p->capability = t.capability | V4L2_TUNER_CAP_FREQ_BANDS; 23015bc3cb74SMauro Carvalho Chehab p->rangelow = t.rangelow; 23025bc3cb74SMauro Carvalho Chehab p->rangehigh = t.rangehigh; 23035bc3cb74SMauro Carvalho Chehab p->modulation = (type == V4L2_TUNER_RADIO) ? 23045bc3cb74SMauro Carvalho Chehab V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; 23055bc3cb74SMauro Carvalho Chehab return 0; 23065bc3cb74SMauro Carvalho Chehab } 230773f35418SHans Verkuil if (is_valid_ioctl(vfd, VIDIOC_G_MODULATOR)) { 23085bc3cb74SMauro Carvalho Chehab struct v4l2_modulator m = { 23095bc3cb74SMauro Carvalho Chehab .index = p->tuner, 23105bc3cb74SMauro Carvalho Chehab }; 23115bc3cb74SMauro Carvalho Chehab 23125bc3cb74SMauro Carvalho Chehab if (type != V4L2_TUNER_RADIO) 23135bc3cb74SMauro Carvalho Chehab return -EINVAL; 231479e8c7beSMauro Carvalho Chehab if (p->index) 231579e8c7beSMauro Carvalho Chehab return -EINVAL; 23165bc3cb74SMauro Carvalho Chehab err = ops->vidioc_g_modulator(file, fh, &m); 23175bc3cb74SMauro Carvalho Chehab if (err) 23185bc3cb74SMauro Carvalho Chehab return err; 23195bc3cb74SMauro Carvalho Chehab p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS; 23205bc3cb74SMauro Carvalho Chehab p->rangelow = m.rangelow; 23215bc3cb74SMauro Carvalho Chehab p->rangehigh = m.rangehigh; 23225bc3cb74SMauro Carvalho Chehab p->modulation = (type == V4L2_TUNER_RADIO) ? 23235bc3cb74SMauro Carvalho Chehab V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; 23245bc3cb74SMauro Carvalho Chehab return 0; 23255bc3cb74SMauro Carvalho Chehab } 23265bc3cb74SMauro Carvalho Chehab return -ENOTTY; 23275bc3cb74SMauro Carvalho Chehab } 23285bc3cb74SMauro Carvalho Chehab 23295bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info { 23305bc3cb74SMauro Carvalho Chehab unsigned int ioctl; 23315bc3cb74SMauro Carvalho Chehab u32 flags; 23325bc3cb74SMauro Carvalho Chehab const char * const name; 23335bc3cb74SMauro Carvalho Chehab union { 23345bc3cb74SMauro Carvalho Chehab u32 offset; 23355bc3cb74SMauro Carvalho Chehab int (*func)(const struct v4l2_ioctl_ops *ops, 23365bc3cb74SMauro Carvalho Chehab struct file *file, void *fh, void *p); 23375bc3cb74SMauro Carvalho Chehab } u; 23385bc3cb74SMauro Carvalho Chehab void (*debug)(const void *arg, bool write_only); 23395bc3cb74SMauro Carvalho Chehab }; 23405bc3cb74SMauro Carvalho Chehab 23415bc3cb74SMauro Carvalho Chehab /* This control needs a priority check */ 23425bc3cb74SMauro Carvalho Chehab #define INFO_FL_PRIO (1 << 0) 23435bc3cb74SMauro Carvalho Chehab /* This control can be valid if the filehandle passes a control handler. */ 23445bc3cb74SMauro Carvalho Chehab #define INFO_FL_CTRL (1 << 1) 23455bc3cb74SMauro Carvalho Chehab /* This is a standard ioctl, no need for special code */ 23465bc3cb74SMauro Carvalho Chehab #define INFO_FL_STD (1 << 2) 23475bc3cb74SMauro Carvalho Chehab /* This is ioctl has its own function */ 23485bc3cb74SMauro Carvalho Chehab #define INFO_FL_FUNC (1 << 3) 23495bc3cb74SMauro Carvalho Chehab /* Queuing ioctl */ 23505bc3cb74SMauro Carvalho Chehab #define INFO_FL_QUEUE (1 << 4) 23515bc3cb74SMauro Carvalho Chehab /* Zero struct from after the field to the end */ 23525bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR(v4l2_struct, field) \ 23535bc3cb74SMauro Carvalho Chehab ((offsetof(struct v4l2_struct, field) + \ 23545bc3cb74SMauro Carvalho Chehab sizeof(((struct v4l2_struct *)0)->field)) << 16) 23555bc3cb74SMauro Carvalho Chehab #define INFO_FL_CLEAR_MASK (_IOC_SIZEMASK << 16) 23565bc3cb74SMauro Carvalho Chehab 23575bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_STD(_ioctl, _vidioc, _debug, _flags) \ 23585bc3cb74SMauro Carvalho Chehab [_IOC_NR(_ioctl)] = { \ 23595bc3cb74SMauro Carvalho Chehab .ioctl = _ioctl, \ 23605bc3cb74SMauro Carvalho Chehab .flags = _flags | INFO_FL_STD, \ 23615bc3cb74SMauro Carvalho Chehab .name = #_ioctl, \ 23625bc3cb74SMauro Carvalho Chehab .u.offset = offsetof(struct v4l2_ioctl_ops, _vidioc), \ 23635bc3cb74SMauro Carvalho Chehab .debug = _debug, \ 23645bc3cb74SMauro Carvalho Chehab } 23655bc3cb74SMauro Carvalho Chehab 23665bc3cb74SMauro Carvalho Chehab #define IOCTL_INFO_FNC(_ioctl, _func, _debug, _flags) \ 23675bc3cb74SMauro Carvalho Chehab [_IOC_NR(_ioctl)] = { \ 23685bc3cb74SMauro Carvalho Chehab .ioctl = _ioctl, \ 23695bc3cb74SMauro Carvalho Chehab .flags = _flags | INFO_FL_FUNC, \ 23705bc3cb74SMauro Carvalho Chehab .name = #_ioctl, \ 23715bc3cb74SMauro Carvalho Chehab .u.func = _func, \ 23725bc3cb74SMauro Carvalho Chehab .debug = _debug, \ 23735bc3cb74SMauro Carvalho Chehab } 23745bc3cb74SMauro Carvalho Chehab 23755bc3cb74SMauro Carvalho Chehab static struct v4l2_ioctl_info v4l2_ioctls[] = { 23765bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0), 23775bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)), 2378e5ce558aSHans Verkuil IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0), 23795bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO), 23805bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE), 23815bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)), 23825bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0), 23835bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO), 2384737c097bSHans Verkuil IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO), 23855bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE), 2386b799d09aSTomasz Stanislawski IOCTL_INFO_STD(VIDIOC_EXPBUF, vidioc_expbuf, v4l_print_exportbuffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_exportbuffer, flags)), 23875bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE), 23885bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), 23895bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_STREAMOFF, v4l_streamoff, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE), 23905bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_PARM, v4l_g_parm, v4l_print_streamparm, INFO_FL_CLEAR(v4l2_streamparm, type)), 23915bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_PARM, v4l_s_parm, v4l_print_streamparm, INFO_FL_PRIO), 2392ca371575SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_STD, vidioc_g_std, v4l_print_std, 0), 23935bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_STD, v4l_s_std, v4l_print_std, INFO_FL_PRIO), 23945bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMSTD, v4l_enumstd, v4l_print_standard, INFO_FL_CLEAR(v4l2_standard, index)), 23955bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMINPUT, v4l_enuminput, v4l_print_enuminput, INFO_FL_CLEAR(v4l2_input, index)), 23965bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_CTRL, v4l_g_ctrl, v4l_print_control, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_control, id)), 23975bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_CTRL, v4l_s_ctrl, v4l_print_control, INFO_FL_PRIO | INFO_FL_CTRL), 23985bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_TUNER, v4l_g_tuner, v4l_print_tuner, INFO_FL_CLEAR(v4l2_tuner, index)), 23995bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_TUNER, v4l_s_tuner, v4l_print_tuner, INFO_FL_PRIO), 24005bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_AUDIO, vidioc_g_audio, v4l_print_audio, 0), 24015bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_AUDIO, vidioc_s_audio, v4l_print_audio, INFO_FL_PRIO), 24025bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYCTRL, v4l_queryctrl, v4l_print_queryctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_queryctrl, id)), 24035bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)), 24045bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0), 24055bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO), 2406f9402a94SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0), 2407f9402a94SHans Verkuil IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO), 24085bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0), 24095bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO), 24105bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)), 24115bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_AUDOUT, vidioc_g_audout, v4l_print_audioout, 0), 24125bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_AUDOUT, vidioc_s_audout, v4l_print_audioout, INFO_FL_PRIO), 24135bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_MODULATOR, v4l_g_modulator, v4l_print_modulator, INFO_FL_CLEAR(v4l2_modulator, index)), 24145bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_MODULATOR, vidioc_s_modulator, v4l_print_modulator, INFO_FL_PRIO), 24155bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_FREQUENCY, v4l_g_frequency, v4l_print_frequency, INFO_FL_CLEAR(v4l2_frequency, tuner)), 24165bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_FREQUENCY, v4l_s_frequency, v4l_print_frequency, INFO_FL_PRIO), 24175bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)), 24185bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)), 24195bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO), 2420865c4642SHans Verkuil IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)), 2421865c4642SHans Verkuil IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)), 24225bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0), 24235bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO), 24245bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0), 24255bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_TRY_FMT, v4l_try_fmt, v4l_print_format, 0), 24265bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUMAUDIO, vidioc_enumaudio, v4l_print_audio, INFO_FL_CLEAR(v4l2_audio, index)), 24275bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUMAUDOUT, vidioc_enumaudout, v4l_print_audioout, INFO_FL_CLEAR(v4l2_audioout, index)), 24285bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_PRIORITY, v4l_g_priority, v4l_print_u32, 0), 24295bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_PRIORITY, v4l_s_priority, v4l_print_u32, INFO_FL_PRIO), 24305bc3cb74SMauro 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)), 24315bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_LOG_STATUS, v4l_log_status, v4l_print_newline, 0), 24325bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_G_EXT_CTRLS, v4l_g_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), 24335bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_EXT_CTRLS, v4l_s_ext_ctrls, v4l_print_ext_controls, INFO_FL_PRIO | INFO_FL_CTRL), 24345bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_TRY_EXT_CTRLS, v4l_try_ext_ctrls, v4l_print_ext_controls, INFO_FL_CTRL), 24355bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes, v4l_print_frmsizeenum, INFO_FL_CLEAR(v4l2_frmsizeenum, pixel_format)), 24365bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals, v4l_print_frmivalenum, INFO_FL_CLEAR(v4l2_frmivalenum, height)), 24375bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_ENC_INDEX, vidioc_g_enc_index, v4l_print_enc_idx, 0), 24385bc3cb74SMauro 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)), 24395bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd, v4l_print_encoder_cmd, INFO_FL_CLEAR(v4l2_encoder_cmd, flags)), 24405bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_DECODER_CMD, vidioc_decoder_cmd, v4l_print_decoder_cmd, INFO_FL_PRIO), 24415bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd, v4l_print_decoder_cmd, 0), 24425bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DBG_S_REGISTER, v4l_dbg_s_register, v4l_print_dbg_register, 0), 24435bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DBG_G_REGISTER, v4l_dbg_g_register, v4l_print_dbg_register, 0), 24445bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_S_HW_FREQ_SEEK, v4l_s_hw_freq_seek, v4l_print_hw_freq_seek, INFO_FL_PRIO), 24455bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings, v4l_print_dv_timings, INFO_FL_PRIO), 24465bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings, v4l_print_dv_timings, 0), 24475bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_DQEVENT, v4l_dqevent, v4l_print_event, 0), 24485bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_SUBSCRIBE_EVENT, v4l_subscribe_event, v4l_print_event_subscription, 0), 24495bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_UNSUBSCRIBE_EVENT, v4l_unsubscribe_event, v4l_print_event_subscription, 0), 24505bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_CREATE_BUFS, v4l_create_bufs, v4l_print_create_buffers, INFO_FL_PRIO | INFO_FL_QUEUE), 24515bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_PREPARE_BUF, v4l_prepare_buf, v4l_print_buffer, INFO_FL_QUEUE), 24525bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings, v4l_print_enum_dv_timings, 0), 24535bc3cb74SMauro Carvalho Chehab IOCTL_INFO_STD(VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings, v4l_print_dv_timings, 0), 24545bc3cb74SMauro 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)), 24555bc3cb74SMauro Carvalho Chehab IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), 245696b03d2aSHans 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)), 2457e6bee368SHans 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)), 24585bc3cb74SMauro Carvalho Chehab }; 24595bc3cb74SMauro Carvalho Chehab #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) 24605bc3cb74SMauro Carvalho Chehab 24615bc3cb74SMauro Carvalho Chehab bool v4l2_is_known_ioctl(unsigned int cmd) 24625bc3cb74SMauro Carvalho Chehab { 24635bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) 24645bc3cb74SMauro Carvalho Chehab return false; 24655bc3cb74SMauro Carvalho Chehab return v4l2_ioctls[_IOC_NR(cmd)].ioctl == cmd; 24665bc3cb74SMauro Carvalho Chehab } 24675bc3cb74SMauro Carvalho Chehab 24685bc3cb74SMauro Carvalho Chehab struct mutex *v4l2_ioctl_get_lock(struct video_device *vdev, unsigned cmd) 24695bc3cb74SMauro Carvalho Chehab { 24705bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) 24715bc3cb74SMauro Carvalho Chehab return vdev->lock; 24725bc3cb74SMauro Carvalho Chehab if (test_bit(_IOC_NR(cmd), vdev->disable_locking)) 24735bc3cb74SMauro Carvalho Chehab return NULL; 24745bc3cb74SMauro Carvalho Chehab if (vdev->queue && vdev->queue->lock && 24755bc3cb74SMauro Carvalho Chehab (v4l2_ioctls[_IOC_NR(cmd)].flags & INFO_FL_QUEUE)) 24765bc3cb74SMauro Carvalho Chehab return vdev->queue->lock; 24775bc3cb74SMauro Carvalho Chehab return vdev->lock; 24785bc3cb74SMauro Carvalho Chehab } 24795bc3cb74SMauro Carvalho Chehab 24805bc3cb74SMauro Carvalho Chehab /* Common ioctl debug function. This function can be used by 24815bc3cb74SMauro Carvalho Chehab external ioctl messages as well as internal V4L ioctl */ 24825bc3cb74SMauro Carvalho Chehab void v4l_printk_ioctl(const char *prefix, unsigned int cmd) 24835bc3cb74SMauro Carvalho Chehab { 24845bc3cb74SMauro Carvalho Chehab const char *dir, *type; 24855bc3cb74SMauro Carvalho Chehab 24865bc3cb74SMauro Carvalho Chehab if (prefix) 24875bc3cb74SMauro Carvalho Chehab printk(KERN_DEBUG "%s: ", prefix); 24885bc3cb74SMauro Carvalho Chehab 24895bc3cb74SMauro Carvalho Chehab switch (_IOC_TYPE(cmd)) { 24905bc3cb74SMauro Carvalho Chehab case 'd': 24915bc3cb74SMauro Carvalho Chehab type = "v4l2_int"; 24925bc3cb74SMauro Carvalho Chehab break; 24935bc3cb74SMauro Carvalho Chehab case 'V': 24945bc3cb74SMauro Carvalho Chehab if (_IOC_NR(cmd) >= V4L2_IOCTLS) { 24955bc3cb74SMauro Carvalho Chehab type = "v4l2"; 24965bc3cb74SMauro Carvalho Chehab break; 24975bc3cb74SMauro Carvalho Chehab } 24985bc3cb74SMauro Carvalho Chehab pr_cont("%s", v4l2_ioctls[_IOC_NR(cmd)].name); 24995bc3cb74SMauro Carvalho Chehab return; 25005bc3cb74SMauro Carvalho Chehab default: 25015bc3cb74SMauro Carvalho Chehab type = "unknown"; 25025bc3cb74SMauro Carvalho Chehab break; 25035bc3cb74SMauro Carvalho Chehab } 25045bc3cb74SMauro Carvalho Chehab 25055bc3cb74SMauro Carvalho Chehab switch (_IOC_DIR(cmd)) { 25065bc3cb74SMauro Carvalho Chehab case _IOC_NONE: dir = "--"; break; 25075bc3cb74SMauro Carvalho Chehab case _IOC_READ: dir = "r-"; break; 25085bc3cb74SMauro Carvalho Chehab case _IOC_WRITE: dir = "-w"; break; 25095bc3cb74SMauro Carvalho Chehab case _IOC_READ | _IOC_WRITE: dir = "rw"; break; 25105bc3cb74SMauro Carvalho Chehab default: dir = "*ERR*"; break; 25115bc3cb74SMauro Carvalho Chehab } 25125bc3cb74SMauro Carvalho Chehab pr_cont("%s ioctl '%c', dir=%s, #%d (0x%08x)", 25135bc3cb74SMauro Carvalho Chehab type, _IOC_TYPE(cmd), dir, _IOC_NR(cmd), cmd); 25145bc3cb74SMauro Carvalho Chehab } 25155bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(v4l_printk_ioctl); 25165bc3cb74SMauro Carvalho Chehab 25175bc3cb74SMauro Carvalho Chehab static long __video_do_ioctl(struct file *file, 25185bc3cb74SMauro Carvalho Chehab unsigned int cmd, void *arg) 25195bc3cb74SMauro Carvalho Chehab { 25205bc3cb74SMauro Carvalho Chehab struct video_device *vfd = video_devdata(file); 25215bc3cb74SMauro Carvalho Chehab const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 25225bc3cb74SMauro Carvalho Chehab bool write_only = false; 25235bc3cb74SMauro Carvalho Chehab struct v4l2_ioctl_info default_info; 25245bc3cb74SMauro Carvalho Chehab const struct v4l2_ioctl_info *info; 25255bc3cb74SMauro Carvalho Chehab void *fh = file->private_data; 25265bc3cb74SMauro Carvalho Chehab struct v4l2_fh *vfh = NULL; 252717028cdbSHans Verkuil int dev_debug = vfd->dev_debug; 25285bc3cb74SMauro Carvalho Chehab long ret = -ENOTTY; 25295bc3cb74SMauro Carvalho Chehab 25305bc3cb74SMauro Carvalho Chehab if (ops == NULL) { 25315bc3cb74SMauro Carvalho Chehab pr_warn("%s: has no ioctl_ops.\n", 25325bc3cb74SMauro Carvalho Chehab video_device_node_name(vfd)); 25335bc3cb74SMauro Carvalho Chehab return ret; 25345bc3cb74SMauro Carvalho Chehab } 25355bc3cb74SMauro Carvalho Chehab 2536b7284bb0SRamakrishnan Muthukrishnan if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) 25375bc3cb74SMauro Carvalho Chehab vfh = file->private_data; 25385bc3cb74SMauro Carvalho Chehab 25395bc3cb74SMauro Carvalho Chehab if (v4l2_is_known_ioctl(cmd)) { 25405bc3cb74SMauro Carvalho Chehab info = &v4l2_ioctls[_IOC_NR(cmd)]; 25415bc3cb74SMauro Carvalho Chehab 25425bc3cb74SMauro Carvalho Chehab if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) && 25435bc3cb74SMauro Carvalho Chehab !((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler)) 25445bc3cb74SMauro Carvalho Chehab goto done; 25455bc3cb74SMauro Carvalho Chehab 2546b7284bb0SRamakrishnan Muthukrishnan if (vfh && (info->flags & INFO_FL_PRIO)) { 25475bc3cb74SMauro Carvalho Chehab ret = v4l2_prio_check(vfd->prio, vfh->prio); 25485bc3cb74SMauro Carvalho Chehab if (ret) 25495bc3cb74SMauro Carvalho Chehab goto done; 25505bc3cb74SMauro Carvalho Chehab } 25515bc3cb74SMauro Carvalho Chehab } else { 25525bc3cb74SMauro Carvalho Chehab default_info.ioctl = cmd; 25535bc3cb74SMauro Carvalho Chehab default_info.flags = 0; 25545bc3cb74SMauro Carvalho Chehab default_info.debug = v4l_print_default; 25555bc3cb74SMauro Carvalho Chehab info = &default_info; 25565bc3cb74SMauro Carvalho Chehab } 25575bc3cb74SMauro Carvalho Chehab 25585bc3cb74SMauro Carvalho Chehab write_only = _IOC_DIR(cmd) == _IOC_WRITE; 25595bc3cb74SMauro Carvalho Chehab if (info->flags & INFO_FL_STD) { 25605bc3cb74SMauro Carvalho Chehab typedef int (*vidioc_op)(struct file *file, void *fh, void *p); 25615bc3cb74SMauro Carvalho Chehab const void *p = vfd->ioctl_ops; 25625bc3cb74SMauro Carvalho Chehab const vidioc_op *vidioc = p + info->u.offset; 25635bc3cb74SMauro Carvalho Chehab 25645bc3cb74SMauro Carvalho Chehab ret = (*vidioc)(file, fh, arg); 25655bc3cb74SMauro Carvalho Chehab } else if (info->flags & INFO_FL_FUNC) { 25665bc3cb74SMauro Carvalho Chehab ret = info->u.func(ops, file, fh, arg); 25675bc3cb74SMauro Carvalho Chehab } else if (!ops->vidioc_default) { 25685bc3cb74SMauro Carvalho Chehab ret = -ENOTTY; 25695bc3cb74SMauro Carvalho Chehab } else { 25705bc3cb74SMauro Carvalho Chehab ret = ops->vidioc_default(file, fh, 2571b7284bb0SRamakrishnan Muthukrishnan vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0, 25725bc3cb74SMauro Carvalho Chehab cmd, arg); 25735bc3cb74SMauro Carvalho Chehab } 25745bc3cb74SMauro Carvalho Chehab 25755bc3cb74SMauro Carvalho Chehab done: 257617028cdbSHans Verkuil if (dev_debug & (V4L2_DEV_DEBUG_IOCTL | V4L2_DEV_DEBUG_IOCTL_ARG)) { 257717028cdbSHans Verkuil if (!(dev_debug & V4L2_DEV_DEBUG_STREAMING) && 257817028cdbSHans Verkuil (cmd == VIDIOC_QBUF || cmd == VIDIOC_DQBUF)) 257917028cdbSHans Verkuil return ret; 258017028cdbSHans Verkuil 25815bc3cb74SMauro Carvalho Chehab v4l_printk_ioctl(video_device_node_name(vfd), cmd); 25825bc3cb74SMauro Carvalho Chehab if (ret < 0) 2583505d04bdSHans Verkuil pr_cont(": error %ld", ret); 258417028cdbSHans Verkuil if (!(dev_debug & V4L2_DEV_DEBUG_IOCTL_ARG)) 25855bc3cb74SMauro Carvalho Chehab pr_cont("\n"); 25865bc3cb74SMauro Carvalho Chehab else if (_IOC_DIR(cmd) == _IOC_NONE) 25875bc3cb74SMauro Carvalho Chehab info->debug(arg, write_only); 25885bc3cb74SMauro Carvalho Chehab else { 25895bc3cb74SMauro Carvalho Chehab pr_cont(": "); 25905bc3cb74SMauro Carvalho Chehab info->debug(arg, write_only); 25915bc3cb74SMauro Carvalho Chehab } 25925bc3cb74SMauro Carvalho Chehab } 25935bc3cb74SMauro Carvalho Chehab 25945bc3cb74SMauro Carvalho Chehab return ret; 25955bc3cb74SMauro Carvalho Chehab } 25965bc3cb74SMauro Carvalho Chehab 25975bc3cb74SMauro Carvalho Chehab static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, 2598ba2d35c1SHans Verkuil void __user **user_ptr, void ***kernel_ptr) 25995bc3cb74SMauro Carvalho Chehab { 26005bc3cb74SMauro Carvalho Chehab int ret = 0; 26015bc3cb74SMauro Carvalho Chehab 26025bc3cb74SMauro Carvalho Chehab switch (cmd) { 260396b1a702SHans Verkuil case VIDIOC_PREPARE_BUF: 26045bc3cb74SMauro Carvalho Chehab case VIDIOC_QUERYBUF: 26055bc3cb74SMauro Carvalho Chehab case VIDIOC_QBUF: 26065bc3cb74SMauro Carvalho Chehab case VIDIOC_DQBUF: { 26075bc3cb74SMauro Carvalho Chehab struct v4l2_buffer *buf = parg; 26085bc3cb74SMauro Carvalho Chehab 26095bc3cb74SMauro Carvalho Chehab if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) { 26105bc3cb74SMauro Carvalho Chehab if (buf->length > VIDEO_MAX_PLANES) { 26115bc3cb74SMauro Carvalho Chehab ret = -EINVAL; 26125bc3cb74SMauro Carvalho Chehab break; 26135bc3cb74SMauro Carvalho Chehab } 26145bc3cb74SMauro Carvalho Chehab *user_ptr = (void __user *)buf->m.planes; 2615ba2d35c1SHans Verkuil *kernel_ptr = (void **)&buf->m.planes; 26165bc3cb74SMauro Carvalho Chehab *array_size = sizeof(struct v4l2_plane) * buf->length; 26175bc3cb74SMauro Carvalho Chehab ret = 1; 26185bc3cb74SMauro Carvalho Chehab } 26195bc3cb74SMauro Carvalho Chehab break; 26205bc3cb74SMauro Carvalho Chehab } 26215bc3cb74SMauro Carvalho Chehab 2622dd519bb3SHans Verkuil case VIDIOC_G_EDID: 2623dd519bb3SHans Verkuil case VIDIOC_S_EDID: { 2624dd519bb3SHans Verkuil struct v4l2_edid *edid = parg; 2625ed45ce2cSHans Verkuil 2626ed45ce2cSHans Verkuil if (edid->blocks) { 26271b8b10ccSHans Verkuil if (edid->blocks > 256) { 26281b8b10ccSHans Verkuil ret = -EINVAL; 26291b8b10ccSHans Verkuil break; 26301b8b10ccSHans Verkuil } 2631ed45ce2cSHans Verkuil *user_ptr = (void __user *)edid->edid; 2632ba2d35c1SHans Verkuil *kernel_ptr = (void **)&edid->edid; 2633ed45ce2cSHans Verkuil *array_size = edid->blocks * 128; 2634ed45ce2cSHans Verkuil ret = 1; 2635ed45ce2cSHans Verkuil } 2636ed45ce2cSHans Verkuil break; 2637ed45ce2cSHans Verkuil } 2638ed45ce2cSHans Verkuil 26395bc3cb74SMauro Carvalho Chehab case VIDIOC_S_EXT_CTRLS: 26405bc3cb74SMauro Carvalho Chehab case VIDIOC_G_EXT_CTRLS: 26415bc3cb74SMauro Carvalho Chehab case VIDIOC_TRY_EXT_CTRLS: { 26425bc3cb74SMauro Carvalho Chehab struct v4l2_ext_controls *ctrls = parg; 26435bc3cb74SMauro Carvalho Chehab 26445bc3cb74SMauro Carvalho Chehab if (ctrls->count != 0) { 26455bc3cb74SMauro Carvalho Chehab if (ctrls->count > V4L2_CID_MAX_CTRLS) { 26465bc3cb74SMauro Carvalho Chehab ret = -EINVAL; 26475bc3cb74SMauro Carvalho Chehab break; 26485bc3cb74SMauro Carvalho Chehab } 26495bc3cb74SMauro Carvalho Chehab *user_ptr = (void __user *)ctrls->controls; 2650ba2d35c1SHans Verkuil *kernel_ptr = (void **)&ctrls->controls; 26515bc3cb74SMauro Carvalho Chehab *array_size = sizeof(struct v4l2_ext_control) 26525bc3cb74SMauro Carvalho Chehab * ctrls->count; 26535bc3cb74SMauro Carvalho Chehab ret = 1; 26545bc3cb74SMauro Carvalho Chehab } 26555bc3cb74SMauro Carvalho Chehab break; 26565bc3cb74SMauro Carvalho Chehab } 26575bc3cb74SMauro Carvalho Chehab } 26585bc3cb74SMauro Carvalho Chehab 26595bc3cb74SMauro Carvalho Chehab return ret; 26605bc3cb74SMauro Carvalho Chehab } 26615bc3cb74SMauro Carvalho Chehab 26625bc3cb74SMauro Carvalho Chehab long 26635bc3cb74SMauro Carvalho Chehab video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, 26645bc3cb74SMauro Carvalho Chehab v4l2_kioctl func) 26655bc3cb74SMauro Carvalho Chehab { 26665bc3cb74SMauro Carvalho Chehab char sbuf[128]; 26675bc3cb74SMauro Carvalho Chehab void *mbuf = NULL; 26685bc3cb74SMauro Carvalho Chehab void *parg = (void *)arg; 26695bc3cb74SMauro Carvalho Chehab long err = -EINVAL; 26705bc3cb74SMauro Carvalho Chehab bool has_array_args; 26715bc3cb74SMauro Carvalho Chehab size_t array_size = 0; 26725bc3cb74SMauro Carvalho Chehab void __user *user_ptr = NULL; 26735bc3cb74SMauro Carvalho Chehab void **kernel_ptr = NULL; 26745bc3cb74SMauro Carvalho Chehab 26755bc3cb74SMauro Carvalho Chehab /* Copy arguments into temp kernel buffer */ 26765bc3cb74SMauro Carvalho Chehab if (_IOC_DIR(cmd) != _IOC_NONE) { 26775bc3cb74SMauro Carvalho Chehab if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { 26785bc3cb74SMauro Carvalho Chehab parg = sbuf; 26795bc3cb74SMauro Carvalho Chehab } else { 26805bc3cb74SMauro Carvalho Chehab /* too big to allocate from stack */ 26815bc3cb74SMauro Carvalho Chehab mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); 26825bc3cb74SMauro Carvalho Chehab if (NULL == mbuf) 26835bc3cb74SMauro Carvalho Chehab return -ENOMEM; 26845bc3cb74SMauro Carvalho Chehab parg = mbuf; 26855bc3cb74SMauro Carvalho Chehab } 26865bc3cb74SMauro Carvalho Chehab 26875bc3cb74SMauro Carvalho Chehab err = -EFAULT; 26885bc3cb74SMauro Carvalho Chehab if (_IOC_DIR(cmd) & _IOC_WRITE) { 26895bc3cb74SMauro Carvalho Chehab unsigned int n = _IOC_SIZE(cmd); 26905bc3cb74SMauro Carvalho Chehab 26915bc3cb74SMauro Carvalho Chehab /* 26925bc3cb74SMauro Carvalho Chehab * In some cases, only a few fields are used as input, 26935bc3cb74SMauro Carvalho Chehab * i.e. when the app sets "index" and then the driver 26945bc3cb74SMauro Carvalho Chehab * fills in the rest of the structure for the thing 26955bc3cb74SMauro Carvalho Chehab * with that index. We only need to copy up the first 26965bc3cb74SMauro Carvalho Chehab * non-input field. 26975bc3cb74SMauro Carvalho Chehab */ 26985bc3cb74SMauro Carvalho Chehab if (v4l2_is_known_ioctl(cmd)) { 26995bc3cb74SMauro Carvalho Chehab u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags; 27005bc3cb74SMauro Carvalho Chehab if (flags & INFO_FL_CLEAR_MASK) 27015bc3cb74SMauro Carvalho Chehab n = (flags & INFO_FL_CLEAR_MASK) >> 16; 27025bc3cb74SMauro Carvalho Chehab } 27035bc3cb74SMauro Carvalho Chehab 27045bc3cb74SMauro Carvalho Chehab if (copy_from_user(parg, (void __user *)arg, n)) 27055bc3cb74SMauro Carvalho Chehab goto out; 27065bc3cb74SMauro Carvalho Chehab 27075bc3cb74SMauro Carvalho Chehab /* zero out anything we don't copy from userspace */ 27085bc3cb74SMauro Carvalho Chehab if (n < _IOC_SIZE(cmd)) 27095bc3cb74SMauro Carvalho Chehab memset((u8 *)parg + n, 0, _IOC_SIZE(cmd) - n); 27105bc3cb74SMauro Carvalho Chehab } else { 27115bc3cb74SMauro Carvalho Chehab /* read-only ioctl */ 27125bc3cb74SMauro Carvalho Chehab memset(parg, 0, _IOC_SIZE(cmd)); 27135bc3cb74SMauro Carvalho Chehab } 27145bc3cb74SMauro Carvalho Chehab } 27155bc3cb74SMauro Carvalho Chehab 27165bc3cb74SMauro Carvalho Chehab err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr); 27175bc3cb74SMauro Carvalho Chehab if (err < 0) 27185bc3cb74SMauro Carvalho Chehab goto out; 27195bc3cb74SMauro Carvalho Chehab has_array_args = err; 27205bc3cb74SMauro Carvalho Chehab 27215bc3cb74SMauro Carvalho Chehab if (has_array_args) { 27225bc3cb74SMauro Carvalho Chehab /* 27235bc3cb74SMauro Carvalho Chehab * When adding new types of array args, make sure that the 27245bc3cb74SMauro Carvalho Chehab * parent argument to ioctl (which contains the pointer to the 27255bc3cb74SMauro Carvalho Chehab * array) fits into sbuf (so that mbuf will still remain 27265bc3cb74SMauro Carvalho Chehab * unused up to here). 27275bc3cb74SMauro Carvalho Chehab */ 27285bc3cb74SMauro Carvalho Chehab mbuf = kmalloc(array_size, GFP_KERNEL); 27295bc3cb74SMauro Carvalho Chehab err = -ENOMEM; 27305bc3cb74SMauro Carvalho Chehab if (NULL == mbuf) 27315bc3cb74SMauro Carvalho Chehab goto out_array_args; 27325bc3cb74SMauro Carvalho Chehab err = -EFAULT; 27335bc3cb74SMauro Carvalho Chehab if (copy_from_user(mbuf, user_ptr, array_size)) 27345bc3cb74SMauro Carvalho Chehab goto out_array_args; 27355bc3cb74SMauro Carvalho Chehab *kernel_ptr = mbuf; 27365bc3cb74SMauro Carvalho Chehab } 27375bc3cb74SMauro Carvalho Chehab 27385bc3cb74SMauro Carvalho Chehab /* Handles IOCTL */ 27395bc3cb74SMauro Carvalho Chehab err = func(file, cmd, parg); 27405bc3cb74SMauro Carvalho Chehab if (err == -ENOIOCTLCMD) 27415bc3cb74SMauro Carvalho Chehab err = -ENOTTY; 2742aa32f4c0SHans Verkuil if (err == 0) { 2743aa32f4c0SHans Verkuil if (cmd == VIDIOC_DQBUF) 2744aa32f4c0SHans Verkuil trace_v4l2_dqbuf(video_devdata(file)->minor, parg); 2745aa32f4c0SHans Verkuil else if (cmd == VIDIOC_QBUF) 2746aa32f4c0SHans Verkuil trace_v4l2_qbuf(video_devdata(file)->minor, parg); 2747aa32f4c0SHans Verkuil } 27485bc3cb74SMauro Carvalho Chehab 27495bc3cb74SMauro Carvalho Chehab if (has_array_args) { 2750ba2d35c1SHans Verkuil *kernel_ptr = (void __force *)user_ptr; 27515bc3cb74SMauro Carvalho Chehab if (copy_to_user(user_ptr, mbuf, array_size)) 27525bc3cb74SMauro Carvalho Chehab err = -EFAULT; 27535bc3cb74SMauro Carvalho Chehab goto out_array_args; 27545bc3cb74SMauro Carvalho Chehab } 27555bc3cb74SMauro Carvalho Chehab /* VIDIOC_QUERY_DV_TIMINGS can return an error, but still have valid 27565bc3cb74SMauro Carvalho Chehab results that must be returned. */ 27575bc3cb74SMauro Carvalho Chehab if (err < 0 && cmd != VIDIOC_QUERY_DV_TIMINGS) 27585bc3cb74SMauro Carvalho Chehab goto out; 27595bc3cb74SMauro Carvalho Chehab 27605bc3cb74SMauro Carvalho Chehab out_array_args: 27615bc3cb74SMauro Carvalho Chehab /* Copy results into user buffer */ 27625bc3cb74SMauro Carvalho Chehab switch (_IOC_DIR(cmd)) { 27635bc3cb74SMauro Carvalho Chehab case _IOC_READ: 27645bc3cb74SMauro Carvalho Chehab case (_IOC_WRITE | _IOC_READ): 27655bc3cb74SMauro Carvalho Chehab if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) 27665bc3cb74SMauro Carvalho Chehab err = -EFAULT; 27675bc3cb74SMauro Carvalho Chehab break; 27685bc3cb74SMauro Carvalho Chehab } 27695bc3cb74SMauro Carvalho Chehab 27705bc3cb74SMauro Carvalho Chehab out: 27715bc3cb74SMauro Carvalho Chehab kfree(mbuf); 27725bc3cb74SMauro Carvalho Chehab return err; 27735bc3cb74SMauro Carvalho Chehab } 27745bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_usercopy); 27755bc3cb74SMauro Carvalho Chehab 27765bc3cb74SMauro Carvalho Chehab long video_ioctl2(struct file *file, 27775bc3cb74SMauro Carvalho Chehab unsigned int cmd, unsigned long arg) 27785bc3cb74SMauro Carvalho Chehab { 27795bc3cb74SMauro Carvalho Chehab return video_usercopy(file, cmd, arg, __video_do_ioctl); 27805bc3cb74SMauro Carvalho Chehab } 27815bc3cb74SMauro Carvalho Chehab EXPORT_SYMBOL(video_ioctl2); 2782