npad.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  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, 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. const auto [stick_l_x_f, stick_l_y_f] =
  231. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
  232. const auto [stick_r_x_f, stick_r_y_f] =
  233. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
  234. using namespace Settings::NativeButton;
  235. pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
  236. pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
  237. pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
  238. pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
  239. pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
  240. pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
  241. pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
  242. pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
  243. pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
  244. pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
  245. pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
  246. pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
  247. pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  248. pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
  249. pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
  250. pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
  251. pad_state.l_stick_right.Assign(
  252. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  253. Input::AnalogDirection::RIGHT));
  254. pad_state.l_stick_left.Assign(
  255. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  256. Input::AnalogDirection::LEFT));
  257. pad_state.l_stick_up.Assign(
  258. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  259. Input::AnalogDirection::UP));
  260. pad_state.l_stick_down.Assign(
  261. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  262. Input::AnalogDirection::DOWN));
  263. pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  264. ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
  265. pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  266. ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
  267. pad_state.r_stick_right.Assign(
  268. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  269. ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
  270. pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  271. ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
  272. pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
  273. pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
  274. lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  275. lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  276. rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  277. rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  278. }
  279. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  280. std::size_t data_len) {
  281. if (!IsControllerActivated())
  282. return;
  283. for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
  284. auto& npad = shared_memory_entries[i];
  285. const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
  286. &npad.handheld_states,
  287. &npad.dual_states,
  288. &npad.left_joy_states,
  289. &npad.right_joy_states,
  290. &npad.pokeball_states,
  291. &npad.libnx};
  292. for (auto* main_controller : controller_npads) {
  293. main_controller->common.entry_count = 16;
  294. main_controller->common.total_entry_count = 17;
  295. const auto& last_entry =
  296. main_controller->npad[main_controller->common.last_entry_index];
  297. main_controller->common.timestamp = core_timing.GetTicks();
  298. main_controller->common.last_entry_index =
  299. (main_controller->common.last_entry_index + 1) % 17;
  300. auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
  301. cur_entry.timestamp = last_entry.timestamp + 1;
  302. cur_entry.timestamp2 = cur_entry.timestamp;
  303. }
  304. const auto& controller_type = connected_controllers[i].type;
  305. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  306. continue;
  307. }
  308. const u32 npad_index = static_cast<u32>(i);
  309. RequestPadStateUpdate(npad_index);
  310. auto& pad_state = npad_pad_states[npad_index];
  311. auto& main_controller =
  312. npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
  313. auto& handheld_entry =
  314. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  315. auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
  316. auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
  317. auto& right_entry =
  318. npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
  319. auto& pokeball_entry =
  320. npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
  321. auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
  322. libnx_entry.connection_status.raw = 0;
  323. switch (controller_type) {
  324. case NPadControllerType::None:
  325. UNREACHABLE();
  326. case NPadControllerType::Handheld:
  327. handheld_entry.connection_status.raw = 0;
  328. handheld_entry.connection_status.IsWired.Assign(1);
  329. handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
  330. handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
  331. handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
  332. handheld_entry.connection_status.IsRightJoyWired.Assign(1);
  333. handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  334. handheld_entry.pad.l_stick = pad_state.l_stick;
  335. handheld_entry.pad.r_stick = pad_state.r_stick;
  336. break;
  337. case NPadControllerType::JoyDual:
  338. dual_entry.connection_status.raw = 0;
  339. dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
  340. dual_entry.connection_status.IsRightJoyConnected.Assign(1);
  341. dual_entry.connection_status.IsConnected.Assign(1);
  342. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  343. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  344. libnx_entry.connection_status.IsConnected.Assign(1);
  345. dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  346. dual_entry.pad.l_stick = pad_state.l_stick;
  347. dual_entry.pad.r_stick = pad_state.r_stick;
  348. break;
  349. case NPadControllerType::JoyLeft:
  350. left_entry.connection_status.raw = 0;
  351. left_entry.connection_status.IsConnected.Assign(1);
  352. left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  353. left_entry.pad.l_stick = pad_state.l_stick;
  354. left_entry.pad.r_stick = pad_state.r_stick;
  355. break;
  356. case NPadControllerType::JoyRight:
  357. right_entry.connection_status.raw = 0;
  358. right_entry.connection_status.IsConnected.Assign(1);
  359. right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  360. right_entry.pad.l_stick = pad_state.l_stick;
  361. right_entry.pad.r_stick = pad_state.r_stick;
  362. break;
  363. case NPadControllerType::Pokeball:
  364. pokeball_entry.connection_status.raw = 0;
  365. pokeball_entry.connection_status.IsConnected.Assign(1);
  366. pokeball_entry.connection_status.IsWired.Assign(1);
  367. pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  368. pokeball_entry.pad.l_stick = pad_state.l_stick;
  369. pokeball_entry.pad.r_stick = pad_state.r_stick;
  370. break;
  371. case NPadControllerType::ProController:
  372. main_controller.connection_status.raw = 0;
  373. main_controller.connection_status.IsConnected.Assign(1);
  374. main_controller.connection_status.IsWired.Assign(1);
  375. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  376. main_controller.pad.l_stick = pad_state.l_stick;
  377. main_controller.pad.r_stick = pad_state.r_stick;
  378. break;
  379. }
  380. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  381. // any controllers.
  382. libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  383. libnx_entry.pad.l_stick = pad_state.l_stick;
  384. libnx_entry.pad.r_stick = pad_state.r_stick;
  385. press_state |= static_cast<u32>(pad_state.pad_states.raw);
  386. }
  387. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  388. shared_memory_entries.size() * sizeof(NPadEntry));
  389. }
  390. void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
  391. style.raw = style_set.raw;
  392. }
  393. Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
  394. return style;
  395. }
  396. void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
  397. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  398. supported_npad_id_types.clear();
  399. supported_npad_id_types.resize(length / sizeof(u32));
  400. std::memcpy(supported_npad_id_types.data(), data, length);
  401. for (std::size_t i = 0; i < connected_controllers.size(); i++) {
  402. auto& controller = connected_controllers[i];
  403. if (!controller.is_connected) {
  404. continue;
  405. }
  406. const auto requested_controller =
  407. i <= MAX_NPAD_ID ? MapSettingsTypeToNPad(Settings::values.players[i].type)
  408. : NPadControllerType::Handheld;
  409. if (!IsControllerSupported(requested_controller)) {
  410. const auto is_handheld = requested_controller == NPadControllerType::Handheld;
  411. if (is_handheld) {
  412. controller.type = NPadControllerType::None;
  413. controller.is_connected = false;
  414. AddNewController(requested_controller);
  415. } else {
  416. controller.type = requested_controller;
  417. InitNewlyAddedControler(i);
  418. }
  419. }
  420. }
  421. }
  422. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  423. ASSERT(max_length < supported_npad_id_types.size());
  424. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  425. }
  426. std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
  427. return supported_npad_id_types.size();
  428. }
  429. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  430. hold_type = joy_hold_type;
  431. }
  432. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  433. return hold_type;
  434. }
  435. void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
  436. const std::size_t npad_index = NPadIdToIndex(npad_id);
  437. ASSERT(npad_index < shared_memory_entries.size());
  438. if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
  439. shared_memory_entries[npad_index].pad_assignment = assignment_mode;
  440. }
  441. }
  442. void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
  443. const std::vector<Vibration>& vibrations) {
  444. LOG_WARNING(Service_HID, "(STUBBED) called");
  445. if (!can_controllers_vibrate) {
  446. return;
  447. }
  448. for (std::size_t i = 0; i < controller_ids.size(); i++) {
  449. std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i));
  450. if (connected_controllers[controller_pos].is_connected) {
  451. // TODO(ogniK): Vibrate the physical controller
  452. }
  453. }
  454. last_processed_vibration = vibrations.back();
  455. }
  456. std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
  457. // TODO(ogniK): Figure out the best time to signal this event. This event seems that it should
  458. // be signalled at least once, and signaled after a new controller is connected?
  459. const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
  460. return styleset_event.readable;
  461. }
  462. Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
  463. return last_processed_vibration;
  464. }
  465. void Controller_NPad::AddNewController(NPadControllerType controller) {
  466. controller = DecideBestController(controller);
  467. if (controller == NPadControllerType::Handheld) {
  468. connected_controllers[8] = {controller, true};
  469. InitNewlyAddedControler(8);
  470. return;
  471. }
  472. const auto pos =
  473. std::find_if(connected_controllers.begin(), connected_controllers.end() - 2,
  474. [](const ControllerHolder& holder) { return !holder.is_connected; });
  475. if (pos == connected_controllers.end() - 2) {
  476. LOG_ERROR(Service_HID, "Cannot connect any more controllers!");
  477. return;
  478. }
  479. const auto controller_id = std::distance(connected_controllers.begin(), pos);
  480. connected_controllers[controller_id] = {controller, true};
  481. InitNewlyAddedControler(controller_id);
  482. }
  483. void Controller_NPad::AddNewControllerAt(NPadControllerType controller, u32 npad_id) {
  484. controller = DecideBestController(controller);
  485. if (controller == NPadControllerType::Handheld) {
  486. connected_controllers[NPadIdToIndex(NPAD_HANDHELD)] = {controller, true};
  487. InitNewlyAddedControler(NPadIdToIndex(NPAD_HANDHELD));
  488. return;
  489. }
  490. connected_controllers[NPadIdToIndex(npad_id)] = {controller, true};
  491. InitNewlyAddedControler(NPadIdToIndex(npad_id));
  492. }
  493. void Controller_NPad::ConnectNPad(u32 npad_id) {
  494. connected_controllers[NPadIdToIndex(npad_id)].is_connected = true;
  495. }
  496. void Controller_NPad::DisconnectNPad(u32 npad_id) {
  497. connected_controllers[NPadIdToIndex(npad_id)].is_connected = false;
  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. InitNewlyAddedControler(npad_index_1);
  520. InitNewlyAddedControler(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{0, 1, 0, 0};
  533. case 2:
  534. return LedPattern{0, 0, 1, 0};
  535. case 3:
  536. return LedPattern{0, 0, 0, 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. UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id);
  547. return LedPattern{0, 0, 0, 0};
  548. };
  549. }
  550. void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
  551. can_controllers_vibrate = can_vibrate;
  552. }
  553. bool Controller_NPad::IsVibrationEnabled() const {
  554. return can_controllers_vibrate;
  555. }
  556. void Controller_NPad::ClearAllConnectedControllers() {
  557. for (auto& controller : connected_controllers) {
  558. if (controller.is_connected && controller.type != NPadControllerType::None) {
  559. controller.type = NPadControllerType::None;
  560. controller.is_connected = false;
  561. }
  562. }
  563. }
  564. void Controller_NPad::DisconnectAllConnectedControllers() {
  565. for (ControllerHolder& controller : connected_controllers) {
  566. controller.is_connected = false;
  567. }
  568. }
  569. void Controller_NPad::ConnectAllDisconnectedControllers() {
  570. for (ControllerHolder& controller : connected_controllers) {
  571. if (controller.type != NPadControllerType::None && !controller.is_connected) {
  572. controller.is_connected = true;
  573. }
  574. }
  575. }
  576. void Controller_NPad::ClearAllControllers() {
  577. for (ControllerHolder& controller : connected_controllers) {
  578. controller.type = NPadControllerType::None;
  579. controller.is_connected = false;
  580. }
  581. }
  582. u32 Controller_NPad::GetAndResetPressState() {
  583. return std::exchange(press_state, 0);
  584. }
  585. bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
  586. if (controller == NPadControllerType::Handheld) {
  587. const bool support_handheld =
  588. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  589. NPAD_HANDHELD) != supported_npad_id_types.end();
  590. // Handheld is not even a supported type, lets stop here
  591. if (!support_handheld) {
  592. return false;
  593. }
  594. // Handheld should not be supported in docked mode
  595. if (Settings::values.use_docked_mode) {
  596. return false;
  597. }
  598. return true;
  599. }
  600. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  601. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  602. switch (controller) {
  603. case NPadControllerType::ProController:
  604. return style.pro_controller;
  605. case NPadControllerType::JoyDual:
  606. return style.joycon_dual;
  607. case NPadControllerType::JoyLeft:
  608. return style.joycon_left;
  609. case NPadControllerType::JoyRight:
  610. return style.joycon_right;
  611. case NPadControllerType::Pokeball:
  612. return style.pokeball;
  613. default:
  614. return false;
  615. }
  616. }
  617. return false;
  618. }
  619. Controller_NPad::NPadControllerType Controller_NPad::DecideBestController(
  620. NPadControllerType priority) const {
  621. if (IsControllerSupported(priority)) {
  622. return priority;
  623. }
  624. const auto is_docked = Settings::values.use_docked_mode;
  625. if (is_docked && priority == NPadControllerType::Handheld) {
  626. priority = NPadControllerType::JoyDual;
  627. if (IsControllerSupported(priority)) {
  628. return priority;
  629. }
  630. }
  631. std::vector<NPadControllerType> priority_list;
  632. switch (priority) {
  633. case NPadControllerType::ProController:
  634. priority_list.push_back(NPadControllerType::JoyDual);
  635. if (!is_docked) {
  636. priority_list.push_back(NPadControllerType::Handheld);
  637. }
  638. priority_list.push_back(NPadControllerType::JoyLeft);
  639. priority_list.push_back(NPadControllerType::JoyRight);
  640. priority_list.push_back(NPadControllerType::Pokeball);
  641. break;
  642. case NPadControllerType::Handheld:
  643. priority_list.push_back(NPadControllerType::JoyDual);
  644. priority_list.push_back(NPadControllerType::ProController);
  645. priority_list.push_back(NPadControllerType::JoyLeft);
  646. priority_list.push_back(NPadControllerType::JoyRight);
  647. priority_list.push_back(NPadControllerType::Pokeball);
  648. break;
  649. case NPadControllerType::JoyDual:
  650. if (!is_docked) {
  651. priority_list.push_back(NPadControllerType::Handheld);
  652. }
  653. priority_list.push_back(NPadControllerType::ProController);
  654. priority_list.push_back(NPadControllerType::JoyLeft);
  655. priority_list.push_back(NPadControllerType::JoyRight);
  656. priority_list.push_back(NPadControllerType::Pokeball);
  657. break;
  658. case NPadControllerType::JoyLeft:
  659. priority_list.push_back(NPadControllerType::JoyRight);
  660. priority_list.push_back(NPadControllerType::JoyDual);
  661. if (!is_docked) {
  662. priority_list.push_back(NPadControllerType::Handheld);
  663. }
  664. priority_list.push_back(NPadControllerType::ProController);
  665. priority_list.push_back(NPadControllerType::Pokeball);
  666. break;
  667. case NPadControllerType::JoyRight:
  668. priority_list.push_back(NPadControllerType::JoyLeft);
  669. priority_list.push_back(NPadControllerType::JoyDual);
  670. if (!is_docked) {
  671. priority_list.push_back(NPadControllerType::Handheld);
  672. }
  673. priority_list.push_back(NPadControllerType::ProController);
  674. priority_list.push_back(NPadControllerType::Pokeball);
  675. break;
  676. case NPadControllerType::Pokeball:
  677. priority_list.push_back(NPadControllerType::JoyLeft);
  678. priority_list.push_back(NPadControllerType::JoyRight);
  679. priority_list.push_back(NPadControllerType::JoyDual);
  680. if (!is_docked) {
  681. priority_list.push_back(NPadControllerType::Handheld);
  682. }
  683. priority_list.push_back(NPadControllerType::ProController);
  684. break;
  685. default:
  686. priority_list.push_back(NPadControllerType::JoyDual);
  687. if (!is_docked) {
  688. priority_list.push_back(NPadControllerType::Handheld);
  689. }
  690. priority_list.push_back(NPadControllerType::ProController);
  691. priority_list.push_back(NPadControllerType::JoyLeft);
  692. priority_list.push_back(NPadControllerType::JoyRight);
  693. priority_list.push_back(NPadControllerType::JoyDual);
  694. break;
  695. }
  696. const auto iter = std::find_if(priority_list.begin(), priority_list.end(),
  697. [this](auto type) { return IsControllerSupported(type); });
  698. if (iter == priority_list.end()) {
  699. UNIMPLEMENTED_MSG("Could not find supported controller!");
  700. return priority;
  701. }
  702. return *iter;
  703. }
  704. } // namespace Service::HID