blob: 28b32f10ffde714ae3c060abb320bc47427131c7 [file] [log] [blame]
/*
* Copyright (C) 2013-2017 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cros-camera/v4l2_device.h"
#include <sys/ioctl.h>
#include "cros-camera/common.h"
namespace cros {
V4L2Subdevice::V4L2Subdevice(const std::string name)
: V4L2Device(name), state_(SubdevState::CLOSED) {
VLOGF_ENTER();
}
V4L2Subdevice::~V4L2Subdevice() {
VLOGF_ENTER();
{
base::AutoLock l(state_lock_);
if (state_ == SubdevState::CLOSED) {
return;
}
}
Close();
}
int V4L2Subdevice::Open(int flags) {
VLOGF_ENTER();
base::AutoLock l(state_lock_);
int status = V4L2Device::Open(flags);
if (status == 0)
state_ = SubdevState::OPEN;
return status;
}
int V4L2Subdevice::Close() {
VLOGF_ENTER();
base::AutoLock l(state_lock_);
int status = V4L2Device::Close();
state_ = (status == 0) ? SubdevState::CLOSED : SubdevState::ERROR;
return status;
}
int V4L2Subdevice::SetFormat(const struct v4l2_subdev_format& format) {
VLOGF_ENTER();
base::AutoLock l(state_lock_);
if ((state_ != SubdevState::OPEN) && (state_ != SubdevState::CONFIGURED)) {
LOGF(ERROR) << "Invalid device state " << static_cast<int>(state_);
return -EINVAL;
}
VLOGF(1) << "VIDIOC_SUBDEV_S_FMT:"
<< " pad:" << format.pad << " which:" << format.which
<< " width:" << format.format.width
<< " height:" << format.format.height << " format:0x"
<< std::hex << format.format.code << " field:" << std::dec
<< format.format.field
<< " color space:" << format.format.colorspace;
int ret = ::ioctl(fd_, VIDIOC_SUBDEV_S_FMT, &format);
if (ret < 0) {
PLOGF(ERROR) << "VIDIOC_SUBDEV_S_FMT failed";
return -EINVAL;
}
VLOGF(2) << "VIDIOC_SUBDEV_S_FMT:"
<< " pad:" << format.pad << " which:" << format.which
<< " width:" << format.format.width
<< " height:" << format.format.height << " format:0x"
<< std::hex << format.format.code << " field:" << std::dec
<< format.format.field
<< " color space:" << format.format.colorspace;
state_ = SubdevState::CONFIGURED;
return 0;
}
int V4L2Subdevice::GetFormat(struct v4l2_subdev_format* format) {
VLOGF_ENTER();
base::AutoLock l(state_lock_);
if ((state_ != SubdevState::OPEN) && (state_ != SubdevState::CONFIGURED)) {
LOGF(ERROR) << "Invalid device state " << static_cast<int>(state_);
return -EINVAL;
}
int ret = ::ioctl(fd_, VIDIOC_SUBDEV_G_FMT, format);
if (ret < 0) {
PLOGF(ERROR) << "VIDIOC_SUBDEV_G_FMT failed";
return -EINVAL;
}
VLOGF(1) << "VIDIOC_SUBDEV_G_FMT:"
<< " pad:" << format->pad << " which:" << format->which
<< " width:" << format->format.width
<< " height:" << format->format.height << " format:0x"
<< std::hex << format->format.code << " field:" << std::dec
<< format->format.field
<< " color space:" << format->format.colorspace;
return 0;
}
int V4L2Subdevice::GetPadFormat(int pad_index,
int* width,
int* height,
int* code) {
VLOGF_ENTER();
if (!width || !height || !code) {
return -EINVAL;
}
struct v4l2_subdev_format format = {};
format.pad = pad_index;
format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
int ret = GetFormat(&format);
if (ret == 0) {
*width = format.format.width;
*height = format.format.height;
*code = format.format.code;
}
return ret;
}
int V4L2Subdevice::SetSelection(const struct v4l2_subdev_selection& selection) {
VLOGF_ENTER();
base::AutoLock l(state_lock_);
if ((state_ != SubdevState::OPEN) && (state_ != SubdevState::CONFIGURED)) {
LOGF(ERROR) << "Invalid device state " << static_cast<int>(state_);
return -EINVAL;
}
VLOGF(1) << "VIDIOC_SUBDEV_S_SELECTION:"
<< " which:" << selection.which << " pad:" << selection.pad
<< " target:" << std::hex << selection.target
<< " flags:" << selection.flags << " left:" << std::dec
<< selection.r.left << " top:" << selection.r.top
<< " width:" << selection.r.width
<< " height:" << selection.r.height;
int ret = ::ioctl(fd_, VIDIOC_SUBDEV_S_SELECTION, &selection);
if (ret < 0) {
PLOGF(ERROR) << "VIDIOC_SUBDEV_S_SELECTION failed";
}
return ret;
}
} // namespace cros