// Copyright 2018 The Chromium 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 "device/gamepad/gamepad_device_linux.h"

#include <fcntl.h>
#include <limits.h>
#include <linux/hidraw.h>
#include <linux/input.h>
#include <linux/joystick.h>
#include <sys/ioctl.h>

#include "base/posix/eintr_wrapper.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "device/gamepad/gamepad_data_fetcher.h"
#include "device/udev_linux/udev.h"

#if defined(OS_CHROMEOS)
#include "chromeos/dbus/permission_broker/permission_broker_client.h"
#endif  // defined(OS_CHROMEOS)

namespace device {

namespace {

const char kInputSubsystem[] = "input";
const char kUsbSubsystem[] = "usb";
const char kUsbDeviceType[] = "usb_device";
const float kMaxLinuxAxisValue = 32767.0;
const int kInvalidEffectId = -1;
const uint16_t kRumbleMagnitudeMax = 0xffff;

const size_t kSpecialKeys[] = {
    // Xbox One S pre-FW update reports Xbox button as SystemMainMenu over BT.
    KEY_MENU,
    // Power is used for the Guide button on the Nvidia Shield 2015 gamepad.
    KEY_POWER,
    // Search is used for the Guide button on the Nvidia Shield 2015 gamepad.
    KEY_SEARCH,
    // Start, Back, and Guide buttons are often reported as Consumer Home or
    // Back.
    KEY_HOMEPAGE, KEY_BACK,
};
const size_t kSpecialKeysLen = base::size(kSpecialKeys);

#define LONG_BITS (CHAR_BIT * sizeof(long))
#define BITS_TO_LONGS(x) (((x) + LONG_BITS - 1) / LONG_BITS)

static inline bool test_bit(int bit, const unsigned long* data) {
  return data[bit / LONG_BITS] & (1UL << (bit % LONG_BITS));
}

GamepadBusType GetEvdevBusType(const base::ScopedFD& fd) {
  struct input_id input_info;
  if (HANDLE_EINTR(ioctl(fd.get(), EVIOCGID, &input_info)) >= 0) {
    if (input_info.bustype == BUS_USB)
      return GAMEPAD_BUS_USB;
    if (input_info.bustype == BUS_BLUETOOTH)
      return GAMEPAD_BUS_BLUETOOTH;
  }
  return GAMEPAD_BUS_UNKNOWN;
}

bool HasRumbleCapability(const base::ScopedFD& fd) {
  unsigned long evbit[BITS_TO_LONGS(EV_MAX)];
  unsigned long ffbit[BITS_TO_LONGS(FF_MAX)];

  if (HANDLE_EINTR(ioctl(fd.get(), EVIOCGBIT(0, EV_MAX), evbit)) < 0 ||
      HANDLE_EINTR(ioctl(fd.get(), EVIOCGBIT(EV_FF, FF_MAX), ffbit)) < 0) {
    return false;
  }

  if (!test_bit(EV_FF, evbit)) {
    return false;
  }

  return test_bit(FF_RUMBLE, ffbit);
}

// Check an evdev device for key codes which sometimes appear on gamepads but
// aren't reported by joydev. If a special key is found, the corresponding entry
// of the |has_special_key| vector is set to true. Returns the number of
// special keys found.
size_t CheckSpecialKeys(const base::ScopedFD& fd,
                        std::vector<bool>* has_special_key) {
  DCHECK(has_special_key);
  unsigned long evbit[BITS_TO_LONGS(EV_MAX)];
  unsigned long keybit[BITS_TO_LONGS(KEY_MAX)];
  size_t found_special_keys = 0;

  has_special_key->clear();
  if (HANDLE_EINTR(ioctl(fd.get(), EVIOCGBIT(0, EV_MAX), evbit)) < 0 ||
      HANDLE_EINTR(ioctl(fd.get(), EVIOCGBIT(EV_KEY, KEY_MAX), keybit)) < 0) {
    return 0;
  }

  if (!test_bit(EV_KEY, evbit)) {
    return 0;
  }

  has_special_key->resize(kSpecialKeysLen, false);
  for (size_t special_index = 0; special_index < kSpecialKeysLen;
       ++special_index) {
    if (test_bit(kSpecialKeys[special_index], keybit)) {
      (*has_special_key)[special_index] = true;
      ++found_special_keys;
    }
  }

  return found_special_keys;
}

bool GetHidrawDevinfo(const base::ScopedFD& fd,
                      GamepadBusType* bus_type,
                      uint16_t* vendor_id,
                      uint16_t* product_id) {
  struct hidraw_devinfo info;
  if (HANDLE_EINTR(ioctl(fd.get(), HIDIOCGRAWINFO, &info)) < 0)
    return false;
  if (bus_type) {
    if (info.bustype == BUS_USB)
      *bus_type = GAMEPAD_BUS_USB;
    else if (info.bustype == BUS_BLUETOOTH)
      *bus_type = GAMEPAD_BUS_BLUETOOTH;
    else
      *bus_type = GAMEPAD_BUS_UNKNOWN;
  }
  if (vendor_id)
    *vendor_id = static_cast<uint16_t>(info.vendor);
  if (product_id)
    *product_id = static_cast<uint16_t>(info.product);
  return true;
}

int StoreRumbleEffect(const base::ScopedFD& fd,
                      int effect_id,
                      uint16_t duration,
                      uint16_t start_delay,
                      uint16_t strong_magnitude,
                      uint16_t weak_magnitude) {
  struct ff_effect effect;
  memset(&effect, 0, sizeof(effect));
  effect.type = FF_RUMBLE;
  effect.id = effect_id;
  effect.replay.length = duration;
  effect.replay.delay = start_delay;
  effect.u.rumble.strong_magnitude = strong_magnitude;
  effect.u.rumble.weak_magnitude = weak_magnitude;

  if (HANDLE_EINTR(ioctl(fd.get(), EVIOCSFF, (const void*)&effect)) < 0)
    return kInvalidEffectId;
  return effect.id;
}

void DestroyEffect(const base::ScopedFD& fd, int effect_id) {
  HANDLE_EINTR(ioctl(fd.get(), EVIOCRMFF, effect_id));
}

bool StartOrStopEffect(const base::ScopedFD& fd, int effect_id, bool do_start) {
  struct input_event start_stop;
  memset(&start_stop, 0, sizeof(start_stop));
  start_stop.type = EV_FF;
  start_stop.code = effect_id;
  start_stop.value = do_start ? 1 : 0;
  ssize_t nbytes = HANDLE_EINTR(
      write(fd.get(), (const void*)&start_stop, sizeof(start_stop)));
  return nbytes == sizeof(start_stop);
}

uint16_t HexStringToUInt16WithDefault(base::StringPiece input,
                                      uint16_t default_value) {
  uint32_t out = 0;
  if (!base::HexStringToUInt(input, &out) ||
      out > std::numeric_limits<uint16_t>::max()) {
    return default_value;
  }
  return static_cast<uint16_t>(out);
}

}  // namespace

GamepadDeviceLinux::GamepadDeviceLinux(
    const std::string& syspath_prefix,
    scoped_refptr<base::SequencedTaskRunner> dbus_runner)
    : syspath_prefix_(syspath_prefix),
      button_indices_used_(Gamepad::kButtonsLengthCap, false),
      dbus_runner_(dbus_runner),
      polling_runner_(base::SequencedTaskRunnerHandle::Get()) {}

GamepadDeviceLinux::~GamepadDeviceLinux() = default;

void GamepadDeviceLinux::DoShutdown() {
  CloseJoydevNode();
  CloseEvdevNode();
  CloseHidrawNode();
}

bool GamepadDeviceLinux::IsEmpty() const {
  return !joydev_fd_.is_valid() && !evdev_fd_.is_valid() &&
         !hidraw_fd_.is_valid();
}

bool GamepadDeviceLinux::SupportsVibration() const {
  if (dualshock4_ || hid_haptics_)
    return true;

  // The Xbox Adaptive Controller reports force feedback capability, but the
  // device itself does not have any vibration actuators.
  if (gamepad_id_ == GamepadId::kMicrosoftProduct0b0a)
    return false;

  return supports_force_feedback_ && evdev_fd_.is_valid();
}

void GamepadDeviceLinux::ReadPadState(Gamepad* pad) {
  DCHECK(joydev_fd_.is_valid());

  // Read button and axis events from the joydev device.
  bool pad_updated = ReadJoydevState(pad);

  // Evdev special buttons must be initialized after we have read from joydev
  // at least once to ensure we do not assign a button index already in use by
  // joydev.
  if (!evdev_special_keys_initialized_)
    InitializeEvdevSpecialKeys();

  // Read button events from the evdev device.
  if (!special_button_map_.empty()) {
    if (ReadEvdevSpecialKeys(pad))
      pad_updated = true;
  }

  if (pad_updated)
    pad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
}

bool GamepadDeviceLinux::ReadJoydevState(Gamepad* pad) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(pad);

