npad.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include <cstring>
  7. #include "common/assert.h"
  8. #include "common/bit_field.h"
  9. #include "common/common_types.h"
  10. #include "common/logging/log.h"
  11. #include "common/settings.h"
  12. #include "core/core.h"
  13. #include "core/core_timing.h"
  14. #include "core/frontend/input.h"
  15. #include "core/hle/kernel/k_event.h"
  16. #include "core/hle/kernel/k_readable_event.h"
  17. #include "core/hle/kernel/k_writable_event.h"
  18. #include "core/hle/kernel/kernel.h"
  19. #include "core/hle/service/hid/controllers/npad.h"
  20. #include "core/hle/service/kernel_helpers.h"
  21. namespace Service::HID {
  22. constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
  23. constexpr s32 HID_TRIGGER_MAX = 0x7fff;
  24. [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
  25. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  26. constexpr u32 BATTERY_FULL = 2;
  27. constexpr u32 MAX_NPAD_ID = 7;
  28. constexpr std::size_t HANDHELD_INDEX = 8;
  29. constexpr std::array<u32, 10> npad_id_list{
  30. 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
  31. };
  32. enum class JoystickId : std::size_t {
  33. Joystick_Left,
  34. Joystick_Right,
  35. };
  36. Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
  37. Settings::ControllerType type) {
  38. switch (type) {
  39. case Settings::ControllerType::ProController:
  40. return NPadControllerType::ProController;
  41. case Settings::ControllerType::DualJoyconDetached:
  42. return NPadControllerType::JoyDual;
  43. case Settings::ControllerType::LeftJoycon:
  44. return NPadControllerType::JoyLeft;
  45. case Settings::ControllerType::RightJoycon:
  46. return NPadControllerType::JoyRight;
  47. case Settings::ControllerType::Handheld:
  48. return NPadControllerType::Handheld;
  49. case Settings::ControllerType::GameCube:
  50. return NPadControllerType::GameCube;
  51. default:
  52. UNREACHABLE();
  53. return NPadControllerType::ProController;
  54. }
  55. }
  56. Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
  57. Controller_NPad::NPadControllerType type) {
  58. switch (type) {
  59. case NPadControllerType::ProController:
  60. return Settings::ControllerType::ProController;
  61. case NPadControllerType::JoyDual:
  62. return Settings::ControllerType::DualJoyconDetached;
  63. case NPadControllerType::JoyLeft:
  64. return Settings::ControllerType::LeftJoycon;
  65. case NPadControllerType::JoyRight:
  66. return Settings::ControllerType::RightJoycon;
  67. case NPadControllerType::Handheld:
  68. return Settings::ControllerType::Handheld;
  69. case NPadControllerType::GameCube:
  70. return Settings::ControllerType::GameCube;
  71. default:
  72. UNREACHABLE();
  73. return Settings::ControllerType::ProController;
  74. }
  75. }
  76. std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
  77. switch (npad_id) {
  78. case 0:
  79. case 1:
  80. case 2:
  81. case 3:
  82. case 4:
  83. case 5:
  84. case 6:
  85. case 7:
  86. return npad_id;
  87. case HANDHELD_INDEX:
  88. case NPAD_HANDHELD:
  89. return HANDHELD_INDEX;
  90. case 9:
  91. case NPAD_UNKNOWN:
  92. return 9;
  93. default:
  94. UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
  95. return 0;
  96. }
  97. }
  98. u32 Controller_NPad::IndexToNPad(std::size_t index) {
  99. switch (index) {
  100. case 0:
  101. case 1:
  102. case 2:
  103. case 3:
  104. case 4:
  105. case 5:
  106. case 6:
  107. case 7:
  108. return static_cast<u32>(index);
  109. case HANDHELD_INDEX:
  110. return NPAD_HANDHELD;
  111. case 9:
  112. return NPAD_UNKNOWN;
  113. default:
  114. UNIMPLEMENTED_MSG("Unknown npad index {}", index);
  115. return 0;
  116. }
  117. }
  118. bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
  119. switch (npad_id) {
  120. case 0:
  121. case 1:
  122. case 2:
  123. case 3:
  124. case 4:
  125. case 5:
  126. case 6:
  127. case 7:
  128. case NPAD_UNKNOWN:
  129. case NPAD_HANDHELD:
  130. return true;
  131. default:
  132. LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
  133. return false;
  134. }
  135. }
  136. bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
  137. return IsNpadIdValid(device_handle.npad_id) &&
  138. device_handle.npad_type < NpadType::MaxNpadType &&
  139. device_handle.device_index < DeviceIndex::MaxDeviceIndex;
  140. }
  141. Controller_NPad::Controller_NPad(Core::System& system_,
  142. KernelHelpers::ServiceContext& service_context_)
  143. : ControllerBase{system_}, service_context{service_context_} {
  144. latest_vibration_values.fill({DEFAULT_VIBRATION_VALUE, DEFAULT_VIBRATION_VALUE});
  145. }
  146. Controller_NPad::~Controller_NPad() {
  147. OnRelease();
  148. }
  149. void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
  150. const auto controller_type = connected_controllers[controller_idx].type;
  151. auto& controller = shared_memory_entries[controller_idx];
  152. if (controller_type == NPadControllerType::None) {
  153. styleset_changed_events[controller_idx]->GetWritableEvent().Signal();
  154. return;
  155. }
  156. controller.style_set.raw = 0; // Zero out
  157. controller.device_type.raw = 0;
  158. controller.system_properties.raw = 0;
  159. switch (controller_type) {
  160. case NPadControllerType::None:
  161. UNREACHABLE();
  162. break;
  163. case NPadControllerType::ProController:
  164. controller.style_set.fullkey.Assign(1);
  165. controller.device_type.fullkey.Assign(1);
  166. controller.system_properties.is_vertical.Assign(1);
  167. controller.system_properties.use_plus.Assign(1);
  168. controller.system_properties.use_minus.Assign(1);
  169. controller.assignment_mode = NpadAssignments::Single;
  170. controller.footer_type = AppletFooterUiType::SwitchProController;
  171. break;
  172. case NPadControllerType::Handheld:
  173. controller.style_set.handheld.Assign(1);
  174. controller.device_type.handheld_left.Assign(1);
  175. controller.device_type.handheld_right.Assign(1);
  176. controller.system_properties.is_vertical.Assign(1);
  177. controller.system_properties.use_plus.Assign(1);
  178. controller.system_properties.use_minus.Assign(1);
  179. controller.assignment_mode = NpadAssignments::Dual;
  180. controller.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  181. break;
  182. case NPadControllerType::JoyDual:
  183. controller.style_set.joycon_dual.Assign(1);
  184. controller.device_type.joycon_left.Assign(1);
  185. controller.device_type.joycon_right.Assign(1);
  186. controller.system_properties.is_vertical.Assign(1);
  187. controller.system_properties.use_plus.Assign(1);
  188. controller.system_properties.use_minus.Assign(1);
  189. controller.assignment_mode = NpadAssignments::Dual;
  190. controller.footer_type = AppletFooterUiType::JoyDual;
  191. break;
  192. case NPadControllerType::JoyLeft:
  193. controller.style_set.joycon_left.Assign(1);
  194. controller.device_type.joycon_left.Assign(1);
  195. controller.system_properties.is_horizontal.Assign(1);
  196. controller.system_properties.use_minus.Assign(1);
  197. controller.assignment_mode = NpadAssignments::Single;
  198. controller.footer_type = AppletFooterUiType::JoyLeftHorizontal;
  199. break;
  200. case NPadControllerType::JoyRight:
  201. controller.style_set.joycon_right.Assign(1);
  202. controller.device_type.joycon_right.Assign(1);
  203. controller.system_properties.is_horizontal.Assign(1);
  204. controller.system_properties.use_plus.Assign(1);
  205. controller.assignment_mode = NpadAssignments::Single;
  206. controller.footer_type = AppletFooterUiType::JoyRightHorizontal;
  207. break;
  208. case NPadControllerType::GameCube:
  209. controller.style_set.gamecube.Assign(1);
  210. // The GC Controller behaves like a wired Pro Controller
  211. controller.device_type.fullkey.Assign(1);
  212. controller.system_properties.is_vertical.Assign(1);
  213. controller.system_properties.use_plus.Assign(1);
  214. break;
  215. case NPadControllerType::Pokeball:
  216. controller.style_set.palma.Assign(1);
  217. controller.device_type.palma.Assign(1);
  218. controller.assignment_mode = NpadAssignments::Single;
  219. break;
  220. }
  221. controller.fullkey_color.attribute = ColorAttributes::Ok;
  222. controller.fullkey_color.fullkey.body = 0;
  223. controller.fullkey_color.fullkey.button = 0;
  224. controller.joycon_color.attribute = ColorAttributes::Ok;
  225. controller.joycon_color.left.body =
  226. Settings::values.players.GetValue()[controller_idx].body_color_left;
  227. controller.joycon_color.left.button =
  228. Settings::values.players.GetValue()[controller_idx].button_color_left;
  229. controller.joycon_color.right.body =
  230. Settings::values.players.GetValue()[controller_idx].body_color_right;
  231. controller.joycon_color.right.button =
  232. Settings::values.players.GetValue()[controller_idx].button_color_right;
  233. // TODO: Investigate when we should report all batery types
  234. controller.battery_level_dual = BATTERY_FULL;
  235. controller.battery_level_left = BATTERY_FULL;
  236. controller.battery_level_right = BATTERY_FULL;
  237. SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
  238. }
  239. void Controller_NPad::OnInit() {
  240. for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
  241. styleset_changed_events[i] =
  242. service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
  243. }
  244. if (!IsControllerActivated()) {
  245. return;
  246. }
  247. OnLoadInputDevices();
  248. if (style.raw == 0) {
  249. // We want to support all controllers
  250. style.handheld.Assign(1);
  251. style.joycon_left.Assign(1);
  252. style.joycon_right.Assign(1);
  253. style.joycon_dual.Assign(1);
  254. style.fullkey.Assign(1);
  255. style.gamecube.Assign(1);
  256. style.palma.Assign(1);
  257. }
  258. std::transform(Settings::values.players.GetValue().begin(),
  259. Settings::values.players.GetValue().end(), connected_controllers.begin(),
  260. [](const Settings::PlayerInput& player) {
  261. return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
  262. player.connected};
  263. });
  264. // Connect the Player 1 or Handheld controller if none are connected.
  265. if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
  266. [](const ControllerHolder& controller) { return controller.is_connected; })) {
  267. const auto controller =
  268. MapSettingsTypeToNPad(Settings::values.players.GetValue()[0].controller_type);
  269. if (controller == NPadControllerType::Handheld) {
  270. Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
  271. connected_controllers[HANDHELD_INDEX] = {controller, true};
  272. } else {
  273. Settings::values.players.GetValue()[0].connected = true;
  274. connected_controllers[0] = {controller, true};
  275. }
  276. }
  277. // Account for handheld
  278. if (connected_controllers[HANDHELD_INDEX].is_connected) {
  279. connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
  280. }
  281. supported_npad_id_types.resize(npad_id_list.size());
  282. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  283. npad_id_list.size() * sizeof(u32));
  284. for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
  285. const auto& controller = connected_controllers[i];
  286. if (controller.is_connected) {
  287. AddNewControllerAt(controller.type, i);
  288. }
  289. }
  290. }
  291. void Controller_NPad::OnLoadInputDevices() {
  292. const auto& players = Settings::values.players.GetValue();
  293. std::lock_guard lock{mutex};
  294. for (std::size_t i = 0; i < players.size(); ++i) {
  295. std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  296. players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
  297. buttons[i].begin(), Input::CreateDevice<Input::ButtonDevice>);
  298. std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  299. players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
  300. sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
  301. std::transform(players[i].vibrations.begin() +
  302. Settings::NativeVibration::VIBRATION_HID_BEGIN,
  303. players[i].vibrations.begin() + Settings::NativeVibration::VIBRATION_HID_END,
  304. vibrations[i].begin(), Input::CreateDevice<Input::VibrationDevice>);
  305. std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
  306. players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
  307. motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
  308. for (std::size_t device_idx = 0; device_idx < vibrations[i].size(); ++device_idx) {
  309. InitializeVibrationDeviceAtIndex(i, device_idx);
  310. }
  311. }
  312. }
  313. void Controller_NPad::OnRelease() {
  314. for (std::size_t npad_idx = 0; npad_idx < vibrations.size(); ++npad_idx) {
  315. for (std::size_t device_idx = 0; device_idx < vibrations[npad_idx].size(); ++device_idx) {
  316. VibrateControllerAtIndex(npad_idx, device_idx, {});
  317. }
  318. }
  319. for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
  320. service_context.CloseEvent(styleset_changed_events[i]);
  321. }
  322. }
  323. void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
  324. std::lock_guard lock{mutex};
  325. const auto controller_idx = NPadIdToIndex(npad_id);
  326. const auto controller_type = connected_controllers[controller_idx].type;
  327. if (!connected_controllers[controller_idx].is_connected) {
  328. return;
  329. }
  330. auto& pad_state = npad_pad_states[controller_idx].pad_states;
  331. auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
  332. auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
  333. auto& trigger_entry = npad_trigger_states[controller_idx];
  334. const auto& button_state = buttons[controller_idx];
  335. const auto& analog_state = sticks[controller_idx];
  336. const auto [stick_l_x_f, stick_l_y_f] =
  337. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
  338. const auto [stick_r_x_f, stick_r_y_f] =
  339. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
  340. using namespace Settings::NativeButton;
  341. if (controller_type != NPadControllerType::JoyLeft) {
  342. pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
  343. pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
  344. pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
  345. pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
  346. pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
  347. pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
  348. pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
  349. pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
  350. pad_state.r_stick_right.Assign(
  351. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  352. ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
  353. pad_state.r_stick_left.Assign(
  354. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  355. ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
  356. pad_state.r_stick_up.Assign(
  357. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  358. ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
  359. pad_state.r_stick_down.Assign(
  360. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  361. ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
  362. rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  363. rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  364. }
  365. if (controller_type != NPadControllerType::JoyRight) {
  366. pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  367. pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
  368. pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
  369. pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
  370. pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
  371. pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
  372. pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
  373. pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
  374. pad_state.l_stick_right.Assign(
  375. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
  376. ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
  377. pad_state.l_stick_left.Assign(
  378. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
  379. ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
  380. pad_state.l_stick_up.Assign(
  381. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
  382. ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
  383. pad_state.l_stick_down.Assign(
  384. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]
  385. ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
  386. lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  387. lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  388. }
  389. if (controller_type == NPadControllerType::JoyLeft) {
  390. pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
  391. pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
  392. }
  393. if (controller_type == NPadControllerType::JoyRight) {
  394. pad_state.right_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
  395. pad_state.right_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
  396. }
  397. if (controller_type == NPadControllerType::GameCube) {
  398. trigger_entry.l_analog = static_cast<s32>(
  399. button_state[ZL - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
  400. trigger_entry.r_analog = static_cast<s32>(
  401. button_state[ZR - BUTTON_HID_BEGIN]->GetStatus() ? HID_TRIGGER_MAX : 0);
  402. pad_state.zl.Assign(false);
  403. pad_state.zr.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
  404. pad_state.l.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
  405. pad_state.r.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
  406. }
  407. }
  408. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  409. std::size_t data_len) {
  410. if (!IsControllerActivated()) {
  411. return;
  412. }
  413. for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
  414. auto& npad = shared_memory_entries[i];
  415. const std::array<NPadGeneric*, 7> controller_npads{
  416. &npad.fullkey_states, &npad.handheld_states, &npad.joy_dual_states,
  417. &npad.joy_left_states, &npad.joy_right_states, &npad.palma_states,
  418. &npad.system_ext_states};
  419. // There is the posibility to have more controllers with analog triggers
  420. const std::array<TriggerGeneric*, 1> controller_triggers{
  421. &npad.gc_trigger_states,
  422. };
  423. for (auto* main_controller : controller_npads) {
  424. main_controller->common.entry_count = 16;
  425. main_controller->common.total_entry_count = 17;
  426. const auto& last_entry =
  427. main_controller->npad[main_controller->common.last_entry_index];
  428. main_controller->common.timestamp = core_timing.GetCPUTicks();
  429. main_controller->common.last_entry_index =
  430. (main_controller->common.last_entry_index + 1) % 17;
  431. auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
  432. cur_entry.timestamp = last_entry.timestamp + 1;
  433. cur_entry.timestamp2 = cur_entry.timestamp;
  434. }
  435. for (auto* analog_trigger : controller_triggers) {
  436. analog_trigger->entry_count = 16;
  437. analog_trigger->total_entry_count = 17;
  438. const auto& last_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
  439. analog_trigger->timestamp = core_timing.GetCPUTicks();
  440. analog_trigger->last_entry_index = (analog_trigger->last_entry_index + 1) % 17;
  441. auto& cur_entry = analog_trigger->trigger[analog_trigger->last_entry_index];
  442. cur_entry.timestamp = last_entry.timestamp + 1;
  443. cur_entry.timestamp2 = cur_entry.timestamp;
  444. }
  445. const auto& controller_type = connected_controllers[i].type;
  446. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  447. continue;
  448. }
  449. const u32 npad_index = static_cast<u32>(i);
  450. RequestPadStateUpdate(npad_index);
  451. auto& pad_state = npad_pad_states[npad_index];
  452. auto& trigger_state = npad_trigger_states[npad_index];
  453. auto& main_controller =
  454. npad.fullkey_states.npad[npad.fullkey_states.common.last_entry_index];
  455. auto& handheld_entry =
  456. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  457. auto& dual_entry = npad.joy_dual_states.npad[npad.joy_dual_states.common.last_entry_index];
  458. auto& left_entry = npad.joy_left_states.npad[npad.joy_left_states.common.last_entry_index];
  459. auto& right_entry =
  460. npad.joy_right_states.npad[npad.joy_right_states.common.last_entry_index];
  461. auto& pokeball_entry = npad.palma_states.npad[npad.palma_states.common.last_entry_index];
  462. auto& libnx_entry =
  463. npad.system_ext_states.npad[npad.system_ext_states.common.last_entry_index];
  464. auto& trigger_entry =
  465. npad.gc_trigger_states.trigger[npad.gc_trigger_states.last_entry_index];
  466. libnx_entry.connection_status.raw = 0;
  467. libnx_entry.connection_status.is_connected.Assign(1);
  468. switch (controller_type) {
  469. case NPadControllerType::None:
  470. UNREACHABLE();
  471. break;
  472. case NPadControllerType::ProController:
  473. main_controller.connection_status.raw = 0;
  474. main_controller.connection_status.is_connected.Assign(1);
  475. main_controller.connection_status.is_wired.Assign(1);
  476. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  477. main_controller.pad.l_stick = pad_state.l_stick;
  478. main_controller.pad.r_stick = pad_state.r_stick;
  479. libnx_entry.connection_status.is_wired.Assign(1);
  480. break;
  481. case NPadControllerType::Handheld:
  482. handheld_entry.connection_status.raw = 0;
  483. handheld_entry.connection_status.is_connected.Assign(1);
  484. handheld_entry.connection_status.is_wired.Assign(1);
  485. handheld_entry.connection_status.is_left_connected.Assign(1);
  486. handheld_entry.connection_status.is_right_connected.Assign(1);
  487. handheld_entry.connection_status.is_left_wired.Assign(1);
  488. handheld_entry.connection_status.is_right_wired.Assign(1);
  489. handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  490. handheld_entry.pad.l_stick = pad_state.l_stick;
  491. handheld_entry.pad.r_stick = pad_state.r_stick;
  492. libnx_entry.connection_status.is_wired.Assign(1);
  493. libnx_entry.connection_status.is_left_connected.Assign(1);
  494. libnx_entry.connection_status.is_right_connected.Assign(1);
  495. libnx_entry.connection_status.is_left_wired.Assign(1);
  496. libnx_entry.connection_status.is_right_wired.Assign(1);
  497. break;
  498. case NPadControllerType::JoyDual:
  499. dual_entry.connection_status.raw = 0;
  500. dual_entry.connection_status.is_connected.Assign(1);
  501. dual_entry.connection_status.is_left_connected.Assign(1);
  502. dual_entry.connection_status.is_right_connected.Assign(1);
  503. dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  504. dual_entry.pad.l_stick = pad_state.l_stick;
  505. dual_entry.pad.r_stick = pad_state.r_stick;
  506. libnx_entry.connection_status.is_left_connected.Assign(1);
  507. libnx_entry.connection_status.is_right_connected.Assign(1);
  508. break;
  509. case NPadControllerType::JoyLeft:
  510. left_entry.connection_status.raw = 0;
  511. left_entry.connection_status.is_connected.Assign(1);
  512. left_entry.connection_status.is_left_connected.Assign(1);
  513. left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  514. left_entry.pad.l_stick = pad_state.l_stick;
  515. left_entry.pad.r_stick = pad_state.r_stick;
  516. libnx_entry.connection_status.is_left_connected.Assign(1);
  517. break;
  518. case NPadControllerType::JoyRight:
  519. right_entry.connection_status.raw = 0;
  520. right_entry.connection_status.is_connected.Assign(1);
  521. right_entry.connection_status.is_right_connected.Assign(1);
  522. right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  523. right_entry.pad.l_stick = pad_state.l_stick;
  524. right_entry.pad.r_stick = pad_state.r_stick;
  525. libnx_entry.connection_status.is_right_connected.Assign(1);
  526. break;
  527. case NPadControllerType::GameCube:
  528. main_controller.connection_status.raw = 0;
  529. main_controller.connection_status.is_connected.Assign(1);
  530. main_controller.connection_status.is_wired.Assign(1);
  531. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  532. main_controller.pad.l_stick = pad_state.l_stick;
  533. main_controller.pad.r_stick = pad_state.r_stick;
  534. trigger_entry.l_analog = trigger_state.l_analog;
  535. trigger_entry.r_analog = trigger_state.r_analog;
  536. libnx_entry.connection_status.is_wired.Assign(1);
  537. break;
  538. case NPadControllerType::Pokeball:
  539. pokeball_entry.connection_status.raw = 0;
  540. pokeball_entry.connection_status.is_connected.Assign(1);
  541. pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  542. pokeball_entry.pad.l_stick = pad_state.l_stick;
  543. pokeball_entry.pad.r_stick = pad_state.r_stick;
  544. break;
  545. }
  546. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  547. // any controllers.
  548. libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  549. libnx_entry.pad.l_stick = pad_state.l_stick;
  550. libnx_entry.pad.r_stick = pad_state.r_stick;
  551. press_state |= static_cast<u32>(pad_state.pad_states.raw);
  552. }
  553. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  554. shared_memory_entries.size() * sizeof(NPadEntry));
  555. }
  556. void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  557. std::size_t data_len) {
  558. if (!IsControllerActivated()) {
  559. return;
  560. }
  561. for (std::size_t i = 0; i < shared_memory_entries.size(); ++i) {
  562. auto& npad = shared_memory_entries[i];
  563. const auto& controller_type = connected_controllers[i].type;
  564. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  565. continue;
  566. }
  567. const std::array<SixAxisGeneric*, 6> controller_sixaxes{
  568. &npad.sixaxis_fullkey, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
  569. &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
  570. };
  571. for (auto* sixaxis_sensor : controller_sixaxes) {
  572. sixaxis_sensor->common.entry_count = 16;
  573. sixaxis_sensor->common.total_entry_count = 17;
  574. const auto& last_entry =
  575. sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
  576. sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
  577. sixaxis_sensor->common.last_entry_index =
  578. (sixaxis_sensor->common.last_entry_index + 1) % 17;
  579. auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
  580. cur_entry.timestamp = last_entry.timestamp + 1;
  581. cur_entry.timestamp2 = cur_entry.timestamp;
  582. }
  583. // Try to read sixaxis sensor states
  584. std::array<MotionDevice, 2> motion_devices;
  585. if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
  586. sixaxis_at_rest = true;
  587. for (std::size_t e = 0; e < motion_devices.size(); ++e) {
  588. const auto& device = motions[i][e];
  589. if (device) {
  590. std::tie(motion_devices[e].accel, motion_devices[e].gyro,
  591. motion_devices[e].rotation, motion_devices[e].orientation,
  592. motion_devices[e].quaternion) = device->GetStatus();
  593. sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f;
  594. }
  595. }
  596. }
  597. auto& full_sixaxis_entry =
  598. npad.sixaxis_fullkey.sixaxis[npad.sixaxis_fullkey.common.last_entry_index];
  599. auto& handheld_sixaxis_entry =
  600. npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
  601. auto& dual_left_sixaxis_entry =
  602. npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
  603. auto& dual_right_sixaxis_entry =
  604. npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
  605. auto& left_sixaxis_entry =
  606. npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
  607. auto& right_sixaxis_entry =
  608. npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
  609. switch (controller_type) {
  610. case NPadControllerType::None:
  611. UNREACHABLE();
  612. break;
  613. case NPadControllerType::ProController:
  614. full_sixaxis_entry.attribute.raw = 0;
  615. if (sixaxis_sensors_enabled && motions[i][0]) {
  616. full_sixaxis_entry.attribute.is_connected.Assign(1);
  617. full_sixaxis_entry.accel = motion_devices[0].accel;
  618. full_sixaxis_entry.gyro = motion_devices[0].gyro;
  619. full_sixaxis_entry.rotation = motion_devices[0].rotation;
  620. full_sixaxis_entry.orientation = motion_devices[0].orientation;
  621. }
  622. break;
  623. case NPadControllerType::Handheld:
  624. handheld_sixaxis_entry.attribute.raw = 0;
  625. if (sixaxis_sensors_enabled && motions[i][0]) {
  626. handheld_sixaxis_entry.attribute.is_connected.Assign(1);
  627. handheld_sixaxis_entry.accel = motion_devices[0].accel;
  628. handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
  629. handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
  630. handheld_sixaxis_entry.orientation = motion_devices[0].orientation;
  631. }
  632. break;
  633. case NPadControllerType::JoyDual:
  634. dual_left_sixaxis_entry.attribute.raw = 0;
  635. dual_right_sixaxis_entry.attribute.raw = 0;
  636. if (sixaxis_sensors_enabled && motions[i][0]) {
  637. // Set motion for the left joycon
  638. dual_left_sixaxis_entry.attribute.is_connected.Assign(1);
  639. dual_left_sixaxis_entry.accel = motion_devices[0].accel;
  640. dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
  641. dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
  642. dual_left_sixaxis_entry.orientation = motion_devices[0].orientation;
  643. }
  644. if (sixaxis_sensors_enabled && motions[i][1]) {
  645. // Set motion for the right joycon
  646. dual_right_sixaxis_entry.attribute.is_connected.Assign(1);
  647. dual_right_sixaxis_entry.accel = motion_devices[1].accel;
  648. dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
  649. dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
  650. dual_right_sixaxis_entry.orientation = motion_devices[1].orientation;
  651. }
  652. break;
  653. case NPadControllerType::JoyLeft:
  654. left_sixaxis_entry.attribute.raw = 0;
  655. if (sixaxis_sensors_enabled && motions[i][0]) {
  656. left_sixaxis_entry.attribute.is_connected.Assign(1);
  657. left_sixaxis_entry.accel = motion_devices[0].accel;
  658. left_sixaxis_entry.gyro = motion_devices[0].gyro;
  659. left_sixaxis_entry.rotation = motion_devices[0].rotation;
  660. left_sixaxis_entry.orientation = motion_devices[0].orientation;
  661. }
  662. break;
  663. case NPadControllerType::JoyRight:
  664. right_sixaxis_entry.attribute.raw = 0;
  665. if (sixaxis_sensors_enabled && motions[i][1]) {
  666. right_sixaxis_entry.attribute.is_connected.Assign(1);
  667. right_sixaxis_entry.accel = motion_devices[1].accel;
  668. right_sixaxis_entry.gyro = motion_devices[1].gyro;
  669. right_sixaxis_entry.rotation = motion_devices[1].rotation;
  670. right_sixaxis_entry.orientation = motion_devices[1].orientation;
  671. }
  672. break;
  673. case NPadControllerType::GameCube:
  674. case NPadControllerType::Pokeball:
  675. break;
  676. }
  677. }
  678. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  679. shared_memory_entries.size() * sizeof(NPadEntry));
  680. }
  681. void Controller_NPad::SetSupportedStyleSet(NpadStyleSet style_set) {
  682. style.raw = style_set.raw;
  683. }
  684. Controller_NPad::NpadStyleSet Controller_NPad::GetSupportedStyleSet() const {
  685. return style;
  686. }
  687. void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
  688. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  689. supported_npad_id_types.clear();
  690. supported_npad_id_types.resize(length / sizeof(u32));
  691. std::memcpy(supported_npad_id_types.data(), data, length);
  692. }
  693. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  694. ASSERT(max_length < supported_npad_id_types.size());
  695. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  696. }
  697. std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
  698. return supported_npad_id_types.size();
  699. }
  700. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  701. hold_type = joy_hold_type;
  702. }
  703. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  704. return hold_type;
  705. }
  706. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  707. handheld_activation_mode = activation_mode;
  708. }
  709. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  710. return handheld_activation_mode;
  711. }
  712. void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
  713. communication_mode = communication_mode_;
  714. }
  715. Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
  716. return communication_mode;
  717. }
  718. void Controller_NPad::SetNpadMode(u32 npad_id, NpadAssignments assignment_mode) {
  719. const std::size_t npad_index = NPadIdToIndex(npad_id);
  720. ASSERT(npad_index < shared_memory_entries.size());
  721. if (shared_memory_entries[npad_index].assignment_mode != assignment_mode) {
  722. shared_memory_entries[npad_index].assignment_mode = assignment_mode;
  723. }
  724. }
  725. bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
  726. const VibrationValue& vibration_value) {
  727. if (!connected_controllers[npad_index].is_connected || !vibrations[npad_index][device_index]) {
  728. return false;
  729. }
  730. const auto& player = Settings::values.players.GetValue()[npad_index];
  731. if (!player.vibration_enabled) {
  732. if (latest_vibration_values[npad_index][device_index].amp_low != 0.0f ||
  733. latest_vibration_values[npad_index][device_index].amp_high != 0.0f) {
  734. // Send an empty vibration to stop any vibrations.
  735. vibrations[npad_index][device_index]->SetRumblePlay(0.0f, 160.0f, 0.0f, 320.0f);
  736. // Then reset the vibration value to its default value.
  737. latest_vibration_values[npad_index][device_index] = DEFAULT_VIBRATION_VALUE;
  738. }
  739. return false;
  740. }
  741. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  742. using std::chrono::duration_cast;
  743. using std::chrono::milliseconds;
  744. using std::chrono::steady_clock;
  745. const auto now = steady_clock::now();
  746. // Filter out non-zero vibrations that are within 10ms of each other.
  747. if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
  748. duration_cast<milliseconds>(now - last_vibration_timepoints[npad_index][device_index]) <
  749. milliseconds(10)) {
  750. return false;
  751. }
  752. last_vibration_timepoints[npad_index][device_index] = now;
  753. }
  754. auto& vibration = vibrations[npad_index][device_index];
  755. const auto player_vibration_strength = static_cast<f32>(player.vibration_strength);
  756. const auto amp_low =
  757. std::min(vibration_value.amp_low * player_vibration_strength / 100.0f, 1.0f);
  758. const auto amp_high =
  759. std::min(vibration_value.amp_high * player_vibration_strength / 100.0f, 1.0f);
  760. return vibration->SetRumblePlay(amp_low, vibration_value.freq_low, amp_high,
  761. vibration_value.freq_high);
  762. }
  763. void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
  764. const VibrationValue& vibration_value) {
  765. if (!IsDeviceHandleValid(vibration_device_handle)) {
  766. return;
  767. }
  768. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  769. return;
  770. }
  771. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  772. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  773. if (!vibration_devices_mounted[npad_index][device_index] ||
  774. !connected_controllers[npad_index].is_connected) {
  775. return;
  776. }
  777. if (vibration_device_handle.device_index == DeviceIndex::None) {
  778. UNREACHABLE_MSG("DeviceIndex should never be None!");
  779. return;
  780. }
  781. // Some games try to send mismatched parameters in the device handle, block these.
  782. if ((connected_controllers[npad_index].type == NPadControllerType::JoyLeft &&
  783. (vibration_device_handle.npad_type == NpadType::JoyconRight ||
  784. vibration_device_handle.device_index == DeviceIndex::Right)) ||
  785. (connected_controllers[npad_index].type == NPadControllerType::JoyRight &&
  786. (vibration_device_handle.npad_type == NpadType::JoyconLeft ||
  787. vibration_device_handle.device_index == DeviceIndex::Left))) {
  788. return;
  789. }
  790. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  791. if (vibration_value.amp_low == latest_vibration_values[npad_index][device_index].amp_low &&
  792. vibration_value.amp_high == latest_vibration_values[npad_index][device_index].amp_high) {
  793. return;
  794. }
  795. if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
  796. latest_vibration_values[npad_index][device_index] = vibration_value;
  797. }
  798. }
  799. void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
  800. const std::vector<VibrationValue>& vibration_values) {
  801. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  802. return;
  803. }
  804. ASSERT_OR_EXECUTE_MSG(
  805. vibration_device_handles.size() == vibration_values.size(), { return; },
  806. "The amount of device handles does not match with the amount of vibration values,"
  807. "this is undefined behavior!");
  808. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  809. VibrateController(vibration_device_handles[i], vibration_values[i]);
  810. }
  811. }
  812. Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
  813. const DeviceHandle& vibration_device_handle) const {
  814. if (!IsDeviceHandleValid(vibration_device_handle)) {
  815. return {};
  816. }
  817. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  818. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  819. return latest_vibration_values[npad_index][device_index];
  820. }
  821. void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
  822. if (!IsDeviceHandleValid(vibration_device_handle)) {
  823. return;
  824. }
  825. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  826. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  827. InitializeVibrationDeviceAtIndex(npad_index, device_index);
  828. }
  829. void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
  830. std::size_t device_index) {
  831. if (!Settings::values.vibration_enabled.GetValue()) {
  832. vibration_devices_mounted[npad_index][device_index] = false;
  833. return;
  834. }
  835. if (vibrations[npad_index][device_index]) {
  836. vibration_devices_mounted[npad_index][device_index] =
  837. vibrations[npad_index][device_index]->GetStatus() == 1;
  838. } else {
  839. vibration_devices_mounted[npad_index][device_index] = false;
  840. }
  841. }
  842. void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  843. permit_vibration_session_enabled = permit_vibration_session;
  844. }
  845. bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
  846. if (!IsDeviceHandleValid(vibration_device_handle)) {
  847. return false;
  848. }
  849. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  850. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  851. return vibration_devices_mounted[npad_index][device_index];
  852. }
  853. Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) {
  854. return styleset_changed_events[NPadIdToIndex(npad_id)]->GetReadableEvent();
  855. }
  856. void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
  857. styleset_changed_events[NPadIdToIndex(npad_id)]->GetWritableEvent().Signal();
  858. }
  859. void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
  860. UpdateControllerAt(controller, npad_index, true);
  861. }
  862. void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
  863. bool connected) {
  864. if (!connected) {
  865. DisconnectNpadAtIndex(npad_index);
  866. return;
  867. }
  868. if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) {
  869. Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type =
  870. MapNPadToSettingsType(controller);
  871. Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true;
  872. connected_controllers[HANDHELD_INDEX] = {controller, true};
  873. InitNewlyAddedController(HANDHELD_INDEX);
  874. return;
  875. }
  876. Settings::values.players.GetValue()[npad_index].controller_type =
  877. MapNPadToSettingsType(controller);
  878. Settings::values.players.GetValue()[npad_index].connected = true;
  879. connected_controllers[npad_index] = {controller, true};
  880. InitNewlyAddedController(npad_index);
  881. }
  882. void Controller_NPad::DisconnectNpad(u32 npad_id) {
  883. DisconnectNpadAtIndex(NPadIdToIndex(npad_id));
  884. }
  885. void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
  886. for (std::size_t device_idx = 0; device_idx < vibrations[npad_index].size(); ++device_idx) {
  887. // Send an empty vibration to stop any vibrations.
  888. VibrateControllerAtIndex(npad_index, device_idx, {});
  889. vibration_devices_mounted[npad_index][device_idx] = false;
  890. }
  891. Settings::values.players.GetValue()[npad_index].connected = false;
  892. connected_controllers[npad_index].is_connected = false;
  893. auto& controller = shared_memory_entries[npad_index];
  894. controller.style_set.raw = 0; // Zero out
  895. controller.device_type.raw = 0;
  896. controller.system_properties.raw = 0;
  897. controller.button_properties.raw = 0;
  898. controller.battery_level_dual = 0;
  899. controller.battery_level_left = 0;
  900. controller.battery_level_right = 0;
  901. controller.fullkey_color = {};
  902. controller.joycon_color = {};
  903. controller.assignment_mode = NpadAssignments::Dual;
  904. controller.footer_type = AppletFooterUiType::None;
  905. SignalStyleSetChangedEvent(IndexToNPad(npad_index));
  906. }
  907. void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
  908. gyroscope_zero_drift_mode = drift_mode;
  909. }
  910. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
  911. return gyroscope_zero_drift_mode;
  912. }
  913. bool Controller_NPad::IsSixAxisSensorAtRest() const {
  914. return sixaxis_at_rest;
  915. }
  916. void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
  917. sixaxis_sensors_enabled = six_axis_status;
  918. }
  919. void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) {
  920. sixaxis_fusion_parameter1 = parameter1;
  921. sixaxis_fusion_parameter2 = parameter2;
  922. }
  923. std::pair<f32, f32> Controller_NPad::GetSixAxisFusionParameters() {
  924. return {
  925. sixaxis_fusion_parameter1,
  926. sixaxis_fusion_parameter2,
  927. };
  928. }
  929. void Controller_NPad::ResetSixAxisFusionParameters() {
  930. sixaxis_fusion_parameter1 = 0.0f;
  931. sixaxis_fusion_parameter2 = 0.0f;
  932. }
  933. void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
  934. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  935. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  936. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  937. // Otherwise, do nothing.
  938. if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft &&
  939. connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) ||
  940. (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
  941. connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
  942. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  943. DisconnectNpad(npad_id_2);
  944. AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
  945. }
  946. }
  947. void Controller_NPad::StartLRAssignmentMode() {
  948. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  949. // controller types from boot, it doesn't really matter about showing a selection screen
  950. is_in_lr_assignment_mode = true;
  951. }
  952. void Controller_NPad::StopLRAssignmentMode() {
  953. is_in_lr_assignment_mode = false;
  954. }
  955. bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
  956. if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
  957. npad_id_2 == NPAD_UNKNOWN) {
  958. return true;
  959. }
  960. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  961. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  962. if (!IsControllerSupported(connected_controllers[npad_index_1].type) ||
  963. !IsControllerSupported(connected_controllers[npad_index_2].type)) {
  964. return false;
  965. }
  966. std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
  967. AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
  968. AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
  969. return true;
  970. }
  971. Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  972. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  973. // These are controllers without led patterns
  974. return LedPattern{0, 0, 0, 0};
  975. }
  976. switch (npad_id) {
  977. case 0:
  978. return LedPattern{1, 0, 0, 0};
  979. case 1:
  980. return LedPattern{1, 1, 0, 0};
  981. case 2:
  982. return LedPattern{1, 1, 1, 0};
  983. case 3:
  984. return LedPattern{1, 1, 1, 1};
  985. case 4:
  986. return LedPattern{1, 0, 0, 1};
  987. case 5:
  988. return LedPattern{1, 0, 1, 0};
  989. case 6:
  990. return LedPattern{1, 0, 1, 1};
  991. case 7:
  992. return LedPattern{0, 1, 1, 0};
  993. default:
  994. return LedPattern{0, 0, 0, 0};
  995. }
  996. }
  997. bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
  998. return unintended_home_button_input_protection[NPadIdToIndex(npad_id)];
  999. }
  1000. void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
  1001. u32 npad_id) {
  1002. unintended_home_button_input_protection[NPadIdToIndex(npad_id)] = is_protection_enabled;
  1003. }
  1004. void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
  1005. analog_stick_use_center_clamp = use_center_clamp;
  1006. }
  1007. void Controller_NPad::ClearAllConnectedControllers() {
  1008. for (auto& controller : connected_controllers) {
  1009. if (controller.is_connected && controller.type != NPadControllerType::None) {
  1010. controller.type = NPadControllerType::None;
  1011. controller.is_connected = false;
  1012. }
  1013. }
  1014. }
  1015. void Controller_NPad::DisconnectAllConnectedControllers() {
  1016. for (auto& controller : connected_controllers) {
  1017. controller.is_connected = false;
  1018. }
  1019. }
  1020. void Controller_NPad::ConnectAllDisconnectedControllers() {
  1021. for (auto& controller : connected_controllers) {
  1022. if (controller.type != NPadControllerType::None && !controller.is_connected) {
  1023. controller.is_connected = true;
  1024. }
  1025. }
  1026. }
  1027. void Controller_NPad::ClearAllControllers() {
  1028. for (auto& controller : connected_controllers) {
  1029. controller.type = NPadControllerType::None;
  1030. controller.is_connected = false;
  1031. }
  1032. }
  1033. u32 Controller_NPad::GetAndResetPressState() {
  1034. return press_state.exchange(0);
  1035. }
  1036. bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
  1037. if (controller == NPadControllerType::Handheld) {
  1038. const bool support_handheld =
  1039. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1040. NPAD_HANDHELD) != supported_npad_id_types.end();
  1041. // Handheld is not even a supported type, lets stop here
  1042. if (!support_handheld) {
  1043. return false;
  1044. }
  1045. // Handheld should not be supported in docked mode
  1046. if (Settings::values.use_docked_mode.GetValue()) {
  1047. return false;
  1048. }
  1049. return true;
  1050. }
  1051. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1052. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  1053. switch (controller) {
  1054. case NPadControllerType::ProController:
  1055. return style.fullkey;
  1056. case NPadControllerType::JoyDual:
  1057. return style.joycon_dual;
  1058. case NPadControllerType::JoyLeft:
  1059. return style.joycon_left;
  1060. case NPadControllerType::JoyRight:
  1061. return style.joycon_right;
  1062. case NPadControllerType::GameCube:
  1063. return style.gamecube;
  1064. case NPadControllerType::Pokeball:
  1065. return style.palma;
  1066. default:
  1067. return false;
  1068. }
  1069. }
  1070. return false;
  1071. }
  1072. } // namespace Service::HID