// Copyright 2014 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 "power_manager/powerd/system/event_device.h"

#include <fcntl.h>
#include <linux/input.h>

#include <base/check.h>
#include <base/logging.h>
#include <base/posix/eintr_wrapper.h>

#include "power_manager/common/power_constants.h"

// Helper macros for accessing the bitfields returned by the kernel interface,
// compare with include/linux/bitops.h.
#define BITS_PER_LONG (sizeof(long) * 8)  // NOLINT(runtime/int)
#define BITS_TO_LONGS(bits) (((bits)-1) / BITS_PER_LONG + 1)
#define BITMASK_GET_BIT(bitmask, bit) \
  ((bitmask[bit / BITS_PER_LONG] >> (bit % BITS_PER_LONG)) & 1)

#define MAX(a, b) ((a) > (b) ? (a) : (b))

namespace power_manager {
namespace system {

namespace {
// C++14's <algorithm> could do std::max(EV_MAX, KEY_MAX, SW_MAX);
static constexpr int kMaxBit = MAX(MAX(EV_MAX, KEY_MAX), SW_MAX);
}  // namespace

EventDevice::EventDevice(int fd, const base::FilePath& path)
    : fd_(fd), path_(path) {}

EventDevice::~EventDevice() {
  fd_watcher_.reset();
  // ENODEV is expected if the device was just unplugged.
  if (close(fd_) != 0 && errno != ENODEV)
    PLOG(ERROR) << "Unable to close FD " << fd_;
}

std::string EventDevice::GetDebugName() {
  return path_.value();
}

std::string EventDevice::GetPhysPath() {
  char phys[256] = "";

  if (TEMP_FAILURE_RETRY(ioctl(fd_, EVIOCGPHYS(sizeof(phys)), phys)) < 0 &&
      errno != ENOENT)
    PLOG(ERROR) << "Could not get topo phys path of " << path_.value();

  return phys;
}

std::string EventDevice::GetName() {
  char name[256] = {0};

  if (TEMP_FAILURE_RETRY(ioctl(fd_, EVIOCGNAME(sizeof(name) - 1), name)) < 0)
    PLOG(ERROR) << "Could not get name of " << path_.value();

  return name;
}

bool EventDevice::IsCrosFp() {
  return GetName() == kCrosFpInputDevName;
}

bool EventDevice::IsLidSwitch() {
  return HasEventBit(0, EV_SW) && HasEventBit(EV_SW, SW_LID);
}

bool EventDevice::IsTabletModeSwitch() {
  return HasEventBit(0, EV_SW) && HasEventBit(EV_SW, SW_TABLET_MODE);
}

bool EventDevice::IsPowerButton() {
  return HasEventBit(0, EV_KEY) && HasEventBit(EV_KEY, KEY_POWER);
}

bool EventDevice::HoverSupported() {
  // Multitouch hover uses just the ABS_MT_DISTANCE event in addition to
  // the normal multi-touch events.
  if (HasEventBit(0, EV_ABS) && HasEventBit(EV_ABS, ABS_MT_DISTANCE))
    return true;

  // Simple single-touch hover presence-only detection uses 3 events:
  // ABS_DISTANCE, BTN_TOUCH, and BTN_TOOL_FINGER.
  if (HasEventBit(0, EV_ABS) && HasEventBit(EV_ABS, ABS_DISTANCE) &&
      HasEventBit(0, EV_KEY) && HasEventBit(EV_KEY, BTN_TOUCH) &&
      HasEventBit(EV_KEY, BTN_TOOL_FINGER))
    return true;

  return false;
}

bool EventDevice::HasLeftButton() {
  return HasEventBit(0, EV_KEY) && HasEventBit(EV_KEY, BTN_LEFT);
}

LidState EventDevice::GetInitialLidState() {
  CHECK(!fd_watcher_) << "GetInitialLidState called after WatchForEvents";
  return GetSwitchBit(SW_LID) ? LidState::CLOSED : LidState::OPEN;
}

TabletMode EventDevice::GetInitialTabletMode() {
  CHECK(!fd_watcher_) << "GetInitialTabletMode called after WatchForEvents";
  return GetSwitchBit(SW_TABLET_MODE) ? TabletMode::ON : TabletMode::OFF;
}

bool EventDevice::HasEventBit(int event_type, int bit) {
  DCHECK(bit <= kMaxBit);

  // bitmask needs to hold kMaxBit+1 bits
  unsigned long bitmask[BITS_TO_LONGS(kMaxBit + 1)];  // NOLINT(runtime/int)
  memset(bitmask, 0, sizeof(bitmask));
  if (TEMP_FAILURE_RETRY(
          ioctl(fd_, EVIOCGBIT(event_type, sizeof(bitmask)), bitmask)) < 0) {
    PLOG(ERROR) << "EVIOCGBIT failed for " << path_.value();
    return false;
  }
  return BITMASK_GET_BIT(bitmask, bit);
}

bool EventDevice::GetSwitchBit(int bit) {
  DCHECK(bit <= kMaxBit);

  // bitmask needs to hold SW_MAX+1 bits
  unsigned long bitmask[BITS_TO_LONGS(SW_MAX + 1)];  // NOLINT(runtime/int)
  memset(bitmask, 0, sizeof(bitmask));
  if (TEMP_FAILURE_RETRY(ioctl(fd_, EVIOCGSW(sizeof(bitmask)), bitmask)) < 0) {
    PLOG(ERROR) << "EVIOCGBIT failed for " << path_.value();
    return false;
  }
  return BITMASK_GET_BIT(bitmask, bit);
}

bool EventDevice::ReadEvents(std::vector<input_event>* events_out) {
  DCHECK(events_out);
  events_out->clear();

  struct input_event events[64];
  ssize_t read_size = HANDLE_EINTR(read(fd_, events, sizeof(events)));
  if (read_size < 0) {
    // ENODEV is expected if the device was just unplugged.
    if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENODEV)
      PLOG(ERROR) << "Reading events from " << path_.value() << " failed";
    return false;
  } else if (read_size == 0) {
    LOG(ERROR) << "Read returned 0 when reading events from " << path_.value();
    return false;
  }

  const size_t num_events = read_size / sizeof(struct input_event);
  if (read_size % sizeof(struct input_event)) {
    LOG(ERROR) << "Read " << read_size << " byte(s) while expecting "
               << sizeof(struct input_event) << "-byte events";
    return false;
  }

  events_out->reserve(num_events);
  for (size_t i = 0; i < num_events; ++i)
    events_out->push_back(events[i]);
  return true;
}

void EventDevice::WatchForEvents(base::Closure new_events_cb) {
  fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(fd_, new_events_cb);
}

EventDeviceFactory::EventDeviceFactory() {}

EventDeviceFactory::~EventDeviceFactory() {}

std::shared_ptr<EventDeviceInterface> EventDeviceFactory::Open(
    const base::FilePath& path) {
  int fd = HANDLE_EINTR(open(path.value().c_str(), O_RDONLY | O_NONBLOCK));
  if (fd < 0) {
    PLOG(ERROR) << "open() failed for " << path.value();
    return std::shared_ptr<EventDeviceInterface>();
  }
  return std::shared_ptr<EventDeviceInterface>(new EventDevice(fd, path));
}

}  // namespace system
}  // namespace power_manager
