blob: 961f88b03ee42a5dd47c78fcd1abbe363fe12bf9 [file] [log] [blame] [edit]
/* Copyright 2023 The ChromiumOS Authors
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* Setters for abstract models of V4L2 pads.
*
* If the model has an fd for a kernel device set, then the setters will
* propagate the new values to the kernel.
*
* Return values:
* - on success: true
* - on failure: false
*/
#include "tools/mctk/yaml_tree.h"
#include <linux/media.h>
#include <linux/types.h>
#include <linux/v4l2-mediabus.h>
#include <linux/v4l2-subdev.h>
#include <linux/videodev2.h>
#include <sys/ioctl.h>
#include <optional>
#include "tools/mctk/debug.h"
#include "tools/mctk/link.h"
#include "tools/mctk/pad.h"
/* This is a macro instead of a function so we can easily print
* the ioctl name in the error message.
*/
#define VIDIOC_SUBDEV_S_WRAP(ioctl_num, ptr) \
do { \
if (this->fd_ent_) { \
if (ioctl(this->fd_ent_.value(), (ioctl_num), &(ptr)) < 0) { \
MCTK_PERROR("ioctl(" #ioctl_num ")"); \
return false; \
} \
} \
\
return true; \
} while (0);
bool V4lMcPad::SetCrop(struct v4l2_rect& crop) {
subdev_.crop = crop;
struct v4l2_subdev_crop subdev_crop = {};
subdev_crop.pad = desc_.index;
subdev_crop.which = V4L2_SUBDEV_FORMAT_ACTIVE;
subdev_crop.rect = crop;
VIDIOC_SUBDEV_S_WRAP(VIDIOC_SUBDEV_S_CROP, subdev_crop);
}
bool V4lMcPad::SetFmt(struct v4l2_mbus_framefmt& fmt) {
subdev_.fmt = fmt;
struct v4l2_subdev_format subdev_format = {};
subdev_format.pad = desc_.index;
subdev_format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
subdev_format.format = fmt;
VIDIOC_SUBDEV_S_WRAP(VIDIOC_SUBDEV_S_FMT, subdev_format);
}
bool V4lMcPad::SetFrameInterval(struct v4l2_fract& frame_interval) {
subdev_.frame_interval = frame_interval;
struct v4l2_subdev_frame_interval subdev_frame_interval = {};
subdev_frame_interval.pad = desc_.index;
subdev_frame_interval.interval = frame_interval;
VIDIOC_SUBDEV_S_WRAP(VIDIOC_SUBDEV_S_FRAME_INTERVAL, subdev_frame_interval);
}
bool V4lMcPad::SetSelection(__u32 target, struct v4l2_rect& r) {
switch (target) {
case V4L2_SEL_TGT_CROP:
subdev_.selection.crop_ = r;
break;
case V4L2_SEL_TGT_CROP_DEFAULT:
subdev_.selection.crop_default_ = r;
break;
case V4L2_SEL_TGT_CROP_BOUNDS:
subdev_.selection.crop_bounds_ = r;
break;
case V4L2_SEL_TGT_NATIVE_SIZE:
subdev_.selection.native_size_ = r;
break;
case V4L2_SEL_TGT_COMPOSE:
subdev_.selection.compose_ = r;
break;
case V4L2_SEL_TGT_COMPOSE_DEFAULT:
subdev_.selection.compose_default_ = r;
break;
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
subdev_.selection.compose_bounds_ = r;
break;
case V4L2_SEL_TGT_COMPOSE_PADDED:
subdev_.selection.compose_padded_ = r;
break;
default:
/* Only 8 targets defined as of kernel 6.5 */
return false;
}
struct v4l2_subdev_selection subdev_selection = {};
subdev_selection.which = V4L2_SUBDEV_FORMAT_ACTIVE;
subdev_selection.pad = desc_.index;
subdev_selection.target = target;
subdev_selection.flags = 0; /* Expect the config to apply precisely */
subdev_selection.r = r;
VIDIOC_SUBDEV_S_WRAP(VIDIOC_SUBDEV_S_SELECTION, subdev_selection);
}