joycon.cpp 26 KB

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