emulated_controller.cpp 31 KB

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