npad.cpp 31 KB

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