npad.cpp 33 KB

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