emulated_controller.cpp 35 KB

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