/* 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 <fcntl.h>
#include <linux/media.h>
#include <sys/ioctl.h>

#include <algorithm>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <base/at_exit.h>
#include <base/command_line.h>
#include <base/containers/contains.h>
#include <base/containers/span.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/optional.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/values.h>
#include <brillo/syslog_logging.h>

#include "tools/crc_ccitt.h"

namespace {

const char kSysfsV4lClassRoot[] = "/sys/class/video4linux";
const char kSysfsNvmemDevicesRoot[] = "/sys/bus/nvmem/devices";
const char kVendorIdPath[] = "device/vendor_id";
const std::vector<std::string> kArgsPattern = {"modules", "list"};
const size_t kEepromIdBlockAlignment = 32u;

struct EepromIdBlock {
  char os[4];
  uint16_t crc;
  uint8_t version;
  uint8_t length;
  uint16_t data_format;
  uint16_t module_pid;
  char module_vid[2];
  char sensor_vid[2];
  uint16_t sensor_pid;
};

struct EepromInfo {
  EepromIdBlock id_block;
  base::FilePath nvmem_path;
};

struct V4L2SensorInfo {
  std::string name;
  std::string vendor_id;
  base::FilePath subdev_path;
};

bool ValidateCameraModuleInfo(base::span<const uint8_t> section) {
  if (section.size() < sizeof(EepromIdBlock)) {
    return false;
  }
  auto* info = reinterpret_cast<const EepromIdBlock*>(section.data());
  const uint16_t crc =
      Crc16CcittFalse(section.subspan(offsetof(EepromIdBlock, version)), 0u);
  return strncmp(info->os, "CrOS", 4) == 0 && info->crc == crc &&
         info->version == 1u;
}

base::Optional<EepromIdBlock> FindCameraEepromIdBlock(const std::string& mem) {
  static_assert(sizeof(EepromIdBlock) <= kEepromIdBlockAlignment);
  const size_t alignment = kEepromIdBlockAlignment;
  const uint8_t* data_end =
      reinterpret_cast<const uint8_t*>(mem.data()) + mem.size();
  for (size_t offset_from_end = alignment + mem.size() % alignment;
       offset_from_end <= mem.size(); offset_from_end += alignment) {
    base::span<const uint8_t> section =
        base::make_span(data_end - offset_from_end, sizeof(EepromIdBlock));
    if (ValidateCameraModuleInfo(section)) {
      return *reinterpret_cast<const EepromIdBlock*>(section.data());
    }
  }
  return base::nullopt;
}

class CameraTool {
 private:
  struct Camera {
    const EepromInfo* eeprom;
    const V4L2SensorInfo* v4l2_sensor;
    std::string sysfs_name;
  };

 public:
  void PrintCameras() {
    const std::vector<Camera> cameras = GetPlatformCameras();

    base::Value root(base::Value::Type::LIST);
    for (const auto& camera : cameras) {
      base::Value node(base::Value::Type::DICTIONARY);
      if (camera.eeprom != nullptr) {
        const EepromIdBlock& b = camera.eeprom->id_block;
        node.SetStringKey("name", camera.sysfs_name);
        node.SetStringKey("module_id",
                          base::StringPrintf("%c%c%04x", b.module_vid[0],
                                             b.module_vid[1], b.module_pid));
        node.SetStringKey("sensor_id",
                          base::StringPrintf("%c%c%04x", b.sensor_vid[0],
                                             b.sensor_vid[1], b.sensor_pid));
      } else {
        CHECK_NE(camera.v4l2_sensor, nullptr);
        node.SetStringKey("name", camera.v4l2_sensor->name);
        node.SetStringKey("vendor", camera.v4l2_sensor->vendor_id);
      }
      root.Append(std::move(node));
    }
    std::string json;
    if (!base::JSONWriter::WriteWithOptions(
            root, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json)) {
      LOG(ERROR) << "Failed to print camera infos";
    }
    std::cout << json << std::endl;
  }

 private:
  void ProbeSensorSubdev(struct media_entity_desc* desc,
                         const base::FilePath& path) {
    V4L2SensorInfo sensor{.name = desc->name};
    std::string vendor_id;
    const base::FilePath& vendor_id_path = path.Append(kVendorIdPath);
    if (base::ReadFileToStringWithMaxSize(vendor_id_path, &vendor_id, 64)) {
      base::TrimWhitespaceASCII(vendor_id, base::TRIM_ALL, &sensor.vendor_id);
    }
    sensor.subdev_path = base::MakeAbsoluteFilePath(path);
    LOG(INFO) << "Found V4L2 sensor subdev on " << sensor.subdev_path;

    v4l2_sensors_.emplace_back(std::move(sensor));
  }

  base::FilePath FindSubdevSysfsByDevId(int major, int minor) {
    base::FileEnumerator dev_enum(base::FilePath(kSysfsV4lClassRoot), false,
                                  base::FileEnumerator::DIRECTORIES,
                                  "v4l-subdev*");
    for (base::FilePath name = dev_enum.Next(); !name.empty();
         name = dev_enum.Next()) {
      base::FilePath dev_path = name.Append("dev");
      std::string dev_id("255:255");
      if (!base::ReadFileToStringWithMaxSize(dev_path, &dev_id,
                                             dev_id.size())) {
        LOG(ERROR) << "Failed to read device ID of '" << dev_path.value()
                   << "' from sysfs";
        continue;
      }
      base::TrimWhitespaceASCII(dev_id, base::TRIM_ALL, &dev_id);

      std::ostringstream stream;
      stream << major << ":" << minor;
      if (dev_id == stream.str())
        return name;
    }

    return base::FilePath();
  }

  void ProbeMediaController(int media_fd) {
    struct media_entity_desc desc;

    for (desc.id = MEDIA_ENT_ID_FLAG_NEXT;
         !ioctl(media_fd, MEDIA_IOC_ENUM_ENTITIES, &desc);
         desc.id |= MEDIA_ENT_ID_FLAG_NEXT) {
      if (desc.type != MEDIA_ENT_T_V4L2_SUBDEV_SENSOR)
        continue;

      const base::FilePath& path =
          FindSubdevSysfsByDevId(desc.dev.major, desc.dev.minor);
      if (path.empty()) {
        LOG(ERROR) << "v4l-subdev node for sensor '" << desc.name
                   << "' not found";
        continue;
      }

      LOG(INFO) << "Probing sensor '" << desc.name << "' ("
                << path.BaseName().value() << ")";
      ProbeSensorSubdev(&desc, path);
    }
  }

  void AddV4L2Sensors() {
    base::FileEnumerator dev_enum(base::FilePath("/dev"), false,
                                  base::FileEnumerator::FILES, "media*");
    for (base::FilePath name = dev_enum.Next(); !name.empty();
         name = dev_enum.Next()) {
      int fd = open(name.value().c_str(), O_RDWR);
      if (fd < 0) {
        LOG(ERROR) << "Failed to open '" << name.value() << "'";
        continue;
      }

      LOG(INFO) << "Probing media device '" << name.value() << "'";
      ProbeMediaController(fd);
      close(fd);
    }
  }

  void AddCameraEeproms() {
    base::FileEnumerator dev_enum(base::FilePath(kSysfsNvmemDevicesRoot), false,
                                  base::FileEnumerator::DIRECTORIES);
    for (base::FilePath dev_path = dev_enum.Next(); !dev_path.empty();
         dev_path = dev_enum.Next()) {
      const base::FilePath nvmem_path =
          base::MakeAbsoluteFilePath(dev_path.Append("nvmem"));
      if (nvmem_path.empty()) {
        LOG(ERROR) << "Failed to resolve absolute nvmem path from " << dev_path;
        continue;
      }
      std::string nvmem;
      if (!base::ReadFileToString(nvmem_path, &nvmem)) {
        LOG(ERROR) << "Failed to read nvmem from " << nvmem_path;
        continue;
      }
      base::Optional<EepromIdBlock> id_block = FindCameraEepromIdBlock(nvmem);
      if (!id_block.has_value())
        continue;
      LOG(INFO) << "Found camera eeprom on " << nvmem_path;
      eeproms_.push_back(EepromInfo{
          .id_block = *id_block,
          .nvmem_path = std::move(nvmem_path),
      });
    }
  }

  std::vector<Camera> GetPlatformCameras() {
    if (eeproms_.empty())
      AddCameraEeproms();
    if (v4l2_sensors_.empty())
      AddV4L2Sensors();

    // Associate probed nvmems and v4l-subdevs by their absolute sysfs device
    // paths. When both devices exist, they are expected to locate on the same
    // I2C bus. For example:
    //   /path/to/i2c/sysfs - i2c-2 - 2-0010 - video4linux - v4l-subdev6
    //                             \- 2-0058 - 2-00580 - nvmem
    std::vector<Camera> cameras;
    std::set<const V4L2SensorInfo*> associated_sensors;
    for (const EepromInfo& eeprom : eeproms_) {
      std::vector<std::string> path;
      eeprom.nvmem_path.GetComponents(&path);
      CHECK_GE(path.size(), 4u);
      auto iter = std::find_if(v4l2_sensors_.begin(), v4l2_sensors_.end(),
                               [&](const V4L2SensorInfo& sensor) {
                                 std::vector<std::string> p;
                                 sensor.subdev_path.GetComponents(&p);
                                 return std::equal(path.begin(), path.end() - 3,
                                                   p.begin());
                               });
      const V4L2SensorInfo* sensor =
          iter != v4l2_sensors_.end() ? &*iter : nullptr;
      cameras.push_back(Camera{
          .eeprom = &eeprom,
          .v4l2_sensor = sensor,
          .sysfs_name = path[path.size() - 4] + '/' + path[path.size() - 3],
      });
      if (sensor != nullptr)
        associated_sensors.insert(sensor);
    }
    for (const V4L2SensorInfo& sensor : v4l2_sensors_) {
      if (!base::Contains(associated_sensors, &sensor)) {
        cameras.push_back(Camera{
            .v4l2_sensor = &sensor,
        });
      }
    }
    return cameras;
  }

 private:
  std::vector<EepromInfo> eeproms_;
  std::vector<V4L2SensorInfo> v4l2_sensors_;
};

bool StringEqualsCaseInsensitiveASCII(const std::string& a,
                                      const std::string& b) {
  return base::EqualsCaseInsensitiveASCII(a, b);
}

}  // namespace

int main(int argc, char* argv[]) {
  // Init CommandLine for InitLogging.
  base::CommandLine::Init(argc, argv);
  base::AtExitManager at_exit_manager;
  brillo::InitLog(brillo::kLogToSyslog | brillo::kLogToStderrIfTty);

  // FIXME: Currently only "modules list" command is supported
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
  const std::vector<std::string>& args = cl->GetArgs();
  if (cl->GetArgs().empty() ||
      !std::equal(kArgsPattern.begin(), kArgsPattern.end(), args.begin(),
                  StringEqualsCaseInsensitiveASCII)) {
    LOG(ERROR) << "Invalid command.";
    LOG(ERROR) << "Try following supported commands:";
    LOG(ERROR) << "  modules - operations on camera modules";
    LOG(ERROR) << "    list - print available modules";
    return 1;
  }

  CameraTool tool;
  tool.PrintCameras();

  return 0;
}