  if (!joydev_fd_.is_valid())
    return false;

  // Read button and axis events from the joydev device.
  bool pad_updated = false;
  js_event event;
  while (HANDLE_EINTR(read(joydev_fd_.get(), &event, sizeof(struct js_event))) >
         0) {
    size_t item = event.number;
    if (event.type & JS_EVENT_AXIS) {
      if (item >= Gamepad::kAxesLengthCap)
        continue;

      pad->axes[item] = event.value / kMaxLinuxAxisValue;

      if (item >= pad->axes_length)
        pad->axes_length = item + 1;
      pad_updated = true;
    } else if (event.type & JS_EVENT_BUTTON) {
      if (item >= Gamepad::kButtonsLengthCap)
        continue;

      pad->buttons[item].pressed = event.value;
      pad->buttons[item].value = event.value ? 1.0 : 0.0;

      // When a joydev device is opened, synthetic events are generated for
      // each joystick button and axis with the JS_EVENT_INIT flag set on the
      // event type. Use this signal to mark these button indices as used.
      if (event.type & JS_EVENT_INIT)
        button_indices_used_[item] = true;

      if (item >= pad->buttons_length)
        pad->buttons_length = item + 1;
      pad_updated = true;
    }
  }
  return pad_updated;
}

void GamepadDeviceLinux::InitializeEvdevSpecialKeys() {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (!evdev_fd_.is_valid())
    return;

  // Do some one-time initialization to decide indices for the evdev special
  // buttons.
  evdev_special_keys_initialized_ = true;
  std::vector<bool> special_key_present;
  size_t unmapped_button_count =
      CheckSpecialKeys(evdev_fd_, &special_key_present);

  special_button_map_.clear();
  if (unmapped_button_count > 0) {
    // Insert special buttons at unused button indices.
    special_button_map_.resize(kSpecialKeysLen, -1);
    size_t button_index = 0;
    for (size_t special_index = 0; special_index < kSpecialKeysLen;
         ++special_index) {
      if (!special_key_present[special_index])
        continue;

      // Advance to the next unused button index.
      while (button_indices_used_[button_index] &&
             button_index < Gamepad::kButtonsLengthCap) {
        ++button_index;
      }
      if (button_index >= Gamepad::kButtonsLengthCap)
        break;

      special_button_map_[special_index] = button_index;
      button_indices_used_[button_index] = true;
      ++button_index;

      if (--unmapped_button_count == 0)
        break;
    }
  }
}

