emulated_controller.cpp 35 KB

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