npad.cpp 50 KB

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