bool GamepadDeviceLinux::ReadEvdevSpecialKeys(Gamepad* pad) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(pad);

  if (!evdev_fd_.is_valid())
    return false;

  // Read special button events through evdev.
  bool pad_updated = false;
  input_event ev;
  ssize_t bytes_read;
  while ((bytes_read = HANDLE_EINTR(
              read(evdev_fd_.get(), &ev, sizeof(input_event)))) > 0) {
    if (size_t{bytes_read} < sizeof(input_event))
      break;
    if (ev.type != EV_KEY)
      continue;

    for (size_t special_index = 0; special_index < kSpecialKeysLen;
         ++special_index) {
      int button_index = special_button_map_[special_index];
      if (button_index < 0)
        continue;
      if (ev.code == kSpecialKeys[special_index]) {
        pad->buttons[button_index].pressed = ev.value;
        pad->buttons[button_index].value = ev.value ? 1.0 : 0.0;
        pad_updated = true;
      }
    }
  }

  return pad_updated;
}

GamepadStandardMappingFunction GamepadDeviceLinux::GetMappingFunction() const {
  return GetGamepadStandardMappingFunction(vendor_id_, product_id_,
                                           version_number_, bus_type_);
}

bool GamepadDeviceLinux::IsSameDevice(const UdevGamepadLinux& pad_info) {
  return pad_info.syspath_prefix == syspath_prefix_;
}

