npad.cpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747
  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. SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
  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. libnx_entry.connection_status.IsConnected.Assign(1);
  341. switch (controller_type) {
  342. case NPadControllerType::None:
  343. UNREACHABLE();
  344. break;
  345. case NPadControllerType::ProController:
  346. main_controller.connection_status.raw = 0;
  347. main_controller.connection_status.IsConnected.Assign(1);
  348. main_controller.connection_status.IsWired.Assign(1);
  349. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  350. main_controller.pad.l_stick = pad_state.l_stick;
  351. main_controller.pad.r_stick = pad_state.r_stick;
  352. libnx_entry.connection_status.IsWired.Assign(1);
  353. break;
  354. case NPadControllerType::Handheld:
  355. handheld_entry.connection_status.raw = 0;
  356. handheld_entry.connection_status.IsConnected.Assign(1);
  357. handheld_entry.connection_status.IsWired.Assign(1);
  358. handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
  359. handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
  360. handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
  361. handheld_entry.connection_status.IsRightJoyWired.Assign(1);
  362. handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  363. handheld_entry.pad.l_stick = pad_state.l_stick;
  364. handheld_entry.pad.r_stick = pad_state.r_stick;
  365. libnx_entry.connection_status.IsWired.Assign(1);
  366. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  367. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  368. libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
  369. libnx_entry.connection_status.IsRightJoyWired.Assign(1);
  370. break;
  371. case NPadControllerType::JoyDual:
  372. dual_entry.connection_status.raw = 0;
  373. dual_entry.connection_status.IsConnected.Assign(1);
  374. dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
  375. dual_entry.connection_status.IsRightJoyConnected.Assign(1);
  376. dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  377. dual_entry.pad.l_stick = pad_state.l_stick;
  378. dual_entry.pad.r_stick = pad_state.r_stick;
  379. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  380. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  381. break;
  382. case NPadControllerType::JoyLeft:
  383. left_entry.connection_status.raw = 0;
  384. left_entry.connection_status.IsConnected.Assign(1);
  385. left_entry.connection_status.IsLeftJoyConnected.Assign(1);
  386. left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  387. left_entry.pad.l_stick = pad_state.l_stick;
  388. left_entry.pad.r_stick = pad_state.r_stick;
  389. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  390. break;
  391. case NPadControllerType::JoyRight:
  392. right_entry.connection_status.raw = 0;
  393. right_entry.connection_status.IsConnected.Assign(1);
  394. right_entry.connection_status.IsRightJoyConnected.Assign(1);
  395. right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  396. right_entry.pad.l_stick = pad_state.l_stick;
  397. right_entry.pad.r_stick = pad_state.r_stick;
  398. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  399. break;
  400. case NPadControllerType::Pokeball:
  401. pokeball_entry.connection_status.raw = 0;
  402. pokeball_entry.connection_status.IsConnected.Assign(1);
  403. pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  404. pokeball_entry.pad.l_stick = pad_state.l_stick;
  405. pokeball_entry.pad.r_stick = pad_state.r_stick;
  406. break;
  407. }
  408. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  409. // any controllers.
  410. libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  411. libnx_entry.pad.l_stick = pad_state.l_stick;
  412. libnx_entry.pad.r_stick = pad_state.r_stick;
  413. press_state |= static_cast<u32>(pad_state.pad_states.raw);
  414. }
  415. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  416. shared_memory_entries.size() * sizeof(NPadEntry));
  417. }
  418. void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
  419. style.raw = style_set.raw;
  420. }
  421. Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
  422. return style;
  423. }
  424. void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
  425. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  426. supported_npad_id_types.clear();
  427. supported_npad_id_types.resize(length / sizeof(u32));
  428. std::memcpy(supported_npad_id_types.data(), data, length);
  429. }
  430. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  431. ASSERT(max_length < supported_npad_id_types.size());
  432. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  433. }
  434. std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
  435. return supported_npad_id_types.size();
  436. }
  437. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  438. hold_type = joy_hold_type;
  439. }
  440. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  441. return hold_type;
  442. }
  443. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  444. handheld_activation_mode = activation_mode;
  445. }
  446. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  447. return handheld_activation_mode;
  448. }
  449. void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
  450. const std::size_t npad_index = NPadIdToIndex(npad_id);
  451. ASSERT(npad_index < shared_memory_entries.size());
  452. if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
  453. shared_memory_entries[npad_index].pad_assignment = assignment_mode;
  454. }
  455. }
  456. void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
  457. const std::vector<Vibration>& vibrations) {
  458. LOG_DEBUG(Service_HID, "(STUBBED) called");
  459. if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
  460. return;
  461. }
  462. for (std::size_t i = 0; i < controller_ids.size(); i++) {
  463. std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i));
  464. if (connected_controllers[controller_pos].is_connected) {
  465. // TODO(ogniK): Vibrate the physical controller
  466. }
  467. }
  468. last_processed_vibration = vibrations.back();
  469. }
  470. Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
  471. return last_processed_vibration;
  472. }
  473. std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
  474. const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
  475. return styleset_event.readable;
  476. }
  477. void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
  478. styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal();
  479. }
  480. void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
  481. UpdateControllerAt(controller, npad_index, true);
  482. }
  483. void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
  484. bool connected) {
  485. if (!connected) {
  486. DisconnectNPadAtIndex(npad_index);
  487. return;
  488. }
  489. if (controller == NPadControllerType::Handheld) {
  490. Settings::values.players[HANDHELD_INDEX].controller_type =
  491. MapNPadToSettingsType(controller);
  492. Settings::values.players[HANDHELD_INDEX].connected = true;
  493. connected_controllers[HANDHELD_INDEX] = {controller, true};
  494. InitNewlyAddedController(HANDHELD_INDEX);
  495. return;
  496. }
  497. Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
  498. Settings::values.players[npad_index].connected = true;
  499. connected_controllers[npad_index] = {controller, true};
  500. InitNewlyAddedController(npad_index);
  501. }
  502. void Controller_NPad::DisconnectNPad(u32 npad_id) {
  503. DisconnectNPadAtIndex(NPadIdToIndex(npad_id));
  504. }
  505. void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) {
  506. Settings::values.players[npad_index].connected = false;
  507. connected_controllers[npad_index].is_connected = false;
  508. auto& controller = shared_memory_entries[npad_index];
  509. controller.joy_styles.raw = 0; // Zero out
  510. controller.device_type.raw = 0;
  511. controller.properties.raw = 0;
  512. SignalStyleSetChangedEvent(IndexToNPad(npad_index));
  513. }
  514. void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
  515. gyroscope_zero_drift_mode = drift_mode;
  516. }
  517. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
  518. return gyroscope_zero_drift_mode;
  519. }
  520. void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
  521. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  522. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  523. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  524. // Otherwise, do nothing.
  525. if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft &&
  526. connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) ||
  527. (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
  528. connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
  529. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  530. DisconnectNPad(npad_id_2);
  531. AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
  532. }
  533. }
  534. void Controller_NPad::StartLRAssignmentMode() {
  535. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  536. // controller types from boot, it doesn't really matter about showing a selection screen
  537. is_in_lr_assignment_mode = true;
  538. }
  539. void Controller_NPad::StopLRAssignmentMode() {
  540. is_in_lr_assignment_mode = false;
  541. }
  542. bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
  543. if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
  544. npad_id_2 == NPAD_UNKNOWN) {
  545. return true;
  546. }
  547. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  548. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  549. if (!IsControllerSupported(connected_controllers[npad_index_1].type) ||
  550. !IsControllerSupported(connected_controllers[npad_index_2].type)) {
  551. return false;
  552. }
  553. std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
  554. AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
  555. AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
  556. return true;
  557. }
  558. Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  559. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  560. // These are controllers without led patterns
  561. return LedPattern{0, 0, 0, 0};
  562. }
  563. switch (npad_id) {
  564. case 0:
  565. return LedPattern{1, 0, 0, 0};
  566. case 1:
  567. return LedPattern{1, 1, 0, 0};
  568. case 2:
  569. return LedPattern{1, 1, 1, 0};
  570. case 3:
  571. return LedPattern{1, 1, 1, 1};
  572. case 4:
  573. return LedPattern{1, 0, 0, 1};
  574. case 5:
  575. return LedPattern{1, 0, 1, 0};
  576. case 6:
  577. return LedPattern{1, 0, 1, 1};
  578. case 7:
  579. return LedPattern{0, 1, 1, 0};
  580. default:
  581. return LedPattern{0, 0, 0, 0};
  582. }
  583. }
  584. void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
  585. can_controllers_vibrate = can_vibrate;
  586. }
  587. bool Controller_NPad::IsVibrationEnabled() const {
  588. return can_controllers_vibrate;
  589. }
  590. void Controller_NPad::ClearAllConnectedControllers() {
  591. for (auto& controller : connected_controllers) {
  592. if (controller.is_connected && controller.type != NPadControllerType::None) {
  593. controller.type = NPadControllerType::None;
  594. controller.is_connected = false;
  595. }
  596. }
  597. }
  598. void Controller_NPad::DisconnectAllConnectedControllers() {
  599. for (auto& controller : connected_controllers) {
  600. controller.is_connected = false;
  601. }
  602. }
  603. void Controller_NPad::ConnectAllDisconnectedControllers() {
  604. for (auto& controller : connected_controllers) {
  605. if (controller.type != NPadControllerType::None && !controller.is_connected) {
  606. controller.is_connected = true;
  607. }
  608. }
  609. }
  610. void Controller_NPad::ClearAllControllers() {
  611. for (auto& controller : connected_controllers) {
  612. controller.type = NPadControllerType::None;
  613. controller.is_connected = false;
  614. }
  615. }
  616. u32 Controller_NPad::GetAndResetPressState() {
  617. return std::exchange(press_state, 0);
  618. }
  619. bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
  620. if (controller == NPadControllerType::Handheld) {
  621. const bool support_handheld =
  622. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  623. NPAD_HANDHELD) != supported_npad_id_types.end();
  624. // Handheld is not even a supported type, lets stop here
  625. if (!support_handheld) {
  626. return false;
  627. }
  628. // Handheld should not be supported in docked mode
  629. if (Settings::values.use_docked_mode) {
  630. return false;
  631. }
  632. return true;
  633. }
  634. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  635. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  636. switch (controller) {
  637. case NPadControllerType::ProController:
  638. return style.pro_controller;
  639. case NPadControllerType::JoyDual:
  640. return style.joycon_dual;
  641. case NPadControllerType::JoyLeft:
  642. return style.joycon_left;
  643. case NPadControllerType::JoyRight:
  644. return style.joycon_right;
  645. case NPadControllerType::Pokeball:
  646. return style.pokeball;
  647. default:
  648. return false;
  649. }
  650. }
  651. return false;
  652. }
  653. } // namespace Service::HID