emulated_devices.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. // Copyright 2021 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included
  4. #include <algorithm>
  5. #include <fmt/format.h>
  6. #include "core/hid/emulated_devices.h"
  7. #include "core/hid/input_converter.h"
  8. namespace Core::HID {
  9. EmulatedDevices::EmulatedDevices() = default;
  10. EmulatedDevices::~EmulatedDevices() = default;
  11. void EmulatedDevices::ReloadFromSettings() {
  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::CreateDevice<Common::Input::InputDevice>(mouse_params);
  22. key_index++;
  23. }
  24. mouse_stick_device = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>(
  25. "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::CreateDevice<Common::Input::InputDevice>(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::CreateDevice<Common::Input::InputDevice>(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::CreateDevice<Common::Input::InputDevice>(keyboard_params);
  55. key_index++;
  56. }
  57. for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {
  58. if (!mouse_button_devices[index]) {
  59. continue;
  60. }
  61. Common::Input::InputCallback button_callback{
  62. [this, index](Common::Input::CallbackStatus callback) {
  63. SetMouseButton(callback, index);
  64. }};
  65. mouse_button_devices[index]->SetCallback(button_callback);
  66. }
  67. for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) {
  68. if (!mouse_analog_devices[index]) {
  69. continue;
  70. }
  71. Common::Input::InputCallback button_callback{
  72. [this, index](Common::Input::CallbackStatus callback) {
  73. SetMouseAnalog(callback, index);
  74. }};
  75. mouse_analog_devices[index]->SetCallback(button_callback);
  76. }
  77. if (mouse_stick_device) {
  78. Common::Input::InputCallback button_callback{
  79. [this](Common::Input::CallbackStatus callback) { SetMouseStick(callback); }};
  80. mouse_stick_device->SetCallback(button_callback);
  81. }
  82. for (std::size_t index = 0; index < keyboard_devices.size(); ++index) {
  83. if (!keyboard_devices[index]) {
  84. continue;
  85. }
  86. Common::Input::InputCallback button_callback{
  87. [this, index](Common::Input::CallbackStatus callback) {
  88. SetKeyboardButton(callback, index);
  89. }};
  90. keyboard_devices[index]->SetCallback(button_callback);
  91. }
  92. for (std::size_t index = 0; index < keyboard_modifier_devices.size(); ++index) {
  93. if (!keyboard_modifier_devices[index]) {
  94. continue;
  95. }
  96. Common::Input::InputCallback button_callback{
  97. [this, index](Common::Input::CallbackStatus callback) {
  98. SetKeyboardModifier(callback, index);
  99. }};
  100. keyboard_modifier_devices[index]->SetCallback(button_callback);
  101. }
  102. }
  103. void EmulatedDevices::UnloadInput() {
  104. for (auto& button : mouse_button_devices) {
  105. button.reset();
  106. }
  107. for (auto& analog : mouse_analog_devices) {
  108. analog.reset();
  109. }
  110. mouse_stick_device.reset();
  111. for (auto& button : keyboard_devices) {
  112. button.reset();
  113. }
  114. for (auto& button : keyboard_modifier_devices) {
  115. button.reset();
  116. }
  117. }
  118. void EmulatedDevices::EnableConfiguration() {
  119. is_configuring = true;
  120. SaveCurrentConfig();
  121. }
  122. void EmulatedDevices::DisableConfiguration() {
  123. is_configuring = false;
  124. }
  125. bool EmulatedDevices::IsConfiguring() const {
  126. return is_configuring;
  127. }
  128. void EmulatedDevices::SaveCurrentConfig() {
  129. if (!is_configuring) {
  130. return;
  131. }
  132. }
  133. void EmulatedDevices::RestoreConfig() {
  134. if (!is_configuring) {
  135. return;
  136. }
  137. ReloadFromSettings();
  138. }
  139. void EmulatedDevices::SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index) {
  140. if (index >= device_status.keyboard_values.size()) {
  141. return;
  142. }
  143. std::lock_guard lock{mutex};
  144. bool value_changed = false;
  145. const auto new_status = TransformToButton(callback);
  146. auto& current_status = device_status.keyboard_values[index];
  147. current_status.toggle = new_status.toggle;
  148. // Update button status with current status
  149. if (!current_status.toggle) {
  150. current_status.locked = false;
  151. if (current_status.value != new_status.value) {
  152. current_status.value = new_status.value;
  153. value_changed = true;
  154. }
  155. } else {
  156. // Toggle button and lock status
  157. if (new_status.value && !current_status.locked) {
  158. current_status.locked = true;
  159. current_status.value = !current_status.value;
  160. value_changed = true;
  161. }
  162. // Unlock button, ready for next press
  163. if (!new_status.value && current_status.locked) {
  164. current_status.locked = false;
  165. }
  166. }
  167. if (!value_changed) {
  168. return;
  169. }
  170. if (is_configuring) {
  171. TriggerOnChange(DeviceTriggerType::Keyboard);
  172. return;
  173. }
  174. // Index should be converted from NativeKeyboard to KeyboardKeyIndex
  175. UpdateKey(index, current_status.value);
  176. TriggerOnChange(DeviceTriggerType::Keyboard);
  177. }
  178. void EmulatedDevices::UpdateKey(std::size_t key_index, bool status) {
  179. constexpr std::size_t KEYS_PER_BYTE = 8;
  180. auto& entry = device_status.keyboard_state.key[key_index / KEYS_PER_BYTE];
  181. const u8 mask = static_cast<u8>(1 << (key_index % KEYS_PER_BYTE));
  182. if (status) {
  183. entry = entry | mask;
  184. } else {
  185. entry = static_cast<u8>(entry & ~mask);
  186. }
  187. }
  188. void EmulatedDevices::SetKeyboardModifier(Common::Input::CallbackStatus callback,
  189. std::size_t index) {
  190. if (index >= device_status.keyboard_moddifier_values.size()) {
  191. return;
  192. }
  193. std::lock_guard lock{mutex};
  194. bool value_changed = false;
  195. const auto new_status = TransformToButton(callback);
  196. auto& current_status = device_status.keyboard_moddifier_values[index];
  197. current_status.toggle = new_status.toggle;
  198. // Update button status with current
  199. if (!current_status.toggle) {
  200. current_status.locked = false;
  201. if (current_status.value != new_status.value) {
  202. current_status.value = new_status.value;
  203. value_changed = true;
  204. }
  205. } else {
  206. // Toggle button and lock status
  207. if (new_status.value && !current_status.locked) {
  208. current_status.locked = true;
  209. current_status.value = !current_status.value;
  210. value_changed = true;
  211. }
  212. // Unlock button ready for next press
  213. if (!new_status.value && current_status.locked) {
  214. current_status.locked = false;
  215. }
  216. }
  217. if (!value_changed) {
  218. return;
  219. }
  220. if (is_configuring) {
  221. TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
  222. return;
  223. }
  224. switch (index) {
  225. case Settings::NativeKeyboard::LeftControl:
  226. case Settings::NativeKeyboard::RightControl:
  227. device_status.keyboard_moddifier_state.control.Assign(current_status.value);
  228. break;
  229. case Settings::NativeKeyboard::LeftShift:
  230. case Settings::NativeKeyboard::RightShift:
  231. device_status.keyboard_moddifier_state.shift.Assign(current_status.value);
  232. break;
  233. case Settings::NativeKeyboard::LeftAlt:
  234. device_status.keyboard_moddifier_state.left_alt.Assign(current_status.value);
  235. break;
  236. case Settings::NativeKeyboard::RightAlt:
  237. device_status.keyboard_moddifier_state.right_alt.Assign(current_status.value);
  238. break;
  239. case Settings::NativeKeyboard::CapsLock:
  240. device_status.keyboard_moddifier_state.caps_lock.Assign(current_status.value);
  241. break;
  242. case Settings::NativeKeyboard::ScrollLock:
  243. device_status.keyboard_moddifier_state.scroll_lock.Assign(current_status.value);
  244. break;
  245. case Settings::NativeKeyboard::NumLock:
  246. device_status.keyboard_moddifier_state.num_lock.Assign(current_status.value);
  247. break;
  248. }
  249. TriggerOnChange(DeviceTriggerType::KeyboardModdifier);
  250. }
  251. void EmulatedDevices::SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index) {
  252. if (index >= device_status.mouse_button_values.size()) {
  253. return;
  254. }
  255. std::lock_guard lock{mutex};
  256. bool value_changed = false;
  257. const auto new_status = TransformToButton(callback);
  258. auto& current_status = device_status.mouse_button_values[index];
  259. current_status.toggle = new_status.toggle;
  260. // Update button status with current
  261. if (!current_status.toggle) {
  262. current_status.locked = false;
  263. if (current_status.value != new_status.value) {
  264. current_status.value = new_status.value;
  265. value_changed = true;
  266. }
  267. } else {
  268. // Toggle button and lock status
  269. if (new_status.value && !current_status.locked) {
  270. current_status.locked = true;
  271. current_status.value = !current_status.value;
  272. value_changed = true;
  273. }
  274. // Unlock button ready for next press
  275. if (!new_status.value && current_status.locked) {
  276. current_status.locked = false;
  277. }
  278. }
  279. if (!value_changed) {
  280. return;
  281. }
  282. if (is_configuring) {
  283. TriggerOnChange(DeviceTriggerType::Mouse);
  284. return;
  285. }
  286. switch (index) {
  287. case Settings::NativeMouseButton::Left:
  288. device_status.mouse_button_state.left.Assign(current_status.value);
  289. break;
  290. case Settings::NativeMouseButton::Right:
  291. device_status.mouse_button_state.right.Assign(current_status.value);
  292. break;
  293. case Settings::NativeMouseButton::Middle:
  294. device_status.mouse_button_state.middle.Assign(current_status.value);
  295. break;
  296. case Settings::NativeMouseButton::Forward:
  297. device_status.mouse_button_state.forward.Assign(current_status.value);
  298. break;
  299. case Settings::NativeMouseButton::Back:
  300. device_status.mouse_button_state.back.Assign(current_status.value);
  301. break;
  302. }
  303. TriggerOnChange(DeviceTriggerType::Mouse);
  304. }
  305. void EmulatedDevices::SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index) {
  306. if (index >= device_status.mouse_analog_values.size()) {
  307. return;
  308. }
  309. std::lock_guard lock{mutex};
  310. const auto analog_value = TransformToAnalog(callback);
  311. device_status.mouse_analog_values[index] = analog_value;
  312. if (is_configuring) {
  313. device_status.mouse_position_state = {};
  314. TriggerOnChange(DeviceTriggerType::Mouse);
  315. return;
  316. }
  317. switch (index) {
  318. case Settings::NativeMouseWheel::X:
  319. device_status.mouse_wheel_state.x = static_cast<s32>(analog_value.value);
  320. break;
  321. case Settings::NativeMouseWheel::Y:
  322. device_status.mouse_wheel_state.y = static_cast<s32>(analog_value.value);
  323. break;
  324. }
  325. TriggerOnChange(DeviceTriggerType::Mouse);
  326. }
  327. void EmulatedDevices::SetMouseStick(Common::Input::CallbackStatus callback) {
  328. std::lock_guard lock{mutex};
  329. const auto touch_value = TransformToTouch(callback);
  330. device_status.mouse_stick_value = touch_value;
  331. if (is_configuring) {
  332. device_status.mouse_position_state = {};
  333. TriggerOnChange(DeviceTriggerType::Mouse);
  334. return;
  335. }
  336. device_status.mouse_position_state.x = touch_value.x.value;
  337. device_status.mouse_position_state.y = touch_value.y.value;
  338. TriggerOnChange(DeviceTriggerType::Mouse);
  339. }
  340. KeyboardValues EmulatedDevices::GetKeyboardValues() const {
  341. return device_status.keyboard_values;
  342. }
  343. KeyboardModifierValues EmulatedDevices::GetKeyboardModdifierValues() const {
  344. return device_status.keyboard_moddifier_values;
  345. }
  346. MouseButtonValues EmulatedDevices::GetMouseButtonsValues() const {
  347. return device_status.mouse_button_values;
  348. }
  349. KeyboardKey EmulatedDevices::GetKeyboard() const {
  350. return device_status.keyboard_state;
  351. }
  352. KeyboardModifier EmulatedDevices::GetKeyboardModifier() const {
  353. return device_status.keyboard_moddifier_state;
  354. }
  355. MouseButton EmulatedDevices::GetMouseButtons() const {
  356. return device_status.mouse_button_state;
  357. }
  358. MousePosition EmulatedDevices::GetMousePosition() const {
  359. return device_status.mouse_position_state;
  360. }
  361. AnalogStickState EmulatedDevices::GetMouseWheel() const {
  362. return device_status.mouse_wheel_state;
  363. }
  364. void EmulatedDevices::TriggerOnChange(DeviceTriggerType type) {
  365. for (const auto& poller_pair : callback_list) {
  366. const InterfaceUpdateCallback& poller = poller_pair.second;
  367. if (poller.on_change) {
  368. poller.on_change(type);
  369. }
  370. }
  371. }
  372. int EmulatedDevices::SetCallback(InterfaceUpdateCallback update_callback) {
  373. std::lock_guard lock{mutex};
  374. callback_list.insert_or_assign(last_callback_key, update_callback);
  375. return last_callback_key++;
  376. }
  377. void EmulatedDevices::DeleteCallback(int key) {
  378. std::lock_guard lock{mutex};
  379. const auto& iterator = callback_list.find(key);
  380. if (iterator == callback_list.end()) {
  381. LOG_ERROR(Input, "Tried to delete non-existent callback {}", key);
  382. return;
  383. }
  384. callback_list.erase(iterator);
  385. }
  386. } // namespace Core::HID