diff options
Diffstat (limited to 'src/input_common/drivers')
| -rw-r--r-- | src/input_common/drivers/android.cpp | 324 | ||||
| -rw-r--r-- | src/input_common/drivers/android.h | 123 |
2 files changed, 416 insertions, 31 deletions
diff --git a/src/input_common/drivers/android.cpp b/src/input_common/drivers/android.cpp index b6a03fdc0..e859cc538 100644 --- a/src/input_common/drivers/android.cpp +++ b/src/input_common/drivers/android.cpp | |||
| @@ -1,30 +1,47 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-3.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <set> | ||
| 5 | #include <common/settings_input.h> | ||
| 6 | #include <jni.h> | ||
| 7 | #include "common/android/android_common.h" | ||
| 8 | #include "common/android/id_cache.h" | ||
| 4 | #include "input_common/drivers/android.h" | 9 | #include "input_common/drivers/android.h" |
| 5 | 10 | ||
| 6 | namespace InputCommon { | 11 | namespace InputCommon { |
| 7 | 12 | ||
| 8 | Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} | 13 | Android::Android(std::string input_engine_) : InputEngine(std::move(input_engine_)) {} |
| 9 | 14 | ||
| 10 | void Android::RegisterController(std::size_t controller_number) { | 15 | void Android::RegisterController(jobject j_input_device) { |
| 11 | PreSetController(GetIdentifier(controller_number)); | 16 | auto env = Common::Android::GetEnvForThread(); |
| 17 | const std::string guid = Common::Android::GetJString( | ||
| 18 | env, static_cast<jstring>( | ||
| 19 | env->CallObjectMethod(j_input_device, Common::Android::GetYuzuDeviceGetGUID()))); | ||
| 20 | const s32 port = env->CallIntMethod(j_input_device, Common::Android::GetYuzuDeviceGetPort()); | ||
| 21 | const auto identifier = GetIdentifier(guid, static_cast<size_t>(port)); | ||
| 22 | PreSetController(identifier); | ||
| 23 | |||
| 24 | if (input_devices.find(identifier) != input_devices.end()) { | ||
| 25 | env->DeleteGlobalRef(input_devices[identifier]); | ||
| 26 | } | ||
| 27 | auto new_device = env->NewGlobalRef(j_input_device); | ||
| 28 | input_devices[identifier] = new_device; | ||
| 12 | } | 29 | } |
| 13 | 30 | ||
| 14 | void Android::SetButtonState(std::size_t controller_number, int button_id, bool value) { | 31 | void Android::SetButtonState(std::string guid, size_t port, int button_id, bool value) { |
| 15 | const auto identifier = GetIdentifier(controller_number); | 32 | const auto identifier = GetIdentifier(guid, port); |
| 16 | SetButton(identifier, button_id, value); | 33 | SetButton(identifier, button_id, value); |
| 17 | } | 34 | } |
| 18 | 35 | ||
| 19 | void Android::SetAxisState(std::size_t controller_number, int axis_id, float value) { | 36 | void Android::SetAxisPosition(std::string guid, size_t port, int axis_id, float value) { |
| 20 | const auto identifier = GetIdentifier(controller_number); | 37 | const auto identifier = GetIdentifier(guid, port); |
| 21 | SetAxis(identifier, axis_id, value); | 38 | SetAxis(identifier, axis_id, value); |
| 22 | } | 39 | } |
| 23 | 40 | ||
| 24 | void Android::SetMotionState(std::size_t controller_number, u64 delta_timestamp, float gyro_x, | 41 | void Android::SetMotionState(std::string guid, size_t port, u64 delta_timestamp, float gyro_x, |
| 25 | float gyro_y, float gyro_z, float accel_x, float accel_y, | 42 | float gyro_y, float gyro_z, float accel_x, float accel_y, |
| 26 | float accel_z) { | 43 | float accel_z) { |
| 27 | const auto identifier = GetIdentifier(controller_number); | 44 | const auto identifier = GetIdentifier(guid, port); |
| 28 | const BasicMotion motion_data{ | 45 | const BasicMotion motion_data{ |
| 29 | .gyro_x = gyro_x, | 46 | .gyro_x = gyro_x, |
| 30 | .gyro_y = gyro_y, | 47 | .gyro_y = gyro_y, |
| @@ -37,10 +54,295 @@ void Android::SetMotionState(std::size_t controller_number, u64 delta_timestamp, | |||
| 37 | SetMotion(identifier, 0, motion_data); | 54 | SetMotion(identifier, 0, motion_data); |
| 38 | } | 55 | } |
| 39 | 56 | ||
| 40 | PadIdentifier Android::GetIdentifier(std::size_t controller_number) const { | 57 | Common::Input::DriverResult Android::SetVibration( |
| 58 | [[maybe_unused]] const PadIdentifier& identifier, | ||
| 59 | [[maybe_unused]] const Common::Input::VibrationStatus& vibration) { | ||
| 60 | auto device = input_devices.find(identifier); | ||
| 61 | if (device != input_devices.end()) { | ||
| 62 | Common::Android::RunJNIOnFiber<void>([&](JNIEnv* env) { | ||
| 63 | float average_intensity = | ||
| 64 | static_cast<float>((vibration.high_amplitude + vibration.low_amplitude) / 2.0); | ||
| 65 | env->CallVoidMethod(device->second, Common::Android::GetYuzuDeviceVibrate(), | ||
| 66 | average_intensity); | ||
| 67 | }); | ||
| 68 | return Common::Input::DriverResult::Success; | ||
| 69 | } | ||
| 70 | return Common::Input::DriverResult::NotSupported; | ||
| 71 | } | ||
| 72 | |||
| 73 | bool Android::IsVibrationEnabled([[maybe_unused]] const PadIdentifier& identifier) { | ||
| 74 | auto device = input_devices.find(identifier); | ||
| 75 | if (device != input_devices.end()) { | ||
| 76 | return Common::Android::RunJNIOnFiber<bool>([&](JNIEnv* env) { | ||
| 77 | return static_cast<bool>(env->CallBooleanMethod( | ||
| 78 | device->second, Common::Android::GetYuzuDeviceGetSupportsVibration())); | ||
| 79 | }); | ||
| 80 | } | ||
| 81 | return false; | ||
| 82 | } | ||
| 83 | |||
| 84 | std::vector<Common::ParamPackage> Android::GetInputDevices() const { | ||
| 85 | std::vector<Common::ParamPackage> devices; | ||
| 86 | auto env = Common::Android::GetEnvForThread(); | ||
| 87 | for (const auto& [key, value] : input_devices) { | ||
| 88 | auto name_object = static_cast<jstring>( | ||
| 89 | env->CallObjectMethod(value, Common::Android::GetYuzuDeviceGetName())); | ||
| 90 | const std::string name = | ||
| 91 | fmt::format("{} {}", Common::Android::GetJString(env, name_object), key.port); | ||
| 92 | devices.emplace_back(Common::ParamPackage{ | ||
| 93 | {"engine", GetEngineName()}, | ||
| 94 | {"display", std::move(name)}, | ||
| 95 | {"guid", key.guid.RawString()}, | ||
| 96 | {"port", std::to_string(key.port)}, | ||
| 97 | }); | ||
| 98 | } | ||
| 99 | return devices; | ||
| 100 | } | ||
| 101 | |||
| 102 | std::set<s32> Android::GetDeviceAxes(JNIEnv* env, jobject& j_device) const { | ||
| 103 | auto j_axes = static_cast<jobjectArray>( | ||
| 104 | env->CallObjectMethod(j_device, Common::Android::GetYuzuDeviceGetAxes())); | ||
| 105 | std::set<s32> axes; | ||
| 106 | for (int i = 0; i < env->GetArrayLength(j_axes); ++i) { | ||
| 107 | jobject axis = env->GetObjectArrayElement(j_axes, i); | ||
| 108 | axes.insert(env->GetIntField(axis, Common::Android::GetIntegerValueField())); | ||
| 109 | } | ||
| 110 | return axes; | ||
| 111 | } | ||
| 112 | |||
| 113 | Common::ParamPackage Android::BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, | ||
| 114 | int axis_y) const { | ||
| 115 | Common::ParamPackage params; | ||
| 116 | params.Set("engine", GetEngineName()); | ||
| 117 | params.Set("port", static_cast<int>(identifier.port)); | ||
| 118 | params.Set("guid", identifier.guid.RawString()); | ||
| 119 | params.Set("axis_x", axis_x); | ||
| 120 | params.Set("axis_y", axis_y); | ||
| 121 | params.Set("offset_x", 0); | ||
| 122 | params.Set("offset_y", 0); | ||
| 123 | params.Set("invert_x", "+"); | ||
| 124 | |||
| 125 | // Invert Y-Axis by default | ||
| 126 | params.Set("invert_y", "-"); | ||
| 127 | return params; | ||
| 128 | } | ||
| 129 | |||
| 130 | Common::ParamPackage Android::BuildAnalogParamPackageForButton(PadIdentifier identifier, s32 axis, | ||
| 131 | bool invert) const { | ||
| 132 | Common::ParamPackage params{}; | ||
| 133 | params.Set("engine", GetEngineName()); | ||
| 134 | params.Set("port", static_cast<int>(identifier.port)); | ||
| 135 | params.Set("guid", identifier.guid.RawString()); | ||
| 136 | params.Set("axis", axis); | ||
| 137 | params.Set("threshold", "0.5"); | ||
| 138 | params.Set("invert", invert ? "-" : "+"); | ||
| 139 | return params; | ||
| 140 | } | ||
| 141 | |||
| 142 | Common::ParamPackage Android::BuildButtonParamPackageForButton(PadIdentifier identifier, | ||
| 143 | s32 button) const { | ||
| 144 | Common::ParamPackage params{}; | ||
| 145 | params.Set("engine", GetEngineName()); | ||
| 146 | params.Set("port", static_cast<int>(identifier.port)); | ||
| 147 | params.Set("guid", identifier.guid.RawString()); | ||
| 148 | params.Set("button", button); | ||
| 149 | return params; | ||
| 150 | } | ||
| 151 | |||
| 152 | bool Android::MatchVID(Common::UUID device, const std::vector<std::string>& vids) const { | ||
| 153 | for (size_t i = 0; i < vids.size(); ++i) { | ||
| 154 | auto fucker = device.RawString(); | ||
| 155 | if (fucker.find(vids[i]) != std::string::npos) { | ||
| 156 | return true; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | return false; | ||
| 160 | } | ||
| 161 | |||
| 162 | AnalogMapping Android::GetAnalogMappingForDevice(const Common::ParamPackage& params) { | ||
| 163 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 164 | return {}; | ||
| 165 | } | ||
| 166 | |||
| 167 | auto identifier = | ||
| 168 | GetIdentifier(params.Get("guid", ""), static_cast<size_t>(params.Get("port", 0))); | ||
| 169 | auto& j_device = input_devices[identifier]; | ||
| 170 | if (j_device == nullptr) { | ||
| 171 | return {}; | ||
| 172 | } | ||
| 173 | |||
| 174 | auto env = Common::Android::GetEnvForThread(); | ||
| 175 | std::set<s32> axes = GetDeviceAxes(env, j_device); | ||
| 176 | if (axes.size() == 0) { | ||
| 177 | return {}; | ||
| 178 | } | ||
| 179 | |||
| 180 | AnalogMapping mapping = {}; | ||
| 181 | if (axes.find(AXIS_X) != axes.end() && axes.find(AXIS_Y) != axes.end()) { | ||
| 182 | mapping.insert_or_assign(Settings::NativeAnalog::LStick, | ||
| 183 | BuildParamPackageForAnalog(identifier, AXIS_X, AXIS_Y)); | ||
| 184 | } | ||
| 185 | |||
| 186 | if (axes.find(AXIS_RX) != axes.end() && axes.find(AXIS_RY) != axes.end()) { | ||
| 187 | mapping.insert_or_assign(Settings::NativeAnalog::RStick, | ||
| 188 | BuildParamPackageForAnalog(identifier, AXIS_RX, AXIS_RY)); | ||
| 189 | } else if (axes.find(AXIS_Z) != axes.end() && axes.find(AXIS_RZ) != axes.end()) { | ||
| 190 | mapping.insert_or_assign(Settings::NativeAnalog::RStick, | ||
| 191 | BuildParamPackageForAnalog(identifier, AXIS_Z, AXIS_RZ)); | ||
| 192 | } | ||
| 193 | return mapping; | ||
| 194 | } | ||
| 195 | |||
| 196 | ButtonMapping Android::GetButtonMappingForDevice(const Common::ParamPackage& params) { | ||
| 197 | if (!params.Has("guid") || !params.Has("port")) { | ||
| 198 | return {}; | ||
| 199 | } | ||
| 200 | |||
| 201 | auto identifier = | ||
| 202 | GetIdentifier(params.Get("guid", ""), static_cast<size_t>(params.Get("port", 0))); | ||
| 203 | auto& j_device = input_devices[identifier]; | ||
| 204 | if (j_device == nullptr) { | ||
| 205 | return {}; | ||
| 206 | } | ||
| 207 | |||
| 208 | auto env = Common::Android::GetEnvForThread(); | ||
| 209 | jintArray j_keys = env->NewIntArray(static_cast<int>(keycode_ids.size())); | ||
| 210 | env->SetIntArrayRegion(j_keys, 0, static_cast<int>(keycode_ids.size()), keycode_ids.data()); | ||
| 211 | auto j_has_keys_object = static_cast<jbooleanArray>( | ||
| 212 | env->CallObjectMethod(j_device, Common::Android::GetYuzuDeviceHasKeys(), j_keys)); | ||
| 213 | jboolean isCopy = false; | ||
| 214 | jboolean* j_has_keys = env->GetBooleanArrayElements(j_has_keys_object, &isCopy); | ||
| 215 | |||
| 216 | std::set<s32> available_keys; | ||
| 217 | for (size_t i = 0; i < keycode_ids.size(); ++i) { | ||
| 218 | if (j_has_keys[i]) { | ||
| 219 | available_keys.insert(keycode_ids[i]); | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | // Some devices use axes instead of buttons for certain controls so we need all the axes here | ||
| 224 | std::set<s32> axes = GetDeviceAxes(env, j_device); | ||
| 225 | |||
| 226 | ButtonMapping mapping = {}; | ||
| 227 | if (axes.find(AXIS_HAT_X) != axes.end() && axes.find(AXIS_HAT_Y) != axes.end()) { | ||
| 228 | mapping.insert_or_assign(Settings::NativeButton::DUp, | ||
| 229 | BuildAnalogParamPackageForButton(identifier, AXIS_HAT_Y, true)); | ||
| 230 | mapping.insert_or_assign(Settings::NativeButton::DDown, | ||
| 231 | BuildAnalogParamPackageForButton(identifier, AXIS_HAT_Y, false)); | ||
| 232 | mapping.insert_or_assign(Settings::NativeButton::DLeft, | ||
| 233 | BuildAnalogParamPackageForButton(identifier, AXIS_HAT_X, true)); | ||
| 234 | mapping.insert_or_assign(Settings::NativeButton::DRight, | ||
| 235 | BuildAnalogParamPackageForButton(identifier, AXIS_HAT_X, false)); | ||
| 236 | } else if (available_keys.find(KEYCODE_DPAD_UP) != available_keys.end() && | ||
| 237 | available_keys.find(KEYCODE_DPAD_DOWN) != available_keys.end() && | ||
| 238 | available_keys.find(KEYCODE_DPAD_LEFT) != available_keys.end() && | ||
| 239 | available_keys.find(KEYCODE_DPAD_RIGHT) != available_keys.end()) { | ||
| 240 | mapping.insert_or_assign(Settings::NativeButton::DUp, | ||
| 241 | BuildButtonParamPackageForButton(identifier, KEYCODE_DPAD_UP)); | ||
| 242 | mapping.insert_or_assign(Settings::NativeButton::DDown, | ||
| 243 | BuildButtonParamPackageForButton(identifier, KEYCODE_DPAD_DOWN)); | ||
| 244 | mapping.insert_or_assign(Settings::NativeButton::DLeft, | ||
| 245 | BuildButtonParamPackageForButton(identifier, KEYCODE_DPAD_LEFT)); | ||
| 246 | mapping.insert_or_assign(Settings::NativeButton::DRight, | ||
| 247 | BuildButtonParamPackageForButton(identifier, KEYCODE_DPAD_RIGHT)); | ||
| 248 | } | ||
| 249 | |||
| 250 | if (axes.find(AXIS_LTRIGGER) != axes.end()) { | ||
| 251 | mapping.insert_or_assign(Settings::NativeButton::ZL, BuildAnalogParamPackageForButton( | ||
| 252 | identifier, AXIS_LTRIGGER, false)); | ||
| 253 | } else if (available_keys.find(KEYCODE_BUTTON_L2) != available_keys.end()) { | ||
| 254 | mapping.insert_or_assign(Settings::NativeButton::ZL, | ||
| 255 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_L2)); | ||
| 256 | } | ||
| 257 | |||
| 258 | if (axes.find(AXIS_RTRIGGER) != axes.end()) { | ||
| 259 | mapping.insert_or_assign(Settings::NativeButton::ZR, BuildAnalogParamPackageForButton( | ||
| 260 | identifier, AXIS_RTRIGGER, false)); | ||
| 261 | } else if (available_keys.find(KEYCODE_BUTTON_R2) != available_keys.end()) { | ||
| 262 | mapping.insert_or_assign(Settings::NativeButton::ZR, | ||
| 263 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_R2)); | ||
| 264 | } | ||
| 265 | |||
| 266 | if (available_keys.find(KEYCODE_BUTTON_A) != available_keys.end()) { | ||
| 267 | if (MatchVID(identifier.guid, flipped_ab_vids)) { | ||
| 268 | mapping.insert_or_assign(Settings::NativeButton::B, BuildButtonParamPackageForButton( | ||
| 269 | identifier, KEYCODE_BUTTON_A)); | ||
| 270 | } else { | ||
| 271 | mapping.insert_or_assign(Settings::NativeButton::A, BuildButtonParamPackageForButton( | ||
| 272 | identifier, KEYCODE_BUTTON_A)); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | if (available_keys.find(KEYCODE_BUTTON_B) != available_keys.end()) { | ||
| 276 | if (MatchVID(identifier.guid, flipped_ab_vids)) { | ||
| 277 | mapping.insert_or_assign(Settings::NativeButton::A, BuildButtonParamPackageForButton( | ||
| 278 | identifier, KEYCODE_BUTTON_B)); | ||
| 279 | } else { | ||
| 280 | mapping.insert_or_assign(Settings::NativeButton::B, BuildButtonParamPackageForButton( | ||
| 281 | identifier, KEYCODE_BUTTON_B)); | ||
| 282 | } | ||
| 283 | } | ||
| 284 | if (available_keys.find(KEYCODE_BUTTON_X) != available_keys.end()) { | ||
| 285 | if (MatchVID(identifier.guid, flipped_xy_vids)) { | ||
| 286 | mapping.insert_or_assign(Settings::NativeButton::Y, BuildButtonParamPackageForButton( | ||
| 287 | identifier, KEYCODE_BUTTON_X)); | ||
| 288 | } else { | ||
| 289 | mapping.insert_or_assign(Settings::NativeButton::X, BuildButtonParamPackageForButton( | ||
| 290 | identifier, KEYCODE_BUTTON_X)); | ||
| 291 | } | ||
| 292 | } | ||
| 293 | if (available_keys.find(KEYCODE_BUTTON_Y) != available_keys.end()) { | ||
| 294 | if (MatchVID(identifier.guid, flipped_xy_vids)) { | ||
| 295 | mapping.insert_or_assign(Settings::NativeButton::X, BuildButtonParamPackageForButton( | ||
| 296 | identifier, KEYCODE_BUTTON_Y)); | ||
| 297 | } else { | ||
| 298 | mapping.insert_or_assign(Settings::NativeButton::Y, BuildButtonParamPackageForButton( | ||
| 299 | identifier, KEYCODE_BUTTON_Y)); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | if (available_keys.find(KEYCODE_BUTTON_L1) != available_keys.end()) { | ||
| 304 | mapping.insert_or_assign(Settings::NativeButton::L, | ||
| 305 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_L1)); | ||
| 306 | } | ||
| 307 | if (available_keys.find(KEYCODE_BUTTON_R1) != available_keys.end()) { | ||
| 308 | mapping.insert_or_assign(Settings::NativeButton::R, | ||
| 309 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_R1)); | ||
| 310 | } | ||
| 311 | |||
| 312 | if (available_keys.find(KEYCODE_BUTTON_THUMBL) != available_keys.end()) { | ||
| 313 | mapping.insert_or_assign( | ||
| 314 | Settings::NativeButton::LStick, | ||
| 315 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_THUMBL)); | ||
| 316 | } | ||
| 317 | if (available_keys.find(KEYCODE_BUTTON_THUMBR) != available_keys.end()) { | ||
| 318 | mapping.insert_or_assign( | ||
| 319 | Settings::NativeButton::RStick, | ||
| 320 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_THUMBR)); | ||
| 321 | } | ||
| 322 | |||
| 323 | if (available_keys.find(KEYCODE_BUTTON_START) != available_keys.end()) { | ||
| 324 | mapping.insert_or_assign( | ||
| 325 | Settings::NativeButton::Plus, | ||
| 326 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_START)); | ||
| 327 | } | ||
| 328 | if (available_keys.find(KEYCODE_BUTTON_SELECT) != available_keys.end()) { | ||
| 329 | mapping.insert_or_assign( | ||
| 330 | Settings::NativeButton::Minus, | ||
| 331 | BuildButtonParamPackageForButton(identifier, KEYCODE_BUTTON_SELECT)); | ||
| 332 | } | ||
| 333 | |||
| 334 | return mapping; | ||
| 335 | } | ||
| 336 | |||
| 337 | Common::Input::ButtonNames Android::GetUIName( | ||
| 338 | [[maybe_unused]] const Common::ParamPackage& params) const { | ||
| 339 | return Common::Input::ButtonNames::Value; | ||
| 340 | } | ||
| 341 | |||
| 342 | PadIdentifier Android::GetIdentifier(const std::string& guid, size_t port) const { | ||
| 41 | return { | 343 | return { |
| 42 | .guid = Common::UUID{}, | 344 | .guid = Common::UUID{guid}, |
| 43 | .port = controller_number, | 345 | .port = port, |
| 44 | .pad = 0, | 346 | .pad = 0, |
| 45 | }; | 347 | }; |
| 46 | } | 348 | } |
diff --git a/src/input_common/drivers/android.h b/src/input_common/drivers/android.h index 3f01817f6..ac60e3598 100644 --- a/src/input_common/drivers/android.h +++ b/src/input_common/drivers/android.h | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <set> | ||
| 7 | #include <jni.h> | ||
| 6 | #include "input_common/input_engine.h" | 8 | #include "input_common/input_engine.h" |
| 7 | 9 | ||
| 8 | namespace InputCommon { | 10 | namespace InputCommon { |
| @@ -15,40 +17,121 @@ public: | |||
| 15 | explicit Android(std::string input_engine_); | 17 | explicit Android(std::string input_engine_); |
| 16 | 18 | ||
| 17 | /** | 19 | /** |
| 18 | * Registers controller number to accept new inputs | 20 | * Registers controller number to accept new inputs. |
| 19 | * @param controller_number the controller number that will take this action | 21 | * @param j_input_device YuzuInputDevice object from the Android frontend to register. |
| 20 | */ | 22 | */ |
| 21 | void RegisterController(std::size_t controller_number); | 23 | void RegisterController(jobject j_input_device); |
| 22 | 24 | ||
| 23 | /** | 25 | /** |
| 24 | * Sets the status of all buttons bound with the key to pressed | 26 | * Sets the status of a button on a specific controller. |
| 25 | * @param controller_number the controller number that will take this action | 27 | * @param guid 32 character hexadecimal string consisting of the controller's PID+VID. |
| 26 | * @param button_id the id of the button | 28 | * @param port Port determined by controller connection order. |
| 27 | * @param value indicates if the button is pressed or not | 29 | * @param button_id The Android Keycode corresponding to this event. |
| 30 | * @param value Whether the button is pressed or not. | ||
| 28 | */ | 31 | */ |
| 29 | void SetButtonState(std::size_t controller_number, int button_id, bool value); | 32 | void SetButtonState(std::string guid, size_t port, int button_id, bool value); |
| 30 | 33 | ||
| 31 | /** | 34 | /** |
| 32 | * Sets the status of a analog input to a specific player index | 35 | * Sets the status of an axis on a specific controller. |
| 33 | * @param controller_number the controller number that will take this action | 36 | * @param guid 32 character hexadecimal string consisting of the controller's PID+VID. |
| 34 | * @param axis_id the id of the axis to move | 37 | * @param port Port determined by controller connection order. |
| 35 | * @param value the analog position of the axis | 38 | * @param axis_id The Android axis ID corresponding to this event. |
| 39 | * @param value Value along the given axis. | ||
| 36 | */ | 40 | */ |
| 37 | void SetAxisState(std::size_t controller_number, int axis_id, float value); | 41 | void SetAxisPosition(std::string guid, size_t port, int axis_id, float value); |
| 38 | 42 | ||
| 39 | /** | 43 | /** |
| 40 | * Sets the status of the motion sensor to a specific player index | 44 | * Sets the status of the motion sensor on a specific controller |
| 41 | * @param controller_number the controller number that will take this action | 45 | * @param guid 32 character hexadecimal string consisting of the controller's PID+VID. |
| 42 | * @param delta_timestamp time passed since last reading | 46 | * @param port Port determined by controller connection order. |
| 43 | * @param gyro_x,gyro_y,gyro_z the gyro sensor readings | 47 | * @param delta_timestamp Time passed since the last read. |
| 44 | * @param accel_x,accel_y,accel_z the accelerometer reading | 48 | * @param gyro_x,gyro_y,gyro_z Gyro sensor readings. |
| 49 | * @param accel_x,accel_y,accel_z Accelerometer sensor readings. | ||
| 45 | */ | 50 | */ |
| 46 | void SetMotionState(std::size_t controller_number, u64 delta_timestamp, float gyro_x, | 51 | void SetMotionState(std::string guid, size_t port, u64 delta_timestamp, float gyro_x, |
| 47 | float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z); | 52 | float gyro_y, float gyro_z, float accel_x, float accel_y, float accel_z); |
| 48 | 53 | ||
| 54 | Common::Input::DriverResult SetVibration( | ||
| 55 | const PadIdentifier& identifier, const Common::Input::VibrationStatus& vibration) override; | ||
| 56 | |||
| 57 | bool IsVibrationEnabled(const PadIdentifier& identifier) override; | ||
| 58 | |||
| 59 | std::vector<Common::ParamPackage> GetInputDevices() const override; | ||
| 60 | |||
| 61 | /** | ||
| 62 | * Gets the axes reported by the YuzuInputDevice. | ||
| 63 | * @param env JNI environment pointer. | ||
| 64 | * @param j_device YuzuInputDevice from the Android frontend. | ||
| 65 | * @return Set of the axes reported by the underlying Android InputDevice | ||
| 66 | */ | ||
| 67 | std::set<s32> GetDeviceAxes(JNIEnv* env, jobject& j_device) const; | ||
| 68 | |||
| 69 | Common::ParamPackage BuildParamPackageForAnalog(PadIdentifier identifier, int axis_x, | ||
| 70 | int axis_y) const; | ||
| 71 | |||
| 72 | Common::ParamPackage BuildAnalogParamPackageForButton(PadIdentifier identifier, s32 axis, | ||
| 73 | bool invert) const; | ||
| 74 | |||
| 75 | Common::ParamPackage BuildButtonParamPackageForButton(PadIdentifier identifier, | ||
| 76 | s32 button) const; | ||
| 77 | |||
| 78 | bool MatchVID(Common::UUID device, const std::vector<std::string>& vids) const; | ||
| 79 | |||
| 80 | AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override; | ||
| 81 | |||
| 82 | ButtonMapping GetButtonMappingForDevice(const Common::ParamPackage& params) override; | ||
| 83 | |||
| 84 | Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override; | ||
| 85 | |||
| 49 | private: | 86 | private: |
| 87 | std::unordered_map<PadIdentifier, jobject> input_devices; | ||
| 88 | |||
| 50 | /// Returns the correct identifier corresponding to the player index | 89 | /// Returns the correct identifier corresponding to the player index |
| 51 | PadIdentifier GetIdentifier(std::size_t controller_number) const; | 90 | PadIdentifier GetIdentifier(const std::string& guid, size_t port) const; |
| 91 | |||
| 92 | static constexpr s32 AXIS_X = 0; | ||
| 93 | static constexpr s32 AXIS_Y = 1; | ||
| 94 | static constexpr s32 AXIS_Z = 11; | ||
| 95 | static constexpr s32 AXIS_RX = 12; | ||
| 96 | static constexpr s32 AXIS_RY = 13; | ||
| 97 | static constexpr s32 AXIS_RZ = 14; | ||
| 98 | static constexpr s32 AXIS_HAT_X = 15; | ||
| 99 | static constexpr s32 AXIS_HAT_Y = 16; | ||
| 100 | static constexpr s32 AXIS_LTRIGGER = 17; | ||
| 101 | static constexpr s32 AXIS_RTRIGGER = 18; | ||
| 102 | |||
| 103 | static constexpr s32 KEYCODE_DPAD_UP = 19; | ||
| 104 | static constexpr s32 KEYCODE_DPAD_DOWN = 20; | ||
| 105 | static constexpr s32 KEYCODE_DPAD_LEFT = 21; | ||
| 106 | static constexpr s32 KEYCODE_DPAD_RIGHT = 22; | ||
| 107 | static constexpr s32 KEYCODE_BUTTON_A = 96; | ||
| 108 | static constexpr s32 KEYCODE_BUTTON_B = 97; | ||
| 109 | static constexpr s32 KEYCODE_BUTTON_X = 99; | ||
| 110 | static constexpr s32 KEYCODE_BUTTON_Y = 100; | ||
| 111 | static constexpr s32 KEYCODE_BUTTON_L1 = 102; | ||
| 112 | static constexpr s32 KEYCODE_BUTTON_R1 = 103; | ||
| 113 | static constexpr s32 KEYCODE_BUTTON_L2 = 104; | ||
| 114 | static constexpr s32 KEYCODE_BUTTON_R2 = 105; | ||
| 115 | static constexpr s32 KEYCODE_BUTTON_THUMBL = 106; | ||
| 116 | static constexpr s32 KEYCODE_BUTTON_THUMBR = 107; | ||
| 117 | static constexpr s32 KEYCODE_BUTTON_START = 108; | ||
| 118 | static constexpr s32 KEYCODE_BUTTON_SELECT = 109; | ||
| 119 | const std::vector<s32> keycode_ids{ | ||
| 120 | KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_RIGHT, | ||
| 121 | KEYCODE_BUTTON_A, KEYCODE_BUTTON_B, KEYCODE_BUTTON_X, KEYCODE_BUTTON_Y, | ||
| 122 | KEYCODE_BUTTON_L1, KEYCODE_BUTTON_R1, KEYCODE_BUTTON_L2, KEYCODE_BUTTON_R2, | ||
| 123 | KEYCODE_BUTTON_THUMBL, KEYCODE_BUTTON_THUMBR, KEYCODE_BUTTON_START, KEYCODE_BUTTON_SELECT, | ||
| 124 | }; | ||
| 125 | |||
| 126 | const std::string sony_vid{"054c"}; | ||
| 127 | const std::string nintendo_vid{"057e"}; | ||
| 128 | const std::string razer_vid{"1532"}; | ||
| 129 | const std::string redmagic_vid{"3537"}; | ||
| 130 | const std::string backbone_labs_vid{"358a"}; | ||
| 131 | const std::vector<std::string> flipped_ab_vids{sony_vid, nintendo_vid, razer_vid, redmagic_vid, | ||
| 132 | backbone_labs_vid}; | ||
| 133 | const std::vector<std::string> flipped_xy_vids{sony_vid, razer_vid, redmagic_vid, | ||
| 134 | backbone_labs_vid}; | ||
| 52 | }; | 135 | }; |
| 53 | 136 | ||
| 54 | } // namespace InputCommon | 137 | } // namespace InputCommon |