// Copyright (c) 2012 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 "update_engine/gpio_handler.h"

#include <base/memory/scoped_ptr.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <glib.h>

#include "update_engine/file_descriptor.h"

using base::Time;
using base::TimeDelta;
using std::string;

using namespace chromeos_update_engine;

namespace chromeos_update_engine {

const char* StandardGpioHandler::gpio_dirs_[kGpioDirMax] = {
  "in",   // kGpioDirIn
  "out",  // kGpioDirOut
};

const char* StandardGpioHandler::gpio_vals_[kGpioValMax] = {
  "1",  // kGpioValUp
  "0",  // kGpioValDown
};

const StandardGpioHandler::GpioDef
StandardGpioHandler::gpio_defs_[kGpioIdMax] = {
  { "dutflaga", "ID_GPIO_DUTFLAGA" },  // kGpioIdDutflaga
  { "dutflagb", "ID_GPIO_DUTFLAGB" },  // kGpioIdDutflagb
};

unsigned StandardGpioHandler::num_instances_ = 0;


StandardGpioHandler::StandardGpioHandler(UdevInterface* udev_iface,
                                         FileDescriptor* fd,
                                         bool is_defer_discovery,
                                         bool is_cache_test_mode)
    : udev_iface_(udev_iface),
      fd_(fd),
      is_cache_test_mode_(is_cache_test_mode),
      is_discovery_attempted_(false),
      is_discovery_successful_(false) {
  CHECK(udev_iface && fd);

  // Ensure there's only one instance of this class.
  CHECK_EQ(num_instances_, static_cast<unsigned>(0));
  num_instances_++;

  // Reset test signal flags.
  ResetTestModeSignalingFlags();

  // If GPIO discovery not deferred, do it.
  if (!is_defer_discovery)
    DiscoverGpios();
}

StandardGpioHandler::~StandardGpioHandler() {
  num_instances_--;
}

bool StandardGpioHandler::IsTestModeSignaled() {
  bool is_returning_cached = false;  // for logging purposes

  // Attempt GPIO discovery first.
  if (DiscoverGpios()) {
    // Force a check if so requested.
    if (!is_cache_test_mode_)
      ResetTestModeSignalingFlags();

    is_returning_cached = !is_first_check_;  // for logging purposes
    if (is_first_check_) {
      is_first_check_ = false;
      DoTestModeSignalingProtocol();
    }
  }

  LOG(INFO) << "result: " << (is_test_mode_ ? "test" : "normal") << " mode"
            << (is_returning_cached ? " (cached)" : "")
            << (is_handshake_completed_ ? "" : " (default)");
  return is_test_mode_;
}


bool StandardGpioHandler::GpioChipUdevEnumHelper::SetupEnumFilters(
    udev_enumerate* udev_enum) {
  CHECK(udev_enum);

  return !(gpio_handler_->udev_iface_->EnumerateAddMatchSubsystem(
               udev_enum, "gpio") ||
           gpio_handler_->udev_iface_->EnumerateAddMatchSysname(
               udev_enum, "gpiochip*"));
}

bool StandardGpioHandler::GpioChipUdevEnumHelper::ProcessDev(udev_device* dev) {
  CHECK(dev);

  // Ensure we did not encounter more than one chip.
  if (num_gpio_chips_++) {
    LOG(ERROR) << "enumerated multiple GPIO chips";
    return false;
  }

  // Obtain GPIO descriptors.
  for (int id = 0; id < kGpioIdMax; id++) {
    const GpioDef* gpio_def = &gpio_defs_[id];
    const char* descriptor =
        gpio_handler_->udev_iface_->DeviceGetPropertyValue(
            dev, gpio_def->udev_property);
    if (!descriptor) {
      LOG(ERROR) << "could not obtain " << gpio_def->name
                 << " descriptor using property " << gpio_def->udev_property;
      return false;
    }
    gpio_handler_->gpios_[id].descriptor = descriptor;
  }

  return true;
}

bool StandardGpioHandler::GpioChipUdevEnumHelper::Finalize() {
  if (num_gpio_chips_ != 1) {
    LOG(ERROR) << "could not enumerate a GPIO chip";
    return false;
  }
  return true;
}

bool StandardGpioHandler::GpioUdevEnumHelper::SetupEnumFilters(
    udev_enumerate* udev_enum) {
  CHECK(udev_enum);
  const string gpio_pattern =
      string("*").append(gpio_handler_->gpios_[id_].descriptor);
  return !(
      gpio_handler_->udev_iface_->EnumerateAddMatchSubsystem(
          udev_enum, "gpio") ||
      gpio_handler_->udev_iface_->EnumerateAddMatchSysname(
          udev_enum, gpio_pattern.c_str()));
}

bool StandardGpioHandler::GpioUdevEnumHelper::ProcessDev(udev_device* dev) {
  CHECK(dev);

  // Ensure we did not encounter more than one GPIO device.
  if (num_gpios_++) {
    LOG(ERROR) << "enumerated multiple GPIO devices for a given descriptor";
    return false;
  }

  // Obtain GPIO device sysfs path.
  const char* dev_path = gpio_handler_->udev_iface_->DeviceGetSyspath(dev);
  if (!dev_path) {
    LOG(ERROR) << "failed to obtain device syspath for GPIO "
               << gpio_defs_[id_].name;
    return false;
  }
  gpio_handler_->gpios_[id_].dev_path = dev_path;

  LOG(INFO) << "obtained device syspath: " << gpio_defs_[id_].name << " -> "
            << gpio_handler_->gpios_[id_].dev_path;
  return true;
}

bool StandardGpioHandler::GpioUdevEnumHelper::Finalize() {
  if (num_gpios_ != 1) {
    LOG(ERROR) << "could not enumerate GPIO device " << gpio_defs_[id_].name;
    return false;
  }
  return true;
}

StandardGpioHandler::GpioDirResetter::GpioDirResetter(
    StandardGpioHandler* handler, GpioId id, GpioDir dir) :
    do_reset_(false), handler_(handler), id_(id), dir_(dir) {
  CHECK(handler);
  CHECK_GE(id, 0);
  CHECK_LT(id, kGpioIdMax);
  CHECK_GE(dir, 0);
  CHECK_LT(dir, kGpioDirMax);
}

StandardGpioHandler::GpioDirResetter::~GpioDirResetter() {
  if (do_reset_ && !handler_->SetGpioDirection(id_, dir_)) {
    LOG(WARNING) << "failed to reset direction of " << gpio_defs_[id_].name
                 << " to " << gpio_dirs_[dir_];
  }
}


bool StandardGpioHandler::InitUdevEnum(struct udev* udev,
                                       UdevEnumHelper* enum_helper) {
  // Obtain a udev enumerate object.
  struct udev_enumerate* udev_enum;
  if (!(udev_enum = udev_iface_->EnumerateNew(udev))) {
    LOG(ERROR) << "failed to obtain udev enumerate context";
    return false;
  }

  // Assign enumerate object to closer.
  scoped_ptr<UdevInterface::UdevEnumerateCloser>
      udev_enum_closer(udev_iface_->NewUdevEnumerateCloser(&udev_enum));

  // Setup enumeration filters.
  if (!enum_helper->SetupEnumFilters(udev_enum)) {
    LOG(ERROR) << "failed to setup udev enumerate filters";
    return false;
  }

  // Scan for matching devices.
  if (udev_iface_->EnumerateScanDevices(udev_enum)) {
    LOG(ERROR) << "udev enumerate scan failed";
    return false;
  }

  // Iterate over matching devices.
  struct udev_list_entry* list_entry;
  for (list_entry = udev_iface_->EnumerateGetListEntry(udev_enum);
       list_entry; list_entry = udev_iface_->ListEntryGetNext(list_entry)) {
    // Obtain device name.
    const char* dev_path = udev_iface_->ListEntryGetName(list_entry);
    if (!dev_path) {
      LOG(ERROR) << "enumerated device has a null name string";
      return false;
    }

    // Obtain device object.
    struct udev_device* dev = udev_iface_->DeviceNewFromSyspath(udev, dev_path);
    if (!dev) {
      LOG(ERROR) << "obtained a null device object for enumerated device";
      return false;
    }
    scoped_ptr<UdevInterface::UdevDeviceCloser>
        dev_closer(udev_iface_->NewUdevDeviceCloser(&dev));

    if (!enum_helper->ProcessDev(dev))
      return false;
  }

  // Make sure postconditions were met.
  return enum_helper->Finalize();
}

void StandardGpioHandler::ResetTestModeSignalingFlags() {
  is_first_check_ = true;
  is_handshake_completed_ = false;
  is_test_mode_ = false;
}

bool StandardGpioHandler::DiscoverGpios() {
  if (is_discovery_attempted_)
    return is_discovery_successful_;

  is_discovery_attempted_ = true;

  // Obtain libudev instance and attach to a dedicated closer.
  struct udev* udev;
  if (!(udev = udev_iface_->New())) {
    LOG(ERROR) << "failed to obtain libudev instance, aborting GPIO discovery";
    return false;
  }
  scoped_ptr<UdevInterface::UdevCloser>
      udev_closer(udev_iface_->NewUdevCloser(&udev));

  // Enumerate GPIO chips, scanning for GPIO descriptors.
  GpioChipUdevEnumHelper chip_enum_helper(this);
  if (!InitUdevEnum(udev, &chip_enum_helper)) {
    LOG(ERROR) << "enumeration error, aborting GPIO discovery";
    return false;
  }

  // Obtain device names for all discovered GPIOs, reusing the udev instance.
  for (int id = 0; id < kGpioIdMax; id++) {
    GpioUdevEnumHelper gpio_enum_helper(this, static_cast<GpioId>(id));
    if (!InitUdevEnum(udev, &gpio_enum_helper)) {
      LOG(ERROR) << "enumeration error, aborting GPIO discovery";
      return false;
    }
  }

  is_discovery_successful_ = true;
  return true;
}

bool StandardGpioHandler::GetGpioDevName(StandardGpioHandler::GpioId id,
                                         string* dev_path_p) {
  CHECK(id >= 0 && id < kGpioIdMax && dev_path_p);

  *dev_path_p = gpios_[id].dev_path;
  return true;
}

bool StandardGpioHandler::OpenGpioFd(StandardGpioHandler::GpioId id,
                                     const char* dev_name,
                                     bool is_write) {
  CHECK(id >= 0 && id < kGpioIdMax && dev_name);
  string file_name = base::StringPrintf("%s/%s", gpios_[id].dev_path.c_str(),
                                        dev_name);
  if (!fd_->Open(file_name.c_str(), (is_write ? O_WRONLY : O_RDONLY))) {
    if (fd_->IsSettingErrno()) {
      PLOG(ERROR) << "failed to open " << file_name
                  << " (" << gpio_defs_[id].name << ") for "
                  << (is_write ? "writing" : "reading");
    } else {
      LOG(ERROR) << "failed to open " << file_name
                 << " (" << gpio_defs_[id].name << ") for "
                 << (is_write ? "writing" : "reading");
    }
    return false;
  }
  return true;
}

bool StandardGpioHandler::SetGpio(StandardGpioHandler::GpioId id,
                                  const char* dev_name, const char* entries[],
                                  const int num_entries, int index) {
  CHECK_GE(id, 0);
  CHECK_LT(id, kGpioIdMax);
  CHECK(dev_name);
  CHECK(entries);
  CHECK_GT(num_entries, 0);
  CHECK_GE(index, 0);
  CHECK_LT(index, num_entries);

  // Open device for writing.
  if (!OpenGpioFd(id, dev_name, true))
    return false;
  ScopedFileDescriptorCloser dev_fd_closer(fd_);

  // Write a string corresponding to the requested output index to the GPIO
  // device, appending a newline.
  string output_str = entries[index];
  output_str += '\n';
  ssize_t write_len = fd_->Write(output_str.c_str(), output_str.length());
  if (write_len != static_cast<ssize_t>(output_str.length())) {
    if (write_len < 0) {
      const string err_str = "failed to write to GPIO";
      if (fd_->IsSettingErrno()) {
        PLOG(ERROR) << err_str;
      } else {
        LOG(ERROR) << err_str;
      }
    } else {
      LOG(ERROR) << "wrong number of bytes written (" << write_len
                 << " instead of " << output_str.length() << ")";
    }
    return false;
  }

  // Close the device explicitly, returning the close result.
  return fd_->Close();
}

bool StandardGpioHandler::GetGpio(StandardGpioHandler::GpioId id,
                                  const char* dev_name, const char* entries[],
                                  const int num_entries, int* index_p) {
  CHECK_GE(id, 0);
  CHECK_LT(id, kGpioIdMax);
  CHECK(dev_name);
  CHECK(entries);
  CHECK_GT(num_entries, 0);
  CHECK(index_p);

  // Open device for reading.
  if (!OpenGpioFd(id, dev_name, false))
    return false;
  ScopedFileDescriptorCloser dev_fd_closer(fd_);

  // Read the GPIO device. We attempt to read more than the max number of
  // characters expected followed by a newline, to ensure that we've indeed read
  // all the data available on the device.
  size_t max_entry_len = 0;
  for (int i = 0; i < num_entries; i++) {
    size_t entry_len = strlen(entries[i]);
    if (entry_len > max_entry_len)
      max_entry_len = entry_len;
  }
  max_entry_len++;  // account for trailing newline
  size_t buf_len = max_entry_len + 1;  // room for excess char / null terminator
  char buf[buf_len];
  memset(buf, 0, buf_len);
  ssize_t read_len = fd_->Read(buf, buf_len);
  if (read_len < 0 || read_len > static_cast<ssize_t>(max_entry_len)) {
    if (read_len < 0) {
      const string err_str = "failed to read GPIO";
      if (fd_->IsSettingErrno()) {
        PLOG(ERROR) << err_str;
      } else {
        LOG(ERROR) << err_str;
      }
    } else {
      LOG(ERROR) << "read too many bytes (" << read_len << ")";
    }
    return false;
  }

  // Remove trailing newline.
  read_len--;
  if (buf[read_len] != '\n') {
    LOG(ERROR) << "read value missing trailing newline";
    return false;
  }
  buf[read_len] = '\0';

  // Identify and write GPIO status.
  for (int i = 0; i < num_entries; i++)
    if (!strcmp(entries[i], buf)) {
      *index_p = i;
      // Close the device explicitly, returning the close result.
      return fd_->Close();
    }

  // Oops, unidentified reading...
  LOG(ERROR) << "read unexpected value from GPIO (`" << buf << "')";
  return false;
}

bool StandardGpioHandler::SetGpioDirection(StandardGpioHandler::GpioId id,
                                           StandardGpioHandler::GpioDir dir) {
  return SetGpio(id, "direction", gpio_dirs_, kGpioDirMax, dir);
}

bool StandardGpioHandler::GetGpioDirection(
    StandardGpioHandler::GpioId id,
    StandardGpioHandler::GpioDir* direction_p) {
  return GetGpio(id, "direction", gpio_dirs_, kGpioDirMax,
                 reinterpret_cast<int*>(direction_p));
}

bool StandardGpioHandler::SetGpioValue(StandardGpioHandler::GpioId id,
                                       StandardGpioHandler::GpioVal value,
                                       bool is_check_direction) {
  // If so instructed, ensure that the GPIO is indeed in the output direction
  // before attempting to write to it.
  if (is_check_direction) {
    GpioDir dir;
    if (!(GetGpioDirection(id, &dir) && dir == kGpioDirOut)) {
      LOG(ERROR) << "couldn't verify that GPIO is in the output direction "
                    "prior to reading from it";
      return false;
    }
  }

  return SetGpio(id, "value", gpio_vals_, kGpioValMax, value);
}

bool StandardGpioHandler::GetGpioValue(StandardGpioHandler::GpioId id,
                                       StandardGpioHandler::GpioVal* value_p,
                                       bool is_check_direction) {
  // If so instructed, ensure that the GPIO is indeed in the input direction
  // before attempting to read from it.
  if (is_check_direction) {
    GpioDir dir;
    if (!(GetGpioDirection(id, &dir) && dir == kGpioDirIn)) {
      LOG(ERROR) << "couldn't verify that GPIO is in the input direction "
                    "prior to reading from it";
      return false;
    }
  }

  return GetGpio(id, "value", gpio_vals_, kGpioValMax,
                 reinterpret_cast<int*>(value_p));
}

bool StandardGpioHandler::DoTestModeSignalingProtocol() {
  // The test mode signaling protocol is designed to provide a robust indication
  // that a Chrome OS device is physically connected to a servo board in a lab
  // setting. It is making very few assumptions about the soundness of the
  // hardware, firmware and kernel driver implementation of the GPIO mechanism.
  // In general, it is performing a three-way handshake between servo and the
  // Chrome OS client, based on changes in the GPIO value readings. The
  // client-side implementation does the following:
  //
  //  1. Check for an initial signal (0) on the input GPIO (dut_flaga).
  //
  //  2. Flip the signal (1 -> 0) on the output GPIO (dut_flagb).
  //
  //  3. Check for a flipped signal (1) on the input GPIO.
  //
  // TODO(garnold) the current implementation is based on sysfs access to GPIOs.
  // We will likely change this to using a specialized in-kernel driver
  // implementation, which would give us better performance and security
  // guarantees.

  LOG(INFO) << "attempting GPIO handshake";

  const char* dutflaga_name = gpio_defs_[kGpioIdDutflaga].name;
  const char* dutflagb_name = gpio_defs_[kGpioIdDutflagb].name;

  // Flip GPIO direction, set it to "in".
  // TODO(garnold) changing the GPIO direction back and forth is necessary for
  // overcoming a firmware/kernel issue which causes the device to be in the
  // "out" state whereas the kernel thinks it is in the "in" state.  This should
  // be abandoned once the firmware and/or kernel driver have been fixed.
  // Details here: http://code.google.com/p/chromium-os/issues/detail?id=27680
  if (!(SetGpioDirection(kGpioIdDutflaga, kGpioDirOut) &&
        SetGpioDirection(kGpioIdDutflaga, kGpioDirIn))) {
    LOG(ERROR) << "failed to flip direction of input GPIO " << dutflaga_name;
    return false;
  }

  // Peek input GPIO state.
  GpioVal dutflaga_gpio_value;
  if (!GetGpioValue(kGpioIdDutflaga, &dutflaga_gpio_value, true)) {
    LOG(ERROR) << "failed to read input GPIO " << dutflaga_name;
    return false;
  }

  // If initial handshake signal not received, abort.
  if (dutflaga_gpio_value != kGpioValDown) {
    LOG(INFO) << "input GPIO " << dutflaga_name
              << " unset, terminating handshake";
    is_handshake_completed_ = true;
    return true;
  }

  // Initialize output GPIO to a default state.
  // TODO(garnold) a similar workaround for possible driver/firmware glitches,
  // we insist on flipping the direction of the GPIO prior to assuming it is in
  // the "out" direction.
  GpioDirResetter dutflagb_dir_resetter(this, kGpioIdDutflagb, kGpioDirIn);
  if (!(SetGpioDirection(kGpioIdDutflagb, kGpioDirIn) &&
        dutflagb_dir_resetter.set_do_reset(
            SetGpioDirection(kGpioIdDutflagb, kGpioDirOut)) &&
        SetGpioValue(kGpioIdDutflagb, kGpioValUp, false))) {
    LOG(ERROR) << "failed to initialize output GPIO " << dutflagb_name;
    return false;
  }

  // Wait, giving the receiving end enough time to sense the fall.
  g_usleep(kServoOutputResponseWaitInSecs * G_USEC_PER_SEC);

  // Flip the output signal.
  if (!SetGpioValue(kGpioIdDutflagb, kGpioValDown, false)) {
    LOG(ERROR) << "failed to flip output GPIO " << dutflagb_name;
    return false;
  }

  // Look for flipped input GPIO value, up to a preset timeout.
  Time expires =
      Time::Now() + TimeDelta::FromSeconds(kServoInputResponseTimeoutInSecs);
  TimeDelta delay =
      TimeDelta::FromMicroseconds(1000000 / kServoInputNumChecksPerSec);
  bool is_first_response_check = true;
  bool is_error = false;
  while (Time::Now() < expires) {
    if (is_first_response_check)
      is_first_response_check = false;
    else
      g_usleep(delay.InMicroseconds());

    // Read input GPIO.
    if (!GetGpioValue(kGpioIdDutflaga, &dutflaga_gpio_value, true)) {
      LOG(ERROR) << "failed to read input GPIO " << dutflaga_name;
      is_error = true;
      break;
    }

    // If dutflaga is now up (flipped), we got our signal!
    if (dutflaga_gpio_value == kGpioValUp) {
      is_test_mode_ = true;
      break;
    }
  }

  if (!is_error) {
    if (is_test_mode_) {
      is_handshake_completed_ = true;
      LOG(INFO) << "GPIO handshake completed, test mode signaled";
    } else {
      LOG(INFO) << "timed out waiting for input GPIO " << dutflaga_name
                << " to flip, terminating handshake";
    }
  }

  return is_handshake_completed_;
}


bool NoopGpioHandler::IsTestModeSignaled() {
  LOG(INFO) << "GPIOs not engaged, defaulting to "
            << (is_test_mode_ ? "test" : "normal") << " mode";
  return is_test_mode_;
}

}  // namespace chromeos_update_engine
