/*
 * Copyright 2015 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 "hal/usb_v1/v4l2_camera_device.h"

#include <fcntl.h>
#include <limits>
#include <linux/videodev2.h>
#include <sys/ioctl.h>

#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <base/posix/safe_strerror.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/threading/thread.h>
#include <base/timer/elapsed_timer.h>

#include "hal/usb_v1/camera_characteristics.h"

namespace arc {

// USB VID and PID are both 4 bytes long.
static const size_t kVidPidSize = 4;
// /sys/class/video4linux/video{N}/device is a symlink to the corresponding
// USB device info directory.
static const char kVidPathTemplate[] =
    "/sys/class/video4linux/%s/device/../idVendor";
static const char kPidPathTemplate[] =
    "/sys/class/video4linux/%s/device/../idProduct";

// The symlinks in /dev/v4l/by-path/ are generated by 60-persistent-v4l.rules,
// and supposed to be persistent for built-in cameras so we can safely reuse it
// across suspend/resume cycles.
static const char kAllowedCameraPrefix[] = "/dev/v4l/by-path/";

static bool ReadIdFile(const std::string& path, std::string* id) {
  char id_buf[kVidPidSize];
  FILE* file = fopen(path.c_str(), "rb");
  if (!file)
    return false;
  const bool success = fread(id_buf, kVidPidSize, 1, file) == 1;
  fclose(file);
  if (!success)
    return false;
  id->append(id_buf, kVidPidSize);
  return true;
}

V4L2CameraDevice::V4L2CameraDevice() : stream_on_(false) {}

V4L2CameraDevice::~V4L2CameraDevice() {
  device_fd_.reset();
}

int V4L2CameraDevice::Connect(const std::string& device_path) {
  VLOG(1) << __func__ << ": Connecting device path: " << device_path;
  if (device_path.compare(0, strlen(kAllowedCameraPrefix),
                          kAllowedCameraPrefix)) {
    LOG(ERROR) << __func__ << ": Invalid device path " << device_path;
    return -EINVAL;
  }
  if (device_fd_.is_valid()) {
    LOG(ERROR) << __func__ << ": A camera device is opened ("
               << device_fd_.get() << "). Please close it first";
    return -EIO;
  }

  device_fd_.reset(RetryDeviceOpen(device_path, O_RDWR));
  if (!device_fd_.is_valid()) {
    return -errno;
  }

  v4l2_capability cap = {};
  if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) != 0) {
    PLOG(ERROR) << __func__ << ": VIDIOC_QUERYCAP fail";
    device_fd_.reset();
    return -errno;
  }

  // TODO(henryhsu): Add MPLANE support.
  if (!((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
        !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) {
    LOG(ERROR) << __func__ << ": This is not a V4L2 video capture device";
    device_fd_.reset();
    return -EIO;
  }

  // Get and set format here is used to prevent multiple camera using.
  // UVC driver will acquire lock in VIDIOC_S_FMT and VIDIOC_S_SMT will fail if
  // the camera is being used by a user. The second user will fail in Connect()
  // instead of StreamOn(). Usually apps show better error message if camera
  // open fails. If start preview fails, some apps do not handle it well.
  int ret;
  v4l2_format fmt = {};
  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  ret = TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_G_FMT, &fmt));
  if (ret < 0) {
    PLOG(ERROR) << __func__ << ": Unable to G_FMT";
    return -errno;
  }
  ret = TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_S_FMT, &fmt));
  if (ret < 0) {
    LOG(WARNING) << __func__
                 << ": Unable to S_FMT: " << base::safe_strerror(errno)
                 << ", maybe camera is being used by another app.";
    return -errno;
  }

  cros::PowerLineFrequency power_line_frequency =
      GetPowerLineFrequency(device_path);

  // Only set power line frequency when the value is correct.
  if (power_line_frequency != cros::PowerLineFrequency::FREQ_ERROR) {
    ret = SetPowerLineFrequency(power_line_frequency);
    if (ret < 0) {
      LOG(ERROR) << __func__ << ": Set power frequency error";
      return -EINVAL;
    }
  }
  return 0;
}

void V4L2CameraDevice::Disconnect() {
  stream_on_ = false;
  device_fd_.reset();
  buffers_at_client_.clear();
}

int V4L2CameraDevice::StreamOn(uint32_t width,
                               uint32_t height,
                               uint32_t pixel_format,
                               float frame_rate,
                               std::vector<int>* fds,
                               uint32_t* buffer_size) {
  if (!device_fd_.is_valid()) {
    LOG(ERROR) << __func__ << ": Device is not opened";
    return -ENODEV;
  }
  if (stream_on_) {
    LOG(ERROR) << __func__ << ": Device has stream already started";
    return -EIO;
  }

  // Some drivers use rational time per frame instead of float frame rate, this
  // constant k is used to convert between both: A fps -> [k/k*A] seconds/frame.
  const int kFrameRatePrecision = 10000;
  int ret;
  v4l2_format fmt = {};
  fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  fmt.fmt.pix.width = width;
  fmt.fmt.pix.height = height;
  fmt.fmt.pix.pixelformat = pixel_format;
  ret = TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_S_FMT, &fmt));
  if (ret < 0) {
    PLOG(ERROR) << __func__ << ": Unable to S_FMT";
    return -errno;
  }
  VLOG(1) << __func__ << ": Actual width: " << fmt.fmt.pix.width
          << ", height: " << fmt.fmt.pix.height << ", pixelformat: " << std::hex
          << fmt.fmt.pix.pixelformat;

  if (width != fmt.fmt.pix.width || height != fmt.fmt.pix.height ||
      pixel_format != fmt.fmt.pix.pixelformat) {
    LOG(ERROR) << __func__ << ": Unsupported format: width " << width
               << ", height " << height << ", pixelformat " << pixel_format;
    return -EINVAL;
  }

  // Set capture framerate in the form of capture interval.
  v4l2_streamparm streamparm = {};
  streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  // The following line checks that the driver knows about framerate get/set.
  if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >=
      0) {
    // Now check if the device is able to accept a capture framerate set.
    if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) {
      // |frame_rate| is float, approximate by a fraction.
      streamparm.parm.capture.timeperframe.numerator = kFrameRatePrecision;
      streamparm.parm.capture.timeperframe.denominator =
          (frame_rate * kFrameRatePrecision);

      if (TEMP_FAILURE_RETRY(
              ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < 0) {
        LOG(ERROR) << __func__ << ": Failed to set camera framerate";
        return -EIO;
      }
      VLOG(1) << __func__ << ": Actual camera driver framerate: "
              << streamparm.parm.capture.timeperframe.denominator << "/"
              << streamparm.parm.capture.timeperframe.numerator;
    }
  }
  float fps = streamparm.parm.capture.timeperframe.denominator /
              streamparm.parm.capture.timeperframe.numerator;
  if (std::fabs(fps - frame_rate) > std::numeric_limits<float>::epsilon()) {
    LOG(ERROR) << __func__ << ": Unsupported frame rate " << frame_rate;
    return -EINVAL;
  }
  *buffer_size = fmt.fmt.pix.sizeimage;
  VLOG(1) << "Buffer size: " << *buffer_size;

  v4l2_requestbuffers req_buffers;
  memset(&req_buffers, 0, sizeof(req_buffers));
  req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  req_buffers.memory = V4L2_MEMORY_MMAP;
  req_buffers.count = kNumVideoBuffers;
  if (TEMP_FAILURE_RETRY(
          ioctl(device_fd_.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
    PLOG(ERROR) << __func__ << ": REQBUFS fails";
    return -errno;
  }
  VLOG(1) << "Requested buffer number: " << req_buffers.count;

  buffers_at_client_.resize(req_buffers.count);
  std::vector<base::ScopedFD> temp_fds;
  for (uint32_t i = 0; i < req_buffers.count; i++) {
    v4l2_exportbuffer expbuf;
    memset(&expbuf, 0, sizeof(expbuf));
    expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    expbuf.index = i;
    if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_EXPBUF, &expbuf)) <
        0) {
      PLOG(ERROR) << __func__ << ": EXPBUF (" << i << ") fails";
      return -errno;
    }
    VLOG(1) << "Exported frame buffer fd: " << expbuf.fd;
    temp_fds.push_back(base::ScopedFD(expbuf.fd));
    buffers_at_client_[i] = false;

    v4l2_buffer buffer = {};
    buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buffer.index = i;
    buffer.memory = V4L2_MEMORY_MMAP;

    if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
      PLOG(ERROR) << __func__ << ": QBUF (" << i << ") fails";
      return -errno;
    }
  }

  v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  if (TEMP_FAILURE_RETRY(
          ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) < 0) {
    PLOG(ERROR) << __func__ << ": STREAMON fails";
    return -errno;
  }

  for (size_t i = 0; i < temp_fds.size(); i++) {
    fds->push_back(temp_fds[i].release());
  }

  stream_on_ = true;
  return 0;
}

int V4L2CameraDevice::StreamOff() {
  if (!device_fd_.is_valid()) {
    LOG(ERROR) << __func__ << ": Device is not opened";
    return -ENODEV;
  }
  // Because UVC driver cannot allow STREAMOFF after REQBUF(0), adding a check
  // here to prevent it.
  if (!stream_on_) {
    return 0;
  }

  v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  if (TEMP_FAILURE_RETRY(
          ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) < 0) {
    PLOG(ERROR) << __func__ << ": STREAMOFF fails";
    return -errno;
  }
  v4l2_requestbuffers req_buffers;
  memset(&req_buffers, 0, sizeof(req_buffers));
  req_buffers.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  req_buffers.memory = V4L2_MEMORY_MMAP;
  req_buffers.count = 0;
  if (TEMP_FAILURE_RETRY(
          ioctl(device_fd_.get(), VIDIOC_REQBUFS, &req_buffers)) < 0) {
    PLOG(ERROR) << __func__ << ": REQBUFS fails";
    return -errno;
  }
  buffers_at_client_.clear();
  stream_on_ = false;
  return 0;
}

int V4L2CameraDevice::GetNextFrameBuffer(uint32_t* buffer_id,
                                         uint32_t* data_size) {
  if (!device_fd_.is_valid()) {
    LOG(ERROR) << __func__ << ": Device is not opened";
    return -ENODEV;
  }
  if (!stream_on_) {
    LOG(ERROR) << __func__ << ": Streaming is not started";
    return -EIO;
  }

  v4l2_buffer buffer;
  memset(&buffer, 0, sizeof(buffer));
  buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buffer.memory = V4L2_MEMORY_MMAP;
  if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < 0) {
    PLOG(ERROR) << __func__ << ": DQBUF fails";
    return -errno;
  }
  VLOG(1) << "DQBUF returns index " << buffer.index << " length "
          << buffer.length;

  if (buffer.index >= buffers_at_client_.size() ||
      buffers_at_client_[buffer.index]) {
    LOG(ERROR) << __func__ << ": Invalid buffer id " << buffer.index;
    return -EINVAL;
  }
  *buffer_id = buffer.index;
  *data_size = buffer.bytesused;
  buffers_at_client_[buffer.index] = true;
  return 0;
}

int V4L2CameraDevice::ReuseFrameBuffer(uint32_t buffer_id) {
  if (!device_fd_.is_valid()) {
    LOG(ERROR) << __func__ << ": Device is not opened";
    return -ENODEV;
  }
  if (!stream_on_) {
    LOG(ERROR) << __func__ << ": Streaming is not started";
    return -EIO;
  }

  VLOG(1) << "Reuse buffer id: " << buffer_id;
  if (buffer_id >= buffers_at_client_.size() ||
      !buffers_at_client_[buffer_id]) {
    LOG(ERROR) << __func__ << ": Invalid buffer id: " << buffer_id;
    return -EINVAL;
  }
  v4l2_buffer buffer;
  memset(&buffer, 0, sizeof(buffer));
  buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  buffer.memory = V4L2_MEMORY_MMAP;
  buffer.index = buffer_id;
  if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
    PLOG(ERROR) << __func__ << ": QBUF fails";
    return -errno;
  }
  buffers_at_client_[buffer.index] = false;
  return 0;
}

const SupportedFormats V4L2CameraDevice::GetDeviceSupportedFormats(
    const std::string& device_path) {
  VLOG(1) << "Query supported formats for " << device_path;
  SupportedFormats formats;
  if (device_path.compare(0, strlen(kAllowedCameraPrefix),
                          kAllowedCameraPrefix)) {
    LOG(ERROR) << __func__ << ": Invalid device path " << device_path;
    return formats;
  }

  base::ScopedFD fd(RetryDeviceOpen(device_path, O_RDONLY));
  if (!fd.is_valid()) {
    return formats;
  }

  v4l2_fmtdesc v4l2_format = {};
  v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
  for (;
       TEMP_FAILURE_RETRY(ioctl(fd.get(), VIDIOC_ENUM_FMT, &v4l2_format)) == 0;
       ++v4l2_format.index) {
    SupportedFormat supported_format;
    supported_format.fourcc = v4l2_format.pixelformat;

    v4l2_frmsizeenum frame_size = {};
    frame_size.pixel_format = v4l2_format.pixelformat;
    for (; HANDLE_EINTR(ioctl(fd.get(), VIDIOC_ENUM_FRAMESIZES, &frame_size)) ==
           0;
         ++frame_size.index) {
      if (frame_size.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
        supported_format.width = frame_size.discrete.width;
        supported_format.height = frame_size.discrete.height;
      } else if (frame_size.type == V4L2_FRMSIZE_TYPE_STEPWISE ||
                 frame_size.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) {
        // TODO(henryhsu): see http://crbug.com/249953, support these devices.
        LOG(ERROR) << __func__
                   << ": Stepwise and continuous frame size are unsupported";
        return formats;
      }

      supported_format.frameRates = GetFrameRateList(
          fd.get(), v4l2_format.pixelformat, frame_size.discrete.width,
          frame_size.discrete.height);
      formats.push_back(supported_format);
    }
  }
  return formats;
}

const DeviceInfos V4L2CameraDevice::GetCameraDeviceInfos() {
  std::unordered_map<std::string, std::string> camera_devices =
      GetCameraDevicesByPattern(std::string(kAllowedCameraPrefix) + "*");

  CameraCharacteristics characteristics;
  DeviceInfos device_infos =
      characteristics.GetCharacteristicsFromFile(camera_devices);

  if (device_infos.empty()) {
    LOG(ERROR) << __func__ << ": Cannot find any camera devices in config file";
    LOG(ERROR) << __func__ << ": List available cameras as follows: ";
    for (const auto& device : camera_devices) {
      size_t pos = device.first.find(":");
      if (pos != std::string::npos) {
        LOG(ERROR) << __func__ << ": Device path: " << device.second
                   << " vid: " << device.first.substr(0, pos)
                   << " pid: " << device.first.substr(pos + 1);
      } else {
        LOG(ERROR) << __func__ << ": Invalid device: " << device.first;
      }
    }
    return DeviceInfos();
  } else {
    VLOG(1) << __func__ << ": Number of cameras: " << device_infos.size();
  }
  return device_infos;
}

// static
bool V4L2CameraDevice::IsCameraDevice(const std::string& device_path) {
  // RetryDeviceOpen() assumes the device is a camera and waits until the camera
  // is ready, so we use open() instead of RetryDeviceOpen() here.
  base::ScopedFD fd(TEMP_FAILURE_RETRY(open(device_path.c_str(), O_RDONLY)));
  if (!fd.is_valid()) {
    PLOG(ERROR) << __func__ << ": Failed to open " << device_path;
    return false;
  }

  v4l2_capability v4l2_cap;
  if (TEMP_FAILURE_RETRY(ioctl(fd.get(), VIDIOC_QUERYCAP, &v4l2_cap)) != 0) {
    return false;
  }

  auto check_mask = [](uint32_t caps) {
    const uint32_t kCaptureMask =
        V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_CAPTURE_MPLANE;
    // Old drivers use (CAPTURE | OUTPUT) for memory-to-memory video devices.
    const uint32_t kOutputMask =
        V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
    const uint32_t kM2mMask = V4L2_CAP_VIDEO_M2M | V4L2_CAP_VIDEO_M2M_MPLANE;
    return (caps & kCaptureMask) && !(caps & kOutputMask) && !(caps & kM2mMask);
  };

  // Prefer to use available capabilities of that specific device node instead
  // of the physical device as a whole, so we can properly ignore the metadata
  // device node.
  if (v4l2_cap.capabilities & V4L2_CAP_DEVICE_CAPS) {
    return check_mask(v4l2_cap.device_caps);
  } else {
    return check_mask(v4l2_cap.capabilities);
  }
}

std::vector<float> V4L2CameraDevice::GetFrameRateList(int fd,
                                                      uint32_t fourcc,
                                                      uint32_t width,
                                                      uint32_t height) {
  std::vector<float> frame_rates;

  v4l2_frmivalenum frame_interval = {};
  frame_interval.pixel_format = fourcc;
  frame_interval.width = width;
  frame_interval.height = height;
  for (; TEMP_FAILURE_RETRY(
             ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &frame_interval)) == 0;
       ++frame_interval.index) {
    if (frame_interval.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
      if (frame_interval.discrete.numerator != 0) {
        frame_rates.push_back(
            frame_interval.discrete.denominator /
            static_cast<float>(frame_interval.discrete.numerator));
      }
    } else if (frame_interval.type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||
               frame_interval.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
      // TODO(henryhsu): see http://crbug.com/249953, support these devices.
      LOG(ERROR) << __func__
                 << ": Stepwise and continuous frame interval are unsupported";
      return frame_rates;
    }
  }
  // Some devices, e.g. Kinect, do not enumerate any frame rates, see
  // http://crbug.com/412284. Set their frame_rate to zero.
  if (frame_rates.empty()) {
    frame_rates.push_back(0);
  }
  return frame_rates;
}

const std::unordered_map<std::string, std::string>
V4L2CameraDevice::GetCameraDevicesByPattern(std::string pattern) {
  const base::FilePath path(pattern);
  base::FileEnumerator enumerator(path.DirName(), false,
                                  base::FileEnumerator::FILES,
                                  path.BaseName().value());
  std::unordered_map<std::string, std::string> devices;

  while (!enumerator.Next().empty()) {
    const base::FileEnumerator::FileInfo info = enumerator.GetInfo();
    const std::string name = info.GetName().value();
    const base::FilePath target_path = path.DirName().Append(name);

    if (!IsCameraDevice(target_path.value())) {
      continue;
    }

    base::FilePath device_path;
    if (!base::NormalizeFilePath(target_path, &device_path)) {
      LOG(ERROR) << __func__ << ": Failed to normalize path "
                 << target_path.value();
      continue;
    }

    if (!base::StartsWith(device_path.value(), "/dev/video",
                          base::CompareCase::SENSITIVE)) {
      LOG(ERROR) << __func__ << ": Invalid device path " << device_path.value();
      continue;
    }
    std::string device_name = device_path.BaseName().value();

    std::string vid_path =
        base::StringPrintf(kVidPathTemplate, device_name.c_str());
    std::string pid_path =
        base::StringPrintf(kPidPathTemplate, device_name.c_str());

    std::string usb_vid, usb_pid;
    if (!ReadIdFile(vid_path, &usb_vid)) {
      VLOG(1) << __func__ << ": Couldn't read VID of " << device_name;
      continue;
    }
    if (!ReadIdFile(pid_path, &usb_pid)) {
      VLOG(1) << __func__ << ": Couldn't read PID of " << device_name;
      continue;
    }
    VLOG(1) << __func__ << ": Device path: " << target_path.value()
            << " vid: " << usb_vid << " pid: " << usb_pid;
    devices.insert(
        std::make_pair(usb_vid + ":" + usb_pid, target_path.value()));
  }
  if (devices.empty()) {
    LOG(ERROR) << __func__ << ": Cannot find any camera devices with pattern "
               << pattern;
  }
  return devices;
}

int V4L2CameraDevice::RetryDeviceOpen(const std::string& device_path,
                                      int flags) {
  const int64_t kDeviceOpenTimeOutInMilliseconds = 2500;
  const int64_t kSleepTimeInMilliseconds = 100;
  int fd;
  base::ElapsedTimer timer;
  int64_t elapsed_time = timer.Elapsed().InMillisecondsRoundedUp();
  while (elapsed_time < kDeviceOpenTimeOutInMilliseconds) {
    fd = TEMP_FAILURE_RETRY(open(device_path.c_str(), flags));
    if (fd != -1) {
      // Make sure ioctl is ok. Once ioctl failed, we have to re-open the
      // device.
      struct v4l2_fmtdesc v4l2_format = {};
      v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
      int ret = TEMP_FAILURE_RETRY(ioctl(fd, VIDIOC_ENUM_FMT, &v4l2_format));
      if (ret == -1) {
        close(fd);
        if (errno != EPERM) {
          PLOG(ERROR) << __func__ << ": Failed to ioctl " << device_path;
          break;
        } else {
          VLOG(1) << __func__ << ": Camera ioctl is not ready";
        }
      } else {
        // Only return fd when ioctl is ready.
        if (elapsed_time >= kSleepTimeInMilliseconds) {
          LOG(INFO) << __func__ << ": Opened the camera device after waiting "
                    << "for " << elapsed_time << " ms";
        }
        return fd;
      }
    } else if (errno != ENOENT) {
      PLOG(ERROR) << __func__ << ": Failed to open " << device_path;
      break;
    }
    base::PlatformThread::Sleep(
        base::TimeDelta::FromMilliseconds(kSleepTimeInMilliseconds));
    elapsed_time = timer.Elapsed().InMillisecondsRoundedUp();
  }
  if (elapsed_time >= kDeviceOpenTimeOutInMilliseconds) {
    PLOG(ERROR) << __func__ << ": Timeout to open " << device_path;
  }
  return -1;
}

cros::PowerLineFrequency V4L2CameraDevice::GetPowerLineFrequency(
    const std::string& device_path) {
  base::ScopedFD fd(RetryDeviceOpen(device_path, O_RDONLY));
  if (!fd.is_valid()) {
    PLOG(ERROR) << __func__ << ": Failed to open " << device_path;
    return cros::PowerLineFrequency::FREQ_ERROR;
  }

  struct v4l2_queryctrl query = {};
  query.id = V4L2_CID_POWER_LINE_FREQUENCY;
  if (TEMP_FAILURE_RETRY(ioctl(fd.get(), VIDIOC_QUERYCTRL, &query)) < 0) {
    LOG(ERROR) << __func__ << ": Power line frequency should support auto or "
               << "50/60Hz";
    return cros::PowerLineFrequency::FREQ_ERROR;
  }

  cros::PowerLineFrequency frequency = cros::GetPowerLineFrequencyForLocation();
  if (frequency == cros::PowerLineFrequency::FREQ_DEFAULT) {
    switch (query.default_value) {
      case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
        frequency = cros::PowerLineFrequency::FREQ_50HZ;
        break;
      case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
        frequency = cros::PowerLineFrequency::FREQ_60HZ;
        break;
      case V4L2_CID_POWER_LINE_FREQUENCY_AUTO:
        frequency = cros::PowerLineFrequency::FREQ_AUTO;
        break;
      default:
        break;
    }
  }

  // Prefer auto setting if camera module supports auto mode.
  if (query.maximum == V4L2_CID_POWER_LINE_FREQUENCY_AUTO) {
    frequency = cros::PowerLineFrequency::FREQ_AUTO;
  } else if (query.minimum >= V4L2_CID_POWER_LINE_FREQUENCY_60HZ) {
    // TODO(shik): Handle this more gracefully for external camera
    LOG(ERROR) << __func__ << ": Camera module should at least support 50/60Hz";
    return cros::PowerLineFrequency::FREQ_ERROR;
  }
  return frequency;
}

int V4L2CameraDevice::SetPowerLineFrequency(cros::PowerLineFrequency setting) {
  int v4l2_freq_setting = V4L2_CID_POWER_LINE_FREQUENCY_DISABLED;
  switch (setting) {
    case cros::PowerLineFrequency::FREQ_50HZ:
      v4l2_freq_setting = V4L2_CID_POWER_LINE_FREQUENCY_50HZ;
      break;
    case cros::PowerLineFrequency::FREQ_60HZ:
      v4l2_freq_setting = V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
      break;
    case cros::PowerLineFrequency::FREQ_AUTO:
      v4l2_freq_setting = V4L2_CID_POWER_LINE_FREQUENCY_AUTO;
      break;
    default:
      LOG(ERROR) << __func__ << ": Invalid setting for power line frequency: "
                 << static_cast<int>(setting);
      return -EINVAL;
  }

  struct v4l2_control control = {};
  control.id = V4L2_CID_POWER_LINE_FREQUENCY;
  control.value = v4l2_freq_setting;
  if (TEMP_FAILURE_RETRY(ioctl(device_fd_.get(), VIDIOC_S_CTRL, &control)) <
      0) {
    LOG(ERROR) << __func__ << ": Error setting power line frequency to "
               << v4l2_freq_setting;
    return -EINVAL;
  }
  VLOG(1) << __func__ << ": Set power line frequency("
          << static_cast<int>(setting) << ") successfully";
  return 0;
}

}  // namespace arc
