emulated_controller.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included
  4. #include "core/hid/emulated_controller.h"
  5. #include "core/hid/input_converter.h"
  6. namespace Core::HID {
  7. constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
  8. constexpr s32 HID_TRIGGER_MAX = 0x7fff;
  9. EmulatedController::EmulatedController(NpadIdType npad_id_type_) : npad_id_type(npad_id_type_) {}
  10. EmulatedController::~EmulatedController() = default;
  11. NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerType type) {
  12. switch (type) {
  13. case Settings::ControllerType::ProController:
  14. return NpadStyleIndex::ProController;
  15. case Settings::ControllerType::DualJoyconDetached:
  16. return NpadStyleIndex::JoyconDual;
  17. case Settings::ControllerType::LeftJoycon:
  18. return NpadStyleIndex::JoyconLeft;
  19. case Settings::ControllerType::RightJoycon:
  20. return NpadStyleIndex::JoyconRight;
  21. case Settings::ControllerType::Handheld:
  22. return NpadStyleIndex::Handheld;
  23. case Settings::ControllerType::GameCube:
  24. return NpadStyleIndex::GameCube;
  25. default:
  26. return NpadStyleIndex::ProController;
  27. }
  28. }
  29. Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleIndex type) {
  30. switch (type) {
  31. case NpadStyleIndex::ProController:
  32. return Settings::ControllerType::ProController;
  33. case NpadStyleIndex::JoyconDual:
  34. return Settings::ControllerType::DualJoyconDetached;
  35. case NpadStyleIndex::JoyconLeft:
  36. return Settings::ControllerType::LeftJoycon;
  37. case NpadStyleIndex::JoyconRight:
  38. return Settings::ControllerType::RightJoycon;
  39. case NpadStyleIndex::Handheld:
  40. return Settings::ControllerType::Handheld;
  41. case NpadStyleIndex::GameCube:
  42. return Settings::ControllerType::GameCube;
  43. default:
  44. return Settings::ControllerType::ProController;
  45. }
  46. }
  47. void EmulatedController::ReloadFromSettings() {
  48. const auto player_index = NpadIdTypeToIndex(npad_id_type);
  49. const auto& player = Settings::values.players.GetValue()[player_index];
  50. for (std::size_t index = 0; index < player.buttons.size(); ++index) {
  51. button_params[index] = Common::ParamPackage(player.buttons[index]);
  52. }
  53. for (std::size_t index = 0; index < player.analogs.size(); ++index) {
  54. stick_params[index] = Common::ParamPackage(player.analogs[index]);
  55. }
  56. for (std::size_t index = 0; index < player.motions.size(); ++index) {
  57. motion_params[index] = Common::ParamPackage(player.motions[index]);
  58. }
  59. controller.colors_state.left = {
  60. .body = player.body_color_left,
  61. .button = player.button_color_left,
  62. };
  63. controller.colors_state.right = {
  64. .body = player.body_color_right,
  65. .button = player.button_color_right,
  66. };
  67. controller.colors_state.fullkey = controller.colors_state.left;
  68. // Other or debug controller should always be a pro controller
  69. if (npad_id_type != NpadIdType::Other) {
  70. SetNpadStyleIndex(MapSettingsTypeToNPad(player.controller_type));
  71. } else {
  72. SetNpadStyleIndex(NpadStyleIndex::ProController);
  73. }
  74. if (player.connected) {
  75. Connect();
  76. } else {
  77. Disconnect();
  78. }
  79. ReloadInput();
  80. }
  81. void EmulatedController::LoadDevices() {
  82. // TODO(german77): Use more buttons to detect the correct device
  83. const auto left_joycon = button_params[Settings::NativeButton::A];
  84. const auto right_joycon = button_params[Settings::NativeButton::DRight];
  85. // Triggers for GC controllers
  86. trigger_params[LeftIndex] = button_params[Settings::NativeButton::ZL];
  87. trigger_params[RightIndex] = button_params[Settings::NativeButton::ZR];
  88. battery_params[LeftIndex] = left_joycon;
  89. battery_params[RightIndex] = right_joycon;
  90. battery_params[LeftIndex].Set("battery", true);
  91. battery_params[RightIndex].Set("battery", true);
  92. output_params[LeftIndex] = left_joycon;
  93. output_params[RightIndex] = right_joycon;
  94. output_params[LeftIndex].Set("output", true);
  95. output_params[RightIndex].Set("output", true);
  96. LoadTASParams();
  97. std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  98. button_params.begin() + Settings::NativeButton::BUTTON_NS_END,
  99. button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
  100. std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  101. stick_params.begin() + Settings::NativeAnalog::STICK_HID_END,
  102. stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
  103. std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
  104. motion_params.begin() + Settings::NativeMotion::MOTION_HID_END,
  105. motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>);
  106. std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(),
  107. Common::Input::CreateDevice<Common::Input::InputDevice>);
  108. std::transform(battery_params.begin(), battery_params.begin(), battery_devices.end(),
  109. Common::Input::CreateDevice<Common::Input::InputDevice>);
  110. std::transform(output_params.begin(), output_params.end(), output_devices.begin(),
  111. Common::Input::CreateDevice<Common::Input::OutputDevice>);
  112. // Initialize TAS devices
  113. std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(),
  114. Common::Input::CreateDevice<Common::Input::InputDevice>);
  115. std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(),
  116. Common::Input::CreateDevice<Common::Input::InputDevice>);
  117. }
  118. void EmulatedController::LoadTASParams() {
  119. const auto player_index = NpadIdTypeToIndex(npad_id_type);
  120. Common::ParamPackage common_params{};
  121. common_params.Set("engine", "tas");
  122. common_params.Set("port", static_cast<int>(player_index));
  123. for (auto& param : tas_button_params) {
  124. param = common_params;
  125. }
  126. for (auto& param : tas_stick_params) {
  127. param = common_params;
  128. }
  129. // TODO(german77): Replace this with an input profile or something better
  130. tas_button_params[Settings::NativeButton::A].Set("button", 0);
  131. tas_button_params[Settings::NativeButton::B].Set("button", 1);
  132. tas_button_params[Settings::NativeButton::X].Set("button", 2);
  133. tas_button_params[Settings::NativeButton::Y].Set("button", 3);
  134. tas_button_params[Settings::NativeButton::LStick].Set("button", 4);
  135. tas_button_params[Settings::NativeButton::RStick].Set("button", 5);
  136. tas_button_params[Settings::NativeButton::L].Set("button", 6);
  137. tas_button_params[Settings::NativeButton::R].Set("button", 7);
  138. tas_button_params[Settings::NativeButton::ZL].Set("button", 8);
  139. tas_button_params[Settings::NativeButton::ZR].Set("button", 9);
  140. tas_button_params[Settings::NativeButton::Plus].Set("button", 10);
  141. tas_button_params[Settings::NativeButton::Minus].Set("button", 11);
  142. tas_button_params[Settings::NativeButton::DLeft].Set("button", 12);
  143. tas_button_params[Settings::NativeButton::DUp].Set("button", 13);
  144. tas_button_params[Settings::NativeButton::DRight].Set("button", 14);
  145. tas_button_params[Settings::NativeButton::DDown].Set("button", 15);
  146. tas_button_params[Settings::NativeButton::SL].Set("button", 16);
  147. tas_button_params[Settings::NativeButton::SR].Set("button", 17);
  148. tas_button_params[Settings::NativeButton::Home].Set("button", 18);
  149. tas_button_params[Settings::NativeButton::Screenshot].Set("button", 19);
  150. tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_x", 0);
  151. tas_stick_params[Settings::NativeAnalog::LStick].Set("axis_y", 1);
  152. tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_x", 2);
  153. tas_stick_params[Settings::NativeAnalog::RStick].Set("axis_y", 3);
  154. }
  155. void EmulatedController::ReloadInput() {
  156. // If you load any device here add the equivalent to the UnloadInput() function
  157. LoadDevices();
  158. for (std::size_t index = 0; index < button_devices.size(); ++index) {
  159. if (!button_devices[index]) {
  160. continue;
  161. }
  162. const auto uuid = Common::UUID{button_params[index].Get("guid", "")};
  163. Common::Input::InputCallback button_callback{
  164. [this, index, uuid](Common::Input::CallbackStatus callback) {
  165. SetButton(callback, index, uuid);
  166. }};
  167. button_devices[index]->SetCallback(button_callback);
  168. button_devices[index]->ForceUpdate();
  169. }
  170. for (std::size_t index = 0; index < stick_devices.size(); ++index) {
  171. if (!stick_devices[index]) {
  172. continue;
  173. }
  174. const auto uuid = Common::UUID{stick_params[index].Get("guid", "")};
  175. Common::Input::InputCallback stick_callback{
  176. [this, index, uuid](Common::Input::CallbackStatus callback) {
  177. SetStick(callback, index, uuid);
  178. }};
  179. stick_devices[index]->SetCallback(stick_callback);
  180. stick_devices[index]->ForceUpdate();
  181. }
  182. for (std::size_t index = 0; index < trigger_devices.size(); ++index) {
  183. if (!trigger_devices[index]) {
  184. continue;
  185. }
  186. const auto uuid = Common::UUID{trigger_params[index].Get("guid", "")};
  187. Common::Input::InputCallback trigger_callback{
  188. [this, index, uuid](Common::Input::CallbackStatus callback) {
  189. SetTrigger(callback, index, uuid);
  190. }};
  191. trigger_devices[index]->SetCallback(trigger_callback);
  192. trigger_devices[index]->ForceUpdate();
  193. }
  194. for (std::size_t index = 0; index < battery_devices.size(); ++index) {
  195. if (!battery_devices[index]) {
  196. continue;
  197. }
  198. Common::Input::InputCallback battery_callback{
  199. [this, index](Common::Input::CallbackStatus callback) { SetBattery(callback, index); }};
  200. battery_devices[index]->SetCallback(battery_callback);
  201. battery_devices[index]->ForceUpdate();
  202. }
  203. for (std::size_t index = 0; index < motion_devices.size(); ++index) {
  204. if (!motion_devices[index]) {
  205. continue;
  206. }
  207. Common::Input::InputCallback motion_callback{
  208. [this, index](Common::Input::CallbackStatus callback) { SetMotion(callback, index); }};
  209. motion_devices[index]->SetCallback(motion_callback);
  210. motion_devices[index]->ForceUpdate();
  211. }
  212. // Use a common UUID for TAS
  213. const auto tas_uuid = Common::UUID{0x0, 0x7A5};
  214. // Register TAS devices. No need to force update
  215. for (std::size_t index = 0; index < tas_button_devices.size(); ++index) {
  216. if (!tas_button_devices[index]) {
  217. continue;
  218. }
  219. Common::Input::InputCallback button_callback{
  220. [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
  221. SetButton(callback, index, tas_uuid);
  222. }};
  223. tas_button_devices[index]->SetCallback(button_callback);
  224. }
  225. for (std::size_t index = 0; index < tas_stick_devices.size(); ++index) {
  226. if (!tas_stick_devices[index]) {
  227. continue;
  228. }
  229. Common::Input::InputCallback stick_callback{
  230. [this, index, tas_uuid](Common::Input::CallbackStatus callback) {
  231. SetStick(callback, index, tas_uuid);
  232. }};
  233. tas_stick_devices[index]->SetCallback(stick_callback);
  234. }
  235. }
  236. void EmulatedController::UnloadInput() {
  237. for (auto& button : button_devices) {
  238. button.reset();
  239. }
  240. for (auto& stick : stick_devices) {
  241. stick.reset();
  242. }
  243. for (auto& motion : motion_devices) {
  244. motion.reset();
  245. }
  246. for (auto& trigger : trigger_devices) {
  247. trigger.reset();
  248. }
  249. for (auto& battery : battery_devices) {
  250. battery.reset();
  251. }
  252. for (auto& output : output_devices) {
  253. output.reset();
  254. }
  255. for (auto& button : tas_button_devices) {
  256. button.reset();
  257. }
  258. for (auto& stick : tas_stick_devices) {
  259. stick.reset();
  260. }
  261. }
  262. void EmulatedController::EnableConfiguration() {
  263. is_configuring = true;
  264. tmp_is_connected = is_connected;
  265. tmp_npad_type = npad_type;
  266. }
  267. void EmulatedController::DisableConfiguration() {
  268. is_configuring = false;
  269. // Apply temporary npad type to the real controller
  270. if (tmp_npad_type != npad_type) {
  271. if (is_connected) {
  272. Disconnect();
  273. }
  274. SetNpadStyleIndex(tmp_npad_type);
  275. }
  276. // Apply temporary connected status to the real controller
  277. if (tmp_is_connected != is_connected) {
  278. if (tmp_is_connected) {
  279. Connect();
  280. return;
  281. }
  282. Disconnect();
  283. }
  284. }
  285. bool EmulatedController::IsConfiguring() const {
  286. return is_configuring;
  287. }
  288. void EmulatedController::SaveCurrentConfig() {
  289. const auto player_index = NpadIdTypeToIndex(npad_id_type);
  290. auto& player = Settings::values.players.GetValue()[player_index];
  291. player.connected = is_connected;
  292. player.controller_type = MapNPadToSettingsType(npad_type);
  293. for (std::size_t index = 0; index < player.buttons.size(); ++index) {
  294. player.buttons[index] = button_params[index].Serialize();
  295. }
  296. for (std::size_t index = 0; index < player.analogs.size(); ++index) {
  297. player.analogs[index] = stick_params[index].Serialize();
  298. }
  299. for (std::size_t index = 0; index < player.motions.size(); ++index) {
  300. player.motions[index] = motion_params[index].Serialize();
  301. }
  302. }
  303. void EmulatedController::RestoreConfig() {
  304. if (!is_configuring) {
  305. return;
  306. }
  307. ReloadFromSettings();
  308. }
  309. std::vector<Common::ParamPackage> EmulatedController::GetMappedDevices(
  310. DeviceIndex device_index) const {
  311. std::vector<Common::ParamPackage> devices;
  312. for (const auto& param : button_params) {
  313. if (!param.Has("engine")) {
  314. continue;
  315. }
  316. const auto devices_it = std::find_if(
  317. devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
  318. return param.Get("engine", "") == param_.Get("engine", "") &&
  319. param.Get("guid", "") == param_.Get("guid", "") &&
  320. param.Get("port", 0) == param_.Get("port", 0);
  321. });
  322. if (devices_it != devices.end()) {
  323. continue;
  324. }
  325. Common::ParamPackage device{};
  326. device.Set("engine", param.Get("engine", ""));
  327. device.Set("guid", param.Get("guid", ""));
  328. device.Set("port", param.Get("port", 0));
  329. devices.push_back(device);
  330. }
  331. for (const auto& param : stick_params) {
  332. if (!param.Has("engine")) {
  333. continue;
  334. }
  335. if (param.Get("engine", "") == "analog_from_button") {
  336. continue;
  337. }
  338. const auto devices_it = std::find_if(
  339. devices.begin(), devices.end(), [param](const Common::ParamPackage param_) {
  340. return param.Get("engine", "") == param_.Get("engine", "") &&
  341. param.Get("guid", "") == param_.Get("guid", "") &&
  342. param.Get("port", 0) == param_.Get("port", 0);
  343. });
  344. if (devices_it != devices.end()) {
  345. continue;
  346. }
  347. Common::ParamPackage device{};
  348. device.Set("engine", param.Get("engine", ""));
  349. device.Set("guid", param.Get("guid", ""));
  350. device.Set("port", param.Get("port", 0));
  351. devices.push_back(device);
  352. }
  353. return devices;
  354. }
  355. Common::ParamPackage EmulatedController::GetButtonParam(std::size_t index) const {
  356. if (index >= button_params.size()) {
  357. return {};
  358. }
  359. return button_params[index];
  360. }
  361. Common::ParamPackage EmulatedController::GetStickParam(std::size_t index) const {
  362. if (index >= stick_params.size()) {
  363. return {};
  364. }
  365. return stick_params[index];
  366. }
  367. Common::ParamPackage EmulatedController::GetMotionParam(std::size_t index) const {
  368. if (index >= motion_params.size()) {
  369. return {};
  370. }
  371. return motion_params[index];
  372. }
  373. void EmulatedController::SetButtonParam(std::size_t index, Common::ParamPackage param) {
  374. if (index >= button_params.size()) {
  375. return;
  376. }
  377. button_params[index] = param;
  378. ReloadInput();
  379. }
  380. void EmulatedController::SetStickParam(std::size_t index, Common::ParamPackage param) {
  381. if (index >= stick_params.size()) {
  382. return;
  383. }
  384. stick_params[index] = param;
  385. ReloadInput();
  386. }
  387. void EmulatedController::SetMotionParam(std::size_t index, Common::ParamPackage param) {
  388. if (index >= motion_params.size()) {
  389. return;
  390. }
  391. motion_params[index] = param;
  392. ReloadInput();
  393. }
  394. void EmulatedController::SetButton(Common::Input::CallbackStatus callback, std::size_t index,
  395. Common::UUID uuid) {
  396. if (index >= controller.button_values.size()) {
  397. return;
  398. }
  399. {
  400. std::lock_guard lock{mutex};
  401. bool value_changed = false;
  402. const auto new_status = TransformToButton(callback);
  403. auto& current_status = controller.button_values[index];
  404. // Only read button values that have the same uuid or are pressed once
  405. if (current_status.uuid != uuid) {
  406. if (!new_status.value) {
  407. return;
  408. }
  409. }
  410. current_status.toggle = new_status.toggle;
  411. current_status.uuid = uuid;
  412. // Update button status with current
  413. if (!current_status.toggle) {
  414. current_status.locked = false;
  415. if (current_status.value != new_status.value) {
  416. current_status.value = new_status.value;
  417. value_changed = true;
  418. }
  419. } else {
  420. // Toggle button and lock status
  421. if (new_status.value && !current_status.locked) {
  422. current_status.locked = true;
  423. current_status.value = !current_status.value;
  424. value_changed = true;
  425. }
  426. // Unlock button ready for next press
  427. if (!new_status.value && current_status.locked) {
  428. current_status.locked = false;
  429. }
  430. }
  431. if (!value_changed) {
  432. return;
  433. }
  434. if (is_configuring) {
  435. controller.npad_button_state.raw = NpadButton::None;
  436. controller.debug_pad_button_state.raw = 0;
  437. TriggerOnChange(ControllerTriggerType::Button, false);
  438. return;
  439. }
  440. switch (index) {
  441. case Settings::NativeButton::A:
  442. controller.npad_button_state.a.Assign(current_status.value);
  443. controller.debug_pad_button_state.a.Assign(current_status.value);
  444. break;
  445. case Settings::NativeButton::B:
  446. controller.npad_button_state.b.Assign(current_status.value);
  447. controller.debug_pad_button_state.b.Assign(current_status.value);
  448. break;
  449. case Settings::NativeButton::X:
  450. controller.npad_button_state.x.Assign(current_status.value);
  451. controller.debug_pad_button_state.x.Assign(current_status.value);
  452. break;
  453. case Settings::NativeButton::Y:
  454. controller.npad_button_state.y.Assign(current_status.value);
  455. controller.debug_pad_button_state.y.Assign(current_status.value);
  456. break;
  457. case Settings::NativeButton::LStick:
  458. controller.npad_button_state.stick_l.Assign(current_status.value);
  459. break;
  460. case Settings::NativeButton::RStick:
  461. controller.npad_button_state.stick_r.Assign(current_status.value);
  462. break;
  463. case Settings::NativeButton::L:
  464. controller.npad_button_state.l.Assign(current_status.value);
  465. controller.debug_pad_button_state.l.Assign(current_status.value);
  466. break;
  467. case Settings::NativeButton::R:
  468. controller.npad_button_state.r.Assign(current_status.value);
  469. controller.debug_pad_button_state.r.Assign(current_status.value);
  470. break;
  471. case Settings::NativeButton::ZL:
  472. controller.npad_button_state.zl.Assign(current_status.value);
  473. controller.debug_pad_button_state.zl.Assign(current_status.value);
  474. break;
  475. case Settings::NativeButton::ZR:
  476. controller.npad_button_state.zr.Assign(current_status.value);
  477. controller.debug_pad_button_state.zr.Assign(current_status.value);
  478. break;
  479. case Settings::NativeButton::Plus:
  480. controller.npad_button_state.plus.Assign(current_status.value);
  481. controller.debug_pad_button_state.plus.Assign(current_status.value);
  482. break;
  483. case Settings::NativeButton::Minus:
  484. controller.npad_button_state.minus.Assign(current_status.value);
  485. controller.debug_pad_button_state.minus.Assign(current_status.value);
  486. break;
  487. case Settings::NativeButton::DLeft:
  488. controller.npad_button_state.left.Assign(current_status.value);
  489. controller.debug_pad_button_state.d_left.Assign(current_status.value);
  490. break;
  491. case Settings::NativeButton::DUp:
  492. controller.npad_button_state.up.Assign(current_status.value);
  493. controller.debug_pad_button_state.d_up.Assign(current_status.value);
  494. break;
  495. case Settings::NativeButton::DRight:
  496. controller.npad_button_state.right.Assign(current_status.value);
  497. controller.debug_pad_button_state.d_right.Assign(current_status.value);
  498. break;
  499. case Settings::NativeButton::DDown:
  500. controller.npad_button_state.down.Assign(current_status.value);
  501. controller.debug_pad_button_state.d_down.Assign(current_status.value);
  502. break;
  503. case Settings::NativeButton::SL:
  504. controller.npad_button_state.left_sl.Assign(current_status.value);
  505. controller.npad_button_state.right_sl.Assign(current_status.value);
  506. break;
  507. case Settings::NativeButton::SR:
  508. controller.npad_button_state.left_sr.Assign(current_status.value);
  509. controller.npad_button_state.right_sr.Assign(current_status.value);
  510. break;
  511. case Settings::NativeButton::Home:
  512. case Settings::NativeButton::Screenshot:
  513. break;
  514. }
  515. }
  516. if (!is_connected) {
  517. if (npad_id_type == NpadIdType::Player1 && npad_type != NpadStyleIndex::Handheld) {
  518. Connect();
  519. }
  520. if (npad_id_type == NpadIdType::Handheld && npad_type == NpadStyleIndex::Handheld) {
  521. Connect();
  522. }
  523. }
  524. TriggerOnChange(ControllerTriggerType::Button, true);
  525. }
  526. void EmulatedController::SetStick(Common::Input::CallbackStatus callback, std::size_t index,
  527. Common::UUID uuid) {
  528. if (index >= controller.stick_values.size()) {
  529. return;
  530. }
  531. std::lock_guard lock{mutex};
  532. const auto stick_value = TransformToStick(callback);
  533. // Only read stick values that have the same uuid or are over the threshold to avoid flapping
  534. if (controller.stick_values[index].uuid != uuid) {
  535. if (!stick_value.down && !stick_value.up && !stick_value.left && !stick_value.right) {
  536. return;
  537. }
  538. }
  539. controller.stick_values[index] = stick_value;
  540. controller.stick_values[index].uuid = uuid;
  541. if (is_configuring) {
  542. controller.analog_stick_state.left = {};
  543. controller.analog_stick_state.right = {};
  544. TriggerOnChange(ControllerTriggerType::Stick, false);
  545. return;
  546. }
  547. const AnalogStickState stick{
  548. .x = static_cast<s32>(controller.stick_values[index].x.value * HID_JOYSTICK_MAX),
  549. .y = static_cast<s32>(controller.stick_values[index].y.value * HID_JOYSTICK_MAX),
  550. };
  551. switch (index) {
  552. case Settings::NativeAnalog::LStick:
  553. controller.analog_stick_state.left = stick;
  554. controller.npad_button_state.stick_l_left.Assign(controller.stick_values[index].left);
  555. controller.npad_button_state.stick_l_up.Assign(controller.stick_values[index].up);
  556. controller.npad_button_state.stick_l_right.Assign(controller.stick_values[index].right);
  557. controller.npad_button_state.stick_l_down.Assign(controller.stick_values[index].down);
  558. break;
  559. case Settings::NativeAnalog::RStick:
  560. controller.analog_stick_state.right = stick;
  561. controller.npad_button_state.stick_r_left.Assign(controller.stick_values[index].left);
  562. controller.npad_button_state.stick_r_up.Assign(controller.stick_values[index].up);
  563. controller.npad_button_state.stick_r_right.Assign(controller.stick_values[index].right);
  564. controller.npad_button_state.stick_r_down.Assign(controller.stick_values[index].down);
  565. break;
  566. }
  567. TriggerOnChange(ControllerTriggerType::Stick, true);
  568. }
  569. void EmulatedController::SetTrigger(Common::Input::CallbackStatus callback, std::size_t index,
  570. Common::UUID uuid) {
  571. if (index >= controller.trigger_values.size()) {
  572. return;
  573. }
  574. std::lock_guard lock{mutex};
  575. const auto trigger_value = TransformToTrigger(callback);
  576. // Only read trigger values that have the same uuid or are pressed once
  577. if (controller.stick_values[index].uuid != uuid) {
  578. if (!trigger_value.pressed.value) {
  579. return;
  580. }
  581. }
  582. controller.trigger_values[index] = trigger_value;
  583. controller.trigger_values[index].uuid = uuid;
  584. if (is_configuring) {
  585. controller.gc_trigger_state.left = 0;
  586. controller.gc_trigger_state.right = 0;
  587. TriggerOnChange(ControllerTriggerType::Trigger, false);
  588. return;
  589. }
  590. const auto trigger = controller.trigger_values[index];
  591. switch (index) {
  592. case Settings::NativeTrigger::LTrigger:
  593. controller.gc_trigger_state.left = static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
  594. controller.npad_button_state.zl.Assign(trigger.pressed.value);
  595. break;
  596. case Settings::NativeTrigger::RTrigger:
  597. controller.gc_trigger_state.right =
  598. static_cast<s32>(trigger.analog.value * HID_TRIGGER_MAX);
  599. controller.npad_button_state.zr.Assign(trigger.pressed.value);
  600. break;
  601. }
  602. TriggerOnChange(ControllerTriggerType::Trigger, true);
  603. }
  604. void EmulatedController::SetMotion(Common::Input::CallbackStatus callback, std::size_t index) {
  605. if (index >= controller.motion_values.size()) {
  606. return;
  607. }
  608. std::lock_guard lock{mutex};
  609. auto& raw_status = controller.motion_values[index].raw_status;
  610. auto& emulated = controller.motion_values[index].emulated;
  611. raw_status = TransformToMotion(callback);
  612. emulated.SetAcceleration(Common::Vec3f{
  613. raw_status.accel.x.value,
  614. raw_status.accel.y.value,
  615. raw_status.accel.z.value,
  616. });
  617. emulated.SetGyroscope(Common::Vec3f{
  618. raw_status.gyro.x.value,
  619. raw_status.gyro.y.value,
  620. raw_status.gyro.z.value,
  621. });
  622. emulated.UpdateRotation(raw_status.delta_timestamp);
  623. emulated.UpdateOrientation(raw_status.delta_timestamp);
  624. force_update_motion = raw_status.force_update;
  625. if (is_configuring) {
  626. TriggerOnChange(ControllerTriggerType::Motion, false);
  627. return;
  628. }
  629. auto& motion = controller.motion_state[index];
  630. motion.accel = emulated.GetAcceleration();
  631. motion.gyro = emulated.GetGyroscope();
  632. motion.rotation = emulated.GetRotations();
  633. motion.orientation = emulated.GetOrientation();
  634. motion.is_at_rest = emulated.IsMoving(motion_sensitivity);
  635. TriggerOnChange(ControllerTriggerType::Motion, true);
  636. }
  637. void EmulatedController::SetBattery(Common::Input::CallbackStatus callback, std::size_t index) {
  638. if (index >= controller.battery_values.size()) {
  639. return;
  640. }
  641. std::lock_guard lock{mutex};
  642. controller.battery_values[index] = TransformToBattery(callback);
  643. if (is_configuring) {
  644. TriggerOnChange(ControllerTriggerType::Battery, false);
  645. return;
  646. }
  647. bool is_charging = false;
  648. bool is_powered = false;
  649. BatteryLevel battery_level = 0;
  650. switch (controller.battery_values[index]) {
  651. case Common::Input::BatteryLevel::Charging:
  652. is_charging = true;
  653. is_powered = true;
  654. battery_level = 6;
  655. break;
  656. case Common::Input::BatteryLevel::Medium:
  657. battery_level = 6;
  658. break;
  659. case Common::Input::BatteryLevel::Low:
  660. battery_level = 4;
  661. break;
  662. case Common::Input::BatteryLevel::Critical:
  663. battery_level = 2;
  664. break;
  665. case Common::Input::BatteryLevel::Empty:
  666. battery_level = 0;
  667. break;
  668. case Common::Input::BatteryLevel::None:
  669. case Common::Input::BatteryLevel::Full:
  670. default:
  671. is_powered = true;
  672. battery_level = 8;
  673. break;
  674. }
  675. switch (index) {
  676. case LeftIndex:
  677. controller.battery_state.left = {
  678. .is_powered = is_powered,
  679. .is_charging = is_charging,
  680. .battery_level = battery_level,
  681. };
  682. break;
  683. case RightIndex:
  684. controller.battery_state.right = {
  685. .is_powered = is_powered,
  686. .is_charging = is_charging,
  687. .battery_level = battery_level,
  688. };
  689. break;
  690. case DualIndex:
  691. controller.battery_state.dual = {
  692. .is_powered = is_powered,
  693. .is_charging = is_charging,
  694. .battery_level = battery_level,
  695. };
  696. break;
  697. }
  698. TriggerOnChange(ControllerTriggerType::Battery, true);
  699. }
  700. bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
  701. if (device_index >= output_devices.size()) {
  702. return false;
  703. }
  704. if (!output_devices[device_index]) {
  705. return false;
  706. }
  707. const auto player_index = NpadIdTypeToIndex(npad_id_type);
  708. const auto& player = Settings::values.players.GetValue()[player_index];
  709. const f32 strength = static_cast<f32>(player.vibration_strength) / 100.0f;
  710. if (!player.vibration_enabled) {
  711. return false;
  712. }
  713. // Exponential amplification is too strong at low amplitudes. Switch to a linear
  714. // amplification if strength is set below 0.7f
  715. const Common::Input::VibrationAmplificationType type =
  716. strength > 0.7f ? Common::Input::VibrationAmplificationType::Exponential
  717. : Common::Input::VibrationAmplificationType::Linear;
  718. const Common::Input::VibrationStatus status = {
  719. .low_amplitude = std::min(vibration.low_amplitude * strength, 1.0f),
  720. .low_frequency = vibration.low_frequency,
  721. .high_amplitude = std::min(vibration.high_amplitude * strength, 1.0f),
  722. .high_frequency = vibration.high_frequency,
  723. .type = type,
  724. };
  725. return output_devices[device_index]->SetVibration(status) ==
  726. Common::Input::VibrationError::None;
  727. }
  728. bool EmulatedController::TestVibration(std::size_t device_index) {
  729. if (device_index >= output_devices.size()) {
  730. return false;
  731. }
  732. if (!output_devices[device_index]) {
  733. return false;
  734. }
  735. // Send a slight vibration to test for rumble support
  736. constexpr Common::Input::VibrationStatus status = {
  737. .low_amplitude = 0.001f,
  738. .low_frequency = 160.0f,
  739. .high_amplitude = 0.001f,
  740. .high_frequency = 320.0f,
  741. .type = Common::Input::VibrationAmplificationType::Linear,
  742. };
  743. return output_devices[device_index]->SetVibration(status) ==
  744. Common::Input::VibrationError::None;
  745. }
  746. void EmulatedController::SetLedPattern() {
  747. for (auto& device : output_devices) {
  748. if (!device) {
  749. continue;
  750. }
  751. const LedPattern pattern = GetLedPattern();
  752. const Common::Input::LedStatus status = {
  753. .led_1 = pattern.position1 != 0,
  754. .led_2 = pattern.position2 != 0,
  755. .led_3 = pattern.position3 != 0,
  756. .led_4 = pattern.position4 != 0,
  757. };
  758. device->SetLED(status);
  759. }
  760. }
  761. void EmulatedController::Connect() {
  762. {
  763. std::lock_guard lock{mutex};
  764. if (is_configuring) {
  765. tmp_is_connected = true;
  766. TriggerOnChange(ControllerTriggerType::Connected, false);
  767. return;
  768. }
  769. if (is_connected) {
  770. return;
  771. }
  772. is_connected = true;
  773. }
  774. TriggerOnChange(ControllerTriggerType::Connected, true);
  775. }
  776. void EmulatedController::Disconnect() {
  777. {
  778. std::lock_guard lock{mutex};
  779. if (is_configuring) {
  780. tmp_is_connected = false;
  781. TriggerOnChange(ControllerTriggerType::Disconnected, false);
  782. return;
  783. }
  784. if (!is_connected) {
  785. return;
  786. }
  787. is_connected = false;
  788. }
  789. TriggerOnChange(ControllerTriggerType::Disconnected, true);
  790. }
  791. bool EmulatedController::IsConnected(bool get_temporary_value) const {
  792. if (get_temporary_value && is_configuring) {
  793. return tmp_is_connected;
  794. }
  795. return is_connected;
  796. }
  797. bool EmulatedController::IsVibrationEnabled() const {
  798. const auto player_index = NpadIdTypeToIndex(npad_id_type);
  799. const auto& player = Settings::values.players.GetValue()[player_index];
  800. return player.vibration_enabled;
  801. }
  802. NpadIdType EmulatedController::GetNpadIdType() const {
  803. return npad_id_type;
  804. }
  805. NpadStyleIndex EmulatedController::GetNpadStyleIndex(bool get_temporary_value) const {
  806. if (get_temporary_value && is_configuring) {
  807. return tmp_npad_type;
  808. }
  809. return npad_type;
  810. }
  811. void EmulatedController::SetNpadStyleIndex(NpadStyleIndex npad_type_) {
  812. {
  813. std::lock_guard lock{mutex};
  814. if (is_configuring) {
  815. if (tmp_npad_type == npad_type_) {
  816. return;
  817. }
  818. tmp_npad_type = npad_type_;
  819. TriggerOnChange(ControllerTriggerType::Type, false);
  820. return;
  821. }
  822. if (npad_type == npad_type_) {
  823. return;
  824. }
  825. if (is_connected) {
  826. LOG_WARNING(Service_HID, "Controller {} type changed while it's connected",
  827. NpadIdTypeToIndex(npad_id_type));
  828. }
  829. npad_type = npad_type_;
  830. }
  831. TriggerOnChange(ControllerTriggerType::Type, true);
  832. }
  833. LedPattern EmulatedController::GetLedPattern() const {
  834. switch (npad_id_type) {
  835. case NpadIdType::Player1:
  836. return LedPattern{1, 0, 0, 0};
  837. case NpadIdType::Player2:
  838. return LedPattern{1, 1, 0, 0};
  839. case NpadIdType::Player3:
  840. return LedPattern{1, 1, 1, 0};
  841. case NpadIdType::Player4:
  842. return LedPattern{1, 1, 1, 1};
  843. case NpadIdType::Player5:
  844. return LedPattern{1, 0, 0, 1};
  845. case NpadIdType::Player6:
  846. return LedPattern{1, 0, 1, 0};
  847. case NpadIdType::Player7:
  848. return LedPattern{1, 0, 1, 1};
  849. case NpadIdType::Player8:
  850. return LedPattern{0, 1, 1, 0};
  851. default:
  852. return LedPattern{0, 0, 0, 0};
  853. }
  854. }
  855. ButtonValues EmulatedController::GetButtonsValues() const {
  856. return controller.button_values;
  857. }
  858. SticksValues EmulatedController::GetSticksValues() const {
  859. return controller.stick_values;
  860. }
  861. TriggerValues EmulatedController::GetTriggersValues() const {
  862. return controller.trigger_values;
  863. }
  864. ControllerMotionValues EmulatedController::GetMotionValues() const {
  865. return controller.motion_values;
  866. }
  867. ColorValues EmulatedController::GetColorsValues() const {
  868. return controller.color_values;
  869. }
  870. BatteryValues EmulatedController::GetBatteryValues() const {
  871. return controller.battery_values;
  872. }
  873. NpadButtonState EmulatedController::GetNpadButtons() const {
  874. if (is_configuring) {
  875. return {};
  876. }
  877. return controller.npad_button_state;
  878. }
  879. DebugPadButton EmulatedController::GetDebugPadButtons() const {
  880. if (is_configuring) {
  881. return {};
  882. }
  883. return controller.debug_pad_button_state;
  884. }
  885. AnalogSticks EmulatedController::GetSticks() const {
  886. if (is_configuring) {
  887. return {};
  888. }
  889. // Some drivers like stick from buttons need constant refreshing
  890. for (auto& device : stick_devices) {
  891. if (!device) {
  892. continue;
  893. }
  894. device->SoftUpdate();
  895. }
  896. return controller.analog_stick_state;
  897. }
  898. NpadGcTriggerState EmulatedController::GetTriggers() const {
  899. if (is_configuring) {
  900. return {};
  901. }
  902. return controller.gc_trigger_state;
  903. }
  904. MotionState EmulatedController::GetMotions() const {
  905. if (force_update_motion) {
  906. for (auto& device : motion_devices) {
  907. if (!device) {
  908. continue;
  909. }
  910. device->ForceUpdate();
  911. }
  912. }
  913. return controller.motion_state;
  914. }
  915. ControllerColors EmulatedController::GetColors() const {
  916. return controller.colors_state;
  917. }
  918. BatteryLevelState EmulatedController::GetBattery() const {
  919. return controller.battery_state;
  920. }
  921. void EmulatedController::TriggerOnChange(ControllerTriggerType type, bool is_npad_service_update) {
  922. for (const auto& poller_pair : callback_list) {
  923. const ControllerUpdateCallback& poller = poller_pair.second;
  924. if (!is_npad_service_update && poller.is_npad_service) {
  925. continue;
  926. }
  927. if (poller.on_change) {
  928. poller.on_change(type);
  929. }
  930. }
  931. }
  932. int EmulatedController::SetCallback(ControllerUpdateCallback update_callback) {
  933. std::lock_guard lock{mutex};
  934. callback_list.insert_or_assign(last_callback_key, update_callback);
  935. return last_callback_key++;
  936. }
  937. void EmulatedController::DeleteCallback(int key) {
  938. std::lock_guard lock{mutex};
  939. const auto& iterator = callback_list.find(key);
  940. if (iterator == callback_list.end()) {
  941. LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
  942. return;
  943. }
  944. callback_list.erase(iterator);
  945. }
  946. } // namespace Core::HID