summaryrefslogtreecommitdiff
path: root/src/input_common/drivers/joycon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/drivers/joycon.cpp')
-rw-r--r--src/input_common/drivers/joycon.cpp677
1 files changed, 677 insertions, 0 deletions
diff --git a/src/input_common/drivers/joycon.cpp b/src/input_common/drivers/joycon.cpp
new file mode 100644
index 000000000..4fcfb4510
--- /dev/null
+++ b/src/input_common/drivers/joycon.cpp
@@ -0,0 +1,677 @@
1// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <fmt/format.h>
5
6#include "common/param_package.h"
7#include "common/polyfill_ranges.h"
8#include "common/polyfill_thread.h"
9#include "common/settings.h"
10#include "common/thread.h"
11#include "input_common/drivers/joycon.h"
12#include "input_common/helpers/joycon_driver.h"
13#include "input_common/helpers/joycon_protocol/joycon_types.h"
14
15namespace InputCommon {
16
17Joycons::Joycons(const std::string& input_engine_) : InputEngine(input_engine_) {
18 // Avoid conflicting with SDL driver
19 if (!Settings::values.enable_joycon_driver) {
20 return;
21 }
22 LOG_INFO(Input, "Joycon driver Initialization started");
23 const int init_res = SDL_hid_init();
24 if (init_res == 0) {
25 Setup();
26 } else {
27 LOG_ERROR(Input, "Hidapi could not be initialized. failed with error = {}", init_res);
28 }
29}
30
31Joycons::~Joycons() {
32 Reset();
33}
34
35void Joycons::Reset() {
36 scan_thread = {};
37 for (const auto& device : left_joycons) {
38 if (!device) {
39 continue;
40 }
41 device->Stop();
42 }
43 for (const auto& device : right_joycons) {
44 if (!device) {
45 continue;
46 }
47 device->Stop();
48 }
49 SDL_hid_exit();
50}
51
52void Joycons::Setup() {
53 u32 port = 0;
54 PreSetController(GetIdentifier(0, Joycon::ControllerType::None));
55 for (auto& device : left_joycons) {
56 PreSetController(GetIdentifier(port, Joycon::ControllerType::Left));
57 device = std::make_shared<Joycon::JoyconDriver>(port++);
58 }
59 port = 0;
60 for (auto& device : right_joycons) {
61 PreSetController(GetIdentifier(port, Joycon::ControllerType::Right));
62 device = std::make_shared<Joycon::JoyconDriver>(port++);
63 }
64
65 scan_thread = std::jthread([this](std::stop_token stop_token) { ScanThread(stop_token); });
66}
67
68void Joycons::ScanThread(std::stop_token stop_token) {
69 constexpr u16 nintendo_vendor_id = 0x057e;
70 Common::SetCurrentThreadName("JoyconScanThread");
71
72 do {
73 SDL_hid_device_info* devs = SDL_hid_enumerate(nintendo_vendor_id, 0x0);
74 SDL_hid_device_info* cur_dev = devs;
75
76 while (cur_dev) {
77 if (IsDeviceNew(cur_dev)) {
78 LOG_DEBUG(Input, "Device Found,type : {:04X} {:04X}", cur_dev->vendor_id,
79 cur_dev->product_id);
80 RegisterNewDevice(cur_dev);
81 }
82 cur_dev = cur_dev->next;
83 }
84
85 SDL_hid_free_enumeration(devs);
86 } while (Common::StoppableTimedWait(stop_token, std::chrono::seconds{5}));
87}
88
89bool Joycons::IsDeviceNew(SDL_hid_device_info* device_info) const {
90 Joycon::ControllerType type{};
91 Joycon::SerialNumber serial_number{};
92
93 const auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type);
94 if (result != Joycon::DriverResult::Success) {
95 return false;
96 }
97
98 const auto result2 = Joycon::JoyconDriver::GetSerialNumber(device_info, serial_number);
99 if (result2 != Joycon::DriverResult::Success) {
100 return false;
101 }
102
103 auto is_handle_identical = [serial_number](std::shared_ptr<Joycon::JoyconDriver> device) {
104 if (!device) {
105 return false;
106 }
107 if (!device->IsConnected()) {
108 return false;
109 }
110 if (device->GetHandleSerialNumber() != serial_number) {
111 return false;
112 }
113 return true;
114 };
115
116 // Check if device already exist
117 switch (type) {
118 case Joycon::ControllerType::Left:
119 for (const auto& device : left_joycons) {
120 if (is_handle_identical(device)) {
121 return false;
122 }
123 }
124 break;
125 case Joycon::ControllerType::Right:
126 for (const auto& device : right_joycons) {
127 if (is_handle_identical(device)) {
128 return false;
129 }
130 }
131 break;
132 default:
133 return false;
134 }
135
136 return true;
137}
138
139void Joycons::RegisterNewDevice(SDL_hid_device_info* device_info) {
140 Joycon::ControllerType type{};
141 auto result = Joycon::JoyconDriver::GetDeviceType(device_info, type);
142 auto handle = GetNextFreeHandle(type);
143 if (handle == nullptr) {
144 LOG_WARNING(Input, "No free handles available");
145 return;
146 }
147 if (result == Joycon::DriverResult::Success) {
148 result = handle->RequestDeviceAccess(device_info);
149 }
150 if (result == Joycon::DriverResult::Success) {
151 LOG_WARNING(Input, "Initialize device");
152
153 const std::size_t port = handle->GetDevicePort();
154 const Joycon::JoyconCallbacks callbacks{
155 .on_battery_data = {[this, port, type](Joycon::Battery value) {
156 OnBatteryUpdate(port, type, value);
157 }},
158 .on_color_data = {[this, port, type](Joycon::Color value) {
159 OnColorUpdate(port, type, value);
160 }},
161 .on_button_data = {[this, port, type](int id, bool value) {
162 OnButtonUpdate(port, type, id, value);
163 }},
164 .on_stick_data = {[this, port, type](int id, f32 value) {
165 OnStickUpdate(port, type, id, value);
166 }},
167 .on_motion_data = {[this, port, type](int id, const Joycon::MotionData& value) {
168 OnMotionUpdate(port, type, id, value);
169 }},
170 .on_ring_data = {[this](f32 ring_data) { OnRingConUpdate(ring_data); }},
171 .on_amiibo_data = {[this, port](const std::vector<u8>& amiibo_data) {
172 OnAmiiboUpdate(port, amiibo_data);
173 }},
174 .on_camera_data = {[this, port](const std::vector<u8>& camera_data,
175 Joycon::IrsResolution format) {
176 OnCameraUpdate(port, camera_data, format);
177 }},
178 };
179
180 handle->InitializeDevice();
181 handle->SetCallbacks(callbacks);
182 }
183}
184
185std::shared_ptr<Joycon::JoyconDriver> Joycons::GetNextFreeHandle(
186 Joycon::ControllerType type) const {
187 if (type == Joycon::ControllerType::Left) {
188 const auto unconnected_device =
189 std::ranges::find_if(left_joycons, [](auto& device) { return !device->IsConnected(); });
190 if (unconnected_device != left_joycons.end()) {
191 return *unconnected_device;
192 }
193 }
194 if (type == Joycon::ControllerType::Right) {
195 const auto unconnected_device = std::ranges::find_if(
196 right_joycons, [](auto& device) { return !device->IsConnected(); });
197
198 if (unconnected_device != right_joycons.end()) {
199 return *unconnected_device;
200 }
201 }
202 return nullptr;
203}
204
205bool Joycons::IsVibrationEnabled(const PadIdentifier& identifier) {
206 const auto handle = GetHandle(identifier);
207 if (handle == nullptr) {
208 return false;
209 }
210 return handle->IsVibrationEnabled();
211}
212
213Common::Input::DriverResult Joycons::SetVibration(const PadIdentifier& identifier,
214 const Common::Input::VibrationStatus& vibration) {
215 const Joycon::VibrationValue native_vibration{
216 .low_amplitude = vibration.low_amplitude,
217 .low_frequency = vibration.low_frequency,
218 .high_amplitude = vibration.high_amplitude,
219 .high_frequency = vibration.high_frequency,
220 };
221 auto handle = GetHandle(identifier);
222 if (handle == nullptr) {
223 return Common::Input::DriverResult::InvalidHandle;
224 }
225
226 handle->SetVibration(native_vibration);
227 return Common::Input::DriverResult::Success;
228}
229
230Common::Input::DriverResult Joycons::SetLeds(const PadIdentifier& identifier,
231 const Common::Input::LedStatus& led_status) {
232 auto handle = GetHandle(identifier);
233 if (handle == nullptr) {
234 return Common::Input::DriverResult::InvalidHandle;
235 }
236 int led_config = led_status.led_1 ? 1 : 0;
237 led_config += led_status.led_2 ? 2 : 0;
238 led_config += led_status.led_3 ? 4 : 0;
239 led_config += led_status.led_4 ? 8 : 0;
240
241 return static_cast<Common::Input::DriverResult>(
242 handle->SetLedConfig(static_cast<u8>(led_config)));
243}
244
245Common::Input::DriverResult Joycons::SetCameraFormat(const PadIdentifier& identifier,
246 Common::Input::CameraFormat camera_format) {
247 auto handle = GetHandle(identifier);
248 if (handle == nullptr) {
249 return Common::Input::DriverResult::InvalidHandle;
250 }
251 return static_cast<Common::Input::DriverResult>(handle->SetIrsConfig(
252 Joycon::IrsMode::ImageTransfer, static_cast<Joycon::IrsResolution>(camera_format)));
253};
254
255Common::Input::NfcState Joycons::SupportsNfc(const PadIdentifier& identifier_) const {
256 return Common::Input::NfcState::Success;
257};
258
259Common::Input::NfcState Joycons::WriteNfcData(const PadIdentifier& identifier_,
260 const std::vector<u8>& data) {
261 return Common::Input::NfcState::NotSupported;
262};
263
264Common::Input::DriverResult Joycons::SetPollingMode(const PadIdentifier& identifier,
265 const Common::Input::PollingMode polling_mode) {
266 auto handle = GetHandle(identifier);
267 if (handle == nullptr) {
268 LOG_ERROR(Input, "Invalid handle {}", identifier.port);
269 return Common::Input::DriverResult::InvalidHandle;
270 }
271
272 switch (polling_mode) {
273 case Common::Input::PollingMode::Active:
274 return static_cast<Common::Input::DriverResult>(handle->SetActiveMode());
275 case Common::Input::PollingMode::Pasive:
276 return static_cast<Common::Input::DriverResult>(handle->SetPasiveMode());
277 case Common::Input::PollingMode::IR:
278 return static_cast<Common::Input::DriverResult>(handle->SetIrMode());
279 case Common::Input::PollingMode::NFC:
280 return static_cast<Common::Input::DriverResult>(handle->SetNfcMode());
281 case Common::Input::PollingMode::Ring:
282 return static_cast<Common::Input::DriverResult>(handle->SetRingConMode());
283 default:
284 return Common::Input::DriverResult::NotSupported;
285 }
286}
287
288void Joycons::OnBatteryUpdate(std::size_t port, Joycon::ControllerType type,
289 Joycon::Battery value) {
290 const auto identifier = GetIdentifier(port, type);
291 if (value.charging != 0) {
292 SetBattery(identifier, Common::Input::BatteryLevel::Charging);
293 return;
294 }
295
296 Common::Input::BatteryLevel battery{};
297 switch (value.status) {
298 case 0:
299 battery = Common::Input::BatteryLevel::Empty;
300 break;
301 case 1:
302 battery = Common::Input::BatteryLevel::Critical;
303 break;
304 case 2:
305 battery = Common::Input::BatteryLevel::Low;
306 break;
307 case 3:
308 battery = Common::Input::BatteryLevel::Medium;
309 break;
310 case 4:
311 default:
312 battery = Common::Input::BatteryLevel::Full;
313 break;
314 }
315 SetBattery(identifier, battery);
316}
317
318void Joycons::OnColorUpdate(std::size_t port, Joycon::ControllerType type,
319 const Joycon::Color& value) {
320 const auto identifier = GetIdentifier(port, type);
321 Common::Input::BodyColorStatus color{
322 .body = value.body,
323 .buttons = value.buttons,
324 .left_grip = value.left_grip,
325 .right_grip = value.right_grip,
326 };
327 SetColor(identifier, color);
328}
329
330void Joycons::OnButtonUpdate(std::size_t port, Joycon::ControllerType type, int id, bool value) {
331 const auto identifier = GetIdentifier(port, type);
332 SetButton(identifier, id, value);
333}
334
335void Joycons::OnStickUpdate(std::size_t port, Joycon::ControllerType type, int id, f32 value) {
336 const auto identifier = GetIdentifier(port, type);
337 SetAxis(identifier, id, value);
338}
339
340void Joycons::OnMotionUpdate(std::size_t port, Joycon::ControllerType type, int id,
341 const Joycon::MotionData& value) {
342 const auto identifier = GetIdentifier(port, type);
343 BasicMotion motion_data{
344 .gyro_x = value.gyro_x,
345 .gyro_y = value.gyro_y,
346 .gyro_z = value.gyro_z,
347 .accel_x = value.accel_x,
348 .accel_y = value.accel_y,
349 .accel_z = value.accel_z,
350 .delta_timestamp = 15000,
351 };
352 SetMotion(identifier, id, motion_data);
353}
354
355void Joycons::OnRingConUpdate(f32 ring_data) {
356 // To simplify ring detection it will always be mapped to an empty identifier for all
357 // controllers
358 constexpr PadIdentifier identifier = {
359 .guid = Common::UUID{},
360 .port = 0,
361 .pad = 0,
362 };
363 SetAxis(identifier, 100, ring_data);
364}
365
366void Joycons::OnAmiiboUpdate(std::size_t port, const std::vector<u8>& amiibo_data) {
367 const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right);
368 const auto nfc_state = amiibo_data.empty() ? Common::Input::NfcState::AmiiboRemoved
369 : Common::Input::NfcState::NewAmiibo;
370 SetNfc(identifier, {nfc_state, amiibo_data});
371}
372
373void Joycons::OnCameraUpdate(std::size_t port, const std::vector<u8>& camera_data,
374 Joycon::IrsResolution format) {
375 const auto identifier = GetIdentifier(port, Joycon::ControllerType::Right);
376 SetCamera(identifier, {static_cast<Common::Input::CameraFormat>(format), camera_data});
377}
378
379std::shared_ptr<Joycon::JoyconDriver> Joycons::GetHandle(PadIdentifier identifier) const {
380 auto is_handle_active = [&](std::shared_ptr<Joycon::JoyconDriver> device) {
381 if (!device) {
382 return false;
383 }
384 if (!device->IsConnected()) {
385 return false;
386 }
387 if (device->GetDevicePort() == identifier.port) {
388 return true;
389 }
390 return false;
391 };
392 const auto type = static_cast<Joycon::ControllerType>(identifier.pad);
393
394 if (type == Joycon::ControllerType::Left) {
395 const auto matching_device = std::ranges::find_if(
396 left_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
397
398 if (matching_device != left_joycons.end()) {
399 return *matching_device;
400 }
401 }
402
403 if (type == Joycon::ControllerType::Right) {
404 const auto matching_device = std::ranges::find_if(
405 right_joycons, [is_handle_active](auto& device) { return is_handle_active(device); });
406
407 if (matching_device != right_joycons.end()) {
408 return *matching_device;
409 }
410 }
411
412 return nullptr;
413}
414
415PadIdentifier Joycons::GetIdentifier(std::size_t port, Joycon::ControllerType type) const {
416 const std::array<u8, 16> guid{0, 0, 0, 0, 0, 0, 0, 0,
417 0, 0, 0, 0, 0, 0, 0, static_cast<u8>(type)};
418 return {
419 .guid = Common::UUID{guid},
420 .port = port,
421 .pad = static_cast<std::size_t>(type),
422 };
423}
424
425Common::ParamPackage Joycons::GetParamPackage(std::size_t port, Joycon::ControllerType type) const {
426 const auto identifier = GetIdentifier(port, type);
427 return {
428 {"engine", GetEngineName()},
429 {"guid", identifier.guid.RawString()},
430 {"port", std::to_string(identifier.port)},
431 {"pad", std::to_string(identifier.pad)},
432 };
433}
434
435std::vector<Common::ParamPackage> Joycons::GetInputDevices() const {
436 std::vector<Common::ParamPackage> devices{};
437
438 auto add_entry = [&](std::shared_ptr<Joycon::JoyconDriver> device) {
439 if (!device) {
440 return;
441 }
442 if (!device->IsConnected()) {
443 return;
444 }
445 auto param = GetParamPackage(device->GetDevicePort(), device->GetHandleDeviceType());
446 std::string name = fmt::format("{} {}", JoyconName(device->GetHandleDeviceType()),
447 device->GetDevicePort() + 1);
448 param.Set("display", std::move(name));
449 devices.emplace_back(param);
450 };
451
452 for (const auto& controller : left_joycons) {
453 add_entry(controller);
454 }
455 for (const auto& controller : right_joycons) {
456 add_entry(controller);
457 }
458
459 // List dual joycon pairs
460 for (std::size_t i = 0; i < MaxSupportedControllers; i++) {
461 if (!left_joycons[i] || !right_joycons[i]) {
462 continue;
463 }
464 if (!left_joycons[i]->IsConnected() || !right_joycons[i]->IsConnected()) {
465 continue;
466 }
467 auto main_param = GetParamPackage(i, left_joycons[i]->GetHandleDeviceType());
468 const auto second_param = GetParamPackage(i, right_joycons[i]->GetHandleDeviceType());
469 const auto type = Joycon::ControllerType::Dual;
470 std::string name = fmt::format("{} {}", JoyconName(type), i + 1);
471
472 main_param.Set("display", std::move(name));
473 main_param.Set("guid2", second_param.Get("guid", ""));
474 main_param.Set("pad", std::to_string(static_cast<size_t>(type)));
475 devices.emplace_back(main_param);
476 }
477
478 return devices;
479}
480
481ButtonMapping Joycons::GetButtonMappingForDevice(const Common::ParamPackage& params) {
482 static constexpr std::array<std::tuple<Settings::NativeButton::Values, Joycon::PadButton, bool>,
483 18>
484 switch_to_joycon_button = {
485 std::tuple{Settings::NativeButton::A, Joycon::PadButton::A, true},
486 {Settings::NativeButton::B, Joycon::PadButton::B, true},
487 {Settings::NativeButton::X, Joycon::PadButton::X, true},
488 {Settings::NativeButton::Y, Joycon::PadButton::Y, true},
489 {Settings::NativeButton::DLeft, Joycon::PadButton::Left, false},
490 {Settings::NativeButton::DUp, Joycon::PadButton::Up, false},
491 {Settings::NativeButton::DRight, Joycon::PadButton::Right, false},
492 {Settings::NativeButton::DDown, Joycon::PadButton::Down, false},
493 {Settings::NativeButton::L, Joycon::PadButton::L, false},
494 {Settings::NativeButton::R, Joycon::PadButton::R, true},
495 {Settings::NativeButton::ZL, Joycon::PadButton::ZL, false},
496 {Settings::NativeButton::ZR, Joycon::PadButton::ZR, true},
497 {Settings::NativeButton::Plus, Joycon::PadButton::Plus, true},
498 {Settings::NativeButton::Minus, Joycon::PadButton::Minus, false},
499 {Settings::NativeButton::Home, Joycon::PadButton::Home, true},
500 {Settings::NativeButton::Screenshot, Joycon::PadButton::Capture, false},
501 {Settings::NativeButton::LStick, Joycon::PadButton::StickL, false},
502 {Settings::NativeButton::RStick, Joycon::PadButton::StickR, true},
503 };
504
505 if (!params.Has("port")) {
506 return {};
507 }
508
509 ButtonMapping mapping{};
510 for (const auto& [switch_button, joycon_button, side] : switch_to_joycon_button) {
511 const std::size_t port = static_cast<std::size_t>(params.Get("port", 0));
512 auto pad = static_cast<Joycon::ControllerType>(params.Get("pad", 0));
513 if (pad == Joycon::ControllerType::Dual) {
514 pad = side ? Joycon::ControllerType::Right : Joycon::ControllerType::Left;
515 }
516
517 Common::ParamPackage button_params = GetParamPackage(port, pad);
518 button_params.Set("button", static_cast<int>(joycon_button));
519 mapping.insert_or_assign(switch_button, std::move(button_params));
520 }
521
522 // Map SL and SR buttons for left joycons
523 if (params.Get("pad", 0) == static_cast<int>(Joycon::ControllerType::Left)) {
524 const std::size_t port = static_cast<std::size_t>(params.Get("port", 0));
525 Common::ParamPackage button_params = GetParamPackage(port, Joycon::ControllerType::Left);
526
527 Common::ParamPackage sl_button_params = button_params;
528 Common::ParamPackage sr_button_params = button_params;
529 sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSL));
530 sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::LeftSR));
531 mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params));
532 mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params));
533 }
534
535 // Map SL and SR buttons for right joycons
536 if (params.Get("pad", 0) == static_cast<int>(Joycon::ControllerType::Right)) {
537 const std::size_t port = static_cast<std::size_t>(params.Get("port", 0));
538 Common::ParamPackage button_params = GetParamPackage(port, Joycon::ControllerType::Right);
539
540 Common::ParamPackage sl_button_params = button_params;
541 Common::ParamPackage sr_button_params = button_params;
542 sl_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSL));
543 sr_button_params.Set("button", static_cast<int>(Joycon::PadButton::RightSR));
544 mapping.insert_or_assign(Settings::NativeButton::SL, std::move(sl_button_params));
545 mapping.insert_or_assign(Settings::NativeButton::SR, std::move(sr_button_params));
546 }
547
548 return mapping;
549}
550
551AnalogMapping Joycons::GetAnalogMappingForDevice(const Common::ParamPackage& params) {
552 if (!params.Has("port")) {
553 return {};
554 }
555
556 const std::size_t port = static_cast<std::size_t>(params.Get("port", 0));
557 auto pad_left = static_cast<Joycon::ControllerType>(params.Get("pad", 0));
558 auto pad_right = pad_left;
559 if (pad_left == Joycon::ControllerType::Dual) {
560 pad_left = Joycon::ControllerType::Left;
561 pad_right = Joycon::ControllerType::Right;
562 }
563
564 AnalogMapping mapping = {};
565 Common::ParamPackage left_analog_params = GetParamPackage(port, pad_left);
566 left_analog_params.Set("axis_x", static_cast<int>(Joycon::PadAxes::LeftStickX));
567 left_analog_params.Set("axis_y", static_cast<int>(Joycon::PadAxes::LeftStickY));
568 mapping.insert_or_assign(Settings::NativeAnalog::LStick, std::move(left_analog_params));
569 Common::ParamPackage right_analog_params = GetParamPackage(port, pad_right);
570 right_analog_params.Set("axis_x", static_cast<int>(Joycon::PadAxes::RightStickX));
571 right_analog_params.Set("axis_y", static_cast<int>(Joycon::PadAxes::RightStickY));
572 mapping.insert_or_assign(Settings::NativeAnalog::RStick, std::move(right_analog_params));
573 return mapping;
574}
575
576MotionMapping Joycons::GetMotionMappingForDevice(const Common::ParamPackage& params) {
577 if (!params.Has("port")) {
578 return {};
579 }
580
581 const std::size_t port = static_cast<std::size_t>(params.Get("port", 0));
582 auto pad_left = static_cast<Joycon::ControllerType>(params.Get("pad", 0));
583 auto pad_right = pad_left;
584 if (pad_left == Joycon::ControllerType::Dual) {
585 pad_left = Joycon::ControllerType::Left;
586 pad_right = Joycon::ControllerType::Right;
587 }
588
589 MotionMapping mapping = {};
590 Common::ParamPackage left_motion_params = GetParamPackage(port, pad_left);
591 left_motion_params.Set("motion", 0);
592 mapping.insert_or_assign(Settings::NativeMotion::MotionLeft, std::move(left_motion_params));
593 Common::ParamPackage right_Motion_params = GetParamPackage(port, pad_right);
594 right_Motion_params.Set("motion", 1);
595 mapping.insert_or_assign(Settings::NativeMotion::MotionRight, std::move(right_Motion_params));
596 return mapping;
597}
598
599Common::Input::ButtonNames Joycons::GetUIButtonName(const Common::ParamPackage& params) const {
600 const auto button = static_cast<Joycon::PadButton>(params.Get("button", 0));
601 switch (button) {
602 case Joycon::PadButton::Left:
603 return Common::Input::ButtonNames::ButtonLeft;
604 case Joycon::PadButton::Right:
605 return Common::Input::ButtonNames::ButtonRight;
606 case Joycon::PadButton::Down:
607 return Common::Input::ButtonNames::ButtonDown;
608 case Joycon::PadButton::Up:
609 return Common::Input::ButtonNames::ButtonUp;
610 case Joycon::PadButton::LeftSL:
611 case Joycon::PadButton::RightSL:
612 return Common::Input::ButtonNames::TriggerSL;
613 case Joycon::PadButton::LeftSR:
614 case Joycon::PadButton::RightSR:
615 return Common::Input::ButtonNames::TriggerSR;
616 case Joycon::PadButton::L:
617 return Common::Input::ButtonNames::TriggerL;
618 case Joycon::PadButton::R:
619 return Common::Input::ButtonNames::TriggerR;
620 case Joycon::PadButton::ZL:
621 return Common::Input::ButtonNames::TriggerZL;
622 case Joycon::PadButton::ZR:
623 return Common::Input::ButtonNames::TriggerZR;
624 case Joycon::PadButton::A:
625 return Common::Input::ButtonNames::ButtonA;
626 case Joycon::PadButton::B:
627 return Common::Input::ButtonNames::ButtonB;
628 case Joycon::PadButton::X:
629 return Common::Input::ButtonNames::ButtonX;
630 case Joycon::PadButton::Y:
631 return Common::Input::ButtonNames::ButtonY;
632 case Joycon::PadButton::Plus:
633 return Common::Input::ButtonNames::ButtonPlus;
634 case Joycon::PadButton::Minus:
635 return Common::Input::ButtonNames::ButtonMinus;
636 case Joycon::PadButton::Home:
637 return Common::Input::ButtonNames::ButtonHome;
638 case Joycon::PadButton::Capture:
639 return Common::Input::ButtonNames::ButtonCapture;
640 case Joycon::PadButton::StickL:
641 return Common::Input::ButtonNames::ButtonStickL;
642 case Joycon::PadButton::StickR:
643 return Common::Input::ButtonNames::ButtonStickR;
644 default:
645 return Common::Input::ButtonNames::Undefined;
646 }
647}
648
649Common::Input::ButtonNames Joycons::GetUIName(const Common::ParamPackage& params) const {
650 if (params.Has("button")) {
651 return GetUIButtonName(params);
652 }
653 if (params.Has("axis")) {
654 return Common::Input::ButtonNames::Value;
655 }
656 if (params.Has("motion")) {
657 return Common::Input::ButtonNames::Engine;
658 }
659
660 return Common::Input::ButtonNames::Invalid;
661}
662
663std::string Joycons::JoyconName(Joycon::ControllerType type) const {
664 switch (type) {
665 case Joycon::ControllerType::Left:
666 return "Left Joycon";
667 case Joycon::ControllerType::Right:
668 return "Right Joycon";
669 case Joycon::ControllerType::Pro:
670 return "Pro Controller";
671 case Joycon::ControllerType::Dual:
672 return "Dual Joycon";
673 default:
674 return "Unknown Switch Controller";
675 }
676}
677} // namespace InputCommon