// 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 "raw_input_gamepad_device_win.h"

// NOTE: <hidsdi.h> must be included before <hidpi.h>. clang-format will want to
// reorder them.
// clang-format off
extern "C" {
#include <hidsdi.h>
#include <hidpi.h>
}
// clang-format on

#include "base/stl_util.h"
#include "base/strings/string_util_win.h"
#include "base/strings/sys_string_conversions.h"
#include "device/gamepad/dualshock4_controller.h"
#include "device/gamepad/gamepad_blocklist.h"
#include "device/gamepad/gamepad_data_fetcher.h"
#include "device/gamepad/hid_haptic_gamepad.h"
#include "device/gamepad/hid_writer_win.h"

namespace device {

namespace {

float NormalizeAxis(long value, long min, long max) {
  return (2.f * (value - min) / static_cast<float>(max - min)) - 1.f;
}

unsigned long GetBitmask(unsigned short bits) {
  return (1 << bits) - 1;
}

const uint32_t kGenericDesktopUsagePage = 0x01;
const uint32_t kGameControlsUsagePage = 0x05;
const uint32_t kButtonUsagePage = 0x09;
const uint32_t kConsumerUsagePage = 0x0c;

const uint32_t kAxisMinimumUsageNumber = 0x30;
const uint32_t kSystemMainMenuUsageNumber = 0x85;
const uint32_t kPowerUsageNumber = 0x30;
const uint32_t kSearchUsageNumber = 0x0221;
const uint32_t kHomeUsageNumber = 0x0223;
const uint32_t kBackUsageNumber = 0x0224;

// The fetcher will collect all HID usages from the Button usage page and any
// additional usages listed below.
struct SpecialUsages {
  const uint16_t usage_page;
  const uint16_t usage;
} kSpecialUsages[] = {
    // Xbox One S pre-FW update reports Xbox button as SystemMainMenu over BT.
    {kGenericDesktopUsagePage, kSystemMainMenuUsageNumber},
    // Power is used for the Guide button on the Nvidia Shield 2015 gamepad.
    {kConsumerUsagePage, kPowerUsageNumber},
    // Search is used for the Guide button on the Nvidia Shield 2017 gamepad.
    {kConsumerUsagePage, kSearchUsageNumber},
    // Start, Back, and Guide buttons are often reported as Consumer Home or
    // Back.
    {kConsumerUsagePage, kHomeUsageNumber},
    {kConsumerUsagePage, kBackUsageNumber},
};
const size_t kSpecialUsagesLen = base::size(kSpecialUsages);

}  // namespace

RawInputGamepadDeviceWin::RawInputGamepadDeviceWin(HANDLE device_handle,
                                                   int source_id)
    : handle_(device_handle),
      source_id_(source_id),
      last_update_timestamp_(GamepadDataFetcher::CurrentTimeInMicroseconds()) {
  ::ZeroMemory(buttons_, sizeof(buttons_));
  ::ZeroMemory(axes_, sizeof(axes_));

  is_valid_ = QueryDeviceInfo();
  if (!is_valid_)
    return;

  const std::string product_name = base::SysWideToUTF8(product_string_);
  const GamepadId gamepad_id =
      GamepadIdList::Get().GetGamepadId(product_name, vendor_id_, product_id_);
  if (Dualshock4Controller::IsDualshock4(gamepad_id)) {
    // Dualshock4 has different behavior over USB and Bluetooth, but the
    // RawInput API does not indicate which transport is in use. Detect the
    // transport type by inspecting the version number reported by the device.
    GamepadBusType bus_type =
        Dualshock4Controller::BusTypeFromVersionNumber(version_number_);
    dualshock4_ = std::make_unique<Dualshock4Controller>(
        gamepad_id, bus_type, std::make_unique<HidWriterWin>(handle_));
  } else if (HidHapticGamepad::IsHidHaptic(vendor_id_, product_id_)) {
    hid_haptics_ = HidHapticGamepad::Create(
        vendor_id_, product_id_, std::make_unique<HidWriterWin>(handle_));
  }
}

RawInputGamepadDeviceWin::~RawInputGamepadDeviceWin() = default;

// static
bool RawInputGamepadDeviceWin::IsGamepadUsageId(uint16_t usage) {
  return usage == kGenericDesktopJoystick || usage == kGenericDesktopGamePad ||
         usage == kGenericDesktopMultiAxisController;
}

void RawInputGamepadDeviceWin::DoShutdown() {
  if (dualshock4_)
    dualshock4_->Shutdown();
  dualshock4_.reset();
  if (hid_haptics_)
    hid_haptics_->Shutdown();
  hid_haptics_.reset();
}

void RawInputGamepadDeviceWin::UpdateGamepad(RAWINPUT* input) {
  NTSTATUS status;

  if (dualshock4_) {
    // Handle Dualshock4 input reports that do not specify HID gamepad usages in
    // the report descriptor.
    uint8_t report_id = input->data.hid.bRawData[0];
    auto report = base::make_span(input->data.hid.bRawData + 1,
                                  input->data.hid.dwSizeHid);
    Gamepad pad;
    if (dualshock4_->ProcessInputReport(report_id, report, &pad)) {
      for (size_t i = 0; i < Gamepad::kAxesLengthCap; ++i)
        axes_[i].value = pad.axes[i];
      for (size_t i = 0; i < Gamepad::kButtonsLengthCap; ++i)
        buttons_[i] = pad.buttons[i].pressed;
      last_update_timestamp_ = GamepadDataFetcher::CurrentTimeInMicroseconds();
      return;
    }
  }

  // Query button state.
  if (buttons_length_ > 0) {
    // Clear the button state
    ::ZeroMemory(buttons_, sizeof(buttons_));
    ULONG buttons_length = 0;

    HidP_GetUsagesEx(HidP_Input, 0, nullptr, &buttons_length, preparsed_data_,
                     reinterpret_cast<PCHAR>(input->data.hid.bRawData),
                     input->data.hid.dwSizeHid);

    std::unique_ptr<USAGE_AND_PAGE[]> usages(
        new USAGE_AND_PAGE[buttons_length]);
    status = HidP_GetUsagesEx(HidP_Input, 0, usages.get(), &buttons_length,
                              preparsed_data_,
                              reinterpret_cast<PCHAR>(input->data.hid.bRawData),
                              input->data.hid.dwSizeHid);

    if (status == HIDP_STATUS_SUCCESS) {
      // Set each reported button to true.
      for (size_t j = 0; j < buttons_length; j++) {
        uint16_t usage_page = usages[j].UsagePage;
        uint16_t usage = usages[j].Usage;
        if (usage_page == kButtonUsagePage && usage > 0) {
          size_t button_index = size_t{usage - 1};
          if (button_index < Gamepad::kButtonsLengthCap)
            buttons_[button_index] = true;
        } else if (usage_page != kButtonUsagePage &&
                   !special_button_map_.empty()) {
          for (size_t special_index = 0; special_index < kSpecialUsagesLen;
               ++special_index) {
            int button_index = special_button_map_[special_index];
            if (button_index < 0)
              continue;
            const auto& special = kSpecialUsages[special_index];
            if (usage_page == special.usage_page && usage == special.usage)
              buttons_[button_index] = true;
          }
        }
      }
    }
  }

  // Query axis state.
  ULONG axis_value = 0;
  LONG scaled_axis_value = 0;
  for (uint32_t i = 0; i < axes_length_; i++) {
    RawGamepadAxis* axis = &axes_[i];

    // If the min is < 0 we have to query the scaled value, otherwise we need
    // the normal unscaled value.
    if (axis->caps.LogicalMin < 0) {
      status = HidP_GetScaledUsageValue(
          HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin,
          &scaled_axis_value, preparsed_data_,
          reinterpret_cast<PCHAR>(input->data.hid.bRawData),
          input->data.hid.dwSizeHid);
      if (status == HIDP_STATUS_SUCCESS) {
        axis->value = NormalizeAxis(scaled_axis_value, axis->caps.PhysicalMin,
                                    axis->caps.PhysicalMax);
      }
    } else {
      status = HidP_GetUsageValue(
          HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin,
          &axis_value, preparsed_data_,
          reinterpret_cast<PCHAR>(input->data.hid.bRawData),
          input->data.hid.dwSizeHid);
      if (status == HIDP_STATUS_SUCCESS) {
        axis->value = NormalizeAxis(axis_value & axis->bitmask,
                                    axis->caps.LogicalMin & axis->bitmask,
                                    axis->caps.LogicalMax & axis->bitmask);
      }
    }
  }

  last_update_timestamp_ = GamepadDataFetcher::CurrentTimeInMicroseconds();
}

void RawInputGamepadDeviceWin::ReadPadState(Gamepad* pad) const {
  DCHECK(pad);

  pad->timestamp = last_update_timestamp_;
  pad->buttons_length = buttons_length_;
  pad->axes_length = axes_length_;
  pad->axes_used = axes_used_;

  for (unsigned int i = 0; i < buttons_length_; i++) {
    pad->buttons[i].used = button_indices_used_[i];
    pad->buttons[i].pressed = buttons_[i];
    pad->buttons[i].value = buttons_[i] ? 1.0 : 0.0;
  }

  for (unsigned int i = 0; i < axes_length_; i++)
    pad->axes[i] = axes_[i].value;
}

bool RawInputGamepadDeviceWin::SupportsVibration() const {
  return dualshock4_ || hid_haptics_;
}

void RawInputGamepadDeviceWin::SetVibration(double strong_magnitude,
                                            double weak_magnitude) {
  if (dualshock4_)
    dualshock4_->SetVibration(strong_magnitude, weak_magnitude);
  else if (hid_haptics_)
    hid_haptics_->SetVibration(strong_magnitude, weak_magnitude);
}

bool RawInputGamepadDeviceWin::QueryDeviceInfo() {
  // Fetch HID properties (RID_DEVICE_INFO_HID) for this device. This includes
  // |vendor_id_|, |product_id_|, |version_number_|, and |usage_|.
  if (!QueryHidInfo())
    return false;

  // Make sure this device is of a type that we want to observe.
  if (!IsGamepadUsageId(usage_))
    return false;

  // Filter out devices that have gamepad-like HID usages but aren't gamepads.
  if (GamepadIsExcluded(vendor_id_, product_id_))
    return false;

  // Fetch the device's |name_| (RIDI_DEVICENAME).
  if (!QueryDeviceName())
    return false;

  // From the name we can guess at the bus type. PCI HID devices have "VEN" and
  // "DEV" instead of "VID" and "PID". PCI HID devices are typically not
  // gamepads and are ignored.
  // Example PCI device name: \\?\HID#VEN_1234&DEV_ABCD
  // TODO(crbug/881539): Potentially allow PCI HID devices to be enumerated, but
  // prefer known gamepads when there is contention.
  std::wstring pci_prefix = L"\\\\?\\HID#VEN_";
  if (!name_.compare(0, pci_prefix.size(), pci_prefix))
    return false;

  // Filter out the virtual digitizer, which was observed after remote desktop.
  // See https://crbug.com/961774 for details.
  if (name_ == L"\\\\?\\VIRTUAL_DIGITIZER")
    return false;

  // We can now use the name to query the OS for a file handle that is used to
  // read the product string from the device. If the OS does not return a valid
  // handle this gamepad is invalid.
  auto hid_handle = OpenHidHandle();
  if (!hid_handle.IsValid())
    return false;

  // Fetch the human-friendly |product_string_|, if available.
  if (!QueryProductString(hid_handle))
    product_string_ = L"Unknown Gamepad";

  // Fetch information about the buttons and axes on this device. This sets
  // |buttons_length_| and |axes_length_| to their correct values and populates
  // |axes_| with capabilities info.
  if (!QueryDeviceCapabilities())
    return false;

  // Gamepads must have at least one button or axis.
  if (buttons_length_ == 0 && axes_length_ == 0)
    return false;

  return true;
}

bool RawInputGamepadDeviceWin::QueryHidInfo() {
  UINT size = 0;

  UINT result =
      ::GetRawInputDeviceInfo(handle_, RIDI_DEVICEINFO, nullptr, &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(0u, result);

  std::unique_ptr<uint8_t[]> buffer(new uint8_t[size]);
  result =
      ::GetRawInputDeviceInfo(handle_, RIDI_DEVICEINFO, buffer.get(), &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(size, result);
  RID_DEVICE_INFO* device_info =
      reinterpret_cast<RID_DEVICE_INFO*>(buffer.get());

  DCHECK_EQ(device_info->dwType, static_cast<DWORD>(RIM_TYPEHID));
  vendor_id_ = static_cast<uint16_t>(device_info->hid.dwVendorId);
  product_id_ = static_cast<uint16_t>(device_info->hid.dwProductId);
  version_number_ = static_cast<uint16_t>(device_info->hid.dwVersionNumber);
  usage_ = device_info->hid.usUsage;

  return true;
}

bool RawInputGamepadDeviceWin::QueryDeviceName() {
  UINT size = 0;

  UINT result =
      ::GetRawInputDeviceInfo(handle_, RIDI_DEVICENAME, nullptr, &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(0u, result);

  std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]);
  result =
      ::GetRawInputDeviceInfo(handle_, RIDI_DEVICENAME, buffer.get(), &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(size, result);

  name_ = buffer.get();

  return true;
}

bool RawInputGamepadDeviceWin::QueryProductString(
    base::win::ScopedHandle& hid_handle) {
  DCHECK(hid_handle.IsValid());
  // HidD_GetProductString may return successfully even if it didn't write to
  // the buffer. Ensure the buffer is zeroed before calling
  // HidD_GetProductString. See https://crbug.com/1205511.
  std::wstring buffer;
  if (!HidD_GetProductString(hid_handle.Get(),
                             base::WriteInto(&buffer, Gamepad::kIdLengthCap),
                             Gamepad::kIdLengthCap)) {
    return false;
  }

  // Remove trailing NUL characters.
  buffer = std::wstring(base::TrimString(buffer, base::WStringPiece(L"\0", 1),
                                         base::TRIM_TRAILING));

  // The product string cannot be empty.
  if (buffer.empty())
    return false;

  product_string_ = std::move(buffer);
  return true;
}

base::win::ScopedHandle RawInputGamepadDeviceWin::OpenHidHandle() {
  return base::win::ScopedHandle(::CreateFile(
      name_.c_str(), GENERIC_READ | GENERIC_WRITE,
      FILE_SHARE_READ | FILE_SHARE_WRITE, /*lpSecurityAttributes=*/nullptr,
      OPEN_EXISTING, /*dwFlagsAndAttributes=*/0, /*hTemplateFile=*/nullptr));
}

bool RawInputGamepadDeviceWin::QueryDeviceCapabilities() {
  UINT size = 0;

  UINT result =
      ::GetRawInputDeviceInfo(handle_, RIDI_PREPARSEDDATA, nullptr, &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(0u, result);

  ppd_buffer_.reset(new uint8_t[size]);
  preparsed_data_ = reinterpret_cast<PHIDP_PREPARSED_DATA>(ppd_buffer_.get());
  result = ::GetRawInputDeviceInfo(handle_, RIDI_PREPARSEDDATA,
                                   ppd_buffer_.get(), &size);
  if (result == static_cast<UINT>(-1)) {
    PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
    return false;
  }
  DCHECK_EQ(size, result);

  HIDP_CAPS caps;
  NTSTATUS status = HidP_GetCaps(preparsed_data_, &caps);
  DCHECK_EQ(HIDP_STATUS_SUCCESS, status);

  QueryButtonCapabilities(caps.NumberInputButtonCaps);
  QueryAxisCapabilities(caps.NumberInputValueCaps);

  return true;
}

void RawInputGamepadDeviceWin::QueryButtonCapabilities(uint16_t button_count) {
  if (button_count > 0) {
    std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps(
        new HIDP_BUTTON_CAPS[button_count]);
    NTSTATUS status = HidP_GetButtonCaps(HidP_Input, button_caps.get(),
                                         &button_count, preparsed_data_);
    DCHECK_EQ(HIDP_STATUS_SUCCESS, status);

    // Collect all inputs from the Button usage page.
    QueryNormalButtonCapabilities(button_caps.get(), button_count);

    // Check for common gamepad buttons that are not on the Button usage page.
    QuerySpecialButtonCapabilities(button_caps.get(), button_count);
  }
}

void RawInputGamepadDeviceWin::QueryNormalButtonCapabilities(
    HIDP_BUTTON_CAPS button_caps[],
    uint16_t button_count) {
  DCHECK(button_caps);

  // Collect all inputs from the Button usage page and assign button indices
  // based on the usage value.
  for (size_t i = 0; i < button_count; ++i) {
    uint16_t usage_page = button_caps[i].UsagePage;
    uint16_t usage_min = button_caps[i].Range.UsageMin;
    uint16_t usage_max = button_caps[i].Range.UsageMax;
    if (usage_min == 0 || usage_max == 0)
      continue;
    size_t button_index_min = size_t{usage_min - 1};
    size_t button_index_max = size_t{usage_max - 1};
    if (usage_page == kButtonUsagePage &&
        button_index_min < Gamepad::kButtonsLengthCap) {
      button_index_max =
          std::min(Gamepad::kButtonsLengthCap - 1, button_index_max);
      buttons_length_ = std::max(buttons_length_, button_index_max + 1);
      for (size_t j = button_index_min; j <= button_index_max; ++j)
        button_indices_used_[j] = true;
    }
  }
}

void RawInputGamepadDeviceWin::QuerySpecialButtonCapabilities(
    HIDP_BUTTON_CAPS button_caps[],
    uint16_t button_count) {
  DCHECK(button_caps);

  // Check for common gamepad buttons that are not on the Button usage page.
  std::vector<bool> has_special_usage(kSpecialUsagesLen, false);
  size_t unmapped_button_count = 0;
  for (size_t i = 0; i < button_count; ++i) {
    uint16_t usage_page = button_caps[i].UsagePage;
    uint16_t usage_min = button_caps[i].Range.UsageMin;
    uint16_t usage_max = button_caps[i].Range.UsageMax;
    for (size_t special_index = 0; special_index < kSpecialUsagesLen;
         ++special_index) {
      const auto& special = kSpecialUsages[special_index];
      if (usage_page == special.usage_page && usage_min <= special.usage &&
          usage_max >= special.usage) {
        has_special_usage[special_index] = true;
        ++unmapped_button_count;
      }
    }
  }

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

      // Advance to the next unused button index.
      while (button_index < Gamepad::kButtonsLengthCap &&
             button_indices_used_[button_index]) {
        ++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;
    }
    buttons_length_ = std::max(buttons_length_, button_index);
  }
}

void RawInputGamepadDeviceWin::QueryAxisCapabilities(uint16_t axis_count) {
  std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[axis_count]);
  HidP_GetValueCaps(HidP_Input, axes_caps.get(), &axis_count, preparsed_data_);

  bool mapped_all_axes = true;

  for (size_t i = 0; i < axis_count; i++) {
    size_t axis_index = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber;
    if (axis_index < Gamepad::kAxesLengthCap && !axes_[axis_index].active) {
      axes_[axis_index].caps = axes_caps[i];
      axes_[axis_index].value = 0;
      axes_[axis_index].active = true;
      axes_[axis_index].bitmask = GetBitmask(axes_caps[i].BitSize);
      axes_length_ = std::max(axes_length_, axis_index + 1);
      axes_used_ |= 1 << axis_index;
    } else {
      mapped_all_axes = false;
    }
  }

  if (!mapped_all_axes) {
    // For axes whose usage puts them outside the standard axesLengthCap range.
    size_t next_index = 0;
    for (size_t i = 0; i < axis_count; i++) {
      size_t usage = axes_caps[i].Range.UsageMin - kAxisMinimumUsageNumber;
      if (usage >= Gamepad::kAxesLengthCap &&
          axes_caps[i].UsagePage <= kGameControlsUsagePage) {
        for (; next_index < Gamepad::kAxesLengthCap; ++next_index) {
          if (!axes_[next_index].active)
            break;
        }
        if (next_index < Gamepad::kAxesLengthCap) {
          axes_[next_index].caps = axes_caps[i];
          axes_[next_index].value = 0;
          axes_[next_index].active = true;
          axes_[next_index].bitmask = GetBitmask(axes_caps[i].BitSize);
          axes_length_ = std::max(axes_length_, next_index + 1);
          axes_used_ |= 1 << next_index;
        }
      }

      if (next_index >= Gamepad::kAxesLengthCap)
        break;
    }
  }
}

base::WeakPtr<AbstractHapticGamepad> RawInputGamepadDeviceWin::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

}  // namespace device