bool GamepadDeviceLinux::OpenJoydevNode(const UdevGamepadLinux& pad_info,
                                        udev_device* device) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(pad_info.type == UdevGamepadLinux::Type::JOYDEV);
  DCHECK(pad_info.syspath_prefix == syspath_prefix_);

  CloseJoydevNode();
  joydev_fd_ =
      base::ScopedFD(open(pad_info.path.c_str(), O_RDONLY | O_NONBLOCK));
  if (!joydev_fd_.is_valid())
    return false;

  udev_device* parent_device =
      device::udev_device_get_parent_with_subsystem_devtype(
          device, kInputSubsystem, nullptr);

  const base::StringPiece vendor_id =
      udev_device_get_sysattr_value(parent_device, "id/vendor");
  const base::StringPiece product_id =
      udev_device_get_sysattr_value(parent_device, "id/product");
  const base::StringPiece version_number =
      udev_device_get_sysattr_value(parent_device, "id/version");
  const base::StringPiece name =
      udev_device_get_sysattr_value(parent_device, "name");

  uint16_t vendor_id_int = HexStringToUInt16WithDefault(vendor_id, 0);
  uint16_t product_id_int = HexStringToUInt16WithDefault(product_id, 0);
  uint16_t version_number_int = HexStringToUInt16WithDefault(version_number, 0);

  // In many cases the information the input subsystem contains isn't
  // as good as the information that the device bus has, walk up further
  // to the subsystem/device type "usb"/"usb_device" and if this device
  // has the same vendor/product id, prefer the description from that.
  struct udev_device* usb_device =
      udev_device_get_parent_with_subsystem_devtype(
          parent_device, kUsbSubsystem, kUsbDeviceType);
  std::string name_string(name);
  if (usb_device) {
    const base::StringPiece usb_vendor_id =
        udev_device_get_sysattr_value(usb_device, "idVendor");
    const base::StringPiece usb_product_id =
        udev_device_get_sysattr_value(usb_device, "idProduct");

    if (vendor_id == usb_vendor_id && product_id == usb_product_id) {
      const char* manufacturer =
          udev_device_get_sysattr_value(usb_device, "manufacturer");
      const char* product =
          udev_device_get_sysattr_value(usb_device, "product");

      if (manufacturer && product) {
        // Replace the previous name string with one containing the better
        // information.
        name_string = base::StringPrintf("%s %s", manufacturer, product);
      }
    }
  }

  joydev_index_ = pad_info.index;
  vendor_id_ = vendor_id_int;
  product_id_ = product_id_int;
  version_number_ = version_number_int;
  name_ = name_string;
  gamepad_id_ = GamepadIdList::Get().GetGamepadId(vendor_id_, product_id_);

  return true;
}

