Commit c712ffa4 authored by Matt Reynolds's avatar Matt Reynolds Committed by Commit Bot

Remove DLL management from RawInputDataFetcher

RawInputDataFetcher uses methods from hid.dll to enumerate and fetch
gamepad state for RawInput devices. The DLL is loaded as needed and
a handle is retained by the data fetcher.

This CL moves the DLL management logic and function pointers to a
separate object that can be shared between the data fetcher and
other classes.

BUG=749295

Change-Id: Ifbdf1d67a4577e91806e3e7ee5ee6e4cae621691
Reviewed-on: https://chromium-review.googlesource.com/871845
Commit-Queue: Matt Reynolds <mattreynolds@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Cr-Commit-Position: refs/heads/master@{#530311}
parent df9acf92
...@@ -60,6 +60,8 @@ component("gamepad") { ...@@ -60,6 +60,8 @@ component("gamepad") {
"gamepad_standard_mappings_win.cc", "gamepad_standard_mappings_win.cc",
"gamepad_user_gesture.cc", "gamepad_user_gesture.cc",
"gamepad_user_gesture.h", "gamepad_user_gesture.h",
"hid_dll_functions_win.cc",
"hid_dll_functions_win.h",
"raw_input_data_fetcher_win.cc", "raw_input_data_fetcher_win.cc",
"raw_input_data_fetcher_win.h", "raw_input_data_fetcher_win.h",
"udev_gamepad_linux.cc", "udev_gamepad_linux.cc",
......
// 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/hid_dll_functions_win.h"
#include "base/files/file_path.h"
namespace device {
HidDllFunctionsWin::HidDllFunctionsWin()
: hid_dll_(
base::LoadNativeLibrary(base::FilePath(FILE_PATH_LITERAL("hid.dll")),
nullptr)) {
if (hid_dll_.is_valid()) {
hidp_get_caps_ = reinterpret_cast<HidPGetCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetCaps"));
hidp_get_button_caps_ = reinterpret_cast<HidPGetButtonCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetButtonCaps"));
hidp_get_value_caps_ = reinterpret_cast<HidPGetValueCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetValueCaps"));
hidp_get_usages_ex_ = reinterpret_cast<HidPGetUsagesExFunc>(
hid_dll_.GetFunctionPointer("HidP_GetUsagesEx"));
hidp_get_usage_value_ = reinterpret_cast<HidPGetUsageValueFunc>(
hid_dll_.GetFunctionPointer("HidP_GetUsageValue"));
hidp_get_scaled_usage_value_ =
reinterpret_cast<HidPGetScaledUsageValueFunc>(
hid_dll_.GetFunctionPointer("HidP_GetScaledUsageValue"));
hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>(
hid_dll_.GetFunctionPointer("HidD_GetProductString"));
}
is_valid_ = hidp_get_caps_ != nullptr && hidp_get_button_caps_ != nullptr &&
hidp_get_value_caps_ != nullptr &&
hidp_get_usages_ex_ != nullptr &&
hidp_get_usage_value_ != nullptr &&
hidp_get_scaled_usage_value_ != nullptr &&
hidd_get_product_string_ != nullptr;
}
} // namespace device
// 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.
#ifndef DEVICE_GAMEPAD_HID_DLL_FUNCTIONS_WIN_
#define DEVICE_GAMEPAD_HID_DLL_FUNCTIONS_WIN_
#include <Unknwn.h>
#include <WinDef.h>
#include <hidsdi.h>
#include <stdint.h>
#include <stdlib.h>
#include <windows.h>
#include "base/scoped_native_library.h"
namespace device {
// Function types we use from hid.dll.
typedef NTSTATUS(__stdcall* HidPGetCapsFunc)(PHIDP_PREPARSED_DATA PreparsedData,
PHIDP_CAPS Capabilities);
typedef NTSTATUS(__stdcall* HidPGetButtonCapsFunc)(
HIDP_REPORT_TYPE ReportType,
PHIDP_BUTTON_CAPS ButtonCaps,
PUSHORT ButtonCapsLength,
PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* HidPGetValueCapsFunc)(
HIDP_REPORT_TYPE ReportType,
PHIDP_VALUE_CAPS ValueCaps,
PUSHORT ValueCapsLength,
PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* HidPGetUsagesExFunc)(
HIDP_REPORT_TYPE ReportType,
USHORT LinkCollection,
PUSAGE_AND_PAGE ButtonList,
ULONG* UsageLength,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef NTSTATUS(__stdcall* HidPGetUsageValueFunc)(
HIDP_REPORT_TYPE ReportType,
USAGE UsagePage,
USHORT LinkCollection,
USAGE Usage,
PULONG UsageValue,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef NTSTATUS(__stdcall* HidPGetScaledUsageValueFunc)(
HIDP_REPORT_TYPE ReportType,
USAGE UsagePage,
USHORT LinkCollection,
USAGE Usage,
PLONG UsageValue,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef BOOLEAN(__stdcall* HidDGetStringFunc)(HANDLE HidDeviceObject,
PVOID Buffer,
ULONG BufferLength);
// Loads hid.dll and provides access to HID methods needed for enumeration and
// polling of RawInput devices on Windows.
class HidDllFunctionsWin {
public:
HidDllFunctionsWin();
~HidDllFunctionsWin() = default;
// Return true if the hid.dll functions were successfully loaded.
bool IsValid() const { return is_valid_; }
// Getters for each hid.dll function.
HidPGetCapsFunc HidPGetCaps() const { return hidp_get_caps_; }
HidPGetButtonCapsFunc HidPGetButtonCaps() const {
return hidp_get_button_caps_;
}
HidPGetValueCapsFunc HidPGetValueCaps() const { return hidp_get_value_caps_; }
HidPGetUsagesExFunc HidPGetUsagesEx() const { return hidp_get_usages_ex_; }
HidPGetUsageValueFunc HidPGetUsageValue() const {
return hidp_get_usage_value_;
}
HidPGetScaledUsageValueFunc HidPGetScaledUsageValue() const {
return hidp_get_scaled_usage_value_;
}
HidDGetStringFunc HidDGetProductString() const {
return hidd_get_product_string_;
}
private:
bool is_valid_;
base::ScopedNativeLibrary hid_dll_;
HidPGetCapsFunc hidp_get_caps_ = nullptr;
HidPGetButtonCapsFunc hidp_get_button_caps_ = nullptr;
HidPGetValueCapsFunc hidp_get_value_caps_ = nullptr;
HidPGetUsagesExFunc hidp_get_usages_ex_ = nullptr;
HidPGetUsageValueFunc hidp_get_usage_value_ = nullptr;
HidPGetScaledUsageValueFunc hidp_get_scaled_usage_value_ = nullptr;
HidDGetStringFunc hidd_get_product_string_ = nullptr;
};
} // namespace device
#endif // DEVICE_GAMEPAD_HID_DLL_FUNCTIONS_WIN_
...@@ -61,9 +61,8 @@ GamepadSource RawInputDataFetcher::source() { ...@@ -61,9 +61,8 @@ GamepadSource RawInputDataFetcher::source() {
} }
void RawInputDataFetcher::OnAddedToProvider() { void RawInputDataFetcher::OnAddedToProvider() {
hid_dll_.Reset(base::LoadNativeLibrary( hid_functions_ = std::make_unique<HidDllFunctionsWin>();
base::FilePath(FILE_PATH_LITERAL("hid.dll")), nullptr)); rawinput_available_ = hid_functions_->IsValid();
rawinput_available_ = GetHidDllFunctions();
} }
RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) { RAWINPUTDEVICE* RawInputDataFetcher::GetRawInputDevices(DWORD flags) {
...@@ -247,6 +246,8 @@ void RawInputDataFetcher::EnumerateDevices() { ...@@ -247,6 +246,8 @@ void RawInputDataFetcher::EnumerateDevices() {
} }
RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
DCHECK(hid_functions_);
DCHECK(hid_functions_->IsValid());
UINT size = 0; UINT size = 0;
// Query basic device info. // Query basic device info.
...@@ -329,8 +330,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { ...@@ -329,8 +330,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
name_buffer.get(), GENERIC_READ | GENERIC_WRITE, name_buffer.get(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hid_handle) { if (hid_handle) {
got_product_string = hidd_get_product_string_(hid_handle, gamepad_info->id, got_product_string = hid_functions_->HidDGetProductString()(
sizeof(gamepad_info->id)); hid_handle, gamepad_info->id, sizeof(gamepad_info->id));
CloseHandle(hid_handle); CloseHandle(hid_handle);
} }
...@@ -357,7 +358,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { ...@@ -357,7 +358,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
DCHECK_EQ(size, result); DCHECK_EQ(size, result);
HIDP_CAPS caps; HIDP_CAPS caps;
NTSTATUS status = hidp_get_caps_(gamepad_info->preparsed_data, &caps); NTSTATUS status =
hid_functions_->HidPGetCaps()(gamepad_info->preparsed_data, &caps);
DCHECK_EQ(HIDP_STATUS_SUCCESS, status); DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
// Query button information. // Query button information.
...@@ -365,8 +367,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { ...@@ -365,8 +367,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
if (count > 0) { if (count > 0) {
std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps( std::unique_ptr<HIDP_BUTTON_CAPS[]> button_caps(
new HIDP_BUTTON_CAPS[count]); new HIDP_BUTTON_CAPS[count]);
status = hidp_get_button_caps_(HidP_Input, button_caps.get(), &count, status = hid_functions_->HidPGetButtonCaps()(
gamepad_info->preparsed_data); HidP_Input, button_caps.get(), &count, gamepad_info->preparsed_data);
DCHECK_EQ(HIDP_STATUS_SUCCESS, status); DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
for (uint32_t i = 0; i < count; ++i) { for (uint32_t i = 0; i < count; ++i) {
...@@ -384,8 +386,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { ...@@ -384,8 +386,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
// Query axis information. // Query axis information.
count = caps.NumberInputValueCaps; count = caps.NumberInputValueCaps;
std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]); std::unique_ptr<HIDP_VALUE_CAPS[]> axes_caps(new HIDP_VALUE_CAPS[count]);
status = hidp_get_value_caps_(HidP_Input, axes_caps.get(), &count, status = hid_functions_->HidPGetValueCaps()(
gamepad_info->preparsed_data); HidP_Input, axes_caps.get(), &count, gamepad_info->preparsed_data);
bool mapped_all_axes = true; bool mapped_all_axes = true;
...@@ -439,6 +441,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) { ...@@ -439,6 +441,8 @@ RawGamepadInfo* RawInputDataFetcher::ParseGamepadInfo(HANDLE hDevice) {
void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input,
RawGamepadInfo* gamepad_info) { RawGamepadInfo* gamepad_info) {
DCHECK(hid_functions_);
DCHECK(hid_functions_->IsValid());
NTSTATUS status; NTSTATUS status;
gamepad_info->report_id++; gamepad_info->report_id++;
...@@ -449,18 +453,18 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, ...@@ -449,18 +453,18 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input,
ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons)); ZeroMemory(gamepad_info->buttons, sizeof(gamepad_info->buttons));
ULONG buttons_length = 0; ULONG buttons_length = 0;
hidp_get_usages_ex_(HidP_Input, 0, NULL, &buttons_length, hid_functions_->HidPGetUsagesEx()(
gamepad_info->preparsed_data, HidP_Input, 0, NULL, &buttons_length, gamepad_info->preparsed_data,
reinterpret_cast<PCHAR>(input->data.hid.bRawData), reinterpret_cast<PCHAR>(input->data.hid.bRawData),
input->data.hid.dwSizeHid); input->data.hid.dwSizeHid);
std::unique_ptr<USAGE_AND_PAGE[]> usages( std::unique_ptr<USAGE_AND_PAGE[]> usages(
new USAGE_AND_PAGE[buttons_length]); new USAGE_AND_PAGE[buttons_length]);
status = status = hid_functions_->HidPGetUsagesEx()(
hidp_get_usages_ex_(HidP_Input, 0, usages.get(), &buttons_length, HidP_Input, 0, usages.get(), &buttons_length,
gamepad_info->preparsed_data, gamepad_info->preparsed_data,
reinterpret_cast<PCHAR>(input->data.hid.bRawData), reinterpret_cast<PCHAR>(input->data.hid.bRawData),
input->data.hid.dwSizeHid); input->data.hid.dwSizeHid);
if (status == HIDP_STATUS_SUCCESS) { if (status == HIDP_STATUS_SUCCESS) {
// Set each reported button to true. // Set each reported button to true.
...@@ -483,7 +487,7 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, ...@@ -483,7 +487,7 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input,
// If the min is < 0 we have to query the scaled value, otherwise we need // If the min is < 0 we have to query the scaled value, otherwise we need
// the normal unscaled value. // the normal unscaled value.
if (axis->caps.LogicalMin < 0) { if (axis->caps.LogicalMin < 0) {
status = hidp_get_scaled_usage_value_( status = hid_functions_->HidPGetScaledUsageValue()(
HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin,
&scaled_axis_value, gamepad_info->preparsed_data, &scaled_axis_value, gamepad_info->preparsed_data,
reinterpret_cast<PCHAR>(input->data.hid.bRawData), reinterpret_cast<PCHAR>(input->data.hid.bRawData),
...@@ -493,7 +497,7 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input, ...@@ -493,7 +497,7 @@ void RawInputDataFetcher::UpdateGamepad(RAWINPUT* input,
axis->caps.PhysicalMax); axis->caps.PhysicalMax);
} }
} else { } else {
status = hidp_get_usage_value_( status = hid_functions_->HidPGetUsageValue()(
HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin, HidP_Input, axis->caps.UsagePage, 0, axis->caps.Range.UsageMin,
&axis_value, gamepad_info->preparsed_data, &axis_value, gamepad_info->preparsed_data,
reinterpret_cast<PCHAR>(input->data.hid.bRawData), reinterpret_cast<PCHAR>(input->data.hid.bRawData),
...@@ -553,48 +557,4 @@ bool RawInputDataFetcher::HandleMessage(UINT message, ...@@ -553,48 +557,4 @@ bool RawInputDataFetcher::HandleMessage(UINT message,
} }
} }
bool RawInputDataFetcher::GetHidDllFunctions() {
hidp_get_caps_ = NULL;
hidp_get_button_caps_ = NULL;
hidp_get_value_caps_ = NULL;
hidp_get_usages_ex_ = NULL;
hidp_get_usage_value_ = NULL;
hidp_get_scaled_usage_value_ = NULL;
hidd_get_product_string_ = NULL;
if (!hid_dll_.is_valid())
return false;
hidp_get_caps_ = reinterpret_cast<HidPGetCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetCaps"));
if (!hidp_get_caps_)
return false;
hidp_get_button_caps_ = reinterpret_cast<HidPGetButtonCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetButtonCaps"));
if (!hidp_get_button_caps_)
return false;
hidp_get_value_caps_ = reinterpret_cast<HidPGetValueCapsFunc>(
hid_dll_.GetFunctionPointer("HidP_GetValueCaps"));
if (!hidp_get_value_caps_)
return false;
hidp_get_usages_ex_ = reinterpret_cast<HidPGetUsagesExFunc>(
hid_dll_.GetFunctionPointer("HidP_GetUsagesEx"));
if (!hidp_get_usages_ex_)
return false;
hidp_get_usage_value_ = reinterpret_cast<HidPGetUsageValueFunc>(
hid_dll_.GetFunctionPointer("HidP_GetUsageValue"));
if (!hidp_get_usage_value_)
return false;
hidp_get_scaled_usage_value_ = reinterpret_cast<HidPGetScaledUsageValueFunc>(
hid_dll_.GetFunctionPointer("HidP_GetScaledUsageValue"));
if (!hidp_get_scaled_usage_value_)
return false;
hidd_get_product_string_ = reinterpret_cast<HidDGetStringFunc>(
hid_dll_.GetFunctionPointer("HidD_GetProductString"));
if (!hidd_get_product_string_)
return false;
return true;
}
} // namespace device } // namespace device
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "device/gamepad/gamepad_data_fetcher.h" #include "device/gamepad/gamepad_data_fetcher.h"
#include "device/gamepad/gamepad_standard_mappings.h" #include "device/gamepad/gamepad_standard_mappings.h"
#include "device/gamepad/hid_dll_functions_win.h"
#include "device/gamepad/public/cpp/gamepad.h" #include "device/gamepad/public/cpp/gamepad.h"
namespace device { namespace device {
...@@ -91,55 +92,6 @@ class RawInputDataFetcher : public GamepadDataFetcher, ...@@ -91,55 +92,6 @@ class RawInputDataFetcher : public GamepadDataFetcher,
RAWINPUTDEVICE* GetRawInputDevices(DWORD flags); RAWINPUTDEVICE* GetRawInputDevices(DWORD flags);
void ClearControllers(); void ClearControllers();
// Function types we use from hid.dll.
typedef NTSTATUS(__stdcall* HidPGetCapsFunc)(
PHIDP_PREPARSED_DATA PreparsedData,
PHIDP_CAPS Capabilities);
typedef NTSTATUS(__stdcall* HidPGetButtonCapsFunc)(
HIDP_REPORT_TYPE ReportType,
PHIDP_BUTTON_CAPS ButtonCaps,
PUSHORT ButtonCapsLength,
PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* HidPGetValueCapsFunc)(
HIDP_REPORT_TYPE ReportType,
PHIDP_VALUE_CAPS ValueCaps,
PUSHORT ValueCapsLength,
PHIDP_PREPARSED_DATA PreparsedData);
typedef NTSTATUS(__stdcall* HidPGetUsagesExFunc)(
HIDP_REPORT_TYPE ReportType,
USHORT LinkCollection,
PUSAGE_AND_PAGE ButtonList,
ULONG* UsageLength,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef NTSTATUS(__stdcall* HidPGetUsageValueFunc)(
HIDP_REPORT_TYPE ReportType,
USAGE UsagePage,
USHORT LinkCollection,
USAGE Usage,
PULONG UsageValue,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef NTSTATUS(__stdcall* HidPGetScaledUsageValueFunc)(
HIDP_REPORT_TYPE ReportType,
USAGE UsagePage,
USHORT LinkCollection,
USAGE Usage,
PLONG UsageValue,
PHIDP_PREPARSED_DATA PreparsedData,
PCHAR Report,
ULONG ReportLength);
typedef BOOLEAN(__stdcall* HidDGetStringFunc)(HANDLE HidDeviceObject,
PVOID Buffer,
ULONG BufferLength);
// Get functions from dynamically loaded hid.dll. Returns true if loading was
// successful.
bool GetHidDllFunctions();
base::ScopedNativeLibrary hid_dll_;
std::unique_ptr<base::win::MessageWindow> window_; std::unique_ptr<base::win::MessageWindow> window_;
bool rawinput_available_; bool rawinput_available_;
bool filter_xinput_; bool filter_xinput_;
...@@ -150,15 +102,8 @@ class RawInputDataFetcher : public GamepadDataFetcher, ...@@ -150,15 +102,8 @@ class RawInputDataFetcher : public GamepadDataFetcher,
typedef std::map<HANDLE, RawGamepadInfo*> ControllerMap; typedef std::map<HANDLE, RawGamepadInfo*> ControllerMap;
ControllerMap controllers_; ControllerMap controllers_;
// Function pointers to HID functionality, retrieved in // HID functions loaded from hid.dll.
// |GetHidDllFunctions|. std::unique_ptr<HidDllFunctionsWin> hid_functions_;
HidPGetCapsFunc hidp_get_caps_;
HidPGetButtonCapsFunc hidp_get_button_caps_;
HidPGetValueCapsFunc hidp_get_value_caps_;
HidPGetUsagesExFunc hidp_get_usages_ex_;
HidPGetUsageValueFunc hidp_get_usage_value_;
HidPGetScaledUsageValueFunc hidp_get_scaled_usage_value_;
HidDGetStringFunc hidd_get_product_string_;
DISALLOW_COPY_AND_ASSIGN(RawInputDataFetcher); DISALLOW_COPY_AND_ASSIGN(RawInputDataFetcher);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment