// Copyright 2019 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIBEC_EC_COMMAND_H_
#define LIBEC_EC_COMMAND_H_

#include <sys/ioctl.h>

#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <limits>
#include <libusb-1.0/libusb.h>

#include <string>
#include <unordered_map>

#include <base/logging.h>
#include <chromeos/ec/cros_ec_dev.h>
#include <chromeos/ec/ec_commands.h>
#include "libec/ec_usb_endpoint.h"

namespace ec {

// Character device exposing the EC command interface.
inline constexpr char kCrosEcPath[] = "/dev/cros_ec";

// Map from |enum ec_status| to the pretty string.
#define EC_MAP_ITEM(k, v) \
  { k, #v }
inline const std::unordered_map<enum ec_status, const char*> kECStatusText =
    EC_STATUS_TEXT;
#undef EC_MAP_ITEM

enum class EcCmdVersionSupportStatus {
  UNKNOWN = 0,
  SUPPORTED = 1,
  UNSUPPORTED = 2,
};

// Upper bound of the host command packet transfer size. Although the EC can
// request a smaller transfer size, this value should never be smaller than
// the largest size the EC can transfer; this value is used to create buffers
// to hold the data to be transferred to and from the EC.
//
// The standard transfer size for v3 commands is is big enough to handle a
// request/response header, flash write offset/size, and 512 bytes of flash
// data:
//   sizeof(ec_host_request):          8
//   sizeof(ec_params_flash_write):    8
//   payload                         512
//                                 = 544 (0x220)
// See
// https://source.chromium.org/chromiumos/_/chromium/chromiumos/platform/ec/+/f3ffccd7d0fe4d0ce60434310795a7bfdaa5274c:chip/stm32/spi.c;l=82;drc=dede4e01ae4c877bb05d671087a6e85a29a0f902
// https://source.chromium.org/chromiumos/_/chromium/chromiumos/platform/ec/+/f3ffccd7d0fe4d0ce60434310795a7bfdaa5274c:chip/npcx/shi.c;l=118;drc=2a5ce905c11807a19035f7a072489df04be4db97
inline constexpr int kMaxPacketSize = 544;

// Empty request or response for the EcCommand template below.
struct EmptyParam {};
// empty struct is one byte in C++, get the size we want instead.
template <typename T>
inline constexpr size_t realsizeof = std::is_empty_v<T> ? 0 : sizeof(T);
// Variable length arrays in request or response for the EcCommand template
// below. T refers to the type of array data and RemainingParams refers to the
// type including remaining parameters in the struct.
template <typename T, typename RemainingParams = EmptyParam>
using ArrayData =
    std::array<T, (kMaxPacketSize - realsizeof<RemainingParams>) / sizeof(T)>;

inline constexpr uint32_t kVersionZero = 0;
inline constexpr uint32_t kVersionOne = 1;

inline constexpr auto kEcCommandUninitializedResult =
    std::numeric_limits<uint32_t>::max();

class EcCommandInterface {
 public:
  virtual ~EcCommandInterface() = default;
  virtual bool Run(int fd) = 0;
  virtual bool Run(ec::EcUsbEndpointInterface& uep) = 0;
  virtual bool RunWithMultipleAttempts(int fd, int num_attempts) = 0;
  virtual uint32_t Version() const = 0;
  virtual uint32_t Command() const = 0;
};

// Helper to build and send the command structures for cros_fp.
template <typename Params, typename Response>
class EcCommand : public EcCommandInterface {
 public:
  explicit EcCommand(uint32_t cmd, uint32_t ver = 0, const Params& req = {})
      : request_(req),
        cmd_({.version = ver,
              .command = cmd,
              // "outsize" is the number of bytes of data going "out"
              // to the EC.
              .outsize = realsizeof<Params>,
              // "insize" is the number of bytes we can accept as the
              // "incoming" data from the EC.
              .insize = realsizeof<Response>,
              .result = kEcCommandUninitializedResult}) {}
  EcCommand(const EcCommand&) = delete;
  EcCommand& operator=(const EcCommand&) = delete;

  ~EcCommand() override = default;

  void SetRespSize(uint32_t insize) { cmd_.insize = insize; }
  void SetReqSize(uint32_t outsize) { cmd_.outsize = outsize; }
  void SetReq(const Params& req) { request_ = req; }

  /**
   * Run an EC command.
   *
   * @param ec_fd file descriptor for the EC device
   * @return true if command runs successfully and response size is same as
   * expected, false otherwise
   *
   * The caller must be careful to only retry EC state-less
   * commands, that can be rerun without consequence.
   */
  bool Run(int ec_fd) override;
  bool Run(ec::EcUsbEndpointInterface& uep) override;

  bool RunWithMultipleAttempts(int fd, int num_attempts) override;

  virtual Response* Resp() { return &response_; }
  virtual const Response* Resp() const { return &response_; }
  virtual uint32_t RespSize() const { return cmd_.insize; }
  Params* Req() { return &request_; }
  const Params* Req() const { return &request_; }
  virtual uint32_t ReqSize() const { return cmd_.outsize; }
  virtual uint32_t Result() const { return cmd_.result; }
  virtual std::string ResultString() const {
    return ResultToString(cmd_.result);
  }

  uint32_t Version() const override { return cmd_.version; }
  uint32_t Command() const override { return cmd_.command; }

 protected:
  struct Data {
    struct cros_ec_command_v2 cmd;
    union {
      Params req;
      Response resp;
    };
  };

  std::string ResultToString(uint32_t ec_cmd_result) const;
  bool ErrorTypeCanBeRetried(uint32_t ec_cmd_result);

 private:
  virtual int ioctl(int fd, uint32_t request, Data* data) {
    return ::ioctl(fd, request, data);
  }
  int usb_xfer(const struct usb_endpoint& uep,
               void* outbuf,
               int outlen,
               void* inbuf,
               int inlen);

  unsigned int kUsbXferTimeoutMs = 1000;

  Params request_{};
  Response response_{};
  struct cros_ec_command_v2 cmd_ {};
};

/**
 * @tparam Params request structure
 * @tparam Response response structure
 * @param ec_fd  File descriptor for opened EC device
 * @return true if command is successful in which case cmd.Result() is
 * EC_RES_SUCCESS. false if either the ioctl fails or the command fails on
 * the EC (returns something other than EC_RES_SUCCESS). If the ioctl fails,
 * cmd.Result() will be kEcCommandUninitializedResult. If the command fails
 * on the EC, cmd.Result() will be set to the error returned by the EC (e.g.,
 * EC_RES_BUSY, EC_RES_UNAVAILABLE, etc.) See ec_command_test.cc for details.
 */
template <typename Params, typename Response>
bool EcCommand<Params, Response>::Run(int ec_fd) {
  cmd_.result = kEcCommandUninitializedResult;

  Data data = {.cmd = cmd_, .req = request_};

  int ret = ioctl(ec_fd, CROS_EC_DEV_IOCXCMD_V2, &data);
  if (ret < 0) {
    PLOG(ERROR) << "cros_ec ioctl command 0x" << std::hex << cmd_.command
                << std::dec << " failed";
    return false;
  }

  cmd_.result = data.cmd.result;
  response_ = data.resp;

  // Log errors returned from the EC. INVALID_COMMAND and INVALID_VERSION are
  // commonly used to probe the EC thus more-or-less expected.
  if (cmd_.result == EC_RES_INVALID_COMMAND ||
      cmd_.result == EC_RES_INVALID_VERSION) {
    LOG(INFO) << "cros_ec does not support cmd=0x" << std::hex << cmd_.command
              << std::dec << " ver=" << cmd_.version;
  } else if (cmd_.result != EC_RES_SUCCESS &&
             cmd_.result != EC_RES_IN_PROGRESS) {
    LOG(WARNING) << "cros_ec returned error=" << ResultToString(cmd_.result)
                 << " for cmd=0x" << std::hex << cmd_.command;
  }

  // Check size in addition to result code to guard against bugs in the
  // command implementation. See ec_command_test.cc for details and example test
  // cases.
  return (static_cast<uint32_t>(ret) == cmd_.insize) &&
         cmd_.result == EC_RES_SUCCESS;
}

template <typename Params, typename Response>
int EcCommand<Params, Response>::usb_xfer(const struct usb_endpoint& uep,
                                          void* outbuf,
                                          int outlen,
                                          void* inbuf,
                                          int inlen) {
  int r, transferred;

  /* Send data out */
  if (outbuf && outlen) {
    transferred = 0;
    r = libusb_bulk_transfer(uep.dev_handle, uep.address,
                             (unsigned char*)outbuf, outlen, &transferred,
                             kUsbXferTimeoutMs);
    if (r < LIBUSB_SUCCESS) {
      LOG(ERROR) << "libusb_bulk_transfer: " << libusb_error_name(r);
      return -1;
    }
    if (transferred != outlen) {
      LOG(ERROR) << "Sent " << transferred << " of " << outlen << " bytes";
      return -1;
    }
    VLOG(1) << "Sent " << outlen << " bytes";
  }

  /* Read reply back */
  if (inbuf && inlen) {
    transferred = 0;
    r = libusb_bulk_transfer(uep.dev_handle, uep.address | 0x80,
                             (unsigned char*)inbuf, inlen, &transferred,
                             kUsbXferTimeoutMs);
    if (r < LIBUSB_SUCCESS) {
      LOG(ERROR) << "libusb_bulk_transfer: " << libusb_error_name(r);
      return -1;
    }
    if (transferred != inlen) {
      LOG(ERROR) << "Received " << transferred << " of " << inlen << " bytes";
      return -1;
    }
    VLOG(1) << "Received " << inlen << " bytes";
  }

  return 0;
}

static inline int sum_bytes(const void* data, int length) {
  const uint8_t* bytes = (const uint8_t*)data;
  int sum = 0;

  for (int i = 0; i < length; i++)
    sum += bytes[i];
  return sum;
}

template <typename Params, typename Response>
bool EcCommand<Params, Response>::Run(ec::EcUsbEndpointInterface& uep) {
  cmd_.result = kEcCommandUninitializedResult;

  if (!uep.ClaimInterface()) {
    LOG(WARNING) << "Failed to claim USB interface";
    return false;
  }

  size_t req_len = sizeof(struct ec_host_request) + cmd_.outsize;
  uint8_t* req_buf = reinterpret_cast<uint8_t*>(malloc(req_len));
  if (req_buf == nullptr) {
    LOG(ERROR) << "Failed to allocate memory for request";
    uep.ReleaseInterface();
    return false;
  }
  struct ec_host_request* req = (struct ec_host_request*)req_buf;
  uint8_t* req_data = req_buf + sizeof(struct ec_host_request);

  req->struct_version = EC_HOST_REQUEST_VERSION; /* 3 */
  req->checksum = 0;
  req->command = cmd_.command;
  req->command_version = cmd_.version;
  req->reserved = 0;
  req->data_len = cmd_.outsize;
  if (cmd_.outsize)
    memcpy(req_data, &request_, cmd_.outsize);
  req->checksum = (uint8_t)(-sum_bytes(req, req_len));

  size_t res_len = sizeof(struct ec_host_response) + cmd_.insize;
  uint8_t* res_buf = reinterpret_cast<uint8_t*>(malloc(res_len));
  if (res_buf == nullptr) {
    LOG(ERROR) << "Failed to allocate memory for response";
    free(req);
    uep.ReleaseInterface();
    return false;
  }
  struct ec_host_response* res = (struct ec_host_response*)res_buf;
  uint8_t* res_data = res_buf + sizeof(struct ec_host_response);
  memset(res_buf, 0, res_len);

  if (usb_xfer(uep.GetEndpointPtr(), req, req_len, res, res_len)) {
    LOG(ERROR) << "Command 0x" << std::hex << cmd_.command << std::dec
               << " over USB failed";
  } else {
    cmd_.result = res->result;
    if (cmd_.insize) {
      memcpy(&response_, res_data, cmd_.insize);
    }
  }

  free(req);
  free(res);

  /* We may fail here but the command was successfully executed. */
  uep.ReleaseInterface();

  return true;
}

template <typename Params, typename Response>
bool EcCommand<Params, Response>::RunWithMultipleAttempts(int fd,
                                                          int num_attempts) {
  for (int retry = 0; retry < num_attempts; retry++) {
    bool ret = Run(fd);

    if (ret) {
      LOG_IF(INFO, retry > 0)
          << "cros_ec ioctl command 0x" << std::hex << cmd_.command << std::dec
          << " succeeded on attempt " << retry + 1 << "/" << num_attempts
          << ".";
      return true;
    }

    if (!ErrorTypeCanBeRetried(Result()) || (errno != ETIMEDOUT)) {
      LOG(ERROR) << "cros_ec ioctl command 0x" << std::hex << cmd_.command
                 << std::dec << " failed on attempt " << retry + 1 << "/"
                 << num_attempts << ", retry is not allowed for error";
      return false;
    }

    LOG(ERROR) << "cros_ec ioctl command 0x" << std::hex << cmd_.command
               << std::dec << " failed on attempt " << retry + 1 << "/"
               << num_attempts;
  }
  return false;
}

template <typename Params, typename Response>
std::string EcCommand<Params, Response>::ResultToString(
    uint32_t ec_cmd_result) const {
  const auto it = kECStatusText.find((enum ec_status)ec_cmd_result);
  if (it == kECStatusText.end()) {
    return std::to_string(ec_cmd_result);
  }
  return std::string(it->second);
}

template <typename Params, typename Response>
bool EcCommand<Params, Response>::ErrorTypeCanBeRetried(
    uint32_t ec_cmd_result) {
  switch (ec_cmd_result) {
    case kEcCommandUninitializedResult:
    case EC_RES_TIMEOUT:
    case EC_RES_BUSY:
      return true;
    default:
      return false;
  }
}

}  // namespace ec

#endif  // LIBEC_EC_COMMAND_H_
