emulated_devices.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <fmt/format.h>
  5. #include "core/hid/emulated_devices.h"
  6. #include "core/hid/input_converter.h"
  7. namespace Core::HID {
  8. EmulatedDevices::EmulatedDevices() = default;
  9. EmulatedDevices::~EmulatedDevices() = default;
  10. void EmulatedDevices::ReloadFromSettings() {
  11. ring_params = Common::ParamPackage(Settings::values.ringcon_analogs);
  12. ReloadInput();
  13. }
  14. void EmulatedDevices::ReloadInput() {
  15. // If you load any device here add the equivalent to the UnloadInput() function
  16. std::size_t key_index = 0;
  17. for (auto& mouse_device : mouse_button_devices) {
  18. Common::ParamPackage mouse_params;
  19. mouse_params.Set("engine", "mouse");
  20. mouse_params.Set("button", static_cast<int>(key_index));
  21. mouse_device = Common::Input::CreateInputDevice(mouse_params);
  22. key_index++;
  23. }
  24. mouse_stick_device =
  25. Common::Input::CreateInputDeviceFromString("engine:mouse,axis_x:0,axis_y:1");
  26. // First two axis are reserved for mouse position
  27. key_index = 2;
  28. for (auto& mouse_device : mouse_analog_devices) {
  29. Common::ParamPackage mouse_params;
  30. mouse_params.Set("engine", "mouse");
  31. mouse_params.Set("axis", static_cast<int>(key_index));
  32. mouse_device = Common::Input::CreateInputDevice(mouse_params);
  33. key_index++;
  34. }
  35. key_index = 0;
  36. for (auto& keyboard_device : keyboard_devices) {
  37. // Keyboard keys are only mapped on port 1, pad 0
  38. Common::ParamPackage keyboard_params;
  39. keyboard_params.Set("engine", "keyboard");
  40. keyboard_params.Set("button", static_cast<int>(key_index));
  41. keyboard_params.Set("port", 1);
  42. keyboard_params.Set("pad", 0);
  43. keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
  44. key_index++;
  45. }
  46. key_index = 0;
  47. for (auto& keyboard_device : keyboard_modifier_devices) {
  48. // Keyboard moddifiers are only mapped on port 1, pad 1
  49. Common::ParamPackage keyboard_params;
  50. keyboard_params.Set("engine", "keyboard");
  51. keyboard_params.Set("button", static_cast<int>(key_index));
  52. keyboard_params.Set("port", 1);
  53. keyboard_params.Set("pad", 1);
  54. keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
  55. key_index++;
  56. }
  57. ring_analog_device = Common::Input::CreateInputDevice(ring_params);
  58. for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
  59. if (!mouse_button_devices[index]) {
  60. continue;
  61. }
  62. mouse_button_devices[index]->SetCallback({
  63. .on_change =
  64. [this, index](const Common::Input::CallbackStatus& callback) {
  65. SetMouseButton(callback, index);
  66. },
  67. });
  68. }
  69. for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) {
  70. if (!mouse_analog_devices[index]) {
  71. continue;
  72. }
  73. mouse_analog_devices[index]->SetCallback({
  74. .on_change =
  75. [this, index](const Common::Input::CallbackStatus& callback) {
  76. SetMouseAnalog(callback, index);
  77. },
  78. });
  79. }
  80. if (mouse_stick_device) {
  81. mouse_stick_device->SetCallback({
  82. .on_change =
  83. [this](const Common::Input::CallbackStatus& callback) { SetMouseStick(callback); },
  84. });
  85. }
  86. for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
  87. if (!keyboard_devices[index]) {
  88. continue;
  89. }
  90. keyboard_devices[index]->SetCallback({
  91. .on_change =
  92. [this, index](const Common::Input::CallbackStatus& callback) {
  93. SetKeyboardButton(callback, index);
  94. },
  95. });
  96. }
  97. for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
  98. if (!keyboard_modifier_devices[index]) {
  99. continue;
  100. }
  101. keyboard_modifier_devices[index]->SetCallback({
  102. .on_change =
  103. [this, index](const Common::Input::CallbackStatus& callback) {
  104. SetKeyboardModifier(callback, index);
  105. },
  106. });
  107. }
  108. if (ring_analog_device) {
  109. ring_analog_device->SetCallback({
  110. .on_change =
  111. [this](const Common::Input::CallbackStatus& callback) { SetRingAnalog(callback); },
  112. });
  113. }
  114. }
  115. void EmulatedDevices::UnloadInput() {
  116. for (auto& button : mouse_button_devices) {
  117. button.reset();
  118. }
  119. for (auto& analog : mouse_analog_devices) {
  120. analog.reset();
  121. }
  122. mouse_stick_device.reset();
  123. for (auto& button : keyboard_devices) {
  124. button.reset();
  125. }
  126. for (auto& button : keyboard_modifier_devices) {
  127. button.reset();
  128. }
  129. ring_analog_device.reset();
  130. }
  131. void EmulatedDevices::EnableConfiguration() {
  132. is_configuring = true;
  133. SaveCurrentConfig();
  134. }
  135. void EmulatedDevices::DisableConfiguration() {
  136. is_configuring = false;
  137. }
  138. bool EmulatedDevices::IsConfiguring() const {
  139. return is_configuring;
  140. }
  141. void EmulatedDevices::SaveCurrentConfig() {
  142. if (!is_configuring) {
  143. return;
  144. }
  145. Settings::values.ringcon_analogs = ring_params.Serialize();
  146. }
  147. void EmulatedDevices::RestoreConfig() {
  148. if (!is_configuring) {
  149. return;
  150. }
  151. ReloadFromSettings();
  152. }
  153. Common::ParamPackage EmulatedDevices::GetRingParam() const {
  154. return ring_params;
  155. }
  156. void EmulatedDevices::SetRingParam(Common::ParamPackage param) {
  157. ring_params = std::move(param);
  158. ReloadInput();
  159. }
  160. void EmulatedDevices::SetKeyboardButton(const Common::Input::CallbackStatus& callback,
  161. std::size_t index) {
  162. if (index >= device_status.keyboard_values.size()) {
  163. return;
  164. }
  165. std::unique_lock lock{mutex};
  166. bool value_changed = false;
  167. const auto new_status = TransformToButton(callback);
  168. auto& current_status = device_status.keyboard_values[index];
  169. current_status.toggle = new_status.toggle;
  170. // Update button status with current status
  171. if (!current_status.toggle) {
  172. current_status.locked = false;
  173. if (current_status.value != new_status.value) {
  174. current_status.value = new_status.value;
  175. value_changed = true;
  176. }
  177. } else {
  178. // Toggle button and lock status
  179. if (new_status.value && !current_status.locked) {
  180. current_status.locked = true;
  181. current_status.value = !current_status.value;
  182. value_changed = true;
  183. }
  184. // Unlock button, ready for next press
  185. if (!new_status.value && current_status.locked) {
  186. current_status.locked = false;
  187. }
  188. }
  189. if (!value_changed) {
  190. return;
  191. }
  192. if (is_configuring) {
  193. lock.unlock();
  194. TriggerOnChange(DeviceTriggerType::Keyboard);
  195. return;
  196. }
  197. // Index should be converted from NativeKeyboard to KeyboardKeyIndex
  198. UpdateKey(index, current_status.value);
  199. lock.unlock();
  200. TriggerOnChange(DeviceTriggerType::Keyboard);
  201. }
  202. void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
  203. constexpr std::size_t KEYS_PER_BYTE = 8;
  204. auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
  205. const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE));
  206. if (status) {
  207. entry = entry | mask;
  208. } else {
  209. entry = static_cast<u8>(entry & ~mask);
  210. }
  211. }
  212. void EmulatedDevices::SetKeyboardModifier(const Common::Input::CallbackStatus& callback,
  213. std::size_t index) {
  214. if (index >= device_status.keyboard_moddifier_values.size()) {
  215. return;
  216. }
  217. std::unique_lock lock{mutex};
  218. bool value_changed = false;
  219. const auto new_status = TransformToButton(callback);
  220. auto& current_status = device_status.keyboard_moddifier_values[index];
  221. current_status.toggle = new_status.toggle;
  222. // Update button status with current
  223. if (!current_status.toggle) {
  224. current_status.locked = false;
  225. if (current_status.value != new_status.value) {
  226. current_status.value = new_status.value;
  227. value_changed = true;
  228. }
  229. } else {
  230. // Toggle button and lock status
  231. if (new_status.value && !current_status.locked) {
  232. current_status.locked = true;
  233. current_status.value = !current_status.value;
  234. value_changed = true;
  235. }
  236. // Unlock button ready for next press
  237. if (!new_status.value && current_status.locked) {
  238. current_status.locked = false;
  239. }
  240. }
  241. if (!value_changed) {
  242. return;
  243. }
  244. if (is_configuring) {
  245. lock.unlock();
  246. TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
  247. return;
  248. }
  249. switch (index) {
  250. case Settings::NativeKeyboard::LeftControl:
  251. case Settings::NativeKeyboard::RightControl:
  252. device_status.keyboard_moddifier_state.control.Assign(current_status.value);
  253. break;
  254. case Settings::NativeKeyboard::LeftShift:
  255. case Settings::NativeKeyboard::RightShift:
  256. device_status.keyboard_moddifier_state.shift.Assign(current_status.value);
  257. break;
  258. case Settings::NativeKeyboard::LeftAlt:
  259. device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value);
  260. break;
  261. case Settings::NativeKeyboard::RightAlt:
  262. device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value);
  263. break;
  264. case Settings::NativeKeyboard::CapsLock:
  265. device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value);
  266. break;
  267. case Settings::NativeKeyboard::ScrollLock:
  268. device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value);
  269. break;
  270. case Settings::NativeKeyboard::NumLock:
  271. device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value);
  272. break;
  273. }
  274. lock.unlock();
  275. TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
  276. }
  277. void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callback,
  278. std::size_t index) {
  279. if (index >= device_status.mouse_button_values.size()) {
  280. return;
  281. }
  282. std::unique_lock lock{mutex};
  283. bool value_changed = false;
  284. const auto new_status = TransformToButton(callback);
  285. auto& current_status = device_status.mouse_button_values[index];
  286. current_status.toggle = new_status.toggle;
  287. // Update button status with current
  288. if (!current_status.toggle) {
  289. current_status.locked = false;
  290. if (current_status.value != new_status.value) {
  291. current_status.value = new_status.value;
  292. value_changed = true;
  293. }
  294. } else {
  295. // Toggle button and lock status
  296. if (new_status.value && !current_status.locked) {
  297. current_status.locked = true;
  298. current_status.value = !current_status.value;
  299. value_changed = true;
  300. }
  301. // Unlock button ready for next press
  302. if (!new_status.value && current_status.locked) {
  303. current_status.locked = false;
  304. }
  305. }
  306. if (!value_changed) {
  307. return;
  308. }
  309. if (is_configuring) {
  310. lock.unlock();
  311. TriggerOnChange(DeviceTriggerType::Mouse);
  312. return;
  313. }
  314. switch (index) {
  315. case Settings::NativeMouseButton::Left:
  316. device_status.mouse_button_state.left.Assign(current_status.value);
  317. break;
  318. case Settings::NativeMouseButton::Right:
  319. device_status.mouse_button_state.right.Assign(current_status.value);
  320. break;
  321. case Settings::NativeMouseButton::Middle:
  322. device_status.mouse_button_state.middle.Assign(current_status.value);
  323. break;
  324. case Settings::NativeMouseButton::Forward:
  325. device_status.mouse_button_state.forward.Assign(current_status.value);
  326. break;
  327. case Settings::NativeMouseButton::Back:
  328. device_status.mouse_button_state.back.Assign(current_status.value);
  329. break;
  330. }
  331. lock.unlock();
  332. TriggerOnChange(DeviceTriggerType::Mouse);
  333. }
  334. void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callback,
  335. std::size_t index) {
  336. if (index >= device_status.mouse_analog_values.size()) {
  337. return;
  338. }
  339. std::unique_lock lock{mutex};
  340. const auto analog_value = TransformToAnalog(callback);
  341. device_status.mouse_analog_values[index] = analog_value;
  342. if (is_configuring) {
  343. device_status.mouse_position_state = {};
  344. lock.unlock();
  345. TriggerOnChange(DeviceTriggerType::Mouse);
  346. return;
  347. }
  348. switch (index) {
  349. case Settings::NativeMouseWheel::X:
  350. device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value);
  351. break;
  352. case Settings::NativeMouseWheel::Y:
  353. device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value);
  354. break;
  355. }
  356. lock.unlock();
  357. TriggerOnChange(DeviceTriggerType::Mouse);
  358. }
  359. void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) {
  360. std::unique_lock lock{mutex};
  361. const auto touch_value = TransformToTouch(callback);
  362. device_status.mouse_stick_value = touch_value;
  363. if (is_configuring) {
  364. device_status.mouse_position_state = {};
  365. lock.unlock();
  366. TriggerOnChange(DeviceTriggerType::Mouse);
  367. return;
  368. }
  369. device_status.mouse_position_state.x = touch_value.x.value;
  370. device_status.mouse_position_state.y = touch_value.y.value;
  371. lock.unlock();
  372. TriggerOnChange(DeviceTriggerType::Mouse);
  373. }
  374. void EmulatedDevices::SetRingAnalog(const Common::Input::CallbackStatus& callback) {
  375. std::lock_guard lock{mutex};
  376. const auto force_value = TransformToStick(callback);
  377. device_status.ring_analog_value = force_value.x;
  378. if (is_configuring) {
  379. device_status.ring_analog_value = {};
  380. TriggerOnChange(DeviceTriggerType::RingController);
  381. return;
  382. }
  383. device_status.ring_analog_state.force = force_value.x.value;
  384. TriggerOnChange(DeviceTriggerType::RingController);
  385. }
  386. KeyboardValues EmulatedDevices::GetKeyboardValues() const {
  387. std::scoped_lock lock{mutex};
  388. return device_status.keyboard_values;
  389. }
  390. KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const {
  391. std::scoped_lock lock{mutex};
  392. return device_status.keyboard_moddifier_values;
  393. }
  394. MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
  395. std::scoped_lock lock{mutex};
  396. return device_status.mouse_button_values;
  397. }
  398. RingAnalogValue EmulatedDevices::GetRingSensorValues() const {
  399. return device_status.ring_analog_value;
  400. }
  401. KeyboardKey EmulatedDevices::GetKeyboard() const {
  402. std::scoped_lock lock{mutex};
  403. return device_status.keyboard_state;
  404. }
  405. KeyboardModifier EmulatedDevices::GetKeyboardModifier() const {
  406. std::scoped_lock lock{mutex};
  407. return device_status.keyboard_moddifier_state;
  408. }
  409. MouseButton EmulatedDevices::GetMouseButtons() const {
  410. std::scoped_lock lock{mutex};
  411. return device_status.mouse_button_state;
  412. }
  413. MousePosition EmulatedDevices::GetMousePosition() const {
  414. std::scoped_lock lock{mutex};
  415. return device_status.mouse_position_state;
  416. }
  417. AnalogStickState EmulatedDevices::GetMouseWheel() const {
  418. std::scoped_lock lock{mutex};
  419. return device_status.mouse_wheel_state;
  420. }
  421. RingSensorForce EmulatedDevices::GetRingSensorForce() const {
  422. return device_status.ring_analog_state;
  423. }
  424. void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
  425. std::scoped_lock lock{callback_mutex};
  426. for (const auto& poller_pair : callback_list) {
  427. const InterfaceUpdateCallback& poller = poller_pair.second;
  428. if (poller.on_change) {
  429. poller.on_change(type);
  430. }
  431. }
  432. }
  433. int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
  434. std::scoped_lock lock{callback_mutex};
  435. callback_list.insert_or_assign(last_callback_key, std::move(update_callback));
  436. return last_callback_key++;
  437. }
  438. void EmulatedDevices::DeleteCallback(int key) {
  439. std::scoped_lock lock{callback_mutex};
  440. const auto& iterator = callback_list.find(key);
  441. if (iterator == callback_list.end()) {
  442. LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
  443. return;
  444. }
  445. callback_list.erase(iterator);
  446. }
  447. } // namespace Core::HID