void GamepadDeviceLinux::CloseJoydevNode() {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  joydev_fd_.reset();
  joydev_index_ = -1;
  vendor_id_ = 0;
  product_id_ = 0;
  version_number_ = 0;
  name_.clear();
  gamepad_id_ = GamepadId::kUnknownGamepad;

  // Button indices must be recomputed once the joydev node is closed.
  button_indices_used_.clear();
  special_button_map_.clear();
  evdev_special_keys_initialized_ = false;
}

bool GamepadDeviceLinux::OpenEvdevNode(const UdevGamepadLinux& pad_info) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(pad_info.type == UdevGamepadLinux::Type::EVDEV);
  DCHECK(pad_info.syspath_prefix == syspath_prefix_);

  CloseEvdevNode();
  evdev_fd_ = base::ScopedFD(open(pad_info.path.c_str(), O_RDWR | O_NONBLOCK));
  if (!evdev_fd_.is_valid())
    return false;

  supports_force_feedback_ = HasRumbleCapability(evdev_fd_);
  bus_type_ = GetEvdevBusType(evdev_fd_);

  return true;
}

void GamepadDeviceLinux::CloseEvdevNode() {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (evdev_fd_.is_valid()) {
    if (effect_id_ != kInvalidEffectId) {
      DestroyEffect(evdev_fd_, effect_id_);
      effect_id_ = kInvalidEffectId;
    }
  }
  evdev_fd_.reset();
  supports_force_feedback_ = false;

  // Clear any entries in |button_indices_used_| that were taken by evdev.
  if (!special_button_map_.empty()) {
    for (int button_index : special_button_map_) {
      if (button_index >= 0)
        button_indices_used_[button_index] = false;
    }
  }
  special_button_map_.clear();
  evdev_special_keys_initialized_ = false;
}

void GamepadDeviceLinux::OpenHidrawNode(const UdevGamepadLinux& pad_info,
                                        OpenDeviceNodeCallback callback) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(pad_info.type == UdevGamepadLinux::Type::HIDRAW);
  DCHECK(pad_info.syspath_prefix == syspath_prefix_);

  CloseHidrawNode();

  auto fd = base::ScopedFD(open(pad_info.path.c_str(), O_RDWR | O_NONBLOCK));

#if defined(OS_CHROMEOS)
  // If we failed to open the device it may be due to insufficient permissions.
  // Try again using the PermissionBrokerClient.
  if (!fd.is_valid()) {
    DCHECK(dbus_runner_);
    DCHECK(polling_runner_);
    auto open_path_callback =
        base::BindOnce(&GamepadDeviceLinux::OnOpenHidrawNodeComplete,
                       weak_factory_.GetWeakPtr(), std::move(callback));
    dbus_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&GamepadDeviceLinux::OpenPathWithPermissionBroker,
                       weak_factory_.GetWeakPtr(), pad_info.path,
                       std::move(open_path_callback)));
    return;
  }
#endif  // defined(OS_CHROMEOS)

  OnOpenHidrawNodeComplete(std::move(callback), std::move(fd));
}

void GamepadDeviceLinux::OnOpenHidrawNodeComplete(
    OpenDeviceNodeCallback callback,
    base::ScopedFD fd) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (fd.is_valid())
    InitializeHidraw(std::move(fd));
  std::move(callback).Run(this);
}

void GamepadDeviceLinux::InitializeHidraw(base::ScopedFD fd) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  DCHECK(fd.is_valid());
  hidraw_fd_ = std::move(fd);

  uint16_t vendor_id;
  uint16_t product_id;
  bool is_dualshock4 = false;
  bool is_hid_haptic = false;
  if (GetHidrawDevinfo(hidraw_fd_, &bus_type_, &vendor_id, &product_id)) {
    is_dualshock4 =
        Dualshock4ControllerLinux::IsDualshock4(vendor_id, product_id);
    is_hid_haptic = HidHapticGamepadLinux::IsHidHaptic(vendor_id, product_id);
    DCHECK_LE(is_dualshock4 + is_hid_haptic, 1);
  }

  if (is_dualshock4 && !dualshock4_)
    dualshock4_ = std::make_unique<Dualshock4ControllerLinux>(hidraw_fd_);

  if (is_hid_haptic && !hid_haptics_) {
    hid_haptics_ =
        HidHapticGamepadLinux::Create(vendor_id, product_id, hidraw_fd_);
  }
}

