/*
 * Copyright 2020 Google LLC
 *
 * 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.
 */

#include "io/smbus/kernel_dev.h"

#include <errno.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/sysinfo.h>
#include <unistd.h>

#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <string>
#include <utility>

#include "absl/cleanup/cleanup.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "io/ioctl.h"
#include "io/smbus/smbus.h"

namespace ecclesia {

namespace {

// The default root hierarchy to look for i2c-* files.
constexpr char kDevRoot[] = "/dev";

int SmbusIoctl(IoctlInterface *ioctl_intf, int fd, uint8_t read_write,
               uint8_t command, int size, union i2c_smbus_data *data) {
  struct i2c_smbus_ioctl_data args;

  args.read_write = read_write;
  args.command = command;
  args.size = size;
  args.data = data;
  return ioctl_intf->Call(fd, I2C_SMBUS, &args);
}

}  // namespace

KernelSmbusAccess::KernelSmbusAccess(std::string dev_dir,
                                     IoctlInterface *ioctl_intf)
    : dev_dir_(std::move(dev_dir)), ioctl_(ioctl_intf) {
  if (dev_dir_.empty()) {
    dev_dir_ = kDevRoot;
  }
}

// Format the correct string and open the bus master device file for specified
// bus location.
// Returns file descriptor on success and -errno on error.
int KernelSmbusAccess::OpenI2CMasterFile(const SmbusBus &bus) const {
  std::string dev_filename =
      absl::StrFormat("%s/i2c-%d", dev_dir_, bus.value());

  int ret = open(dev_filename.c_str(), O_RDWR);
  if (ret < 0) {
    ret = -errno;
    PLOG(ERROR) << "Unable to open " << dev_filename;
  }
  return ret;
}

// Open the device file for the device at 'loc' and set the requested
// slave address.
// Returns file descriptor on success and -errno on error.
int KernelSmbusAccess::OpenI2CSlaveFile(const SmbusLocation &loc) const {
  int ret = OpenI2CMasterFile(loc.bus());
  if (ret < 0) {
    return ret;
  }
  int fd = ret;

  if (ioctl_->Call(fd, I2C_SLAVE, loc.address().value()) < 0) {
    absl::Cleanup fd_closer = [fd]() { close(fd); };
    ret = -errno;
    PLOG(ERROR) << "SMBus device " << loc << ": "
                << "Unable to set slave address to 0x" << std::hex
                << loc.address().value();
    return ret;
  }
  return fd;
}

// Check the functionality of the adapter driver of the i2c slave at 'fd'
// for the given I2C_FUNC_* flags in 'flags'
// Returns 0 if requested functionality is supported, -EOPNOTSUPP if not
// supported and -errno on error
int KernelSmbusAccess::CheckFunctionality(int fd, uint64_t flags) const {
  int ret = 0;
  uint64_t funcs = 0;

  int result = ioctl_->Call(fd, I2C_FUNCS, &funcs);
  if (result < 0) {
    ret = -errno;
  } else if (!(funcs & flags)) {
    ret = -EOPNOTSUPP;
  }
  return ret;
}

absl::Status KernelSmbusAccess::ProbeDevice(const SmbusLocation &loc) const {
  // This is the same device probing logic used in i2cdetect.
  absl::Status status;
  if ((loc.address().value() >= 0x30 && loc.address().value() <= 0x37) ||
      (loc.address().value() >= 0x50 && loc.address().value() <= 0x5f)) {
    // Quick write can corrupt Atmel EEPROMs, so use a short read instead.
    uint8_t data;
    status = Read8(loc, 0, &data);
  } else {
    // Read byte can lock the bus for write-only devices.
    // Same with a write quick of '1', see http://b/2374009 for details.
    status = WriteQuick(loc, 0);
  }

  if (!status.ok()) {
    LOG(ERROR) << status.message();
    return absl::NotFoundError(absl::StrFormat(
        "SMBus device %s: probe found no device.", absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::WriteQuick(const SmbusLocation &loc,
                                           uint8_t data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  int result =
      SmbusIoctl(ioctl_, fd, data, I2C_SMBUS_WRITE, I2C_SMBUS_QUICK, nullptr);

  if (result < 0) {
    status = absl::InternalError(absl::StrFormat(
        "WriteQuick to device %s failed.", absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::SendByte(const SmbusLocation &loc,
                                         uint8_t data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  int result =
      SmbusIoctl(ioctl_, fd, I2C_SMBUS_WRITE, data, I2C_SMBUS_BYTE, nullptr);

  if (result < 0) {
    status = absl::InternalError(absl::StrFormat(
        "SendByte to device %s failed.", absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::ReceiveByte(const SmbusLocation &loc,
                                            uint8_t *data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  union i2c_smbus_data i2c_data {
    0
  };
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &i2c_data) <
      0) {
    status = absl::InternalError(absl::StrFormat(
        "ReceiveByte from device %s failed.", absl::FormatStreamed(loc)));
  } else {
    *data = static_cast<uint8_t>(i2c_data.byte);
  }

  return status;
}

absl::Status KernelSmbusAccess::Write8(const SmbusLocation &loc, int command,
                                       uint8_t data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  union i2c_smbus_data i2c_data {};
  i2c_data.byte = data;
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_WRITE, command, I2C_SMBUS_BYTE_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(absl::StrFormat("Write8 to device %s failed.",
                                                 absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::Read8(const SmbusLocation &loc, int command,
                                      uint8_t *data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  union i2c_smbus_data i2c_data {};
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_READ, command, I2C_SMBUS_BYTE_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(absl::StrFormat("Read8 from device %s failed.",
                                                 absl::FormatStreamed(loc)));
  } else {
    *data = static_cast<uint8_t>(i2c_data.byte);
  }

  return status;
}

absl::Status KernelSmbusAccess::Write16(const SmbusLocation &loc, int command,
                                        uint16_t data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  union i2c_smbus_data i2c_data {};
  i2c_data.word = data;
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_WRITE, command, I2C_SMBUS_WORD_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(absl::StrFormat(
        "Write16 from device %s failed.", absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::Read16(const SmbusLocation &loc, int command,
                                       uint16_t *data) const {
  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;
  union i2c_smbus_data i2c_data {};
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_READ, command, I2C_SMBUS_WORD_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(absl::StrFormat(
        "Read16 from device %s failed.", absl::FormatStreamed(loc)));
  } else {
    *data = static_cast<uint16_t>(i2c_data.word);
  }

  return status;
}

absl::Status KernelSmbusAccess::WriteBlockI2C(
    const SmbusLocation &loc, int command,
    absl::Span<const unsigned char> data) const {
  // Linux interface only supports up to 32 bytes.
  if (data.size() > I2C_SMBUS_BLOCK_MAX) {
    return absl::InternalError(
        absl::StrFormat("Can not write %d to device %s, "
                        "Linux interface only supports up to 32 bytes.",
                        data.size(), absl::FormatStreamed(loc)));
  }

  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  absl::Status status;

  union i2c_smbus_data i2c_data {};
  memcpy(&i2c_data.block[1], data.data(), data.size());
  i2c_data.block[0] = data.size();

  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_WRITE, command, I2C_SMBUS_I2C_BLOCK_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(
        absl::StrFormat("WriteBlock size of %d to device %s failed.",
                        data.size(), absl::FormatStreamed(loc)));
  }

  return status;
}

absl::Status KernelSmbusAccess::ReadBlockI2C(const SmbusLocation &loc,
                                             int command,
                                             absl::Span<unsigned char> data,
                                             size_t *len) const {
  // Linux interface only supports up to 32 bytes.
  if (data.size() > I2C_SMBUS_BLOCK_MAX) {
    return absl::InternalError(
        absl::StrFormat("Can not write %d to device %s, "
                        "Linux interface only supports up to 32 bytes.",
                        data.size(), absl::FormatStreamed(loc)));
  }

  // Open connection to i2c slave.
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) {
    return absl::InternalError(
        absl::StrFormat("Open device %s failed.", absl::FormatStreamed(loc)));
  }

  absl::Cleanup fd_closer = [fd]() { close(fd); };

  // Check that driver can support I2C block reads
  int ret = CheckFunctionality(fd, I2C_FUNC_SMBUS_READ_I2C_BLOCK);
  if (ret != 0) {
    return absl::UnimplementedError(
        absl::StrFormat("Device %s does not support I2c ReadBlock.",
                        absl::FormatStreamed(loc)));
  }

  absl::Status status;
  union i2c_smbus_data i2c_data {};
  if (SmbusIoctl(ioctl_, fd, I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA,
                 &i2c_data) < 0) {
    status = absl::InternalError(
        absl::StrFormat("ReadBlock size of %d from device %s failed.",
                        data.size(), absl::FormatStreamed(loc)));

  } else {
    *len = std::min(static_cast<size_t>(i2c_data.block[0]), data.size());
    memcpy(data.data(), &i2c_data.block[1], *len);
  }

  return status;
}

bool KernelSmbusAccess::SupportBlockRead(const SmbusLocation &loc) const {
  int fd = OpenI2CSlaveFile(loc);
  if (fd < 0) return false;

  absl::Cleanup fd_closer = [fd]() { close(fd); };
  return CheckFunctionality(fd, I2C_FUNC_SMBUS_READ_I2C_BLOCK) == 0;
}

}  // namespace ecclesia
