npad.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  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. std::transform(players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_BEGIN,
  233. players[i].motions.begin() + Settings::NativeMotion::MOTION_HID_END,
  234. motions[i].begin(), Input::CreateDevice<Input::MotionDevice>);
  235. }
  236. }
  237. void Controller_NPad::OnRelease() {}
  238. void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
  239. const auto controller_idx = NPadIdToIndex(npad_id);
  240. [[maybe_unused]] const auto controller_type = connected_controllers[controller_idx].type;
  241. if (!connected_controllers[controller_idx].is_connected) {
  242. return;
  243. }
  244. auto& pad_state = npad_pad_states[controller_idx].pad_states;
  245. auto& lstick_entry = npad_pad_states[controller_idx].l_stick;
  246. auto& rstick_entry = npad_pad_states[controller_idx].r_stick;
  247. const auto& button_state = buttons[controller_idx];
  248. const auto& analog_state = sticks[controller_idx];
  249. const auto& motion_state = motions[controller_idx];
  250. const auto [stick_l_x_f, stick_l_y_f] =
  251. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
  252. const auto [stick_r_x_f, stick_r_y_f] =
  253. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
  254. using namespace Settings::NativeButton;
  255. pad_state.a.Assign(button_state[A - BUTTON_HID_BEGIN]->GetStatus());
  256. pad_state.b.Assign(button_state[B - BUTTON_HID_BEGIN]->GetStatus());
  257. pad_state.x.Assign(button_state[X - BUTTON_HID_BEGIN]->GetStatus());
  258. pad_state.y.Assign(button_state[Y - BUTTON_HID_BEGIN]->GetStatus());
  259. pad_state.l_stick.Assign(button_state[LStick - BUTTON_HID_BEGIN]->GetStatus());
  260. pad_state.r_stick.Assign(button_state[RStick - BUTTON_HID_BEGIN]->GetStatus());
  261. pad_state.l.Assign(button_state[L - BUTTON_HID_BEGIN]->GetStatus());
  262. pad_state.r.Assign(button_state[R - BUTTON_HID_BEGIN]->GetStatus());
  263. pad_state.zl.Assign(button_state[ZL - BUTTON_HID_BEGIN]->GetStatus());
  264. pad_state.zr.Assign(button_state[ZR - BUTTON_HID_BEGIN]->GetStatus());
  265. pad_state.plus.Assign(button_state[Plus - BUTTON_HID_BEGIN]->GetStatus());
  266. pad_state.minus.Assign(button_state[Minus - BUTTON_HID_BEGIN]->GetStatus());
  267. pad_state.d_left.Assign(button_state[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  268. pad_state.d_up.Assign(button_state[DUp - BUTTON_HID_BEGIN]->GetStatus());
  269. pad_state.d_right.Assign(button_state[DRight - BUTTON_HID_BEGIN]->GetStatus());
  270. pad_state.d_down.Assign(button_state[DDown - BUTTON_HID_BEGIN]->GetStatus());
  271. pad_state.l_stick_right.Assign(
  272. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  273. Input::AnalogDirection::RIGHT));
  274. pad_state.l_stick_left.Assign(
  275. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  276. Input::AnalogDirection::LEFT));
  277. pad_state.l_stick_up.Assign(
  278. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  279. Input::AnalogDirection::UP));
  280. pad_state.l_stick_down.Assign(
  281. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetAnalogDirectionStatus(
  282. Input::AnalogDirection::DOWN));
  283. pad_state.r_stick_right.Assign(
  284. analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  285. ->GetAnalogDirectionStatus(Input::AnalogDirection::RIGHT));
  286. pad_state.r_stick_left.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  287. ->GetAnalogDirectionStatus(Input::AnalogDirection::LEFT));
  288. pad_state.r_stick_up.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  289. ->GetAnalogDirectionStatus(Input::AnalogDirection::UP));
  290. pad_state.r_stick_down.Assign(analog_state[static_cast<std::size_t>(JoystickId::Joystick_Right)]
  291. ->GetAnalogDirectionStatus(Input::AnalogDirection::DOWN));
  292. pad_state.left_sl.Assign(button_state[SL - BUTTON_HID_BEGIN]->GetStatus());
  293. pad_state.left_sr.Assign(button_state[SR - BUTTON_HID_BEGIN]->GetStatus());
  294. lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  295. lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  296. rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  297. rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  298. }
  299. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  300. std::size_t data_len) {
  301. if (!IsControllerActivated()) {
  302. return;
  303. }
  304. for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
  305. auto& npad = shared_memory_entries[i];
  306. const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
  307. &npad.handheld_states,
  308. &npad.dual_states,
  309. &npad.left_joy_states,
  310. &npad.right_joy_states,
  311. &npad.pokeball_states,
  312. &npad.libnx};
  313. for (auto* main_controller : controller_npads) {
  314. main_controller->common.entry_count = 16;
  315. main_controller->common.total_entry_count = 17;
  316. const auto& last_entry =
  317. main_controller->npad[main_controller->common.last_entry_index];
  318. main_controller->common.timestamp = core_timing.GetCPUTicks();
  319. main_controller->common.last_entry_index =
  320. (main_controller->common.last_entry_index + 1) % 17;
  321. auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
  322. cur_entry.timestamp = last_entry.timestamp + 1;
  323. cur_entry.timestamp2 = cur_entry.timestamp;
  324. }
  325. const auto& controller_type = connected_controllers[i].type;
  326. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  327. continue;
  328. }
  329. const u32 npad_index = static_cast<u32>(i);
  330. RequestPadStateUpdate(npad_index);
  331. auto& pad_state = npad_pad_states[npad_index];
  332. auto& main_controller =
  333. npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
  334. auto& handheld_entry =
  335. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  336. auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
  337. auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
  338. auto& right_entry =
  339. npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
  340. auto& pokeball_entry =
  341. npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
  342. auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
  343. libnx_entry.connection_status.raw = 0;
  344. libnx_entry.connection_status.IsConnected.Assign(1);
  345. auto& full_sixaxis_entry =
  346. npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
  347. auto& handheld_sixaxis_entry =
  348. npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
  349. auto& dual_left_sixaxis_entry =
  350. npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
  351. auto& dual_right_sixaxis_entry =
  352. npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
  353. auto& left_sixaxis_entry =
  354. npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
  355. auto& right_sixaxis_entry =
  356. npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
  357. switch (controller_type) {
  358. case NPadControllerType::None:
  359. UNREACHABLE();
  360. break;
  361. case NPadControllerType::ProController:
  362. main_controller.connection_status.raw = 0;
  363. main_controller.connection_status.IsConnected.Assign(1);
  364. main_controller.connection_status.IsWired.Assign(1);
  365. main_controller.pad.pad_states.raw = pad_state.pad_states.raw;
  366. main_controller.pad.l_stick = pad_state.l_stick;
  367. main_controller.pad.r_stick = pad_state.r_stick;
  368. libnx_entry.connection_status.IsWired.Assign(1);
  369. break;
  370. case NPadControllerType::Handheld:
  371. handheld_entry.connection_status.raw = 0;
  372. handheld_entry.connection_status.IsConnected.Assign(1);
  373. handheld_entry.connection_status.IsWired.Assign(1);
  374. handheld_entry.connection_status.IsLeftJoyConnected.Assign(1);
  375. handheld_entry.connection_status.IsRightJoyConnected.Assign(1);
  376. handheld_entry.connection_status.IsLeftJoyWired.Assign(1);
  377. handheld_entry.connection_status.IsRightJoyWired.Assign(1);
  378. handheld_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  379. handheld_entry.pad.l_stick = pad_state.l_stick;
  380. handheld_entry.pad.r_stick = pad_state.r_stick;
  381. libnx_entry.connection_status.IsWired.Assign(1);
  382. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  383. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  384. libnx_entry.connection_status.IsLeftJoyWired.Assign(1);
  385. libnx_entry.connection_status.IsRightJoyWired.Assign(1);
  386. break;
  387. case NPadControllerType::JoyDual:
  388. dual_entry.connection_status.raw = 0;
  389. dual_entry.connection_status.IsConnected.Assign(1);
  390. dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
  391. dual_entry.connection_status.IsRightJoyConnected.Assign(1);
  392. dual_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  393. dual_entry.pad.l_stick = pad_state.l_stick;
  394. dual_entry.pad.r_stick = pad_state.r_stick;
  395. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  396. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  397. break;
  398. case NPadControllerType::JoyLeft:
  399. left_entry.connection_status.raw = 0;
  400. left_entry.connection_status.IsConnected.Assign(1);
  401. left_entry.connection_status.IsLeftJoyConnected.Assign(1);
  402. left_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  403. left_entry.pad.l_stick = pad_state.l_stick;
  404. left_entry.pad.r_stick = pad_state.r_stick;
  405. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  406. break;
  407. case NPadControllerType::JoyRight:
  408. right_entry.connection_status.raw = 0;
  409. right_entry.connection_status.IsConnected.Assign(1);
  410. right_entry.connection_status.IsRightJoyConnected.Assign(1);
  411. right_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  412. right_entry.pad.l_stick = pad_state.l_stick;
  413. right_entry.pad.r_stick = pad_state.r_stick;
  414. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  415. break;
  416. case NPadControllerType::Pokeball:
  417. pokeball_entry.connection_status.raw = 0;
  418. pokeball_entry.connection_status.IsConnected.Assign(1);
  419. pokeball_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  420. pokeball_entry.pad.l_stick = pad_state.l_stick;
  421. pokeball_entry.pad.r_stick = pad_state.r_stick;
  422. break;
  423. }
  424. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  425. // any controllers.
  426. libnx_entry.pad.pad_states.raw = pad_state.pad_states.raw;
  427. libnx_entry.pad.l_stick = pad_state.l_stick;
  428. libnx_entry.pad.r_stick = pad_state.r_stick;
  429. press_state |= static_cast<u32>(pad_state.pad_states.raw);
  430. }
  431. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  432. shared_memory_entries.size() * sizeof(NPadEntry));
  433. }
  434. void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  435. std::size_t data_len) {
  436. if (!IsControllerActivated()) {
  437. return;
  438. }
  439. for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
  440. auto& npad = shared_memory_entries[i];
  441. const auto& controller_type = connected_controllers[i].type;
  442. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  443. continue;
  444. }
  445. const std::array<SixAxisGeneric*, 6> controller_sixaxes{
  446. &npad.sixaxis_full, &npad.sixaxis_handheld, &npad.sixaxis_dual_left,
  447. &npad.sixaxis_dual_right, &npad.sixaxis_left, &npad.sixaxis_right,
  448. };
  449. for (auto* sixaxis_sensor : controller_sixaxes) {
  450. sixaxis_sensor->common.entry_count = 16;
  451. sixaxis_sensor->common.total_entry_count = 17;
  452. const auto& last_entry =
  453. sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
  454. sixaxis_sensor->common.timestamp = core_timing.GetCPUTicks();
  455. sixaxis_sensor->common.last_entry_index =
  456. (sixaxis_sensor->common.last_entry_index + 1) % 17;
  457. auto& cur_entry = sixaxis_sensor->sixaxis[sixaxis_sensor->common.last_entry_index];
  458. cur_entry.timestamp = last_entry.timestamp + 1;
  459. cur_entry.timestamp2 = cur_entry.timestamp;
  460. }
  461. // Try to read sixaxis sensor states
  462. std::array<MotionDevice, 2> motion_devices;
  463. if (sixaxis_sensors_enabled && Settings::values.motion_enabled) {
  464. sixaxis_at_rest = true;
  465. for (std::size_t e = 0; e < motion_devices.size(); ++e) {
  466. const auto& device = motions[i][e];
  467. if (device) {
  468. std::tie(motion_devices[e].accel, motion_devices[e].gyro,
  469. motion_devices[e].rotation, motion_devices[e].orientation) =
  470. device->GetStatus();
  471. sixaxis_at_rest = sixaxis_at_rest && motion_devices[e].gyro.Length2() < 0.0001f;
  472. }
  473. }
  474. }
  475. auto& main_controller =
  476. npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
  477. auto& handheld_entry =
  478. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  479. auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
  480. auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
  481. auto& right_entry =
  482. npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
  483. auto& pokeball_entry =
  484. npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
  485. auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
  486. auto& full_sixaxis_entry =
  487. npad.sixaxis_full.sixaxis[npad.sixaxis_full.common.last_entry_index];
  488. auto& handheld_sixaxis_entry =
  489. npad.sixaxis_handheld.sixaxis[npad.sixaxis_handheld.common.last_entry_index];
  490. auto& dual_left_sixaxis_entry =
  491. npad.sixaxis_dual_left.sixaxis[npad.sixaxis_dual_left.common.last_entry_index];
  492. auto& dual_right_sixaxis_entry =
  493. npad.sixaxis_dual_right.sixaxis[npad.sixaxis_dual_right.common.last_entry_index];
  494. auto& left_sixaxis_entry =
  495. npad.sixaxis_left.sixaxis[npad.sixaxis_left.common.last_entry_index];
  496. auto& right_sixaxis_entry =
  497. npad.sixaxis_right.sixaxis[npad.sixaxis_right.common.last_entry_index];
  498. switch (controller_type) {
  499. case NPadControllerType::None:
  500. UNREACHABLE();
  501. break;
  502. case NPadControllerType::ProController:
  503. if (sixaxis_sensors_enabled && motions[i][0]) {
  504. full_sixaxis_entry.accel = motion_devices[0].accel;
  505. full_sixaxis_entry.gyro = motion_devices[0].gyro;
  506. full_sixaxis_entry.rotation = motion_devices[0].rotation;
  507. full_sixaxis_entry.orientation = motion_devices[0].orientation;
  508. }
  509. break;
  510. case NPadControllerType::Handheld:
  511. if (sixaxis_sensors_enabled && motions[i][0]) {
  512. handheld_sixaxis_entry.accel = motion_devices[0].accel;
  513. handheld_sixaxis_entry.gyro = motion_devices[0].gyro;
  514. handheld_sixaxis_entry.rotation = motion_devices[0].rotation;
  515. handheld_sixaxis_entry.orientation = motion_devices[0].orientation;
  516. }
  517. break;
  518. case NPadControllerType::JoyDual:
  519. if (sixaxis_sensors_enabled && motions[i][0]) {
  520. // Set motion for the left joycon
  521. dual_left_sixaxis_entry.accel = motion_devices[0].accel;
  522. dual_left_sixaxis_entry.gyro = motion_devices[0].gyro;
  523. dual_left_sixaxis_entry.rotation = motion_devices[0].rotation;
  524. dual_left_sixaxis_entry.orientation = motion_devices[0].orientation;
  525. }
  526. if (sixaxis_sensors_enabled && motions[i][1]) {
  527. // Set motion for the right joycon
  528. dual_right_sixaxis_entry.accel = motion_devices[1].accel;
  529. dual_right_sixaxis_entry.gyro = motion_devices[1].gyro;
  530. dual_right_sixaxis_entry.rotation = motion_devices[1].rotation;
  531. dual_right_sixaxis_entry.orientation = motion_devices[1].orientation;
  532. }
  533. break;
  534. case NPadControllerType::JoyLeft:
  535. if (sixaxis_sensors_enabled && motions[i][0]) {
  536. left_sixaxis_entry.accel = motion_devices[0].accel;
  537. left_sixaxis_entry.gyro = motion_devices[0].gyro;
  538. left_sixaxis_entry.rotation = motion_devices[0].rotation;
  539. left_sixaxis_entry.orientation = motion_devices[0].orientation;
  540. }
  541. break;
  542. case NPadControllerType::JoyRight:
  543. if (sixaxis_sensors_enabled && motions[i][1]) {
  544. right_sixaxis_entry.accel = motion_devices[1].accel;
  545. right_sixaxis_entry.gyro = motion_devices[1].gyro;
  546. right_sixaxis_entry.rotation = motion_devices[1].rotation;
  547. right_sixaxis_entry.orientation = motion_devices[1].orientation;
  548. }
  549. break;
  550. case NPadControllerType::Pokeball:
  551. break;
  552. }
  553. }
  554. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  555. shared_memory_entries.size() * sizeof(NPadEntry));
  556. }
  557. void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
  558. style.raw = style_set.raw;
  559. }
  560. Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
  561. return style;
  562. }
  563. void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
  564. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  565. supported_npad_id_types.clear();
  566. supported_npad_id_types.resize(length / sizeof(u32));
  567. std::memcpy(supported_npad_id_types.data(), data, length);
  568. }
  569. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  570. ASSERT(max_length < supported_npad_id_types.size());
  571. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  572. }
  573. std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
  574. return supported_npad_id_types.size();
  575. }
  576. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  577. hold_type = joy_hold_type;
  578. }
  579. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  580. return hold_type;
  581. }
  582. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  583. handheld_activation_mode = activation_mode;
  584. }
  585. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  586. return handheld_activation_mode;
  587. }
  588. void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
  589. const std::size_t npad_index = NPadIdToIndex(npad_id);
  590. ASSERT(npad_index < shared_memory_entries.size());
  591. if (shared_memory_entries[npad_index].pad_assignment != assignment_mode) {
  592. shared_memory_entries[npad_index].pad_assignment = assignment_mode;
  593. }
  594. }
  595. void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
  596. const std::vector<Vibration>& vibrations) {
  597. LOG_DEBUG(Service_HID, "(STUBBED) called");
  598. if (!Settings::values.vibration_enabled || !can_controllers_vibrate) {
  599. return;
  600. }
  601. for (std::size_t i = 0; i < controller_ids.size(); i++) {
  602. std::size_t controller_pos = NPadIdToIndex(static_cast<u32>(i));
  603. if (connected_controllers[controller_pos].is_connected) {
  604. // TODO(ogniK): Vibrate the physical controller
  605. }
  606. }
  607. last_processed_vibration = vibrations.back();
  608. }
  609. Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
  610. return last_processed_vibration;
  611. }
  612. std::shared_ptr<Kernel::ReadableEvent> Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) const {
  613. const auto& styleset_event = styleset_changed_events[NPadIdToIndex(npad_id)];
  614. return styleset_event.readable;
  615. }
  616. void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
  617. styleset_changed_events[NPadIdToIndex(npad_id)].writable->Signal();
  618. }
  619. void Controller_NPad::AddNewControllerAt(NPadControllerType controller, std::size_t npad_index) {
  620. UpdateControllerAt(controller, npad_index, true);
  621. }
  622. void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::size_t npad_index,
  623. bool connected) {
  624. if (!connected) {
  625. DisconnectNPadAtIndex(npad_index);
  626. return;
  627. }
  628. if (controller == NPadControllerType::Handheld) {
  629. Settings::values.players[HANDHELD_INDEX].controller_type =
  630. MapNPadToSettingsType(controller);
  631. Settings::values.players[HANDHELD_INDEX].connected = true;
  632. connected_controllers[HANDHELD_INDEX] = {controller, true};
  633. InitNewlyAddedController(HANDHELD_INDEX);
  634. return;
  635. }
  636. Settings::values.players[npad_index].controller_type = MapNPadToSettingsType(controller);
  637. Settings::values.players[npad_index].connected = true;
  638. connected_controllers[npad_index] = {controller, true};
  639. InitNewlyAddedController(npad_index);
  640. }
  641. void Controller_NPad::DisconnectNPad(u32 npad_id) {
  642. DisconnectNPadAtIndex(NPadIdToIndex(npad_id));
  643. }
  644. void Controller_NPad::DisconnectNPadAtIndex(std::size_t npad_index) {
  645. Settings::values.players[npad_index].connected = false;
  646. connected_controllers[npad_index].is_connected = false;
  647. auto& controller = shared_memory_entries[npad_index];
  648. controller.joy_styles.raw = 0; // Zero out
  649. controller.device_type.raw = 0;
  650. controller.properties.raw = 0;
  651. SignalStyleSetChangedEvent(IndexToNPad(npad_index));
  652. }
  653. void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
  654. gyroscope_zero_drift_mode = drift_mode;
  655. }
  656. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
  657. return gyroscope_zero_drift_mode;
  658. }
  659. bool Controller_NPad::IsSixAxisSensorAtRest() const {
  660. return sixaxis_at_rest;
  661. }
  662. void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
  663. sixaxis_sensors_enabled = six_axis_status;
  664. }
  665. void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
  666. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  667. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  668. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  669. // Otherwise, do nothing.
  670. if ((connected_controllers[npad_index_1].type == NPadControllerType::JoyLeft &&
  671. connected_controllers[npad_index_2].type == NPadControllerType::JoyRight) ||
  672. (connected_controllers[npad_index_2].type == NPadControllerType::JoyLeft &&
  673. connected_controllers[npad_index_1].type == NPadControllerType::JoyRight)) {
  674. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  675. DisconnectNPad(npad_id_2);
  676. AddNewControllerAt(NPadControllerType::JoyDual, npad_index_1);
  677. }
  678. }
  679. void Controller_NPad::StartLRAssignmentMode() {
  680. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  681. // controller types from boot, it doesn't really matter about showing a selection screen
  682. is_in_lr_assignment_mode = true;
  683. }
  684. void Controller_NPad::StopLRAssignmentMode() {
  685. is_in_lr_assignment_mode = false;
  686. }
  687. bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
  688. if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
  689. npad_id_2 == NPAD_UNKNOWN) {
  690. return true;
  691. }
  692. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  693. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  694. if (!IsControllerSupported(connected_controllers[npad_index_1].type) ||
  695. !IsControllerSupported(connected_controllers[npad_index_2].type)) {
  696. return false;
  697. }
  698. std::swap(connected_controllers[npad_index_1].type, connected_controllers[npad_index_2].type);
  699. AddNewControllerAt(connected_controllers[npad_index_1].type, npad_index_1);
  700. AddNewControllerAt(connected_controllers[npad_index_2].type, npad_index_2);
  701. return true;
  702. }
  703. Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  704. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  705. // These are controllers without led patterns
  706. return LedPattern{0, 0, 0, 0};
  707. }
  708. switch (npad_id) {
  709. case 0:
  710. return LedPattern{1, 0, 0, 0};
  711. case 1:
  712. return LedPattern{1, 1, 0, 0};
  713. case 2:
  714. return LedPattern{1, 1, 1, 0};
  715. case 3:
  716. return LedPattern{1, 1, 1, 1};
  717. case 4:
  718. return LedPattern{1, 0, 0, 1};
  719. case 5:
  720. return LedPattern{1, 0, 1, 0};
  721. case 6:
  722. return LedPattern{1, 0, 1, 1};
  723. case 7:
  724. return LedPattern{0, 1, 1, 0};
  725. default:
  726. return LedPattern{0, 0, 0, 0};
  727. }
  728. }
  729. void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
  730. can_controllers_vibrate = can_vibrate;
  731. }
  732. bool Controller_NPad::IsVibrationEnabled() const {
  733. return can_controllers_vibrate;
  734. }
  735. void Controller_NPad::ClearAllConnectedControllers() {
  736. for (auto& controller : connected_controllers) {
  737. if (controller.is_connected && controller.type != NPadControllerType::None) {
  738. controller.type = NPadControllerType::None;
  739. controller.is_connected = false;
  740. }
  741. }
  742. }
  743. void Controller_NPad::DisconnectAllConnectedControllers() {
  744. for (auto& controller : connected_controllers) {
  745. controller.is_connected = false;
  746. }
  747. }
  748. void Controller_NPad::ConnectAllDisconnectedControllers() {
  749. for (auto& controller : connected_controllers) {
  750. if (controller.type != NPadControllerType::None && !controller.is_connected) {
  751. controller.is_connected = true;
  752. }
  753. }
  754. }
  755. void Controller_NPad::ClearAllControllers() {
  756. for (auto& controller : connected_controllers) {
  757. controller.type = NPadControllerType::None;
  758. controller.is_connected = false;
  759. }
  760. }
  761. u32 Controller_NPad::GetAndResetPressState() {
  762. return std::exchange(press_state, 0);
  763. }
  764. bool Controller_NPad::IsControllerSupported(NPadControllerType controller) const {
  765. if (controller == NPadControllerType::Handheld) {
  766. const bool support_handheld =
  767. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  768. NPAD_HANDHELD) != supported_npad_id_types.end();
  769. // Handheld is not even a supported type, lets stop here
  770. if (!support_handheld) {
  771. return false;
  772. }
  773. // Handheld should not be supported in docked mode
  774. if (Settings::values.use_docked_mode) {
  775. return false;
  776. }
  777. return true;
  778. }
  779. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  780. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  781. switch (controller) {
  782. case NPadControllerType::ProController:
  783. return style.pro_controller;
  784. case NPadControllerType::JoyDual:
  785. return style.joycon_dual;
  786. case NPadControllerType::JoyLeft:
  787. return style.joycon_left;
  788. case NPadControllerType::JoyRight:
  789. return style.joycon_right;
  790. case NPadControllerType::Pokeball:
  791. return style.pokeball;
  792. default:
  793. return false;
  794. }
  795. }
  796. return false;
  797. }
  798. } // namespace Service::HID