// 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.

#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_HANDLER_H_
#define CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_HANDLER_H_

#include <libudev.h>

#include <string>

#include "update_engine/file_descriptor.h"
#include "update_engine/udev_interface.h"

namespace chromeos_update_engine {

// An abstract GPIO handler interface. Serves as basic for both concrete and
// mock implementations.
class GpioHandler {
 public:
  GpioHandler() {}
  virtual ~GpioHandler() {};  // ensure virtual destruction

  // Returns true iff GPIOs have been used to signal an automated test case.
  // This call may trigger a (deferred) GPIO discovery step prior to engaging in
  // the signaling protocol; if discovery did not reveal GPIO devices, or the
  // protocol has terminated prematurely, it will conservatively default to
  // false.
  virtual bool IsTestModeSignaled() = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(GpioHandler);
};


// Concrete implementation of GPIO signal handling. Currently, it only utilizes
// the two Chromebook-specific GPIOs (aka 'dut_flaga' and 'dut_flagb') in
// deciding whether a lab test mode has been signaled.  Internal logic includes
// detection, setup and reading from / writing to GPIOs. Detection is done via
// libudev calls.  This class should be instantiated at most once to avoid race
// conditions in communicating over GPIO signals; instantiating a second
// object will actually cause a runtime error.
class StandardGpioHandler : public GpioHandler {
 public:
  // This constructor accepts a udev interface |udev_iface| and a reusable file
  // descriptor |fd|. The value of |is_defer_discovery| determines whether GPIO
  // discovery should be attempted right away (false) or done lazily, when
  // necessitated by other calls (true). If |is_cache_test_mode| is true,
  // checking for test mode signal is done only once and further queries return
  // the cached result.
  StandardGpioHandler(UdevInterface* udev_iface, FileDescriptor* fd,
                      bool is_defer_discovery, bool is_cache_test_mode);

  // Free all resources, allow to reinstantiate.
  virtual ~StandardGpioHandler();

  // Returns true iff GPIOs have been used to signal an automated test case. The
  // check is performed at most once and the result is cached and returned on
  // subsequent calls, unless |is_force| is true. This call may trigger a
  // delayed GPIO discovery prior to engaging in the signaling protocol; if the
  // delay period has not elapsed, it will conservatively default to false.
  virtual bool IsTestModeSignaled();

 private:
  // GPIO identifiers, currently includes only the two dutflags.
  enum GpioId {
    kGpioIdDutflaga = 0,
    kGpioIdDutflagb,
    kGpioIdMax  // marker, do not remove!
  };

  // GPIO direction specifier.
  enum GpioDir {
    kGpioDirIn = 0,
    kGpioDirOut,
    kGpioDirMax  // marker, do not remove!
  };

  // GPIO value.
  enum GpioVal {
    kGpioValUp = 0,
    kGpioValDown,
    kGpioValMax  // marker, do not remove!
  };

  // GPIO definition data.
  struct GpioDef {
    const char* name;           // referential name of this GPIO
    const char* udev_property;  // udev property containing the device id
  };

  // GPIO runtime control structure.
  struct Gpio {
    std::string descriptor;  // unique GPIO descriptor
    std::string dev_path;    // sysfs device name
  };

  // The number of seconds we wait before flipping the output signal (aka,
  // producing the "challenge" signal). Assuming a 1 second sampling frequency
  // on the servo side, a two second wait should be enough.
  static const int kServoOutputResponseWaitInSecs = 2;

  // The total number of seconds we wait for a servo response from the point we
  // flip the output signal. Assuming a 1 second sampling frequency on the servo
  // side, a two second wait should suffice. We add one more second for grace
  // (servod / hardware processing delays, etc).
  static const int kServoInputResponseTimeoutInSecs = 3;

  // The number of times per second we check for a servo response. Five seems
  // like a reasonable value.
  static const int kServoInputNumChecksPerSec = 5;

  // GPIO value/direction conversion tables.
  static const char* gpio_dirs_[kGpioDirMax];
  static const char* gpio_vals_[kGpioValMax];

