summaryrefslogtreecommitdiff
path: root/chromium/device/gamepad
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/device/gamepad')
-rw-r--r--chromium/device/gamepad/gamepad_device_linux.cc82
-rw-r--r--chromium/device/gamepad/gamepad_device_linux.h12
-rw-r--r--chromium/device/gamepad/gamepad_device_mac.mm4
-rw-r--r--chromium/device/gamepad/gamepad_id_list.cc17
-rw-r--r--chromium/device/gamepad/gamepad_id_list.h6
-rw-r--r--chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc8
-rw-r--r--chromium/device/gamepad/gamepad_standard_mappings.cc30
-rw-r--r--chromium/device/gamepad/gamepad_standard_mappings_linux.cc89
-rw-r--r--chromium/device/gamepad/gamepad_standard_mappings_mac.mm68
-rw-r--r--chromium/device/gamepad/gamepad_standard_mappings_win.cc78
-rw-r--r--chromium/device/gamepad/nintendo_controller.cc70
-rw-r--r--chromium/device/gamepad/public/cpp/gamepad.h22
-rw-r--r--chromium/device/gamepad/raw_input_gamepad_device_win.cc28
-rw-r--r--chromium/device/gamepad/raw_input_gamepad_device_win.h15
14 files changed, 395 insertions, 134 deletions
diff --git a/chromium/device/gamepad/gamepad_device_linux.cc b/chromium/device/gamepad/gamepad_device_linux.cc
index f188c2a69e8..ea02ce18f51 100644
--- a/chromium/device/gamepad/gamepad_device_linux.cc
+++ b/chromium/device/gamepad/gamepad_device_linux.cc
@@ -197,6 +197,40 @@ uint16_t HexStringToUInt16WithDefault(base::StringPiece input,
return static_cast<uint16_t>(out);
}
+#if defined(OS_CHROMEOS)
+void OnOpenPathSuccess(
+ chromeos::PermissionBrokerClient::OpenPathCallback callback,
+ scoped_refptr<base::SequencedTaskRunner> polling_runner,
+ base::ScopedFD fd) {
+ polling_runner->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), std::move(fd)));
+}
+
+void OnOpenPathError(
+ chromeos::PermissionBrokerClient::OpenPathCallback callback,
+ scoped_refptr<base::SequencedTaskRunner> polling_runner,
+ const std::string& error_name,
+ const std::string& error_message) {
+ polling_runner->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), base::ScopedFD()));
+}
+
+void OpenPathWithPermissionBroker(
+ const std::string& path,
+ chromeos::PermissionBrokerClient::OpenPathCallback callback,
+ scoped_refptr<base::SequencedTaskRunner> polling_runner) {
+ 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(&OnOpenPathSuccess, copyable_callback, polling_runner);
+ auto error_callback =
+ base::BindOnce(&OnOpenPathError, copyable_callback, polling_runner);
+ client->OpenPath(path, std::move(success_callback),
+ std::move(error_callback));
+}
+#endif // defined(OS_CHROMEOS)
+
} // namespace
GamepadDeviceLinux::GamepadDeviceLinux(
@@ -250,6 +284,12 @@ void GamepadDeviceLinux::ReadPadState(Gamepad* pad) {
pad_updated = true;
}
+ // Mark used buttons.
+ for (size_t button_index = 0; button_index < Gamepad::kButtonsLengthCap;
+ ++button_index) {
+ pad->buttons[button_index].used = button_indices_used_[button_index];
+ }
+
if (pad_updated)
pad->timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
}
@@ -272,6 +312,7 @@ bool GamepadDeviceLinux::ReadJoydevState(Gamepad* pad) {
continue;
pad->axes[item] = event.value / kMaxLinuxAxisValue;
+ pad->axes_used |= 1 << item;
if (item >= pad->axes_length)
pad->axes_length = item + 1;
@@ -280,6 +321,7 @@ bool GamepadDeviceLinux::ReadJoydevState(Gamepad* pad) {
if (item >= Gamepad::kButtonsLengthCap)
continue;
+ pad->buttons[item].used = true;
pad->buttons[item].pressed = event.value;
pad->buttons[item].value = event.value ? 1.0 : 0.0;
@@ -530,9 +572,8 @@ void GamepadDeviceLinux::OpenHidrawNode(const UdevGamepadLinux& pad_info,
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)));
+ base::BindOnce(&OpenPathWithPermissionBroker, pad_info.path,
+ std::move(open_path_callback), polling_runner_));
return;
}
#endif // defined(OS_CHROMEOS)
@@ -601,40 +642,6 @@ void GamepadDeviceLinux::CloseHidrawNode() {
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());
@@ -696,6 +703,7 @@ void GamepadDeviceLinux::SetZeroVibration() {
}
base::WeakPtr<AbstractHapticGamepad> GamepadDeviceLinux::GetWeakPtr() {
+ DCHECK(polling_runner_->RunsTasksInCurrentSequence());
return weak_factory_.GetWeakPtr();
}
diff --git a/chromium/device/gamepad/gamepad_device_linux.h b/chromium/device/gamepad/gamepad_device_linux.h
index 7b4f25e4398..3ef9a0ccdea 100644
--- a/chromium/device/gamepad/gamepad_device_linux.h
+++ b/chromium/device/gamepad/gamepad_device_linux.h
@@ -99,8 +99,6 @@ class GamepadDeviceLinux final : public AbstractHapticGamepad {
base::WeakPtr<AbstractHapticGamepad> GetWeakPtr() override;
private:
- using OpenPathCallback = base::OnceCallback<void(base::ScopedFD)>;
-
// AbstractHapticGamepad private implementation.
void DoShutdown() override;
@@ -108,15 +106,6 @@ class GamepadDeviceLinux final : public AbstractHapticGamepad {
base::ScopedFD fd);
void InitializeHidraw(base::ScopedFD fd);
-#if defined(OS_CHROMEOS)
- void OpenPathWithPermissionBroker(const std::string& path,
- OpenPathCallback callback);
- void OnOpenPathSuccess(OpenPathCallback callback, base::ScopedFD fd);
- void OnOpenPathError(OpenPathCallback callback,
- const std::string& error_name,
- const std::string& error_message);
-#endif
-
// The syspath prefix is used to identify device nodes that refer to the same
// underlying gamepad through different interfaces.
//
@@ -206,6 +195,7 @@ class GamepadDeviceLinux final : public AbstractHapticGamepad {
// Task runner to use for gamepad polling.
scoped_refptr<base::SequencedTaskRunner> polling_runner_;
+ // Weak pointer factory for use only on the |polling_runner_| thread.
base::WeakPtrFactory<GamepadDeviceLinux> weak_factory_{this};
};
diff --git a/chromium/device/gamepad/gamepad_device_mac.mm b/chromium/device/gamepad/gamepad_device_mac.mm
index 90802da1eda..611a301ecc1 100644
--- a/chromium/device/gamepad/gamepad_device_mac.mm
+++ b/chromium/device/gamepad/gamepad_device_mac.mm
@@ -208,6 +208,7 @@ bool GamepadDeviceMac::AddButtons(Gamepad* gamepad) {
continue;
button_elements_[button_index] = element;
+ gamepad->buttons[button_index].used = true;
button_count = std::max(button_count, button_index + 1);
} else {
// Check for common gamepad buttons that are not on the Button usage
@@ -241,6 +242,7 @@ bool GamepadDeviceMac::AddButtons(Gamepad* gamepad) {
break;
button_elements_[button_index] = special_element[special_index];
+ gamepad->buttons[button_index].used = true;
button_count = std::max(button_count, button_index + 1);
if (--unmapped_button_count == 0)
@@ -351,6 +353,8 @@ bool GamepadDeviceMac::AddAxes(Gamepad* gamepad) {
axis_minimums_[axis_index] = axis_min;
axis_maximums_[axis_index] = axis_max;
axis_report_sizes_[axis_index] = IOHIDElementGetReportSize(element);
+
+ gamepad->axes_used |= 1 << axis_index;
}
}
diff --git a/chromium/device/gamepad/gamepad_id_list.cc b/chromium/device/gamepad/gamepad_id_list.cc
index 831bc8e40b9..14accc69dec 100644
--- a/chromium/device/gamepad/gamepad_id_list.cc
+++ b/chromium/device/gamepad/gamepad_id_list.cc
@@ -142,6 +142,9 @@ constexpr struct GamepadInfo {
// Elecom Co., Ltd
{0x056e, 0x2003, kXInputTypeNone},
{0x056e, 0x2004, kXInputTypeXbox360},
+ {0x056e, 0x200f, kXInputTypeNone},
+ {0x056e, 0x2010, kXInputTypeNone},
+ {0x056e, 0x2013, kXInputTypeXbox360},
// Nintendo Co., Ltd
{0x057e, 0x0306, kXInputTypeNone},
{0x057e, 0x0330, kXInputTypeNone},
@@ -371,6 +374,7 @@ constexpr struct GamepadInfo {
{0x0f0d, 0x008a, kXInputTypeNone},
{0x0f0d, 0x008b, kXInputTypeNone},
{0x0f0d, 0x0090, kXInputTypeNone},
+ {0x0f0d, 0x00c1, kXInputTypeNone},
{0x0f0d, 0x00ee, kXInputTypeNone},
// Jess Technology Co., Ltd
{0x0f30, 0x010b, kXInputTypeXbox},
@@ -649,9 +653,16 @@ GamepadId GamepadIdList::GetGamepadId(base::StringPiece product_name,
uint16_t vendor_id,
uint16_t product_id) const {
const auto* entry = GetGamepadInfo(vendor_id, product_id);
- // The ID value combines the vendor and product IDs.
- return entry ? static_cast<GamepadId>((vendor_id << 16) | product_id)
- : GamepadId::kUnknownGamepad;
+ if (entry) {
+ // The ID value combines the vendor and product IDs.
+ return static_cast<GamepadId>((vendor_id << 16) | product_id);
+ }
+ // Special cases for devices which don't report a valid vendor ID.
+ if (vendor_id == 0x0 && product_id == 0x0 &&
+ product_name == "Lic Pro Controller") {
+ return GamepadId::kPowerALicPro;
+ }
+ return GamepadId::kUnknownGamepad;
}
std::vector<std::tuple<uint16_t, uint16_t, XInputType>>
diff --git a/chromium/device/gamepad/gamepad_id_list.h b/chromium/device/gamepad/gamepad_id_list.h
index ca1ee7feba3..0bde5a720c9 100644
--- a/chromium/device/gamepad/gamepad_id_list.h
+++ b/chromium/device/gamepad/gamepad_id_list.h
@@ -33,15 +33,19 @@ enum XInputType {
enum class GamepadId : uint32_t {
// ID value representing an unknown gamepad or non-gamepad.
kUnknownGamepad = 0,
-
+ // Fake IDs for devices which report as 0x0000 0x0000
+ kPowerALicPro = 0x0000ff00,
// ID values for supported devices.
kAsusTekProduct4500 = 0x0b054500,
kBroadcomProduct8502 = 0x0a5c8502,
kDragonRiseProduct0006 = 0x00790006,
kDragonRiseProduct0011 = 0x00790011,
+ kElecomProduct200f = 0x056e200f,
+ kElecomProduct2010 = 0x056e2010,
kGoogleProduct2c40 = 0x18d12c40,
kGoogleProduct9400 = 0x18d19400,
kGreenAsiaProduct0003 = 0x0e8f0003,
+ kHoriProduct00c1 = 0x0f0d00c1,
kLakeviewResearchProduct0005 = 0x09250005,
kLakeviewResearchProduct8866 = 0x09258866,
kLogitechProductc216 = 0x046dc216,
diff --git a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc
index 38a6cb45240..0d16efd0222 100644
--- a/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc
+++ b/chromium/device/gamepad/gamepad_platform_data_fetcher_android.cc
@@ -121,15 +121,17 @@ static void JNI_GamepadList_SetGamepadData(
std::vector<float> buttons;
base::android::JavaFloatArrayToFloatVector(env, jbuttons, &buttons);
- // Set Gamepad buttonslength to total number of axes on the gamepad
- // device. Only return the first buttonsLengthCap if axeslength captured by
+ // Set Gamepad buttonslength to total number of buttons on the gamepad
+ // device. Only return the first buttonsLengthCap if buttonslength captured by
// GamepadList is larger than buttonsLengthCap.
pad.buttons_length = std::min(static_cast<int>(buttons.size()),
static_cast<int>(Gamepad::kButtonsLengthCap));
// Copy buttons state to the Gamepad buttons[].
for (unsigned int j = 0; j < pad.buttons_length; j++) {
- pad.buttons[j].pressed = buttons[j];
+ pad.buttons[j].pressed =
+ buttons[j] > GamepadButton::kDefaultButtonPressedThreshold;
+ pad.buttons[j].touched = buttons[j] > 0.0f;
pad.buttons[j].value = buttons[j];
}
}
diff --git a/chromium/device/gamepad/gamepad_standard_mappings.cc b/chromium/device/gamepad/gamepad_standard_mappings.cc
index e30498514cb..94645a0fbfa 100644
--- a/chromium/device/gamepad/gamepad_standard_mappings.cc
+++ b/chromium/device/gamepad/gamepad_standard_mappings.cc
@@ -6,25 +6,31 @@
namespace device {
-GamepadButton AxisToButton(float input) {
- float value = (input + 1.f) / 2.f;
+namespace {
+
+const float kButtonAxisDeadzone = 0.01f;
+
+GamepadButton ValueToButton(float value) {
bool pressed = value > GamepadButton::kDefaultButtonPressedThreshold;
- bool touched = value > 0.0f;
+ bool touched = value > 0.f;
return GamepadButton(pressed, touched, value);
}
+} // namespace
+
+GamepadButton AxisToButton(float input) {
+ float value = (input + 1.f) / 2.f;
+ return ValueToButton(value);
+}
+
GamepadButton AxisNegativeAsButton(float input) {
- float value = (input < -0.5f) ? 1.f : 0.f;
- bool pressed = value > GamepadButton::kDefaultButtonPressedThreshold;
- bool touched = value > 0.0f;
- return GamepadButton(pressed, touched, value);
+ float value = input < -kButtonAxisDeadzone ? -input : 0.f;
+ return ValueToButton(value);
}
GamepadButton AxisPositiveAsButton(float input) {
- float value = (input > 0.5f) ? 1.f : 0.f;
- bool pressed = value > GamepadButton::kDefaultButtonPressedThreshold;
- bool touched = value > 0.0f;
- return GamepadButton(pressed, touched, value);
+ float value = input > kButtonAxisDeadzone ? input : 0.f;
+ return ValueToButton(value);
}
GamepadButton ButtonFromButtonAndAxis(GamepadButton button, float axis) {
@@ -33,7 +39,7 @@ GamepadButton ButtonFromButtonAndAxis(GamepadButton button, float axis) {
}
GamepadButton NullButton() {
- return GamepadButton(false, false, 0.0);
+ return GamepadButton();
}
void DpadFromAxis(Gamepad* mapped, float dir) {
diff --git a/chromium/device/gamepad/gamepad_standard_mappings_linux.cc b/chromium/device/gamepad/gamepad_standard_mappings_linux.cc
index bf685f48653..d438c3d93bf 100644
--- a/chromium/device/gamepad/gamepad_standard_mappings_linux.cc
+++ b/chromium/device/gamepad/gamepad_standard_mappings_linux.cc
@@ -35,6 +35,13 @@ enum StadiaGamepadButtons {
STADIA_GAMEPAD_BUTTON_COUNT
};
+// The Switch Pro controller has a Capture button that has no equivalent in the
+// Standard Gamepad.
+enum SwitchProButtons {
+ SWITCH_PRO_BUTTON_CAPTURE = BUTTON_INDEX_COUNT,
+ SWITCH_PRO_BUTTON_COUNT
+};
+
void MapperXInputStyleGamepad(const Gamepad& input, Gamepad* mapped) {
*mapped = input;
mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
@@ -613,11 +620,8 @@ void MapperSwitchJoyCon(const Gamepad& input, Gamepad* mapped) {
}
void MapperSwitchPro(const Gamepad& input, Gamepad* mapped) {
- // The Switch Pro controller has a Capture button that has no equivalent in
- // the Standard Gamepad.
- const size_t kSwitchProExtraButtonCount = 1;
*mapped = input;
- mapped->buttons_length = BUTTON_INDEX_COUNT + kSwitchProExtraButtonCount;
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
mapped->axes_length = AXIS_INDEX_COUNT;
}
@@ -768,7 +772,18 @@ void MapperSnakebyteIDroidCon(const Gamepad& input, Gamepad* mapped) {
mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[5];
mapped->buttons[BUTTON_INDEX_META] = NullButton();
- if (input.axes_length == 7) {
+ if ((input.axes_used & 0b1000000) == 0) {
+ // "Game controller 1" mode: digital triggers.
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] =
+ AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] =
+ AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[4]);
+ } else {
// "Game controller 2" mode: analog triggers.
mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] =
AxisPositiveAsButton(input.axes[2]);
@@ -781,31 +796,67 @@ void MapperSnakebyteIDroidCon(const Gamepad& input, Gamepad* mapped) {
AxisNegativeAsButton(input.axes[5]);
mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_META] = NullButton();
mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
- } else {
- // "Game controller 1" mode: digital triggers.
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[8];
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[9];
- mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_DOWN] =
- AxisPositiveAsButton(input.axes[5]);
- mapped->buttons[BUTTON_INDEX_DPAD_LEFT] =
- AxisNegativeAsButton(input.axes[4]);
- mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
- AxisPositiveAsButton(input.axes[4]);
}
+
mapped->buttons_length = BUTTON_INDEX_COUNT - 1; // no meta
mapped->axes_length = AXIS_INDEX_COUNT;
}
+void MapperHoripadSwitch(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[SWITCH_PRO_BUTTON_CAPTURE] = input.buttons[13];
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
+void MapperElecomWiredDirectInput(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_DPAD_UP] = AxisNegativeAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_DOWN] = AxisPositiveAsButton(input.axes[5]);
+ mapped->buttons[BUTTON_INDEX_DPAD_LEFT] = AxisNegativeAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_DPAD_RIGHT] =
+ AxisPositiveAsButton(input.axes[4]);
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[9];
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons_length = BUTTON_INDEX_COUNT;
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
+void MapperElecomWirelessDirectInput(const Gamepad& input, Gamepad* mapped) {
+ MapperElecomWiredDirectInput(input, mapped);
+
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[2];
+}
+
constexpr struct MappingData {
GamepadId gamepad_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
+ // PowerA Wireless Controller - Nintendo GameCube style
+ {GamepadId::kPowerALicPro, MapperSwitchPro},
// DragonRise Generic USB
{GamepadId::kDragonRiseProduct0006, MapperDragonRiseGeneric},
+ // HORIPAD for Nintendo Switch
+ {GamepadId::kHoriProduct00c1, MapperHoripadSwitch},
// Xbox One S (Bluetooth)
{GamepadId::kMicrosoftProduct02e0, MapperXboxOneS},
// Xbox One S (Bluetooth)
@@ -882,6 +933,10 @@ constexpr struct MappingData {
{GamepadId::kPrototypeVendorProduct9401, MapperStadiaControllerOldFirmware},
// Snakebyte iDroid:con
{GamepadId::kBroadcomProduct8502, MapperSnakebyteIDroidCon},
+ // Elecom JC-U4013SBK (DirectInput mode)
+ {GamepadId::kElecomProduct200f, MapperElecomWiredDirectInput},
+ // Elecom JC-U4113SBK (DirectInput mode)
+ {GamepadId::kElecomProduct2010, MapperElecomWirelessDirectInput},
};
} // namespace
diff --git a/chromium/device/gamepad/gamepad_standard_mappings_mac.mm b/chromium/device/gamepad/gamepad_standard_mappings_mac.mm
index d42d6a7ccca..7d068935155 100644
--- a/chromium/device/gamepad/gamepad_standard_mappings_mac.mm
+++ b/chromium/device/gamepad/gamepad_standard_mappings_mac.mm
@@ -26,6 +26,13 @@ enum StadiaGamepadButtons {
STADIA_GAMEPAD_BUTTON_COUNT
};
+// The Switch Pro controller has a Capture button that has no equivalent in the
+// Standard Gamepad.
+enum SwitchProButtons {
+ SWITCH_PRO_BUTTON_CAPTURE = BUTTON_INDEX_COUNT,
+ SWITCH_PRO_BUTTON_COUNT
+};
+
void MapperXbox360Gamepad(const Gamepad& input, Gamepad* mapped) {
*mapped = input;
mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = AxisToButton(input.axes[2]);
@@ -536,11 +543,8 @@ void MapperSwitchJoyCon(const Gamepad& input, Gamepad* mapped) {
}
void MapperSwitchPro(const Gamepad& input, Gamepad* mapped) {
- // The Switch Pro controller has a Capture button that has no equivalent in
- // the Standard Gamepad.
- const size_t kSwitchProExtraButtonCount = 1;
*mapped = input;
- mapped->buttons_length = BUTTON_INDEX_COUNT + kSwitchProExtraButtonCount;
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
mapped->axes_length = AXIS_INDEX_COUNT;
}
@@ -583,12 +587,68 @@ void MapperXboxOneBluetooth(const Gamepad& input, Gamepad* mapped) {
mapped->axes_length = AXIS_INDEX_COUNT;
}
+void MapperSnakebyteIDroidCon(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_META] = NullButton();
+ DpadFromAxis(mapped, input.axes[9]);
+
+ // The iDroid:con has two different modes. Distinguish them based on which
+ // axes are used.
+ if ((input.axes_used & 0b11000) == 0) {
+ // "Game controller 1" mode: digital triggers.
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[9];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ } else {
+ // "Game controller 2" mode: analog triggers.
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] =
+ AxisPositiveAsButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] =
+ AxisNegativeAsButton(input.axes[2]);
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+ }
+
+ mapped->buttons_length = BUTTON_INDEX_COUNT - 1; // no meta
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
+void MapperHoripadSwitch(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ DpadFromAxis(mapped, input.axes[9]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[SWITCH_PRO_BUTTON_CAPTURE] = input.buttons[13];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[2];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
constexpr struct MappingData {
GamepadId gamepad_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
+ // PowerA Wireless Controller - Nintendo GameCube style
+ {GamepadId::kPowerALicPro, MapperSwitchPro},
+ // Snakebyte iDroid:con
+ {GamepadId::kBroadcomProduct8502, MapperSnakebyteIDroidCon},
// DragonRise Generic USB
{GamepadId::kDragonRiseProduct0006, MapperDragonRiseGeneric},
+ // HORIPAD for Nintendo Switch
+ {GamepadId::kHoriProduct00c1, MapperHoripadSwitch},
// Xbox 360 Wired
{GamepadId::kMicrosoftProduct028e, MapperXbox360Gamepad},
// Xbox 360 Wireless
diff --git a/chromium/device/gamepad/gamepad_standard_mappings_win.cc b/chromium/device/gamepad/gamepad_standard_mappings_win.cc
index aed6ca57a25..a4f48b2f7b6 100644
--- a/chromium/device/gamepad/gamepad_standard_mappings_win.cc
+++ b/chromium/device/gamepad/gamepad_standard_mappings_win.cc
@@ -26,6 +26,13 @@ enum StadiaGamepadButtons {
STADIA_GAMEPAD_BUTTON_COUNT
};
+// The Switch Pro controller has a Capture button that has no equivalent in the
+// Standard Gamepad.
+enum SwitchProButtons {
+ SWITCH_PRO_BUTTON_CAPTURE = BUTTON_INDEX_COUNT,
+ SWITCH_PRO_BUTTON_COUNT
+};
+
void MapperLogitechDInput(const Gamepad& input, Gamepad* mapped) {
*mapped = input;
mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
@@ -53,11 +60,11 @@ void Mapper2Axes8Keys(const Gamepad& input, Gamepad* mapped) {
AxisPositiveAsButton(input.axes[0]);
// Missing buttons
- mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = GamepadButton();
- mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = GamepadButton();
- mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = GamepadButton();
- mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = GamepadButton();
- mapped->buttons[BUTTON_INDEX_META] = GamepadButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = NullButton();
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = NullButton();
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = NullButton();
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = NullButton();
+ mapped->buttons[BUTTON_INDEX_META] = NullButton();
mapped->buttons_length = BUTTON_INDEX_COUNT - 1;
mapped->axes_length = 0;
@@ -392,11 +399,8 @@ void MapperSwitchJoyCon(const Gamepad& input, Gamepad* mapped) {
}
void MapperSwitchPro(const Gamepad& input, Gamepad* mapped) {
- // The Switch Pro controller has a Capture button that has no equivalent in
- // the Standard Gamepad.
- const size_t kSwitchProExtraButtonCount = 1;
*mapped = input;
- mapped->buttons_length = BUTTON_INDEX_COUNT + kSwitchProExtraButtonCount;
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
mapped->axes_length = AXIS_INDEX_COUNT;
}
@@ -416,12 +420,68 @@ void MapperSwitchComposite(const Gamepad& input, Gamepad* mapped) {
mapped->axes_length = AXIS_INDEX_COUNT;
}
+void MapperSnakebyteIDroidCon(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[3];
+ mapped->buttons[BUTTON_INDEX_QUATERNARY] = input.buttons[4];
+ mapped->buttons[BUTTON_INDEX_LEFT_SHOULDER] = input.buttons[6];
+ mapped->buttons[BUTTON_INDEX_RIGHT_SHOULDER] = input.buttons[7];
+ mapped->buttons[BUTTON_INDEX_BACK_SELECT] = input.buttons[10];
+ mapped->buttons[BUTTON_INDEX_START] = input.buttons[11];
+ mapped->buttons[BUTTON_INDEX_LEFT_THUMBSTICK] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_RIGHT_THUMBSTICK] = input.buttons[5];
+ mapped->buttons[BUTTON_INDEX_META] = NullButton();
+ DpadFromAxis(mapped, input.axes[9]);
+
+ // The iDroid:con has two different modes. Distinguish them based on which
+ // axes are used.
+ if ((input.axes_used & 0b11000) == 0) {
+ // "Game controller 1" mode: digital triggers.
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] = input.buttons[8];
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] = input.buttons[9];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ } else {
+ // "Game controller 2" mode: analog triggers.
+ mapped->buttons[BUTTON_INDEX_LEFT_TRIGGER] =
+ AxisPositiveAsButton(input.axes[2]);
+ mapped->buttons[BUTTON_INDEX_RIGHT_TRIGGER] =
+ AxisNegativeAsButton(input.axes[2]);
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[3];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[4];
+ }
+
+ mapped->buttons_length = BUTTON_INDEX_COUNT - 1; // no meta
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
+void MapperHoripadSwitch(const Gamepad& input, Gamepad* mapped) {
+ *mapped = input;
+ mapped->buttons[BUTTON_INDEX_PRIMARY] = input.buttons[1];
+ mapped->buttons[BUTTON_INDEX_SECONDARY] = input.buttons[2];
+ mapped->buttons[BUTTON_INDEX_TERTIARY] = input.buttons[0];
+ DpadFromAxis(mapped, input.axes[9]);
+ mapped->buttons[BUTTON_INDEX_META] = input.buttons[12];
+ mapped->buttons[SWITCH_PRO_BUTTON_CAPTURE] = input.buttons[13];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_X] = input.axes[0];
+ mapped->axes[AXIS_INDEX_LEFT_STICK_Y] = input.axes[1];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_X] = input.axes[2];
+ mapped->axes[AXIS_INDEX_RIGHT_STICK_Y] = input.axes[5];
+ mapped->buttons_length = SWITCH_PRO_BUTTON_COUNT;
+ mapped->axes_length = AXIS_INDEX_COUNT;
+}
+
constexpr struct MappingData {
GamepadId gamepad_id;
GamepadStandardMappingFunction function;
} AvailableMappings[] = {
+ // PowerA Wireless Controller - Nintendo GameCube style
+ {GamepadId::kPowerALicPro, MapperSwitchPro},
+ // Snakebyte iDroid:con
+ {GamepadId::kBroadcomProduct8502, MapperSnakebyteIDroidCon},
// 2Axes 8Keys Game Pad
{GamepadId::kDragonRiseProduct0011, Mapper2Axes8Keys},
+ // HORIPAD for Nintendo Switch
+ {GamepadId::kHoriProduct00c1, MapperHoripadSwitch},
// Logitech F310, D-mode
{GamepadId::kLogitechProductc216, MapperLogitechDInput},
// Logitech F510, D-mode
diff --git a/chromium/device/gamepad/nintendo_controller.cc b/chromium/device/gamepad/nintendo_controller.cc
index 662cc20c878..66c0a0c8509 100644
--- a/chromium/device/gamepad/nintendo_controller.cc
+++ b/chromium/device/gamepad/nintendo_controller.cc
@@ -95,6 +95,15 @@ const uint8_t kGyroPerformance208Hz = 0x01;
const uint8_t kAccelerometerFilterBandwidth100Hz = 0x01;
const uint8_t kPlayerLightPattern1 = 0x01;
+// Bogus calibration value that should be ignored.
+const uint16_t kCalBogusValue = 0xfff;
+
+// Default calibration values to use if the controller returns bogus values.
+const uint16_t kCalDefaultDeadzone = 160;
+const uint16_t kCalDefaultMin = 550;
+const uint16_t kCalDefaultCenter = 2050;
+const uint16_t kCalDefaultMax = 3550;
+
// Parameters for the "strong" and "weak" components of the dual-rumble effect.
const double kVibrationFrequencyStrongRumble = 141.0;
const double kVibrationFrequencyWeakRumble = 182.0;
@@ -304,6 +313,11 @@ void UnpackSwitchAnalogStickParameters(
DCHECK(data);
// Only fetch the dead zone and range ratio. The other parameters are unknown.
UnpackShorts(data[3], data[4], data[5], &cal.dead_zone, &cal.range_ratio);
+ if (cal.dead_zone == kCalBogusValue) {
+ // If the controller reports an invalid dead zone, default to something
+ // reasonable.
+ cal.dead_zone = kCalDefaultDeadzone;
+ }
}
// Unpack the IMU calibration data into |cal|
@@ -349,14 +363,30 @@ void UnpackSwitchAnalogStickCalibration(
UnpackShorts(data[9], data[10], data[11], &cal.rx_center, &cal.ry_center);
UnpackShorts(data[12], data[13], data[14], &cal.rx_min, &cal.ry_min);
UnpackShorts(data[15], data[16], data[17], &cal.rx_max, &cal.ry_max);
- cal.lx_min = cal.lx_center - cal.lx_min;
- cal.lx_max = cal.lx_center + cal.lx_max;
- cal.ly_min = cal.ly_center - cal.ly_min;
- cal.ly_max = cal.ly_center + cal.ly_max;
- cal.rx_min = cal.rx_center - cal.rx_min;
- cal.rx_max = cal.rx_center + cal.rx_max;
- cal.ry_min = cal.ry_center - cal.ry_min;
- cal.ry_max = cal.ry_center + cal.ry_max;
+ if (cal.lx_min == kCalBogusValue && cal.ly_max == kCalBogusValue) {
+ // If the controller reports bogus values, default to something reasonable.
+ cal.lx_min = kCalDefaultMin;
+ cal.lx_center = kCalDefaultCenter;
+ cal.lx_max = kCalDefaultMax;
+ cal.ly_min = kCalDefaultMin;
+ cal.ly_center = kCalDefaultCenter;
+ cal.ly_max = kCalDefaultMax;
+ cal.rx_min = kCalDefaultMin;
+ cal.rx_center = kCalDefaultCenter;
+ cal.rx_max = kCalDefaultMax;
+ cal.ry_min = kCalDefaultMin;
+ cal.ry_center = kCalDefaultCenter;
+ cal.ry_max = kCalDefaultMax;
+ } else {
+ cal.lx_min = cal.lx_center - cal.lx_min;
+ cal.lx_max = cal.lx_center + cal.lx_max;
+ cal.ly_min = cal.ly_center - cal.ly_min;
+ cal.ly_max = cal.ly_center + cal.ly_max;
+ cal.rx_min = cal.rx_center - cal.rx_min;
+ cal.rx_max = cal.rx_center + cal.rx_max;
+ cal.ry_min = cal.ry_center - cal.ry_min;
+ cal.ry_max = cal.ry_center + cal.ry_max;
+ }
}
// Unpack one frame of IMU data into |imu_data|.
@@ -796,6 +826,9 @@ GamepadBusType BusTypeFromDeviceInfo(const mojom::HidDeviceInfo* device_info) {
// Joy Cons can only be connected over Bluetooth. When connected through
// a Charging Grip, the grip's ID is reported instead.
return GAMEPAD_BUS_BLUETOOTH;
+ case GamepadId::kPowerALicPro:
+ // The PowerA controller can only be connected over Bluetooth.
+ return GAMEPAD_BUS_BLUETOOTH;
default:
break;
}
@@ -878,6 +911,7 @@ bool NintendoController::IsNintendoController(GamepadId gamepad_id) {
case GamepadId::kNintendoProduct2007:
case GamepadId::kNintendoProduct2009:
case GamepadId::kNintendoProduct200e:
+ case GamepadId::kPowerALicPro:
return true;
default:
break;
@@ -918,7 +952,8 @@ GamepadHand NintendoController::GetGamepadHand() const {
return GamepadHand::kNone;
switch (gamepad_id_) {
case GamepadId::kNintendoProduct2009:
- // Switch Pro is held in both hands.
+ case GamepadId::kPowerALicPro:
+ // Switch Pro and PowerA are held in both hands.
return GamepadHand::kNone;
case GamepadId::kNintendoProduct2006:
// Joy-Con L is held in the left hand.
@@ -961,6 +996,7 @@ bool NintendoController::IsUsable() const {
case GamepadId::kNintendoProduct2009:
case GamepadId::kNintendoProduct2006:
case GamepadId::kNintendoProduct2007:
+ case GamepadId::kPowerALicPro:
return true;
case GamepadId::kNintendoProduct200e:
// Only usable as a composite device.
@@ -1001,8 +1037,12 @@ void NintendoController::InitializeGamepadState(bool has_standard_mapping,
Gamepad& pad) const {
pad.buttons_length = SWITCH_BUTTON_INDEX_COUNT;
pad.axes_length = device::AXIS_INDEX_COUNT;
- pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
- pad.vibration_actuator.not_null = true;
+ if (gamepad_id_ == GamepadId::kPowerALicPro) {
+ pad.vibration_actuator.not_null = false;
+ } else {
+ pad.vibration_actuator.type = GamepadHapticActuatorType::kDualRumble;
+ pad.vibration_actuator.not_null = true;
+ }
pad.timestamp = GamepadDataFetcher::CurrentTimeInMicroseconds();
if (is_composite_) {
// Composite devices use the same product ID as the Switch Charging Grip.
@@ -1407,7 +1447,13 @@ void NintendoController::ContinueInitSequence(
case kPendingEnableVibration:
if (spi_subcommand == kSubCommandEnableVibration) {
CancelTimeout();
- MakeInitSequenceRequests(kPendingSetHomeLight);
+ // PowerA controller doesn't have a home light and trying to set it will
+ // fail, so skip this step.
+ if (gamepad_id_ == GamepadId::kPowerALicPro) {
+ MakeInitSequenceRequests(kPendingSetInputReportMode);
+ } else {
+ MakeInitSequenceRequests(kPendingSetHomeLight);
+ }
}
break;
case kPendingSetHomeLight:
diff --git a/chromium/device/gamepad/public/cpp/gamepad.h b/chromium/device/gamepad/public/cpp/gamepad.h
index 9203c4ffbe1..3477d3d251a 100644
--- a/chromium/device/gamepad/public/cpp/gamepad.h
+++ b/chromium/device/gamepad/public/cpp/gamepad.h
@@ -8,6 +8,8 @@
#include <stddef.h>
#include <cstdint>
+#include <limits>
+
#include "base/component_export.h"
#include "base/strings/string16.h"
@@ -20,12 +22,14 @@ class GamepadButton {
// Matches XInput's trigger deadzone.
static constexpr float kDefaultButtonPressedThreshold = 30.f / 255.f;
- GamepadButton() : pressed(false), touched(false), value(0.) {}
+ GamepadButton() = default;
GamepadButton(bool pressed, bool touched, double value)
- : pressed(pressed), touched(touched), value(value) {}
- bool pressed;
- bool touched;
- double value;
+ : used(true), pressed(pressed), touched(touched), value(value) {}
+ // Whether the button is actually reported by the gamepad at all.
+ bool used{false};
+ bool pressed{false};
+ bool touched{false};
+ double value{0.};
};
enum class GamepadHapticActuatorType { kVibration = 0, kDualRumble = 1 };
@@ -125,6 +129,14 @@ class COMPONENT_EXPORT(GAMEPAD_PUBLIC) Gamepad {
// Number of valid entries in the axes array.
unsigned axes_length;
+ // Bitfield indicating which entries of the axes array are actually used. If
+ // the axes index is actually used for this gamepad then the corresponding bit
+ // will be 1.
+ uint32_t axes_used;
+ static_assert(Gamepad::kAxesLengthCap <=
+ std::numeric_limits<uint32_t>::digits,
+ "axes_used is not large enough");
+
// Normalized values representing axes, in the range [-1..1].
double axes[kAxesLengthCap];
diff --git a/chromium/device/gamepad/raw_input_gamepad_device_win.cc b/chromium/device/gamepad/raw_input_gamepad_device_win.cc
index 5ba8b9f38f1..57473ca36e3 100644
--- a/chromium/device/gamepad/raw_input_gamepad_device_win.cc
+++ b/chromium/device/gamepad/raw_input_gamepad_device_win.cc
@@ -212,8 +212,10 @@ void RawInputGamepadDeviceWin::ReadPadState(Gamepad* pad) const {
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;
}
@@ -405,25 +407,18 @@ void RawInputGamepadDeviceWin::QueryButtonCapabilities(uint16_t button_count) {
HidP_Input, button_caps.get(), &button_count, preparsed_data_);
DCHECK_EQ(HIDP_STATUS_SUCCESS, status);
- // Keep track of which button indices are in use.
- std::vector<bool> button_indices_used(Gamepad::kButtonsLengthCap, false);
-
// Collect all inputs from the Button usage page.
- QueryNormalButtonCapabilities(button_caps.get(), button_count,
- &button_indices_used);
+ 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,
- &button_indices_used);
+ QuerySpecialButtonCapabilities(button_caps.get(), button_count);
}
}
void RawInputGamepadDeviceWin::QueryNormalButtonCapabilities(
HIDP_BUTTON_CAPS button_caps[],
- uint16_t button_count,
- std::vector<bool>* button_indices_used) {
+ uint16_t button_count) {
DCHECK(button_caps);
- DCHECK(button_indices_used);
// Collect all inputs from the Button usage page and assign button indices
// based on the usage value.
@@ -441,17 +436,15 @@ void RawInputGamepadDeviceWin::QueryNormalButtonCapabilities(
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;
+ button_indices_used_[j] = true;
}
}
}
void RawInputGamepadDeviceWin::QuerySpecialButtonCapabilities(
HIDP_BUTTON_CAPS button_caps[],
- uint16_t button_count,
- std::vector<bool>* button_indices_used) {
+ uint16_t button_count) {
DCHECK(button_caps);
- DCHECK(button_indices_used);
// Check for common gamepad buttons that are not on the Button usage page.
std::vector<bool> has_special_usage(kSpecialUsagesLen, false);
@@ -483,19 +476,20 @@ void RawInputGamepadDeviceWin::QuerySpecialButtonCapabilities(
// Advance to the next unused button index.
while (button_index < Gamepad::kButtonsLengthCap &&
- (*button_indices_used)[button_index]) {
+ 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_indices_used_[button_index] = true;
++button_index;
if (--unmapped_button_count == 0)
break;
}
+ buttons_length_ = std::max(buttons_length_, button_index);
}
}
@@ -516,6 +510,7 @@ void RawInputGamepadDeviceWin::QueryAxisCapabilities(uint16_t axis_count) {
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;
}
@@ -538,6 +533,7 @@ void RawInputGamepadDeviceWin::QueryAxisCapabilities(uint16_t axis_count) {
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;
}
}
diff --git a/chromium/device/gamepad/raw_input_gamepad_device_win.h b/chromium/device/gamepad/raw_input_gamepad_device_win.h
index 3c7c8999b74..60a90b15826 100644
--- a/chromium/device/gamepad/raw_input_gamepad_device_win.h
+++ b/chromium/device/gamepad/raw_input_gamepad_device_win.h
@@ -97,11 +97,9 @@ class RawInputGamepadDeviceWin final : public AbstractHapticGamepad {
bool QueryDeviceCapabilities();
void QueryButtonCapabilities(uint16_t button_count);
void QueryNormalButtonCapabilities(HIDP_BUTTON_CAPS button_caps[],
- uint16_t button_count,
- std::vector<bool>* button_indices_used);
+ uint16_t button_count);
void QuerySpecialButtonCapabilities(HIDP_BUTTON_CAPS button_caps[],
- uint16_t button_count,
- std::vector<bool>* button_indices_used);
+ uint16_t button_count);
void QueryAxisCapabilities(uint16_t axis_count);
// True if the device described by this object is a valid RawInput gamepad.
@@ -129,6 +127,15 @@ class RawInputGamepadDeviceWin final : public AbstractHapticGamepad {
size_t buttons_length_ = 0;
bool buttons_[Gamepad::kButtonsLengthCap];
+ // Keep track of which button indices are in use.
+ std::vector<bool> button_indices_used_{Gamepad::kButtonsLengthCap, false};
+
+ // Bitfield to keep track of which axes indices are in use.
+ uint32_t axes_used_ = 0;
+ static_assert(Gamepad::kAxesLengthCap <=
+ std::numeric_limits<uint32_t>::digits,
+ "axes_used_ is not large enough");
+
// Mapping from "Special" usage index (defined by the kSpecialUsages table)
// to an index within the |buttons_| array, or -1 if the special usage is not
// mapped for this device.