void GamepadDeviceLinux::CloseHidrawNode() {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (dualshock4_)
    dualshock4_->Shutdown();
  dualshock4_.reset();
  if (hid_haptics_)
    hid_haptics_->Shutdown();
  hid_haptics_.reset();
  hidraw_fd_.reset();
}

#if defined(OS_CHROMEOS)
void GamepadDeviceLinux::OpenPathWithPermissionBroker(
    const std::string& path,
    OpenPathCallback callback) {
  DCHECK(dbus_runner_->RunsTasksInCurrentSequence());
  auto* client = chromeos::PermissionBrokerClient::Get();
  DCHECK(client) << "Could not get permission broker client.";
  auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
  auto success_callback =
      base::BindOnce(&GamepadDeviceLinux::OnOpenPathSuccess,
                     weak_factory_.GetWeakPtr(), copyable_callback);
  auto error_callback =
      base::BindOnce(&GamepadDeviceLinux::OnOpenPathError,
                     weak_factory_.GetWeakPtr(), copyable_callback);
  client->OpenPath(path, std::move(success_callback),
                   std::move(error_callback));
}

void GamepadDeviceLinux::OnOpenPathSuccess(OpenPathCallback callback,
                                           base::ScopedFD fd) {
  DCHECK(dbus_runner_->RunsTasksInCurrentSequence());
  polling_runner_->PostTask(FROM_HERE,
                            base::BindOnce(std::move(callback), std::move(fd)));
}

void GamepadDeviceLinux::OnOpenPathError(OpenPathCallback callback,
                                         const std::string& error_name,
                                         const std::string& error_message) {
  DCHECK(dbus_runner_->RunsTasksInCurrentSequence());
  polling_runner_->PostTask(
      FROM_HERE, base::BindOnce(std::move(callback), base::ScopedFD()));
}
#endif

void GamepadDeviceLinux::SetVibration(double strong_magnitude,
                                      double weak_magnitude) {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (dualshock4_) {
    dualshock4_->SetVibration(strong_magnitude, weak_magnitude);
    return;
  }

  if (hid_haptics_) {
    hid_haptics_->SetVibration(strong_magnitude, weak_magnitude);
    return;
  }

  uint16_t strong_magnitude_scaled =
      static_cast<uint16_t>(strong_magnitude * kRumbleMagnitudeMax);
  uint16_t weak_magnitude_scaled =
      static_cast<uint16_t>(weak_magnitude * kRumbleMagnitudeMax);

  // AbstractHapticGamepad will call SetZeroVibration when the effect is
  // complete, so we don't need to set the duration here except to make sure it
  // is at least as long as the maximum duration.
  uint16_t duration_millis =
      static_cast<uint16_t>(GamepadHapticActuator::kMaxEffectDurationMillis);

  // Upload the effect and get the new effect ID. If we already created an
  // effect on this device, reuse its ID.
  effect_id_ =
      StoreRumbleEffect(evdev_fd_, effect_id_, duration_millis, 0,
                        strong_magnitude_scaled, weak_magnitude_scaled);

  if (effect_id_ != kInvalidEffectId)
    StartOrStopEffect(evdev_fd_, effect_id_, true);
}

void GamepadDeviceLinux::SetZeroVibration() {
  DCHECK(polling_runner_->RunsTasksInCurrentSequence());
  if (dualshock4_) {
    dualshock4_->SetZeroVibration();
    return;
  }

  if (hid_haptics_) {
    hid_haptics_->SetZeroVibration();
    return;
  }

  if (effect_id_ != kInvalidEffectId)
    StartOrStopEffect(evdev_fd_, effect_id_, false);
}

}  // namespace device