  // GPIO definitions.
  static const GpioDef gpio_defs_[kGpioIdMax];

  // Udev device enumeration helper classes. First here is an interface
  // definition, which provides callbacks for enumeration setup and processing.
  class UdevEnumHelper {
   public:
    UdevEnumHelper(StandardGpioHandler* gpio_handler)
        : gpio_handler_(gpio_handler) {}

    // Setup the enumeration filters.
    virtual bool SetupEnumFilters(udev_enumerate* udev_enum) = 0;

    // Processes an enumerated device. Returns true upon success, false
    // otherwise.
    virtual bool ProcessDev(udev_device* dev) = 0;

    // Finalize the enumeration.
    virtual bool Finalize() = 0;

   protected:
    StandardGpioHandler* gpio_handler_;

   private:
    DISALLOW_COPY_AND_ASSIGN(UdevEnumHelper);
  };

  // Specialized udev enumerate helper for extracting GPIO descriptors from the
  // GPIO chip device.
  class GpioChipUdevEnumHelper : public UdevEnumHelper {
   public:
    GpioChipUdevEnumHelper(StandardGpioHandler* gpio_handler)
        : UdevEnumHelper(gpio_handler), num_gpio_chips_(0) {}
    virtual bool SetupEnumFilters(udev_enumerate* udev_enum);
    virtual bool ProcessDev(udev_device* dev);
    virtual bool Finalize();

   private:
    // Records the number of times a GPIO chip has been enumerated (should not
    // exceed 1).
    int num_gpio_chips_;

    DISALLOW_COPY_AND_ASSIGN(GpioChipUdevEnumHelper);
  };

  // Specialized udev enumerate helper for extracting a sysfs device path from a
  // GPIO device.
  class GpioUdevEnumHelper : public UdevEnumHelper {
   public:
    GpioUdevEnumHelper(StandardGpioHandler* gpio_handler, GpioId id)
        : UdevEnumHelper(gpio_handler), num_gpios_(0), id_(id) {}
    virtual bool SetupEnumFilters(udev_enumerate* udev_enum);
    virtual bool ProcessDev(udev_device* dev);
    virtual bool Finalize();

   private:
    // Records the number of times a GPIO has been enumerated with a given
    // descriptor (should not exceed 1).
    int num_gpios_;

    // The enumerated GPIO identifier.
    GpioId id_;

    DISALLOW_COPY_AND_ASSIGN(GpioUdevEnumHelper);
  };

  // Helper class for resetting a GPIO direction.
  class GpioDirResetter {
   public:
    GpioDirResetter(StandardGpioHandler* handler, GpioId id, GpioDir dir);
    ~GpioDirResetter();

    bool do_reset() const {
      return do_reset_;
    }
    bool set_do_reset(bool do_reset) {
      return (do_reset_ = do_reset);
    }

   private:
    // Determines whether or not the GPIO direction should be reset to the
    // initial value.
    bool do_reset_;

    // The GPIO handler to use for changing the GPIO direction.
    StandardGpioHandler* handler_;

    // The GPIO identifier and initial direction.
    GpioId id_;
    GpioDir dir_;
  };

  // An initialization helper performing udev enumeration. |enum_helper|
  // implements an enumeration initialization and processing methods. Returns
  // true upon success, false otherwise.
  bool InitUdevEnum(struct udev* udev, UdevEnumHelper* enum_helper);

  // Resets the object's flags which determine the status of test mode
  // signaling.
  void ResetTestModeSignalingFlags();

  // Attempt GPIO discovery, at most once. Returns true if discovery process was
  // successfully completed, false otherwise.
  bool DiscoverGpios();

  // Assigns a copy of the device name of GPIO |id| to |dev_path_p|. Assumes
  // initialization. Returns true upon success, false otherwise.
  bool GetGpioDevName(GpioId id, std::string* dev_path_p);

  // Open a sysfs file device |dev_name| of GPIO |id|, for either reading or
  // writing depending on |is_write|.  Uses the internal file descriptor for
  // this purpose, which can be reused as long as it is closed between
  // successive opens. Returns true upon success, false otherwise (optionally,
  // with errno set accordingly).
  bool OpenGpioFd(GpioId id, const char* dev_name, bool is_write);

