diff options
Diffstat (limited to 'drivers/media/v4l2-core/v4l2-ioctl.c')
-rw-r--r-- | drivers/media/v4l2-core/v4l2-ioctl.c | 142 |
1 files changed, 114 insertions, 28 deletions
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 6e7b8b682d13..650dc1956f73 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -310,8 +310,8 @@ static void v4l_print_format(const void *arg, bool write_only) case V4L2_BUF_TYPE_VIDEO_OVERLAY: case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: win = &p->fmt.win; - pr_cont(", wxh=%dx%d, x,y=%d,%d, field=%s, chromakey=0x%08x, global_alpha=0x%02x\n", - win->w.width, win->w.height, win->w.left, win->w.top, + pr_cont(", (%d,%d)/%ux%u, field=%s, chromakey=0x%08x, global_alpha=0x%02x\n", + win->w.left, win->w.top, win->w.width, win->w.height, prt_names(win->field, v4l2_field_names), win->chromakey, win->global_alpha); break; @@ -343,8 +343,9 @@ static void v4l_print_format(const void *arg, bool write_only) case V4L2_BUF_TYPE_META_OUTPUT: meta = &p->fmt.meta; pixelformat = meta->dataformat; - pr_cont(", dataformat=%p4cc, buffersize=%u\n", - &pixelformat, meta->buffersize); + pr_cont(", dataformat=%p4cc, buffersize=%u, width=%u, height=%u, bytesperline=%u\n", + &pixelformat, meta->buffersize, meta->width, + meta->height, meta->bytesperline); break; } } @@ -483,12 +484,20 @@ static void v4l_print_create_buffers(const void *arg, bool write_only) { const struct v4l2_create_buffers *p = arg; - pr_cont("index=%d, count=%d, memory=%s, capabilities=0x%08x, max num buffers=%u", + pr_cont("index=%d, count=%d, memory=%s, capabilities=0x%08x, max num buffers=%u, ", p->index, p->count, prt_names(p->memory, v4l2_memory_names), p->capabilities, p->max_num_buffers); v4l_print_format(&p->format, write_only); } +static void v4l_print_remove_buffers(const void *arg, bool write_only) +{ + const struct v4l2_remove_buffers *p = arg; + + pr_cont("type=%s, index=%u, count=%u\n", + prt_names(p->type, v4l2_type_names), p->index, p->count); +} + static void v4l_print_streamparm(const void *arg, bool write_only) { const struct v4l2_streamparm *p = arg; @@ -580,12 +589,12 @@ static void v4l_print_cropcap(const void *arg, bool write_only) { const struct v4l2_cropcap *p = arg; - pr_cont("type=%s, bounds wxh=%dx%d, x,y=%d,%d, defrect wxh=%dx%d, x,y=%d,%d, pixelaspect %d/%d\n", + pr_cont("type=%s, bounds (%d,%d)/%ux%u, defrect (%d,%d)/%ux%u, pixelaspect %d/%d\n", prt_names(p->type, v4l2_type_names), - p->bounds.width, p->bounds.height, p->bounds.left, p->bounds.top, - p->defrect.width, p->defrect.height, + p->bounds.width, p->bounds.height, p->defrect.left, p->defrect.top, + p->defrect.width, p->defrect.height, p->pixelaspect.numerator, p->pixelaspect.denominator); } @@ -593,20 +602,20 @@ static void v4l_print_crop(const void *arg, bool write_only) { const struct v4l2_crop *p = arg; - pr_cont("type=%s, wxh=%dx%d, x,y=%d,%d\n", + pr_cont("type=%s, crop=(%d,%d)/%ux%u\n", prt_names(p->type, v4l2_type_names), - p->c.width, p->c.height, - p->c.left, p->c.top); + p->c.left, p->c.top, + p->c.width, p->c.height); } static void v4l_print_selection(const void *arg, bool write_only) { const struct v4l2_selection *p = arg; - pr_cont("type=%s, target=%d, flags=0x%x, wxh=%dx%d, x,y=%d,%d\n", + pr_cont("type=%s, target=%d, flags=0x%x, rect=(%d,%d)/%ux%u\n", prt_names(p->type, v4l2_type_names), p->target, p->flags, - p->r.width, p->r.height, p->r.left, p->r.top); + p->r.left, p->r.top, p->r.width, p->r.height); } static void v4l_print_jpegcompression(const void *arg, bool write_only) @@ -884,7 +893,9 @@ static bool check_ext_ctrls(struct v4l2_ext_controls *c, unsigned long ioctl) return false; break; case V4L2_CTRL_WHICH_DEF_VAL: - /* Default value cannot be changed */ + case V4L2_CTRL_WHICH_MIN_VAL: + case V4L2_CTRL_WHICH_MAX_VAL: + /* Default, minimum or maximum value cannot be changed */ if (ioctl == VIDIOC_S_EXT_CTRLS || ioctl == VIDIOC_TRY_EXT_CTRLS) { c->error_idx = c->count; @@ -1298,6 +1309,8 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_RGBX1010102: descr = "32-bit RGBX 10-10-10-2"; break; case V4L2_PIX_FMT_RGBA1010102: descr = "32-bit RGBA 10-10-10-2"; break; case V4L2_PIX_FMT_ARGB2101010: descr = "32-bit ARGB 2-10-10-10"; break; + case V4L2_PIX_FMT_BGR48: descr = "48-bit BGR 16-16-16"; break; + case V4L2_PIX_FMT_RGB48: descr = "48-bit RGB 16-16-16"; break; case V4L2_PIX_FMT_BGR48_12: descr = "12-bit Depth BGR"; break; case V4L2_PIX_FMT_ABGR64_12: descr = "12-bit Depth BGRA"; break; case V4L2_PIX_FMT_GREY: descr = "8-bit Greyscale"; break; @@ -1312,8 +1325,11 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_Y10BPACK: descr = "10-bit Greyscale (Packed)"; break; case V4L2_PIX_FMT_Y10P: descr = "10-bit Greyscale (MIPI Packed)"; break; case V4L2_PIX_FMT_IPU3_Y10: descr = "10-bit greyscale (IPU3 Packed)"; break; + case V4L2_PIX_FMT_Y12P: descr = "12-bit Greyscale (MIPI Packed)"; break; + case V4L2_PIX_FMT_Y14P: descr = "14-bit Greyscale (MIPI Packed)"; break; case V4L2_PIX_FMT_Y8I: descr = "Interleaved 8-bit Greyscale"; break; case V4L2_PIX_FMT_Y12I: descr = "Interleaved 12-bit Greyscale"; break; + case V4L2_PIX_FMT_Y16I: descr = "Interleaved 16-bit Greyscale"; break; case V4L2_PIX_FMT_Z16: descr = "16-bit Depth"; break; case V4L2_PIX_FMT_INZI: descr = "Planar 10:16 Greyscale Depth"; break; case V4L2_PIX_FMT_CNF4: descr = "4-bit Depth Confidence (Packed)"; break; @@ -1347,8 +1363,10 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_YUV48_12: descr = "12-bit YUV 4:4:4 Packed"; break; case V4L2_PIX_FMT_NV12: descr = "Y/UV 4:2:0"; break; case V4L2_PIX_FMT_NV21: descr = "Y/VU 4:2:0"; break; + case V4L2_PIX_FMT_NV15: descr = "10-bit Y/UV 4:2:0 (Packed)"; break; case V4L2_PIX_FMT_NV16: descr = "Y/UV 4:2:2"; break; case V4L2_PIX_FMT_NV61: descr = "Y/VU 4:2:2"; break; + case V4L2_PIX_FMT_NV20: descr = "10-bit Y/UV 4:2:2 (Packed)"; break; case V4L2_PIX_FMT_NV24: descr = "Y/UV 4:4:4"; break; case V4L2_PIX_FMT_NV42: descr = "Y/VU 4:4:4"; break; case V4L2_PIX_FMT_P010: descr = "10-bit Y/UV 4:2:0"; break; @@ -1445,6 +1463,9 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_META_FMT_VIVID: descr = "Vivid Metadata"; break; case V4L2_META_FMT_RK_ISP1_PARAMS: descr = "Rockchip ISP1 3A Parameters"; break; case V4L2_META_FMT_RK_ISP1_STAT_3A: descr = "Rockchip ISP1 3A Statistics"; break; + case V4L2_META_FMT_RK_ISP1_EXT_PARAMS: descr = "Rockchip ISP1 Ext 3A Params"; break; + case V4L2_META_FMT_C3ISP_PARAMS: descr = "Amlogic C3 ISP Parameters"; break; + case V4L2_META_FMT_C3ISP_STATS: descr = "Amlogic C3 ISP Statistics"; break; case V4L2_PIX_FMT_NV12_8L128: descr = "NV12 (8x128 Linear)"; break; case V4L2_PIX_FMT_NV12M_8L128: descr = "NV12M (8x128 Linear)"; break; case V4L2_PIX_FMT_NV12_10BE_8L128: descr = "10-bit NV12 (8x128 Linear, BE)"; break; @@ -1452,6 +1473,16 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_Y210: descr = "10-bit YUYV Packed"; break; case V4L2_PIX_FMT_Y212: descr = "12-bit YUYV Packed"; break; case V4L2_PIX_FMT_Y216: descr = "16-bit YUYV Packed"; break; + case V4L2_META_FMT_RPI_BE_CFG: descr = "RPi PiSP BE Config format"; break; + case V4L2_META_FMT_RPI_FE_CFG: descr = "RPi PiSP FE Config format"; break; + case V4L2_META_FMT_RPI_FE_STATS: descr = "RPi PiSP FE Statistics format"; break; + case V4L2_META_FMT_GENERIC_8: descr = "8-bit Generic Metadata"; break; + case V4L2_META_FMT_GENERIC_CSI2_10: descr = "8-bit Generic Meta, 10b CSI-2"; break; + case V4L2_META_FMT_GENERIC_CSI2_12: descr = "8-bit Generic Meta, 12b CSI-2"; break; + case V4L2_META_FMT_GENERIC_CSI2_14: descr = "8-bit Generic Meta, 14b CSI-2"; break; + case V4L2_META_FMT_GENERIC_CSI2_16: descr = "8-bit Generic Meta, 16b CSI-2"; break; + case V4L2_META_FMT_GENERIC_CSI2_20: descr = "8-bit Generic Meta, 20b CSI-2"; break; + case V4L2_META_FMT_GENERIC_CSI2_24: descr = "8-bit Generic Meta, 24b CSI-2"; break; default: /* Compressed formats */ @@ -1511,6 +1542,16 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) case V4L2_PIX_FMT_MT2110T: descr = "Mediatek 10bit Tile Mode"; break; case V4L2_PIX_FMT_MT2110R: descr = "Mediatek 10bit Raster Mode"; break; case V4L2_PIX_FMT_HEXTILE: descr = "Hextile Compressed Format"; break; + case V4L2_PIX_FMT_PISP_COMP1_RGGB: descr = "PiSP 8b RGRG/GBGB mode1 compr"; break; + case V4L2_PIX_FMT_PISP_COMP1_GRBG: descr = "PiSP 8b GRGR/BGBG mode1 compr"; break; + case V4L2_PIX_FMT_PISP_COMP1_GBRG: descr = "PiSP 8b GBGB/RGRG mode1 compr"; break; + case V4L2_PIX_FMT_PISP_COMP1_BGGR: descr = "PiSP 8b BGBG/GRGR mode1 compr"; break; + case V4L2_PIX_FMT_PISP_COMP1_MONO: descr = "PiSP 8b monochrome mode1 compr"; break; + case V4L2_PIX_FMT_PISP_COMP2_RGGB: descr = "PiSP 8b RGRG/GBGB mode2 compr"; break; + case V4L2_PIX_FMT_PISP_COMP2_GRBG: descr = "PiSP 8b GRGR/BGBG mode2 compr"; break; + case V4L2_PIX_FMT_PISP_COMP2_GBRG: descr = "PiSP 8b GBGB/RGRG mode2 compr"; break; + case V4L2_PIX_FMT_PISP_COMP2_BGGR: descr = "PiSP 8b BGBG/GRGR mode2 compr"; break; + case V4L2_PIX_FMT_PISP_COMP2_MONO: descr = "PiSP 8b monochrome mode2 compr"; break; default: if (fmt->description[0]) return; @@ -1522,6 +1563,22 @@ static void v4l_fill_fmtdesc(struct v4l2_fmtdesc *fmt) } } + if (fmt->type == V4L2_BUF_TYPE_META_CAPTURE) { + switch (fmt->pixelformat) { + case V4L2_META_FMT_GENERIC_8: + case V4L2_META_FMT_GENERIC_CSI2_10: + case V4L2_META_FMT_GENERIC_CSI2_12: + case V4L2_META_FMT_GENERIC_CSI2_14: + case V4L2_META_FMT_GENERIC_CSI2_16: + case V4L2_META_FMT_GENERIC_CSI2_20: + case V4L2_META_FMT_GENERIC_CSI2_24: + fmt->flags |= V4L2_FMT_FLAG_META_LINE_BASED; + break; + default: + fmt->flags &= ~V4L2_FMT_FLAG_META_LINE_BASED; + } + } + if (descr) WARN_ON(strscpy(fmt->description, descr, sz) < 0); fmt->flags |= flags; @@ -2092,6 +2149,7 @@ static int v4l_overlay(const struct v4l2_ioctl_ops *ops, static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_requestbuffers *p = arg; int ret = check_fmt(file, p->type); @@ -2100,6 +2158,10 @@ static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops, memset_after(p, 0, flags); + p->capabilities = 0; + if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) + p->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; + return ops->vidioc_reqbufs(file, fh, p); } @@ -2133,6 +2195,7 @@ static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops, static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { + struct video_device *vfd = video_devdata(file); struct v4l2_create_buffers *create = arg; int ret = check_fmt(file, create->format.type); @@ -2143,6 +2206,10 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops, v4l_sanitize_format(&create->format); + create->capabilities = 0; + if (is_valid_ioctl(vfd, VIDIOC_REMOVE_BUFS)) + create->capabilities = V4L2_BUF_CAP_SUPPORTS_REMOVE_BUFS; + ret = ops->vidioc_create_bufs(file, fh, create); if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || @@ -2161,6 +2228,17 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops, return ret ? ret : ops->vidioc_prepare_buf(file, fh, b); } +static int v4l_remove_bufs(const struct v4l2_ioctl_ops *ops, + struct file *file, void *fh, void *arg) +{ + struct v4l2_remove_buffers *remove = arg; + + if (ops->vidioc_remove_bufs) + return ops->vidioc_remove_bufs(file, fh, remove); + + return -ENOTTY; +} + static int v4l_g_parm(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { @@ -2212,17 +2290,26 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, struct file *file, void *fh, void *arg) { struct video_device *vfd = video_devdata(file); + struct v4l2_query_ext_ctrl qec = {}; struct v4l2_queryctrl *p = arg; struct v4l2_fh *vfh = test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL; + int ret; if (vfh && vfh->ctrl_handler) return v4l2_queryctrl(vfh->ctrl_handler, p); if (vfd->ctrl_handler) return v4l2_queryctrl(vfd->ctrl_handler, p); - if (ops->vidioc_queryctrl) - return ops->vidioc_queryctrl(file, fh, p); - return -ENOTTY; + if (!ops->vidioc_query_ext_ctrl) + return -ENOTTY; + + /* Simulate query_ext_ctr using query_ctrl. */ + qec.id = p->id; + ret = ops->vidioc_query_ext_ctrl(file, fh, &qec); + if (ret) + return ret; + v4l2_query_ext_ctrl_to_v4l2_queryctrl(p, &qec); + return ret; } static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops, @@ -2273,8 +2360,6 @@ static int v4l_g_ctrl(const struct v4l2_ioctl_ops *ops, return v4l2_g_ctrl(vfh->ctrl_handler, p); if (vfd->ctrl_handler) return v4l2_g_ctrl(vfd->ctrl_handler, p); - if (ops->vidioc_g_ctrl) - return ops->vidioc_g_ctrl(file, fh, p); if (ops->vidioc_g_ext_ctrls == NULL) return -ENOTTY; @@ -2308,8 +2393,6 @@ static int v4l_s_ctrl(const struct v4l2_ioctl_ops *ops, return v4l2_s_ctrl(vfh, vfh->ctrl_handler, p); if (vfd->ctrl_handler) return v4l2_s_ctrl(NULL, vfd->ctrl_handler, p); - if (ops->vidioc_s_ctrl) - return ops->vidioc_s_ctrl(file, fh, p); if (ops->vidioc_s_ext_ctrls == NULL) return -ENOTTY; @@ -2754,8 +2837,7 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops, p->capability = m.capability | V4L2_TUNER_CAP_FREQ_BANDS; p->rangelow = m.rangelow; p->rangehigh = m.rangehigh; - p->modulation = (type == V4L2_TUNER_RADIO) ? - V4L2_BAND_MODULATION_FM : V4L2_BAND_MODULATION_VSB; + p->modulation = V4L2_BAND_MODULATION_FM; return 0; } return -ENOTTY; @@ -2910,6 +2992,7 @@ static const struct v4l2_ioctl_info v4l2_ioctls[] = { IOCTL_INFO(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0), IOCTL_INFO(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)), IOCTL_INFO(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)), + IOCTL_INFO(VIDIOC_REMOVE_BUFS, v4l_remove_bufs, v4l_print_remove_buffers, INFO_FL_PRIO | INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_remove_buffers, type)), }; #define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls) @@ -3147,13 +3230,13 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, case VIDIOC_SUBDEV_S_ROUTING: { struct v4l2_subdev_routing *routing = parg; - if (routing->num_routes > 256) + if (routing->len_routes > 256) return -E2BIG; *user_ptr = u64_to_user_ptr(routing->routes); *kernel_ptr = (void **)&routing->routes; *array_size = sizeof(struct v4l2_subdev_route) - * routing->num_routes; + * routing->len_routes; ret = 1; break; } @@ -3407,11 +3490,14 @@ video_usercopy(struct file *file, unsigned int orig_cmd, unsigned long arg, * FIXME: subdev IOCTLS are partially handled here and partially in * v4l2-subdev.c and the 'always_copy' flag can only be set for IOCTLS * defined here as part of the 'v4l2_ioctls' array. As - * VIDIOC_SUBDEV_G_ROUTING needs to return results to applications even - * in case of failure, but it is not defined here as part of the + * VIDIOC_SUBDEV_[GS]_ROUTING needs to return results to applications + * even in case of failure, but it is not defined here as part of the * 'v4l2_ioctls' array, insert an ad-hoc check to address that. */ - if (err < 0 && !always_copy && cmd != VIDIOC_SUBDEV_G_ROUTING) + if (cmd == VIDIOC_SUBDEV_G_ROUTING || cmd == VIDIOC_SUBDEV_S_ROUTING) + always_copy = true; + + if (err < 0 && !always_copy) goto out; if (has_array_args) { |