npad.cpp 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560
  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 "common/settings.h"
  12. #include "core/core_timing.h"
  13. #include "core/hid/emulated_controller.h"
  14. #include "core/hid/hid_core.h"
  15. #include "core/hle/kernel/k_event.h"
  16. #include "core/hle/kernel/k_readable_event.h"
  17. #include "core/hle/kernel/k_writable_event.h"
  18. #include "core/hle/service/hid/controllers/npad.h"
  19. #include "core/hle/service/hid/errors.h"
  20. #include "core/hle/service/kernel_helpers.h"
  21. namespace Service::HID {
  22. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  23. constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
  24. Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
  25. Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
  26. Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
  27. Core::HID::NpadIdType::Handheld,
  28. };
  29. bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
  30. switch (npad_id) {
  31. case Core::HID::NpadIdType::Player1:
  32. case Core::HID::NpadIdType::Player2:
  33. case Core::HID::NpadIdType::Player3:
  34. case Core::HID::NpadIdType::Player4:
  35. case Core::HID::NpadIdType::Player5:
  36. case Core::HID::NpadIdType::Player6:
  37. case Core::HID::NpadIdType::Player7:
  38. case Core::HID::NpadIdType::Player8:
  39. case Core::HID::NpadIdType::Other:
  40. case Core::HID::NpadIdType::Handheld:
  41. return true;
  42. default:
  43. LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
  44. return false;
  45. }
  46. }
  47. bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
  48. const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
  49. const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
  50. const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  51. return npad_id && npad_type && device_index;
  52. }
  53. bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
  54. const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
  55. const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
  56. const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  57. return npad_id && npad_type && device_index;
  58. }
  59. Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
  60. KernelHelpers::ServiceContext& service_context_)
  61. : ControllerBase{hid_core_}, service_context{service_context_} {
  62. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  63. auto& controller = controller_data[i];
  64. controller.device = hid_core.GetEmulatedControllerByIndex(i);
  65. controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
  66. Core::HID::DEFAULT_VIBRATION_VALUE;
  67. controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
  68. Core::HID::DEFAULT_VIBRATION_VALUE;
  69. Core::HID::ControllerUpdateCallback engine_callback{
  70. .on_change = [this,
  71. i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
  72. .is_npad_service = true,
  73. };
  74. controller.callback_key = controller.device->SetCallback(engine_callback);
  75. }
  76. }
  77. Controller_NPad::~Controller_NPad() {
  78. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  79. auto& controller = controller_data[i];
  80. controller.device->DeleteCallback(controller.callback_key);
  81. }
  82. OnRelease();
  83. }
  84. void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
  85. std::size_t controller_idx) {
  86. if (type == Core::HID::ControllerTriggerType::All) {
  87. ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
  88. ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
  89. return;
  90. }
  91. if (controller_idx >= controller_data.size()) {
  92. return;
  93. }
  94. auto& controller = controller_data[controller_idx];
  95. const auto is_connected = controller.device->IsConnected();
  96. const auto npad_type = controller.device->GetNpadStyleIndex();
  97. const auto npad_id = controller.device->GetNpadIdType();
  98. switch (type) {
  99. case Core::HID::ControllerTriggerType::Connected:
  100. case Core::HID::ControllerTriggerType::Disconnected:
  101. if (is_connected == controller.is_connected) {
  102. return;
  103. }
  104. UpdateControllerAt(npad_type, npad_id, is_connected);
  105. break;
  106. case Core::HID::ControllerTriggerType::Battery: {
  107. if (!controller.device->IsConnected()) {
  108. return;
  109. }
  110. auto& shared_memory = controller.shared_memory_entry;
  111. const auto& battery_level = controller.device->GetBattery();
  112. shared_memory.battery_level_dual = battery_level.dual.battery_level;
  113. shared_memory.battery_level_left = battery_level.left.battery_level;
  114. shared_memory.battery_level_right = battery_level.right.battery_level;
  115. break;
  116. }
  117. default:
  118. break;
  119. }
  120. }
  121. void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
  122. auto& controller = GetControllerFromNpadIdType(npad_id);
  123. if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
  124. return;
  125. }
  126. LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
  127. const auto controller_type = controller.device->GetNpadStyleIndex();
  128. auto& shared_memory = controller.shared_memory_entry;
  129. if (controller_type == Core::HID::NpadStyleIndex::None) {
  130. controller.styleset_changed_event->GetWritableEvent().Signal();
  131. return;
  132. }
  133. shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
  134. shared_memory.device_type.raw = 0;
  135. shared_memory.system_properties.raw = 0;
  136. switch (controller_type) {
  137. case Core::HID::NpadStyleIndex::None:
  138. UNREACHABLE();
  139. break;
  140. case Core::HID::NpadStyleIndex::ProController:
  141. shared_memory.style_tag.fullkey.Assign(1);
  142. shared_memory.device_type.fullkey.Assign(1);
  143. shared_memory.system_properties.is_vertical.Assign(1);
  144. shared_memory.system_properties.use_plus.Assign(1);
  145. shared_memory.system_properties.use_minus.Assign(1);
  146. shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
  147. break;
  148. case Core::HID::NpadStyleIndex::Handheld:
  149. shared_memory.style_tag.handheld.Assign(1);
  150. shared_memory.device_type.handheld_left.Assign(1);
  151. shared_memory.device_type.handheld_right.Assign(1);
  152. shared_memory.system_properties.is_vertical.Assign(1);
  153. shared_memory.system_properties.use_plus.Assign(1);
  154. shared_memory.system_properties.use_minus.Assign(1);
  155. shared_memory.system_properties.use_directional_buttons.Assign(1);
  156. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  157. shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  158. break;
  159. case Core::HID::NpadStyleIndex::JoyconDual:
  160. shared_memory.style_tag.joycon_dual.Assign(1);
  161. if (controller.is_dual_left_connected) {
  162. shared_memory.device_type.joycon_left.Assign(1);
  163. shared_memory.system_properties.use_minus.Assign(1);
  164. }
  165. if (controller.is_dual_right_connected) {
  166. shared_memory.device_type.joycon_right.Assign(1);
  167. shared_memory.system_properties.use_plus.Assign(1);
  168. }
  169. shared_memory.system_properties.use_directional_buttons.Assign(1);
  170. shared_memory.system_properties.is_vertical.Assign(1);
  171. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  172. if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
  173. shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
  174. } else if (controller.is_dual_left_connected) {
  175. shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
  176. } else {
  177. shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
  178. }
  179. break;
  180. case Core::HID::NpadStyleIndex::JoyconLeft:
  181. shared_memory.style_tag.joycon_left.Assign(1);
  182. shared_memory.device_type.joycon_left.Assign(1);
  183. shared_memory.system_properties.is_horizontal.Assign(1);
  184. shared_memory.system_properties.use_minus.Assign(1);
  185. shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
  186. break;
  187. case Core::HID::NpadStyleIndex::JoyconRight:
  188. shared_memory.style_tag.joycon_right.Assign(1);
  189. shared_memory.device_type.joycon_right.Assign(1);
  190. shared_memory.system_properties.is_horizontal.Assign(1);
  191. shared_memory.system_properties.use_plus.Assign(1);
  192. shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
  193. break;
  194. case Core::HID::NpadStyleIndex::GameCube:
  195. shared_memory.style_tag.gamecube.Assign(1);
  196. shared_memory.device_type.fullkey.Assign(1);
  197. shared_memory.system_properties.is_vertical.Assign(1);
  198. shared_memory.system_properties.use_plus.Assign(1);
  199. break;
  200. case Core::HID::NpadStyleIndex::Pokeball:
  201. shared_memory.style_tag.palma.Assign(1);
  202. shared_memory.device_type.palma.Assign(1);
  203. break;
  204. case Core::HID::NpadStyleIndex::NES:
  205. shared_memory.style_tag.lark.Assign(1);
  206. shared_memory.device_type.fullkey.Assign(1);
  207. break;
  208. case Core::HID::NpadStyleIndex::SNES:
  209. shared_memory.style_tag.lucia.Assign(1);
  210. shared_memory.device_type.fullkey.Assign(1);
  211. shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
  212. break;
  213. case Core::HID::NpadStyleIndex::N64:
  214. shared_memory.style_tag.lagoon.Assign(1);
  215. shared_memory.device_type.fullkey.Assign(1);
  216. shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
  217. break;
  218. case Core::HID::NpadStyleIndex::SegaGenesis:
  219. shared_memory.style_tag.lager.Assign(1);
  220. shared_memory.device_type.fullkey.Assign(1);
  221. break;
  222. default:
  223. break;
  224. }
  225. const auto& body_colors = controller.device->GetColors();
  226. shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
  227. shared_memory.fullkey_color.fullkey = body_colors.fullkey;
  228. shared_memory.joycon_color.attribute = ColorAttribute::Ok;
  229. shared_memory.joycon_color.left = body_colors.left;
  230. shared_memory.joycon_color.right = body_colors.right;
  231. // TODO: Investigate when we should report all batery types
  232. const auto& battery_level = controller.device->GetBattery();
  233. shared_memory.battery_level_dual = battery_level.dual.battery_level;
  234. shared_memory.battery_level_left = battery_level.left.battery_level;
  235. shared_memory.battery_level_right = battery_level.right.battery_level;
  236. controller.is_connected = true;
  237. controller.device->Connect();
  238. SignalStyleSetChangedEvent(npad_id);
  239. WriteEmptyEntry(controller.shared_memory_entry);
  240. }
  241. void Controller_NPad::OnInit() {
  242. if (!IsControllerActivated()) {
  243. return;
  244. }
  245. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  246. auto& controller = controller_data[i];
  247. controller.styleset_changed_event =
  248. service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
  249. }
  250. supported_npad_id_types.resize(npad_id_list.size());
  251. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  252. npad_id_list.size() * sizeof(Core::HID::NpadIdType));
  253. // Prefill controller buffers
  254. for (auto& controller : controller_data) {
  255. auto& npad = controller.shared_memory_entry;
  256. npad.fullkey_color = {
  257. .attribute = ColorAttribute::NoController,
  258. .fullkey = {},
  259. };
  260. npad.joycon_color = {
  261. .attribute = ColorAttribute::NoController,
  262. .left = {},
  263. .right = {},
  264. };
  265. // HW seems to initialize the first 19 entries
  266. for (std::size_t i = 0; i < 19; ++i) {
  267. WriteEmptyEntry(npad);
  268. }
  269. }
  270. }
  271. void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
  272. NPadGenericState dummy_pad_state{};
  273. NpadGcTriggerState dummy_gc_state{};
  274. dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
  275. npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
  276. dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1;
  277. npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
  278. dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
  279. npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
  280. dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
  281. npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
  282. dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
  283. npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
  284. dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1;
  285. npad.palma_lifo.WriteNextEntry(dummy_pad_state);
  286. dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
  287. npad.system_ext_lifo.WriteNextEntry(dummy_pad_state);
  288. dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
  289. npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
  290. }
  291. void Controller_NPad::OnRelease() {
  292. is_controller_initialized = false;
  293. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  294. auto& controller = controller_data[i];
  295. service_context.CloseEvent(controller.styleset_changed_event);
  296. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  297. VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
  298. }
  299. }
  300. }
  301. void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
  302. std::scoped_lock lock{mutex};
  303. auto& controller = GetControllerFromNpadIdType(npad_id);
  304. const auto controller_type = controller.device->GetNpadStyleIndex();
  305. if (!controller.device->IsConnected()) {
  306. return;
  307. }
  308. auto& pad_entry = controller.npad_pad_state;
  309. auto& trigger_entry = controller.npad_trigger_state;
  310. const auto button_state = controller.device->GetNpadButtons();
  311. const auto stick_state = controller.device->GetSticks();
  312. using btn = Core::HID::NpadButton;
  313. pad_entry.npad_buttons.raw = btn::None;
  314. if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
  315. constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
  316. btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
  317. btn::StickRRight | btn::StickRDown;
  318. pad_entry.npad_buttons.raw = button_state.raw & right_button_mask;
  319. pad_entry.r_stick = stick_state.right;
  320. }
  321. if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
  322. constexpr btn left_button_mask =
  323. btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
  324. btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
  325. pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
  326. pad_entry.l_stick = stick_state.left;
  327. }
  328. if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
  329. pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
  330. pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
  331. }
  332. if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
  333. pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
  334. pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
  335. }
  336. if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
  337. const auto& trigger_state = controller.device->GetTriggers();
  338. trigger_entry.l_analog = trigger_state.left;
  339. trigger_entry.r_analog = trigger_state.right;
  340. pad_entry.npad_buttons.zl.Assign(false);
  341. pad_entry.npad_buttons.zr.Assign(button_state.r);
  342. pad_entry.npad_buttons.l.Assign(button_state.zl);
  343. pad_entry.npad_buttons.r.Assign(button_state.zr);
  344. }
  345. }
  346. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  347. std::size_t data_len) {
  348. if (!IsControllerActivated()) {
  349. return;
  350. }
  351. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  352. auto& controller = controller_data[i];
  353. auto& npad = controller.shared_memory_entry;
  354. const auto& controller_type = controller.device->GetNpadStyleIndex();
  355. if (controller_type == Core::HID::NpadStyleIndex::None ||
  356. !controller.device->IsConnected()) {
  357. // Refresh shared memory
  358. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  359. &controller.shared_memory_entry, sizeof(NpadInternalState));
  360. continue;
  361. }
  362. RequestPadStateUpdate(controller.device->GetNpadIdType());
  363. auto& pad_state = controller.npad_pad_state;
  364. auto& libnx_state = controller.npad_libnx_state;
  365. auto& trigger_state = controller.npad_trigger_state;
  366. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  367. // any controllers.
  368. libnx_state.connection_status.raw = 0;
  369. libnx_state.connection_status.is_connected.Assign(1);
  370. switch (controller_type) {
  371. case Core::HID::NpadStyleIndex::None:
  372. UNREACHABLE();
  373. break;
  374. case Core::HID::NpadStyleIndex::ProController:
  375. case Core::HID::NpadStyleIndex::NES:
  376. case Core::HID::NpadStyleIndex::SNES:
  377. case Core::HID::NpadStyleIndex::N64:
  378. case Core::HID::NpadStyleIndex::SegaGenesis:
  379. pad_state.connection_status.raw = 0;
  380. pad_state.connection_status.is_connected.Assign(1);
  381. pad_state.connection_status.is_wired.Assign(1);
  382. libnx_state.connection_status.is_wired.Assign(1);
  383. pad_state.sampling_number =
  384. npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  385. npad.fullkey_lifo.WriteNextEntry(pad_state);
  386. break;
  387. case Core::HID::NpadStyleIndex::Handheld:
  388. pad_state.connection_status.raw = 0;
  389. pad_state.connection_status.is_connected.Assign(1);
  390. pad_state.connection_status.is_wired.Assign(1);
  391. pad_state.connection_status.is_left_connected.Assign(1);
  392. pad_state.connection_status.is_right_connected.Assign(1);
  393. pad_state.connection_status.is_left_wired.Assign(1);
  394. pad_state.connection_status.is_right_wired.Assign(1);
  395. libnx_state.connection_status.is_wired.Assign(1);
  396. libnx_state.connection_status.is_left_connected.Assign(1);
  397. libnx_state.connection_status.is_right_connected.Assign(1);
  398. libnx_state.connection_status.is_left_wired.Assign(1);
  399. libnx_state.connection_status.is_right_wired.Assign(1);
  400. pad_state.sampling_number =
  401. npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  402. npad.handheld_lifo.WriteNextEntry(pad_state);
  403. break;
  404. case Core::HID::NpadStyleIndex::JoyconDual:
  405. pad_state.connection_status.raw = 0;
  406. pad_state.connection_status.is_connected.Assign(1);
  407. if (controller.is_dual_left_connected) {
  408. pad_state.connection_status.is_left_connected.Assign(1);
  409. libnx_state.connection_status.is_left_connected.Assign(1);
  410. }
  411. if (controller.is_dual_right_connected) {
  412. pad_state.connection_status.is_right_connected.Assign(1);
  413. libnx_state.connection_status.is_right_connected.Assign(1);
  414. }
  415. pad_state.sampling_number =
  416. npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
  417. npad.joy_dual_lifo.WriteNextEntry(pad_state);
  418. break;
  419. case Core::HID::NpadStyleIndex::JoyconLeft:
  420. pad_state.connection_status.raw = 0;
  421. pad_state.connection_status.is_connected.Assign(1);
  422. pad_state.connection_status.is_left_connected.Assign(1);
  423. libnx_state.connection_status.is_left_connected.Assign(1);
  424. pad_state.sampling_number =
  425. npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  426. npad.joy_left_lifo.WriteNextEntry(pad_state);
  427. break;
  428. case Core::HID::NpadStyleIndex::JoyconRight:
  429. pad_state.connection_status.raw = 0;
  430. pad_state.connection_status.is_connected.Assign(1);
  431. pad_state.connection_status.is_right_connected.Assign(1);
  432. libnx_state.connection_status.is_right_connected.Assign(1);
  433. pad_state.sampling_number =
  434. npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  435. npad.joy_right_lifo.WriteNextEntry(pad_state);
  436. break;
  437. case Core::HID::NpadStyleIndex::GameCube:
  438. pad_state.connection_status.raw = 0;
  439. pad_state.connection_status.is_connected.Assign(1);
  440. pad_state.connection_status.is_wired.Assign(1);
  441. libnx_state.connection_status.is_wired.Assign(1);
  442. pad_state.sampling_number =
  443. npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  444. trigger_state.sampling_number =
  445. npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
  446. npad.fullkey_lifo.WriteNextEntry(pad_state);
  447. npad.gc_trigger_lifo.WriteNextEntry(trigger_state);
  448. break;
  449. case Core::HID::NpadStyleIndex::Pokeball:
  450. pad_state.connection_status.raw = 0;
  451. pad_state.connection_status.is_connected.Assign(1);
  452. pad_state.sampling_number =
  453. npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
  454. npad.palma_lifo.WriteNextEntry(pad_state);
  455. break;
  456. default:
  457. break;
  458. }
  459. libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
  460. libnx_state.l_stick = pad_state.l_stick;
  461. libnx_state.r_stick = pad_state.r_stick;
  462. npad.system_ext_lifo.WriteNextEntry(pad_state);
  463. press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
  464. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  465. &controller.shared_memory_entry, sizeof(NpadInternalState));
  466. }
  467. }
  468. void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  469. std::size_t data_len) {
  470. if (!IsControllerActivated()) {
  471. return;
  472. }
  473. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  474. auto& controller = controller_data[i];
  475. const auto& controller_type = controller.device->GetNpadStyleIndex();
  476. if (controller_type == Core::HID::NpadStyleIndex::None ||
  477. !controller.device->IsConnected()) {
  478. continue;
  479. }
  480. auto& npad = controller.shared_memory_entry;
  481. const auto& motion_state = controller.device->GetMotions();
  482. auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
  483. auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
  484. auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
  485. auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
  486. auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
  487. auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
  488. if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
  489. controller.sixaxis_at_rest = true;
  490. for (std::size_t e = 0; e < motion_state.size(); ++e) {
  491. controller.sixaxis_at_rest =
  492. controller.sixaxis_at_rest && motion_state[e].is_at_rest;
  493. }
  494. }
  495. switch (controller_type) {
  496. case Core::HID::NpadStyleIndex::None:
  497. UNREACHABLE();
  498. break;
  499. case Core::HID::NpadStyleIndex::ProController:
  500. sixaxis_fullkey_state.attribute.raw = 0;
  501. if (controller.sixaxis_sensor_enabled) {
  502. sixaxis_fullkey_state.attribute.is_connected.Assign(1);
  503. sixaxis_fullkey_state.accel = motion_state[0].accel;
  504. sixaxis_fullkey_state.gyro = motion_state[0].gyro;
  505. sixaxis_fullkey_state.rotation = motion_state[0].rotation;
  506. sixaxis_fullkey_state.orientation = motion_state[0].orientation;
  507. }
  508. break;
  509. case Core::HID::NpadStyleIndex::Handheld:
  510. sixaxis_handheld_state.attribute.raw = 0;
  511. if (controller.sixaxis_sensor_enabled) {
  512. sixaxis_handheld_state.attribute.is_connected.Assign(1);
  513. sixaxis_handheld_state.accel = motion_state[0].accel;
  514. sixaxis_handheld_state.gyro = motion_state[0].gyro;
  515. sixaxis_handheld_state.rotation = motion_state[0].rotation;
  516. sixaxis_handheld_state.orientation = motion_state[0].orientation;
  517. }
  518. break;
  519. case Core::HID::NpadStyleIndex::JoyconDual:
  520. sixaxis_dual_left_state.attribute.raw = 0;
  521. sixaxis_dual_right_state.attribute.raw = 0;
  522. if (controller.sixaxis_sensor_enabled) {
  523. // Set motion for the left joycon
  524. sixaxis_dual_left_state.attribute.is_connected.Assign(1);
  525. sixaxis_dual_left_state.accel = motion_state[0].accel;
  526. sixaxis_dual_left_state.gyro = motion_state[0].gyro;
  527. sixaxis_dual_left_state.rotation = motion_state[0].rotation;
  528. sixaxis_dual_left_state.orientation = motion_state[0].orientation;
  529. }
  530. if (controller.sixaxis_sensor_enabled) {
  531. // Set motion for the right joycon
  532. sixaxis_dual_right_state.attribute.is_connected.Assign(1);
  533. sixaxis_dual_right_state.accel = motion_state[1].accel;
  534. sixaxis_dual_right_state.gyro = motion_state[1].gyro;
  535. sixaxis_dual_right_state.rotation = motion_state[1].rotation;
  536. sixaxis_dual_right_state.orientation = motion_state[1].orientation;
  537. }
  538. break;
  539. case Core::HID::NpadStyleIndex::JoyconLeft:
  540. sixaxis_left_lifo_state.attribute.raw = 0;
  541. if (controller.sixaxis_sensor_enabled) {
  542. sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
  543. sixaxis_left_lifo_state.accel = motion_state[0].accel;
  544. sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
  545. sixaxis_left_lifo_state.rotation = motion_state[0].rotation;
  546. sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
  547. }
  548. break;
  549. case Core::HID::NpadStyleIndex::JoyconRight:
  550. sixaxis_right_lifo_state.attribute.raw = 0;
  551. if (controller.sixaxis_sensor_enabled) {
  552. sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
  553. sixaxis_right_lifo_state.accel = motion_state[1].accel;
  554. sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
  555. sixaxis_right_lifo_state.rotation = motion_state[1].rotation;
  556. sixaxis_right_lifo_state.orientation = motion_state[1].orientation;
  557. }
  558. break;
  559. default:
  560. break;
  561. }
  562. sixaxis_fullkey_state.sampling_number =
  563. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  564. sixaxis_handheld_state.sampling_number =
  565. npad.sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  566. sixaxis_dual_left_state.sampling_number =
  567. npad.sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  568. sixaxis_dual_right_state.sampling_number =
  569. npad.sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  570. sixaxis_left_lifo_state.sampling_number =
  571. npad.sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  572. sixaxis_right_lifo_state.sampling_number =
  573. npad.sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  574. if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
  575. // This buffer only is updated on handheld on HW
  576. npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
  577. } else {
  578. // Handheld doesn't update this buffer on HW
  579. npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
  580. }
  581. npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
  582. npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
  583. npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
  584. npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
  585. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  586. &controller.shared_memory_entry, sizeof(NpadInternalState));
  587. }
  588. }
  589. void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
  590. hid_core.SetSupportedStyleTag(style_set);
  591. if (is_controller_initialized) {
  592. return;
  593. }
  594. // Once SetSupportedStyleSet is called controllers are fully initialized
  595. is_controller_initialized = true;
  596. // Connect all active controllers
  597. for (auto& controller : controller_data) {
  598. const auto& device = controller.device;
  599. if (device->IsConnected()) {
  600. AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
  601. }
  602. }
  603. }
  604. Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
  605. if (!is_controller_initialized) {
  606. return {Core::HID::NpadStyleSet::None};
  607. }
  608. return hid_core.GetSupportedStyleTag();
  609. }
  610. void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
  611. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  612. supported_npad_id_types.clear();
  613. supported_npad_id_types.resize(length / sizeof(u32));
  614. std::memcpy(supported_npad_id_types.data(), data, length);
  615. }
  616. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  617. ASSERT(max_length < supported_npad_id_types.size());
  618. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  619. }
  620. std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
  621. return supported_npad_id_types.size();
  622. }
  623. void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
  624. hold_type = joy_hold_type;
  625. }
  626. Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
  627. return hold_type;
  628. }
  629. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  630. handheld_activation_mode = activation_mode;
  631. }
  632. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  633. return handheld_activation_mode;
  634. }
  635. void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
  636. communication_mode = communication_mode_;
  637. }
  638. Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
  639. return communication_mode;
  640. }
  641. void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
  642. NpadJoyAssignmentMode assignment_mode) {
  643. if (!IsNpadIdValid(npad_id)) {
  644. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  645. return;
  646. }
  647. auto& controller = GetControllerFromNpadIdType(npad_id);
  648. if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
  649. controller.shared_memory_entry.assignment_mode = assignment_mode;
  650. }
  651. if (!controller.device->IsConnected()) {
  652. return;
  653. }
  654. if (assignment_mode == NpadJoyAssignmentMode::Dual) {
  655. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) {
  656. DisconnectNpad(npad_id);
  657. controller.is_dual_left_connected = true;
  658. controller.is_dual_right_connected = false;
  659. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  660. return;
  661. }
  662. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
  663. DisconnectNpad(npad_id);
  664. controller.is_dual_left_connected = false;
  665. controller.is_dual_right_connected = true;
  666. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  667. return;
  668. }
  669. return;
  670. }
  671. // This is for NpadJoyAssignmentMode::Single
  672. // Only JoyconDual get affected by this function
  673. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
  674. return;
  675. }
  676. if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
  677. DisconnectNpad(npad_id);
  678. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  679. return;
  680. }
  681. if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
  682. DisconnectNpad(npad_id);
  683. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  684. return;
  685. }
  686. // We have two controllers connected to the same npad_id we need to split them
  687. const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId();
  688. auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
  689. DisconnectNpad(npad_id);
  690. if (npad_device_type == NpadJoyDeviceType::Left) {
  691. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  692. controller_2.is_dual_left_connected = false;
  693. controller_2.is_dual_right_connected = true;
  694. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
  695. } else {
  696. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  697. controller_2.is_dual_left_connected = true;
  698. controller_2.is_dual_right_connected = false;
  699. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
  700. }
  701. }
  702. bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
  703. std::size_t device_index,
  704. const Core::HID::VibrationValue& vibration_value) {
  705. auto& controller = GetControllerFromNpadIdType(npad_id);
  706. if (!controller.device->IsConnected()) {
  707. return false;
  708. }
  709. if (!controller.device->IsVibrationEnabled()) {
  710. if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
  711. controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
  712. // Send an empty vibration to stop any vibrations.
  713. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
  714. controller.device->SetVibration(device_index, vibration);
  715. // Then reset the vibration value to its default value.
  716. controller.vibration[device_index].latest_vibration_value =
  717. Core::HID::DEFAULT_VIBRATION_VALUE;
  718. }
  719. return false;
  720. }
  721. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  722. using std::chrono::duration_cast;
  723. using std::chrono::milliseconds;
  724. using std::chrono::steady_clock;
  725. const auto now = steady_clock::now();
  726. // Filter out non-zero vibrations that are within 10ms of each other.
  727. if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
  728. duration_cast<milliseconds>(
  729. now - controller.vibration[device_index].last_vibration_timepoint) <
  730. milliseconds(10)) {
  731. return false;
  732. }
  733. controller.vibration[device_index].last_vibration_timepoint = now;
  734. }
  735. Core::HID::VibrationValue vibration{
  736. vibration_value.low_amplitude, vibration_value.low_frequency,
  737. vibration_value.high_amplitude, vibration_value.high_frequency};
  738. return controller.device->SetVibration(device_index, vibration);
  739. }
  740. void Controller_NPad::VibrateController(
  741. const Core::HID::VibrationDeviceHandle& vibration_device_handle,
  742. const Core::HID::VibrationValue& vibration_value) {
  743. if (!IsDeviceHandleValid(vibration_device_handle)) {
  744. return;
  745. }
  746. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  747. return;
  748. }
  749. auto& controller = GetControllerFromHandle(vibration_device_handle);
  750. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  751. if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
  752. return;
  753. }
  754. if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
  755. UNREACHABLE_MSG("DeviceIndex should never be None!");
  756. return;
  757. }
  758. // Some games try to send mismatched parameters in the device handle, block these.
  759. if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  760. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
  761. vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
  762. (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
  763. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
  764. vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
  765. return;
  766. }
  767. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  768. if (vibration_value.low_amplitude ==
  769. controller.vibration[device_index].latest_vibration_value.low_amplitude &&
  770. vibration_value.high_amplitude ==
  771. controller.vibration[device_index].latest_vibration_value.high_amplitude) {
  772. return;
  773. }
  774. if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
  775. vibration_value)) {
  776. controller.vibration[device_index].latest_vibration_value = vibration_value;
  777. }
  778. }
  779. void Controller_NPad::VibrateControllers(
  780. const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
  781. const std::vector<Core::HID::VibrationValue>& vibration_values) {
  782. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  783. return;
  784. }
  785. ASSERT_OR_EXECUTE_MSG(
  786. vibration_device_handles.size() == vibration_values.size(), { return; },
  787. "The amount of device handles does not match with the amount of vibration values,"
  788. "this is undefined behavior!");
  789. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  790. VibrateController(vibration_device_handles[i], vibration_values[i]);
  791. }
  792. }
  793. Core::HID::VibrationValue Controller_NPad::GetLastVibration(
  794. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  795. if (!IsDeviceHandleValid(vibration_device_handle)) {
  796. return {};
  797. }
  798. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  799. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  800. return controller.vibration[device_index].latest_vibration_value;
  801. }
  802. void Controller_NPad::InitializeVibrationDevice(
  803. const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
  804. if (!IsDeviceHandleValid(vibration_device_handle)) {
  805. return;
  806. }
  807. const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
  808. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  809. InitializeVibrationDeviceAtIndex(npad_index, device_index);
  810. }
  811. void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
  812. std::size_t device_index) {
  813. auto& controller = GetControllerFromNpadIdType(npad_id);
  814. if (!Settings::values.vibration_enabled.GetValue()) {
  815. controller.vibration[device_index].device_mounted = false;
  816. return;
  817. }
  818. controller.vibration[device_index].device_mounted =
  819. controller.device->TestVibration(device_index);
  820. }
  821. void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  822. permit_vibration_session_enabled = permit_vibration_session;
  823. }
  824. bool Controller_NPad::IsVibrationDeviceMounted(
  825. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  826. if (!IsDeviceHandleValid(vibration_device_handle)) {
  827. return false;
  828. }
  829. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  830. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  831. return controller.vibration[device_index].device_mounted;
  832. }
  833. Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
  834. if (!IsNpadIdValid(npad_id)) {
  835. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  836. // Fallback to player 1
  837. const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
  838. return controller.styleset_changed_event->GetReadableEvent();
  839. }
  840. const auto& controller = GetControllerFromNpadIdType(npad_id);
  841. return controller.styleset_changed_event->GetReadableEvent();
  842. }
  843. void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
  844. const auto& controller = GetControllerFromNpadIdType(npad_id);
  845. controller.styleset_changed_event->GetWritableEvent().Signal();
  846. }
  847. void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
  848. Core::HID::NpadIdType npad_id) {
  849. UpdateControllerAt(controller, npad_id, true);
  850. }
  851. void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
  852. Core::HID::NpadIdType npad_id, bool connected) {
  853. auto& controller = GetControllerFromNpadIdType(npad_id);
  854. if (!connected) {
  855. DisconnectNpad(npad_id);
  856. return;
  857. }
  858. controller.device->SetNpadStyleIndex(type);
  859. InitNewlyAddedController(npad_id);
  860. }
  861. void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
  862. if (!IsNpadIdValid(npad_id)) {
  863. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  864. return;
  865. }
  866. LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
  867. auto& controller = GetControllerFromNpadIdType(npad_id);
  868. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  869. // Send an empty vibration to stop any vibrations.
  870. VibrateControllerAtIndex(npad_id, device_idx, {});
  871. controller.vibration[device_idx].device_mounted = false;
  872. }
  873. auto& shared_memory_entry = controller.shared_memory_entry;
  874. // Don't reset shared_memory_entry.assignment_mode this value is persistent
  875. shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
  876. shared_memory_entry.device_type.raw = 0;
  877. shared_memory_entry.system_properties.raw = 0;
  878. shared_memory_entry.button_properties.raw = 0;
  879. shared_memory_entry.battery_level_dual = 0;
  880. shared_memory_entry.battery_level_left = 0;
  881. shared_memory_entry.battery_level_right = 0;
  882. shared_memory_entry.fullkey_color = {
  883. .attribute = ColorAttribute::NoController,
  884. .fullkey = {},
  885. };
  886. shared_memory_entry.joycon_color = {
  887. .attribute = ColorAttribute::NoController,
  888. .left = {},
  889. .right = {},
  890. };
  891. shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
  892. controller.is_dual_left_connected = true;
  893. controller.is_dual_right_connected = true;
  894. controller.is_connected = false;
  895. controller.device->Disconnect();
  896. SignalStyleSetChangedEvent(npad_id);
  897. WriteEmptyEntry(controller.shared_memory_entry);
  898. }
  899. ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
  900. GyroscopeZeroDriftMode drift_mode) {
  901. if (!IsDeviceHandleValid(sixaxis_handle)) {
  902. LOG_ERROR(Service_HID, "Invalid handle");
  903. return NpadInvalidHandle;
  904. }
  905. auto& controller = GetControllerFromHandle(sixaxis_handle);
  906. switch (sixaxis_handle.npad_type) {
  907. case Core::HID::NpadStyleIndex::ProController:
  908. controller.sixaxis_fullkey.gyroscope_zero_drift_mode = drift_mode;
  909. break;
  910. case Core::HID::NpadStyleIndex::Handheld:
  911. controller.sixaxis_handheld.gyroscope_zero_drift_mode = drift_mode;
  912. break;
  913. case Core::HID::NpadStyleIndex::JoyconDual:
  914. case Core::HID::NpadStyleIndex::GameCube:
  915. case Core::HID::NpadStyleIndex::Pokeball:
  916. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  917. controller.sixaxis_dual_left.gyroscope_zero_drift_mode = drift_mode;
  918. break;
  919. }
  920. controller.sixaxis_dual_right.gyroscope_zero_drift_mode = drift_mode;
  921. break;
  922. case Core::HID::NpadStyleIndex::JoyconLeft:
  923. controller.sixaxis_left.gyroscope_zero_drift_mode = drift_mode;
  924. break;
  925. case Core::HID::NpadStyleIndex::JoyconRight:
  926. controller.sixaxis_right.gyroscope_zero_drift_mode = drift_mode;
  927. break;
  928. default:
  929. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  930. return NpadInvalidHandle;
  931. }
  932. return ResultSuccess;
  933. }
  934. ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
  935. GyroscopeZeroDriftMode& drift_mode) const {
  936. if (!IsDeviceHandleValid(sixaxis_handle)) {
  937. LOG_ERROR(Service_HID, "Invalid handle");
  938. return NpadInvalidHandle;
  939. }
  940. auto& controller = GetControllerFromHandle(sixaxis_handle);
  941. switch (sixaxis_handle.npad_type) {
  942. case Core::HID::NpadStyleIndex::ProController:
  943. drift_mode = controller.sixaxis_fullkey.gyroscope_zero_drift_mode;
  944. break;
  945. case Core::HID::NpadStyleIndex::Handheld:
  946. drift_mode = controller.sixaxis_handheld.gyroscope_zero_drift_mode;
  947. break;
  948. case Core::HID::NpadStyleIndex::JoyconDual:
  949. case Core::HID::NpadStyleIndex::GameCube:
  950. case Core::HID::NpadStyleIndex::Pokeball:
  951. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  952. drift_mode = controller.sixaxis_dual_left.gyroscope_zero_drift_mode;
  953. break;
  954. }
  955. drift_mode = controller.sixaxis_dual_right.gyroscope_zero_drift_mode;
  956. break;
  957. case Core::HID::NpadStyleIndex::JoyconLeft:
  958. drift_mode = controller.sixaxis_left.gyroscope_zero_drift_mode;
  959. break;
  960. case Core::HID::NpadStyleIndex::JoyconRight:
  961. drift_mode = controller.sixaxis_right.gyroscope_zero_drift_mode;
  962. break;
  963. default:
  964. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  965. return NpadInvalidHandle;
  966. }
  967. return ResultSuccess;
  968. }
  969. ResultCode Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle,
  970. bool& is_at_rest) const {
  971. if (!IsDeviceHandleValid(sixaxis_handle)) {
  972. LOG_ERROR(Service_HID, "Invalid handle");
  973. return NpadInvalidHandle;
  974. }
  975. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  976. is_at_rest = controller.sixaxis_at_rest;
  977. return ResultSuccess;
  978. }
  979. ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
  980. Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const {
  981. if (!IsDeviceHandleValid(sixaxis_handle)) {
  982. LOG_ERROR(Service_HID, "Invalid handle");
  983. return NpadInvalidHandle;
  984. }
  985. // We don't support joycon firmware updates
  986. is_firmware_available = false;
  987. return ResultSuccess;
  988. }
  989. ResultCode Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
  990. bool sixaxis_status) {
  991. if (!IsDeviceHandleValid(sixaxis_handle)) {
  992. LOG_ERROR(Service_HID, "Invalid handle");
  993. return NpadInvalidHandle;
  994. }
  995. auto& controller = GetControllerFromHandle(sixaxis_handle);
  996. controller.sixaxis_sensor_enabled = sixaxis_status;
  997. return ResultSuccess;
  998. }
  999. ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled(
  1000. Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_fusion_enabled) const {
  1001. if (!IsDeviceHandleValid(sixaxis_handle)) {
  1002. LOG_ERROR(Service_HID, "Invalid handle");
  1003. return NpadInvalidHandle;
  1004. }
  1005. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1006. switch (sixaxis_handle.npad_type) {
  1007. case Core::HID::NpadStyleIndex::ProController:
  1008. is_fusion_enabled = controller.sixaxis_fullkey.is_fusion_enabled;
  1009. break;
  1010. case Core::HID::NpadStyleIndex::Handheld:
  1011. is_fusion_enabled = controller.sixaxis_handheld.is_fusion_enabled;
  1012. break;
  1013. case Core::HID::NpadStyleIndex::JoyconDual:
  1014. case Core::HID::NpadStyleIndex::GameCube:
  1015. case Core::HID::NpadStyleIndex::Pokeball:
  1016. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1017. is_fusion_enabled = controller.sixaxis_dual_left.is_fusion_enabled;
  1018. break;
  1019. }
  1020. is_fusion_enabled = controller.sixaxis_dual_right.is_fusion_enabled;
  1021. break;
  1022. case Core::HID::NpadStyleIndex::JoyconLeft:
  1023. is_fusion_enabled = controller.sixaxis_left.is_fusion_enabled;
  1024. break;
  1025. case Core::HID::NpadStyleIndex::JoyconRight:
  1026. is_fusion_enabled = controller.sixaxis_right.is_fusion_enabled;
  1027. break;
  1028. default:
  1029. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  1030. return NpadInvalidHandle;
  1031. }
  1032. return ResultSuccess;
  1033. }
  1034. ResultCode Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
  1035. bool is_fusion_enabled) {
  1036. if (!IsDeviceHandleValid(sixaxis_handle)) {
  1037. LOG_ERROR(Service_HID, "Invalid handle");
  1038. return NpadInvalidHandle;
  1039. }
  1040. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1041. switch (sixaxis_handle.npad_type) {
  1042. case Core::HID::NpadStyleIndex::ProController:
  1043. controller.sixaxis_fullkey.is_fusion_enabled = is_fusion_enabled;
  1044. break;
  1045. case Core::HID::NpadStyleIndex::Handheld:
  1046. controller.sixaxis_handheld.is_fusion_enabled = is_fusion_enabled;
  1047. break;
  1048. case Core::HID::NpadStyleIndex::JoyconDual:
  1049. case Core::HID::NpadStyleIndex::GameCube:
  1050. case Core::HID::NpadStyleIndex::Pokeball:
  1051. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1052. controller.sixaxis_dual_left.is_fusion_enabled = is_fusion_enabled;
  1053. break;
  1054. }
  1055. controller.sixaxis_dual_right.is_fusion_enabled = is_fusion_enabled;
  1056. break;
  1057. case Core::HID::NpadStyleIndex::JoyconLeft:
  1058. controller.sixaxis_left.is_fusion_enabled = is_fusion_enabled;
  1059. break;
  1060. case Core::HID::NpadStyleIndex::JoyconRight:
  1061. controller.sixaxis_right.is_fusion_enabled = is_fusion_enabled;
  1062. break;
  1063. default:
  1064. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  1065. return NpadInvalidHandle;
  1066. }
  1067. return ResultSuccess;
  1068. }
  1069. ResultCode Controller_NPad::SetSixAxisFusionParameters(
  1070. Core::HID::SixAxisSensorHandle sixaxis_handle,
  1071. Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
  1072. if (!IsDeviceHandleValid(sixaxis_handle)) {
  1073. LOG_ERROR(Service_HID, "Invalid handle");
  1074. return NpadInvalidHandle;
  1075. }
  1076. const auto param1 = sixaxis_fusion_parameters.parameter1;
  1077. if (param1 < 0.0f || param1 > 1.0f) {
  1078. return InvalidSixAxisFusionRange;
  1079. }
  1080. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1081. switch (sixaxis_handle.npad_type) {
  1082. case Core::HID::NpadStyleIndex::ProController:
  1083. controller.sixaxis_fullkey.fusion = sixaxis_fusion_parameters;
  1084. break;
  1085. case Core::HID::NpadStyleIndex::Handheld:
  1086. controller.sixaxis_handheld.fusion = sixaxis_fusion_parameters;
  1087. break;
  1088. case Core::HID::NpadStyleIndex::JoyconDual:
  1089. case Core::HID::NpadStyleIndex::GameCube:
  1090. case Core::HID::NpadStyleIndex::Pokeball:
  1091. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1092. controller.sixaxis_dual_left.fusion = sixaxis_fusion_parameters;
  1093. break;
  1094. }
  1095. controller.sixaxis_dual_right.fusion = sixaxis_fusion_parameters;
  1096. break;
  1097. case Core::HID::NpadStyleIndex::JoyconLeft:
  1098. controller.sixaxis_left.fusion = sixaxis_fusion_parameters;
  1099. break;
  1100. case Core::HID::NpadStyleIndex::JoyconRight:
  1101. controller.sixaxis_right.fusion = sixaxis_fusion_parameters;
  1102. break;
  1103. default:
  1104. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  1105. return NpadInvalidHandle;
  1106. }
  1107. return ResultSuccess;
  1108. }
  1109. ResultCode Controller_NPad::GetSixAxisFusionParameters(
  1110. Core::HID::SixAxisSensorHandle sixaxis_handle,
  1111. Core::HID::SixAxisSensorFusionParameters& parameters) const {
  1112. if (!IsDeviceHandleValid(sixaxis_handle)) {
  1113. LOG_ERROR(Service_HID, "Invalid handle");
  1114. return NpadInvalidHandle;
  1115. }
  1116. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  1117. switch (sixaxis_handle.npad_type) {
  1118. case Core::HID::NpadStyleIndex::ProController:
  1119. parameters = controller.sixaxis_fullkey.fusion;
  1120. break;
  1121. case Core::HID::NpadStyleIndex::Handheld:
  1122. parameters = controller.sixaxis_handheld.fusion;
  1123. break;
  1124. case Core::HID::NpadStyleIndex::JoyconDual:
  1125. case Core::HID::NpadStyleIndex::GameCube:
  1126. case Core::HID::NpadStyleIndex::Pokeball:
  1127. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1128. parameters = controller.sixaxis_dual_left.fusion;
  1129. break;
  1130. }
  1131. parameters = controller.sixaxis_dual_right.fusion;
  1132. break;
  1133. case Core::HID::NpadStyleIndex::JoyconLeft:
  1134. parameters = controller.sixaxis_left.fusion;
  1135. break;
  1136. case Core::HID::NpadStyleIndex::JoyconRight:
  1137. parameters = controller.sixaxis_right.fusion;
  1138. break;
  1139. default:
  1140. LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
  1141. return NpadInvalidHandle;
  1142. }
  1143. return ResultSuccess;
  1144. }
  1145. void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
  1146. Core::HID::NpadIdType npad_id_2) {
  1147. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  1148. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  1149. npad_id_2);
  1150. return;
  1151. }
  1152. auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
  1153. auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
  1154. const auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
  1155. const auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
  1156. bool merge_controllers = false;
  1157. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  1158. // Otherwise, do nothing.
  1159. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
  1160. controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
  1161. merge_controllers = true;
  1162. }
  1163. if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
  1164. controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) {
  1165. merge_controllers = true;
  1166. }
  1167. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
  1168. controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight &&
  1169. controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
  1170. merge_controllers = true;
  1171. }
  1172. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
  1173. controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
  1174. !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
  1175. merge_controllers = true;
  1176. }
  1177. if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
  1178. controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
  1179. controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
  1180. merge_controllers = true;
  1181. }
  1182. if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
  1183. controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
  1184. !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
  1185. merge_controllers = true;
  1186. }
  1187. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
  1188. controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
  1189. controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected &&
  1190. !controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
  1191. merge_controllers = true;
  1192. }
  1193. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
  1194. controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
  1195. !controller_1.is_dual_left_connected && controller_1.is_dual_right_connected &&
  1196. controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
  1197. merge_controllers = true;
  1198. }
  1199. if (merge_controllers) {
  1200. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  1201. DisconnectNpad(npad_id_2);
  1202. controller_1.is_dual_left_connected = true;
  1203. controller_1.is_dual_right_connected = true;
  1204. AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
  1205. return;
  1206. }
  1207. LOG_WARNING(Service_HID,
  1208. "Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, "
  1209. "dual_1(left/right):{}/{}, dual_2(left/right):{}/{}",
  1210. npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(),
  1211. controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected,
  1212. controller_1.is_dual_right_connected, controller_2.is_dual_left_connected,
  1213. controller_2.is_dual_right_connected);
  1214. }
  1215. void Controller_NPad::StartLRAssignmentMode() {
  1216. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  1217. // controller types from boot, it doesn't really matter about showing a selection screen
  1218. is_in_lr_assignment_mode = true;
  1219. }
  1220. void Controller_NPad::StopLRAssignmentMode() {
  1221. is_in_lr_assignment_mode = false;
  1222. }
  1223. bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
  1224. Core::HID::NpadIdType npad_id_2) {
  1225. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  1226. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  1227. npad_id_2);
  1228. return false;
  1229. }
  1230. if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
  1231. npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
  1232. npad_id_2 == Core::HID::NpadIdType::Other) {
  1233. return true;
  1234. }
  1235. const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
  1236. const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
  1237. const auto type_index_1 = controller_1->GetNpadStyleIndex();
  1238. const auto type_index_2 = controller_2->GetNpadStyleIndex();
  1239. const auto is_connected_1 = controller_1->IsConnected();
  1240. const auto is_connected_2 = controller_2->IsConnected();
  1241. if (!IsControllerSupported(type_index_1) && is_connected_1) {
  1242. return false;
  1243. }
  1244. if (!IsControllerSupported(type_index_2) && is_connected_2) {
  1245. return false;
  1246. }
  1247. UpdateControllerAt(type_index_2, npad_id_1, is_connected_2);
  1248. UpdateControllerAt(type_index_1, npad_id_2, is_connected_1);
  1249. return true;
  1250. }
  1251. Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
  1252. if (!IsNpadIdValid(npad_id)) {
  1253. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1254. return Core::HID::LedPattern{0, 0, 0, 0};
  1255. }
  1256. const auto& controller = GetControllerFromNpadIdType(npad_id).device;
  1257. return controller->GetLedPattern();
  1258. }
  1259. bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
  1260. Core::HID::NpadIdType npad_id) const {
  1261. if (!IsNpadIdValid(npad_id)) {
  1262. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1263. // Return the default value
  1264. return false;
  1265. }
  1266. const auto& controller = GetControllerFromNpadIdType(npad_id);
  1267. return controller.unintended_home_button_input_protection;
  1268. }
  1269. void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
  1270. Core::HID::NpadIdType npad_id) {
  1271. if (!IsNpadIdValid(npad_id)) {
  1272. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1273. return;
  1274. }
  1275. auto& controller = GetControllerFromNpadIdType(npad_id);
  1276. controller.unintended_home_button_input_protection = is_protection_enabled;
  1277. }
  1278. void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
  1279. analog_stick_use_center_clamp = use_center_clamp;
  1280. }
  1281. void Controller_NPad::ClearAllConnectedControllers() {
  1282. for (auto& controller : controller_data) {
  1283. if (controller.device->IsConnected() &&
  1284. controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
  1285. controller.device->Disconnect();
  1286. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1287. }
  1288. }
  1289. }
  1290. void Controller_NPad::DisconnectAllConnectedControllers() {
  1291. for (auto& controller : controller_data) {
  1292. controller.device->Disconnect();
  1293. }
  1294. }
  1295. void Controller_NPad::ConnectAllDisconnectedControllers() {
  1296. for (auto& controller : controller_data) {
  1297. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
  1298. !controller.device->IsConnected()) {
  1299. controller.device->Connect();
  1300. }
  1301. }
  1302. }
  1303. void Controller_NPad::ClearAllControllers() {
  1304. for (auto& controller : controller_data) {
  1305. controller.device->Disconnect();
  1306. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1307. }
  1308. }
  1309. Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
  1310. return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
  1311. }
  1312. bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
  1313. if (controller == Core::HID::NpadStyleIndex::Handheld) {
  1314. const bool support_handheld =
  1315. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1316. Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
  1317. // Handheld is not even a supported type, lets stop here
  1318. if (!support_handheld) {
  1319. return false;
  1320. }
  1321. // Handheld shouldn't be supported in docked mode
  1322. if (Settings::values.use_docked_mode.GetValue()) {
  1323. return false;
  1324. }
  1325. return true;
  1326. }
  1327. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1328. [](Core::HID::NpadIdType npad_id) {
  1329. return npad_id <= Core::HID::NpadIdType::Player8;
  1330. })) {
  1331. Core::HID::NpadStyleTag style = GetSupportedStyleSet();
  1332. switch (controller) {
  1333. case Core::HID::NpadStyleIndex::ProController:
  1334. return style.fullkey;
  1335. case Core::HID::NpadStyleIndex::JoyconDual:
  1336. return style.joycon_dual;
  1337. case Core::HID::NpadStyleIndex::JoyconLeft:
  1338. return style.joycon_left;
  1339. case Core::HID::NpadStyleIndex::JoyconRight:
  1340. return style.joycon_right;
  1341. case Core::HID::NpadStyleIndex::GameCube:
  1342. return style.gamecube;
  1343. case Core::HID::NpadStyleIndex::Pokeball:
  1344. return style.palma;
  1345. case Core::HID::NpadStyleIndex::NES:
  1346. return style.lark;
  1347. case Core::HID::NpadStyleIndex::SNES:
  1348. return style.lucia;
  1349. case Core::HID::NpadStyleIndex::N64:
  1350. return style.lagoon;
  1351. case Core::HID::NpadStyleIndex::SegaGenesis:
  1352. return style.lager;
  1353. default:
  1354. return false;
  1355. }
  1356. }
  1357. return false;
  1358. }
  1359. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1360. const Core::HID::SixAxisSensorHandle& device_handle) {
  1361. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1362. return GetControllerFromNpadIdType(npad_id);
  1363. }
  1364. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1365. const Core::HID::SixAxisSensorHandle& device_handle) const {
  1366. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1367. return GetControllerFromNpadIdType(npad_id);
  1368. }
  1369. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1370. const Core::HID::VibrationDeviceHandle& device_handle) {
  1371. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1372. return GetControllerFromNpadIdType(npad_id);
  1373. }
  1374. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1375. const Core::HID::VibrationDeviceHandle& device_handle) const {
  1376. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1377. return GetControllerFromNpadIdType(npad_id);
  1378. }
  1379. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1380. Core::HID::NpadIdType npad_id) {
  1381. if (!IsNpadIdValid(npad_id)) {
  1382. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1383. npad_id = Core::HID::NpadIdType::Player1;
  1384. }
  1385. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1386. return controller_data[npad_index];
  1387. }
  1388. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1389. Core::HID::NpadIdType npad_id) const {
  1390. if (!IsNpadIdValid(npad_id)) {
  1391. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1392. npad_id = Core::HID::NpadIdType::Player1;
  1393. }
  1394. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1395. return controller_data[npad_index];
  1396. }
  1397. } // namespace Service::HID