  // Writes a value to device |dev_name| of GPIO |id|. The index |output| is
  // used to index the corresponding string to be written from the list
  // |entries| of length |num_entries|.  Returns true upon success, false
  // otherwise.
  bool SetGpio(GpioId id, const char* dev_name, const char* entries[],
               const int num_entries, int output);

  // Reads a value from device |dev_name| of GPIO |id|. The list |entries| of
  // length |num_entries| is used to convert the read string into an index,
  // which is written to |input_p|. The call will fail if the value being read
  // is not listed in |entries|. Returns true upon success, false otherwise.
  bool GetGpio(GpioId id, const char* dev_name, const char* entries[],
               const int num_entries, int* input_p);

  // Sets GPIO |id| to to operate in a given |direction|. Assumes
  // initialization. Returns true on success, false otherwise.
  bool SetGpioDirection(GpioId id, GpioDir direction);

  // Assigns the current direction of GPIO |id| into |direction_p|. Assumes
  // initialization. Returns true on success, false otherwise.
  bool GetGpioDirection(GpioId id, GpioDir* direction_p);

  // Sets the value of GPIO |id| to |value|. Assumues initialization. The GPIO
  // direction should be set to 'out' prior to this call. If
  // |is_check_direction| is true, it'll ensure that the direction is indeed
  // 'out' prior to attempting the write. Returns true on success, false
  // otherwise.
  bool SetGpioValue(GpioId id, GpioVal value, bool is_check_direction);

  // Reads the value of a GPIO |id| and stores it in |value_p|. Assumes
  // initialization.  The GPIO direction should be set to 'in' prior to this
  // call. If |is_check_direction| is true, it'll ensure that the direction is
  // indeed 'in' prior to attempting the read. Returns true upon success, false
  // otherwise.
  bool GetGpioValue(GpioId id, GpioVal *value_p, bool is_check_direction);

  // Invokes the actual GPIO handshake protocol to determine whether test mode
  // was signaled. Returns true iff the handshake has terminated gracefully
  // without encountering any errors; note that a true value does *not* mean
  // that a test mode signal has been detected.  The spec for this protocol:
  // https://docs.google.com/a/google.com/document/d/1DB-35ptck1wT1TYrgS5AC5Y3ALfHok-iPA7kLBw2XCI/edit
  bool DoTestModeSignalingProtocol();

  // Dynamic counter for the number of instances this class has. Used to enforce
  // that no more than one instance created. Thread-unsafe.
  static unsigned num_instances_;

  // GPIO control structures.
  Gpio gpios_[kGpioIdMax];

  // Udev interface.
  UdevInterface* const udev_iface_;

  // A file abstraction for handling GPIO devices.
  FileDescriptor* const fd_;

  // Determines whether test mode signal should be checked at most once and
  // cached, or reestablished on each query.
  const bool is_cache_test_mode_;

  // Indicates whether GPIO discovery was performed, and whether it's been
  // successful.
  bool is_discovery_attempted_;
  bool is_discovery_successful_;

  // Persistent state of the test mode check.
  bool is_first_check_;
  bool is_handshake_completed_;
  bool is_test_mode_;

  DISALLOW_COPY_AND_ASSIGN(StandardGpioHandler);
};


// A "no-op" GPIO handler, initialized to return either test or normal mode
// signal. This is useful for disabling the GPIO functionality in production
// code.
class NoopGpioHandler : public GpioHandler {
 public:
  // This constructor accepts a single argument, which is the value to be
  // returned by repeated calls to IsTestModeSignaled().
  NoopGpioHandler(bool is_test_mode) : is_test_mode_(is_test_mode) {}

  // Returns the constant Boolean value handed to the constructor.
  virtual bool IsTestModeSignaled();

 private:
  // Stores the constant value to return on subsequent test mode checks.
  bool is_test_mode_;

  DISALLOW_COPY_AND_ASSIGN(NoopGpioHandler);
};

}  // namespace chromeos_update_engine

#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_GPIO_HANDLER_H_
