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