npad.cpp 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  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/kernel.h"
  15. #include "core/hle/kernel/readable_event.h"
  16. #include "core/hle/kernel/writable_event.h"
  17. #include "core/hle/service/hid/controllers/npad.h"
  18. #include "core/settings.h"
  19. namespace Service::HID {
  20. constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
  21. [[maybe_unused]] constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
  22. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  23. constexpr u32 BATTERY_FULL = 2;
  24. constexpr u32 MAX_NPAD_ID = 7;
  25. constexpr std::size_t HANDHELD_INDEX = 8;
  26. constexpr std::array<u32, 10> npad_id_list{
  27. 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
  28. };
  29. enum class JoystickId : std::size_t {
  30. Joystick_Left,
  31. Joystick_Right,
  32. };
  33. Controller_NPad::NPadControllerType Controller_NPad::MapSettingsTypeToNPad(
  34. Settings::ControllerType type) {
  35. switch (type) {
  36. case Settings::ControllerType::ProController:
  37. return NPadControllerType::ProController;
  38. case Settings::ControllerType::DualJoyconDetached:
  39. return NPadControllerType::JoyDual;
  40. case Settings::ControllerType::LeftJoycon:
  41. return NPadControllerType::JoyLeft;
  42. case Settings::ControllerType::RightJoycon:
  43. return NPadControllerType::JoyRight;
  44. case Settings::ControllerType::Handheld:
  45. return NPadControllerType::Handheld;
  46. default:
  47. UNREACHABLE();
  48. return NPadControllerType::ProController;
  49. }
  50. }
  51. Settings::ControllerType Controller_NPad::MapNPadToSettingsType(
  52. Controller_NPad::NPadControllerType type) {
  53. switch (type) {
  54. case NPadControllerType::ProController:
  55. return Settings::ControllerType::ProController;
  56. case NPadControllerType::JoyDual:
  57. return Settings::ControllerType::DualJoyconDetached;
  58. case NPadControllerType::JoyLeft:
  59. return Settings::ControllerType::LeftJoycon;
  60. case NPadControllerType::JoyRight:
  61. return Settings::ControllerType::RightJoycon;
  62. case NPadControllerType::Handheld:
  63. return Settings::ControllerType::Handheld;
  64. default:
  65. UNREACHABLE();
  66. return Settings::ControllerType::ProController;
  67. }
  68. }
  69. std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
  70. switch (npad_id) {
  71. case 0:
  72. case 1:
  73. case 2:
  74. case 3:
  75. case 4:
  76. case 5:
  77. case 6:
  78. case 7:
  79. return npad_id;
  80. case HANDHELD_INDEX:
  81. case NPAD_HANDHELD:
  82. return HANDHELD_INDEX;
  83. case 9:
  84. case NPAD_UNKNOWN:
  85. return 9;
  86. default:
  87. UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
  88. return 0;
  89. }
  90. }
  91. u32 Controller_NPad::IndexToNPad(std::size_t index) {
  92. switch (index) {
  93. case 0:
  94. case 1:
  95. case 2:
  96. case 3:
  97. case 4:
  98. case 5:
  99. case 6:
  100. case 7:
  101. return static_cast<u32>(index);
  102. case HANDHELD_INDEX:
  103. return NPAD_HANDHELD;
  104. case 9:
  105. return NPAD_UNKNOWN;
  106. default:
  107. UNIMPLEMENTED_MSG("Unknown npad index {}", index);
  108. return 0;
  109. }
  110. }
  111. Controller_NPad::Controller_NPad(Core::System& system) : ControllerBase(system), system(system) {}
  112. Controller_NPad::~Controller_NPad() = default;
  113. void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
  114. const auto controller_type = connected_controllers[controller_idx].type;
  115. auto& controller = shared_memory_entries[controller_idx];
  116. if (controller_type == NPadControllerType::None) {
  117. styleset_changed_events[controller_idx].writable->Signal();
  118. return;
  119. }
  120. controller.joy_styles.raw = 0; // Zero out
  121. controller.device_type.raw = 0;
  122. controller.properties.raw = 0;
  123. switch (controller_type) {
  124. case NPadControllerType::None:
  125. UNREACHABLE();
  126. break;
  127. case NPadControllerType::ProController:
  128. controller.joy_styles.pro_controller.Assign(1);
  129. controller.device_type.pro_controller.Assign(1);
  130. controller.properties.is_vertical.Assign(1);
  131. controller.properties.use_plus.Assign(1);
  132. controller.properties.use_minus.Assign(1);
  133. controller.pad_assignment = NPadAssignments::Single;
  134. break;
  135. case NPadControllerType::Handheld:
  136. controller.joy_styles.handheld.Assign(1);
  137. controller.device_type.handheld.Assign(1);
  138. controller.properties.is_vertical.Assign(1);
  139. controller.properties.use_plus.Assign(1);
  140. controller.properties.use_minus.Assign(1);
  141. controller.pad_assignment = NPadAssignments::Dual;
  142. break;
  143. case NPadControllerType::JoyDual:
  144. controller.joy_styles.joycon_dual.Assign(1);
  145. controller.device_type.joycon_left.Assign(1);
  146. controller.device_type.joycon_right.Assign(1);
  147. controller.properties.is_vertical.Assign(1);
  148. controller.properties.use_plus.Assign(1);
  149. controller.properties.use_minus.Assign(1);
  150. controller.pad_assignment = NPadAssignments::Dual;
  151. break;
  152. case NPadControllerType::JoyLeft:
  153. controller.joy_styles.joycon_left.Assign(1);
  154. controller.device_type.joycon_left.Assign(1);
  155. controller.properties.is_horizontal.Assign(1);
  156. controller.properties.use_minus.Assign(1);
  157. controller.pad_assignment = NPadAssignments::Single;
  158. break;
  159. case NPadControllerType::JoyRight:
  160. controller.joy_styles.joycon_right.Assign(1);
  161. controller.device_type.joycon_right.Assign(1);
  162. controller.properties.is_horizontal.Assign(1);
  163. controller.properties.use_plus.Assign(1);
  164. controller.pad_assignment = NPadAssignments::Single;
  165. break;
  166. case NPadControllerType::Pokeball:
  167. controller.joy_styles.pokeball.Assign(1);
  168. controller.device_type.pokeball.Assign(1);
  169. controller.pad_assignment = NPadAssignments::Single;
  170. break;
  171. }
  172. controller.single_color_error = ColorReadError::ReadOk;
  173. controller.single_color.body_color = 0;
  174. controller.single_color.button_color = 0;
  175. controller.dual_color_error = ColorReadError::ReadOk;
  176. controller.left_color.body_color = Settings::values.players[controller_idx].body_color_left;
  177. controller.left_color.button_color = Settings::values.players[controller_idx].button_color_left;
  178. controller.right_color.body_color = Settings::values.players[controller_idx].body_color_right;
  179. controller.right_color.button_color =
  180. Settings::values.players[controller_idx].button_color_right;
  181. controller.battery_level[0] = BATTERY_FULL;
  182. controller.battery_level[1] = BATTERY_FULL;
  183. controller.battery_level[2] = BATTERY_FULL;
  184. styleset_changed_events[controller_idx].writable->Signal();
  185. }
  186. void Controller_NPad::OnInit() {
  187. auto& kernel = system.Kernel();
  188. for (std::size_t i = 0; i < styleset_changed_events.size(); i++) {
  189. styleset_changed_events[i] = Kernel::WritableEvent::CreateEventPair(
  190. kernel, fmt::format("npad:NpadStyleSetChanged_{}", i));
  191. }
  192. if (!IsControllerActivated()) {
  193. return;
  194. }
  195. if (style.raw == 0) {
  196. // We want to support all controllers
  197. style.handheld.Assign(1);
  198. style.joycon_left.Assign(1);
  199. style.joycon_right.Assign(1);
  200. style.joycon_dual.Assign(1);
  201. style.pro_controller.Assign(1);
  202. style.pokeball.Assign(1);
  203. }
  204. std::transform(Settings::values.players.begin(), Settings::values.players.end(),
  205. connected_controllers.begin(), [](const Settings::PlayerInput& player) {
  206. return ControllerHolder{MapSettingsTypeToNPad(player.controller_type),
  207. player.connected};
  208. });
  209. // Account for handheld
  210. if (connected_controllers[HANDHELD_INDEX].is_connected) {
  211. connected_controllers[HANDHELD_INDEX].type = NPadControllerType::Handheld;
  212. }
  213. supported_npad_id_types.resize(npad_id_list.size());
  214. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  215. npad_id_list.size() * sizeof(u32));
  216. for (std::size_t i = 0; i < connected_controllers.size(); ++i) {
  217. const auto& controller = connected_controllers[i];
  218. if (controller.is_connected) {
  219. AddNewControllerAt(controller.type, i);
  220. }
  221. }
  222. }
  223. void Controller_NPad::OnLoadInputDevices() {
  224. const auto& players = Settings::values.players;
  225. for (std::size_t i = 0; i < players.size(); ++i) {
  226. std::transform(players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  227. players[i].buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
  228. buttons[i].begin(), Input::CreateDevice<Input::ButtonDevice>);
  229. std::transform(players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  230. players[i].analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
  231. sticks[i].begin(), Input::CreateDevice<Input::AnalogDevice>);
  232. }
  233. }
  234. void Controller_NPad::OnRelease() {}
  235. void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
  236. const auto controller_idx = NPadIdToIndex(npad_id);
  237. [[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type;
  238. if (!connected_controllers[controller_idx].is_connected) {
  239. return;
  240. }
  241. auto& pad_state = npad_pad_states[controller_idx].pad_states;
  242. auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
  243. auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
  244. const auto& button_state = buttons[controller_idx];
  245. const auto& analog_state = sticks[controller_idx];
  246. const auto [stick_l_x_f, stick_l_y_f] =
  247. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
  248. const auto [stick_r_x_f, stick_r_y_f] =
  249. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
  250. using namespace Settings::NativeButton;
  251. pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
  252. pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
  253. pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
  254. pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
  255. pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
  256. pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
  257. pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
  258. pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
  259. pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
  260. pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
  261. pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
  262. pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
  263. pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  264. pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
  265. pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
  266. pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
  267. pad_state.l_stick_right.Assign(
  268. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  269. Input::AnalogDirection::RIGHT));
  270. pad_state.l_stick_left.Assign(
  271. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  272. Input::AnalogDirection::LEFT));
  273. pad_state.l_stick_up.Assign(
  274. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  275. Input::AnalogDirection::UP));
  276. pad_state.l_stick_down.Assign(
  277. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  278. Input::AnalogDirection::DOWN));
  279. pad_state.r_stick_right.Assign(
  280. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  281. ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
  282. pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  283. ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
  284. pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  285. ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
  286. pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  287. ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
  288. pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
  289. pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
  290. lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  291. lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  292. rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  293. rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  294. }
  295. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  296. std::size_t data_len) {
  297. if (!IsControllerActivated()) {
  298. return;
  299. }
  300. for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
  301. auto& npad = shared_memory_entries[i];
  302. const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
  303. &npad.handheld_states,
  304. &npad.dual_states,
  305. &npad.left_joy_states,
  306. &npad.right_joy_states,
  307. &npad.pokeball_states,
  308. &npad.libnx};
  309. for (auto* main_controller : controller_npads) {
  310. main_controller->common.entry_count = 16;
  311. main_controller->common.total_entry_count = 17;
  312. const auto& last_entry =
  313. main_controller->npad[main_controller->common.last_entry_index];
  314. main_controller->common.timestamp = core_timing.GetCPUTicks();
  315. main_controller->common.last_entry_index =
  316. (main_controller->common.last_entry_index + 1) % 17;
  317. auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
  318. cur_entry.timestamp = last_entry.timestamp + 1;
  319. cur_entry.timestamp2 = cur_entry.timestamp;
  320. }
  321. const auto& controller_type = connected_controllers[i].type;
  322. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  323. continue;
  324. }
  325. const u32 npad_index = static_cast<u32>(i);
  326. RequestPadStateUpdate(npad_index);
  327. auto& pad_state = npad_pad_states[npad_index];
  328. auto& main_controller =
  329. npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
  330. auto& handheld_entry =
  331. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  332. auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
  333. auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
  334. auto& right_entry =
  335. npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
  336. auto& pokeball_entry =
  337. npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
  338. auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
  339. libnx_entry.connection_status.raw = 0;
  340. switch (controller_type) {
  341. case NPadControllerType::None:
  342. UNREACHABLE();
  343. break;
  344. case NPadControllerType::ProController:
  345. main_controller.connection_status.raw = 0;
  346. main_controller.connection_status.IsConnected.Assign(1);
  347. main_controller.connection_status.IsWired.Assign(1);
  348. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  349. main_controller.pad.l_stick = pad_state.l_stick;
  350. main_controller.pad.r_stick = pad_state.r_stick;
  351. break;
  352. case NPadControllerType::Handheld:
  353. handheld_entry.connection_status.raw = 0;
  354. handheld_entry.connection_status.IsWired.Assign(1);
  355. handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
  356. handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
  357. handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
  358. handheld_entry.connection_status.IsRightJoyWired.Assign(1);
  359. handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  360. handheld_entry.pad.l_stick = pad_state.l_stick;
  361. handheld_entry.pad.r_stick = pad_state.r_stick;
  362. break;
  363. case NPadControllerType::JoyDual:
  364. dual_entry.connection_status.raw = 0;
  365. dual_entry.connection_status.IsConnected.Assign(1);
  366. dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
  367. dual_entry.connection_status.IsRightJoyConnected.Assign(1);
  368. dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  369. dual_entry.pad.l_stick = pad_state.l_stick;
  370. dual_entry.pad.r_stick = pad_state.r_stick;
  371. libnx_entry.connection_status.IsConnected.Assign(1);
  372. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  373. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  374. break;
  375. case NPadControllerType::JoyLeft:
  376. left_entry.connection_status.raw = 0;
  377. left_entry.connection_status.IsConnected.Assign(1);
  378. left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  379. left_entry.pad.l_stick = pad_state.l_stick;
  380. left_entry.pad.r_stick = pad_state.r_stick;
  381. break;
  382. case NPadControllerType::JoyRight:
  383. right_entry.connection_status.raw = 0;
  384. right_entry.connection_status.IsConnected.Assign(1);
  385. right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  386. right_entry.pad.l_stick = pad_state.l_stick;
  387. right_entry.pad.r_stick = pad_state.r_stick;
  388. break;
  389. case NPadControllerType::Pokeball:
  390. pokeball_entry.connection_status.raw = 0;
  391. pokeball_entry.connection_status.IsConnected.Assign(1);
  392. pokeball_entry.connection_status.IsWired.Assign(1);
  393. pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  394. pokeball_entry.pad.l_stick = pad_state.l_stick;
  395. pokeball_entry.pad.r_stick = pad_state.r_stick;
  396. break;
  397. }
  398. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  399. // any controllers.
  400. libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  401. libnx_entry.pad.l_stick = pad_state.l_stick;
  402. libnx_entry.pad.r_stick = pad_state.r_stick;
  403. press_state |= static_cast<u32>(pad_state.pad_states.raw);
  404. }
  405. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  406. shared_memory_entries.size() * sizeof(NPadEntry));
  407. }
  408. void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
  409. style.raw = style_set.raw;
  410. }
  411. Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
  412. return style;
  413. }
  414. void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
  415. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  416. supported_npad_id_types.clear();
  417. supported_npad_id_types.resize(length / sizeof(u32));
  418. std::memcpy(supported_npad_id_types.data(), data, length);
  419. }
  420. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  421. ASSERT(max_length < supported_npad_id_types.size());
  422. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  423. }
  424. std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
  425. return supported_npad_id_types.size();
  426. }
  427. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  428. hold_type = joy_hold_type;
  429. }
  430. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  431. return hold_type;
  432. }
  433. void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
  434. const std::size_t npad_index = NPadIdToIndex(npad_id);
  435. ASSERT(npad_index < shared_memory_entries.size());
  436. if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
  437. shared_memory_entries[npad_index].pad_assignment = assignment_mode;
  438. }
  439. }
  440. void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
  441. const std::vector<Vibration>& vibrations) {
  442. LOG_DEBUG(Service_HID, "(STUBBED) called");
  443. if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
  444. return;
  445. }
  446. for (std::size_t i = 0; i < controller_ids.size(); i++) {
  447. std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i));
  448. if (connected_controllers[controller_pos].is_connected) {
  449. // TODO(ogniK): Vibrate the physical controller
  450. }
  451. }
  452. last_processed_vibration = vibrations.back();
  453. }
  454. std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
  455. const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
  456. return styleset_event.readable;
  457. }
  458. Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
  459. return last_processed_vibration;
  460. }
  461. void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
  462. UpdateControllerAt(controller, npad_index, true);
  463. }
  464. void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
  465. bool connected) {
  466. if (!connected) {
  467. DisconnectNPad(IndexToNPad(npad_index));
  468. return;
  469. }
  470. if (controller == NPadControllerType::Handheld) {
  471. Settings::values.players[HANDHELD_INDEX].controller_type =
  472. MapNPadToSettingsType(controller);
  473. Settings::values.players[HANDHELD_INDEX].connected = true;
  474. connected_controllers[HANDHELD_INDEX] = {controller, true};
  475. InitNewlyAddedController(HANDHELD_INDEX);
  476. return;
  477. }
  478. Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
  479. Settings::values.players[npad_index].connected = true;
  480. connected_controllers[npad_index] = {controller, true};
  481. InitNewlyAddedController(npad_index);
  482. }
  483. void Controller_NPad::DisconnectNPad(u32 npad_id) {
  484. const auto npad_index = NPadIdToIndex(npad_id);
  485. connected_controllers[npad_index].is_connected = false;
  486. Settings::values.players[npad_index].connected = false;
  487. auto& controller = shared_memory_entries[npad_index];
  488. controller.joy_styles.raw = 0; // Zero out
  489. controller.device_type.raw = 0;
  490. controller.properties.raw = 0;
  491. styleset_changed_events[npad_index].writable->Signal();
  492. }
  493. void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
  494. gyroscope_zero_drift_mode = drift_mode;
  495. }
  496. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
  497. return gyroscope_zero_drift_mode;
  498. }
  499. void Controller_NPad::StartLRAssignmentMode() {
  500. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  501. // controller types from boot, it doesn't really matter about showing a selection screen
  502. is_in_lr_assignment_mode = true;
  503. }
  504. void Controller_NPad::StopLRAssignmentMode() {
  505. is_in_lr_assignment_mode = false;
  506. }
  507. bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
  508. if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
  509. npad_id_2 == NPAD_UNKNOWN) {
  510. return true;
  511. }
  512. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  513. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  514. if (!IsControllerSupported(connected_controllers[npad_index_1].type) ||
  515. !IsControllerSupported(connected_controllers[npad_index_2].type)) {
  516. return false;
  517. }
  518. std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
  519. AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
  520. AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
  521. return true;
  522. }
  523. Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  524. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  525. // These are controllers without led patterns
  526. return LedPattern{0, 0, 0, 0};
  527. }
  528. switch (npad_id) {
  529. case 0:
  530. return LedPattern{1, 0, 0, 0};
  531. case 1:
  532. return LedPattern{1, 1, 0, 0};
  533. case 2:
  534. return LedPattern{1, 1, 1, 0};
  535. case 3:
  536. return LedPattern{1, 1, 1, 1};
  537. case 4:
  538. return LedPattern{1, 0, 0, 1};
  539. case 5:
  540. return LedPattern{1, 0, 1, 0};
  541. case 6:
  542. return LedPattern{1, 0, 1, 1};
  543. case 7:
  544. return LedPattern{0, 1, 1, 0};
  545. default:
  546. return LedPattern{0, 0, 0, 0};
  547. }
  548. }
  549. void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
  550. can_controllers_vibrate = can_vibrate;
  551. }
  552. bool Controller_NPad::IsVibrationEnabled() const {
  553. return can_controllers_vibrate;
  554. }
  555. void Controller_NPad::ClearAllConnectedControllers() {
  556. for (auto& controller : connected_controllers) {
  557. if (controller.is_connected && controller.type != NPadControllerType::None) {
  558. controller.type = NPadControllerType::None;
  559. controller.is_connected = false;
  560. }
  561. }
  562. }
  563. void Controller_NPad::DisconnectAllConnectedControllers() {
  564. for (ControllerHolder& controller : connected_controllers) {
  565. controller.is_connected = false;
  566. }
  567. }
  568. void Controller_NPad::ConnectAllDisconnectedControllers() {
  569. for (ControllerHolder& controller : connected_controllers) {
  570. if (controller.type != NPadControllerType::None && !controller.is_connected) {
  571. controller.is_connected = true;
  572. }
  573. }
  574. }
  575. void Controller_NPad::ClearAllControllers() {
  576. for (ControllerHolder& controller : connected_controllers) {
  577. controller.type = NPadControllerType::None;
  578. controller.is_connected = false;
  579. }
  580. }
  581. u32 Controller_NPad::GetAndResetPressState() {
  582. return std::exchange(press_state, 0);
  583. }
  584. bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
  585. if (controller == NPadControllerType::Handheld) {
  586. const bool support_handheld =
  587. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  588. NPAD_HANDHELD) != supported_npad_id_types.end();
  589. // Handheld is not even a supported type, lets stop here
  590. if (!support_handheld) {
  591. return false;
  592. }
  593. // Handheld should not be supported in docked mode
  594. if (Settings::values.use_docked_mode) {
  595. return false;
  596. }
  597. return true;
  598. }
  599. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  600. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  601. switch (controller) {
  602. case NPadControllerType::ProController:
  603. return style.pro_controller;
  604. case NPadControllerType::JoyDual:
  605. return style.joycon_dual;
  606. case NPadControllerType::JoyLeft:
  607. return style.joycon_left;
  608. case NPadControllerType::JoyRight:
  609. return style.joycon_right;
  610. case NPadControllerType::Pokeball:
  611. return style.pokeball;
  612. default:
  613. return false;
  614. }
  615. }
  616. return false;
  617. }
  618. Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
  619. NPadControllerType priority) const {
  620. if (IsControllerSupported(priority)) {
  621. return priority;
  622. }
  623. const auto is_docked = Settings::values.use_docked_mode;
  624. if (is_docked && priority == NPadControllerType::Handheld) {
  625. priority = NPadControllerType::JoyDual;
  626. if (IsControllerSupported(priority)) {
  627. return priority;
  628. }
  629. }
  630. std::vector<NPadControllerType> priority_list;
  631. switch (priority) {
  632. case NPadControllerType::ProController:
  633. priority_list.push_back(NPadControllerType::JoyDual);
  634. if (!is_docked) {
  635. priority_list.push_back(NPadControllerType::Handheld);
  636. }
  637. priority_list.push_back(NPadControllerType::JoyLeft);
  638. priority_list.push_back(NPadControllerType::JoyRight);
  639. priority_list.push_back(NPadControllerType::Pokeball);
  640. break;
  641. case NPadControllerType::Handheld:
  642. priority_list.push_back(NPadControllerType::JoyDual);
  643. priority_list.push_back(NPadControllerType::ProController);
  644. priority_list.push_back(NPadControllerType::JoyLeft);
  645. priority_list.push_back(NPadControllerType::JoyRight);
  646. priority_list.push_back(NPadControllerType::Pokeball);
  647. break;
  648. case NPadControllerType::JoyDual:
  649. if (!is_docked) {
  650. priority_list.push_back(NPadControllerType::Handheld);
  651. }
  652. priority_list.push_back(NPadControllerType::ProController);
  653. priority_list.push_back(NPadControllerType::JoyLeft);
  654. priority_list.push_back(NPadControllerType::JoyRight);
  655. priority_list.push_back(NPadControllerType::Pokeball);
  656. break;
  657. case NPadControllerType::JoyLeft:
  658. priority_list.push_back(NPadControllerType::JoyRight);
  659. priority_list.push_back(NPadControllerType::JoyDual);
  660. if (!is_docked) {
  661. priority_list.push_back(NPadControllerType::Handheld);
  662. }
  663. priority_list.push_back(NPadControllerType::ProController);
  664. priority_list.push_back(NPadControllerType::Pokeball);
  665. break;
  666. case NPadControllerType::JoyRight:
  667. priority_list.push_back(NPadControllerType::JoyLeft);
  668. priority_list.push_back(NPadControllerType::JoyDual);
  669. if (!is_docked) {
  670. priority_list.push_back(NPadControllerType::Handheld);
  671. }
  672. priority_list.push_back(NPadControllerType::ProController);
  673. priority_list.push_back(NPadControllerType::Pokeball);
  674. break;
  675. case NPadControllerType::Pokeball:
  676. priority_list.push_back(NPadControllerType::JoyLeft);
  677. priority_list.push_back(NPadControllerType::JoyRight);
  678. priority_list.push_back(NPadControllerType::JoyDual);
  679. if (!is_docked) {
  680. priority_list.push_back(NPadControllerType::Handheld);
  681. }
  682. priority_list.push_back(NPadControllerType::ProController);
  683. break;
  684. default:
  685. priority_list.push_back(NPadControllerType::JoyDual);
  686. if (!is_docked) {
  687. priority_list.push_back(NPadControllerType::Handheld);
  688. }
  689. priority_list.push_back(NPadControllerType::ProController);
  690. priority_list.push_back(NPadControllerType::JoyLeft);
  691. priority_list.push_back(NPadControllerType::JoyRight);
  692. priority_list.push_back(NPadControllerType::JoyDual);
  693. break;
  694. }
  695. const auto iter = std::find_if(priority_list.begin(), priority_list.end(),
  696. [this](auto type) { return IsControllerSupported(type); });
  697. if (iter == priority_list.end()) {
  698. UNIMPLEMENTED_MSG("Could not find supported controller!");
  699. return priority;
  700. }
  701. return *iter;
  702. }
  703. } // namespace Service::HID