npad.cpp 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245
  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/kernel_helpers.h"
  20. namespace Service::HID {
  21. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  22. constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
  23. Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
  24. Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
  25. Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
  26. Core::HID::NpadIdType::Handheld,
  27. };
  28. bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
  29. switch (npad_id) {
  30. case Core::HID::NpadIdType::Player1:
  31. case Core::HID::NpadIdType::Player2:
  32. case Core::HID::NpadIdType::Player3:
  33. case Core::HID::NpadIdType::Player4:
  34. case Core::HID::NpadIdType::Player5:
  35. case Core::HID::NpadIdType::Player6:
  36. case Core::HID::NpadIdType::Player7:
  37. case Core::HID::NpadIdType::Player8:
  38. case Core::HID::NpadIdType::Other:
  39. case Core::HID::NpadIdType::Handheld:
  40. return true;
  41. default:
  42. LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
  43. return false;
  44. }
  45. }
  46. bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
  47. return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
  48. device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
  49. device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  50. }
  51. bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
  52. return IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id)) &&
  53. device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType &&
  54. device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  55. }
  56. Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
  57. KernelHelpers::ServiceContext& service_context_)
  58. : ControllerBase{hid_core_}, service_context{service_context_} {
  59. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  60. auto& controller = controller_data[i];
  61. controller.device = hid_core.GetEmulatedControllerByIndex(i);
  62. controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
  63. DEFAULT_VIBRATION_VALUE;
  64. controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
  65. DEFAULT_VIBRATION_VALUE;
  66. Core::HID::ControllerUpdateCallback engine_callback{
  67. .on_change = [this,
  68. i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
  69. .is_npad_service = true,
  70. };
  71. controller.callback_key = controller.device->SetCallback(engine_callback);
  72. }
  73. }
  74. Controller_NPad::~Controller_NPad() {
  75. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  76. auto& controller = controller_data[i];
  77. controller.device->DeleteCallback(controller.callback_key);
  78. }
  79. OnRelease();
  80. }
  81. void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
  82. std::size_t controller_idx) {
  83. if (type == Core::HID::ControllerTriggerType::All) {
  84. ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
  85. ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
  86. return;
  87. }
  88. if (controller_idx >= controller_data.size()) {
  89. return;
  90. }
  91. auto& controller = controller_data[controller_idx];
  92. const auto is_connected = controller.device->IsConnected();
  93. const auto npad_type = controller.device->GetNpadStyleIndex();
  94. const auto npad_id = controller.device->GetNpadIdType();
  95. switch (type) {
  96. case Core::HID::ControllerTriggerType::Connected:
  97. case Core::HID::ControllerTriggerType::Disconnected:
  98. if (is_connected == controller.is_connected) {
  99. return;
  100. }
  101. UpdateControllerAt(npad_type, npad_id, is_connected);
  102. break;
  103. case Core::HID::ControllerTriggerType::Battery: {
  104. if (!controller.is_connected) {
  105. return;
  106. }
  107. auto& shared_memory = controller.shared_memory_entry;
  108. const auto& battery_level = controller.device->GetBattery();
  109. shared_memory.battery_level_dual = battery_level.dual.battery_level;
  110. shared_memory.battery_level_left = battery_level.left.battery_level;
  111. shared_memory.battery_level_right = battery_level.right.battery_level;
  112. break;
  113. }
  114. default:
  115. break;
  116. }
  117. }
  118. void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
  119. LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
  120. auto& controller = GetControllerFromNpadIdType(npad_id);
  121. const auto controller_type = controller.device->GetNpadStyleIndex();
  122. auto& shared_memory = controller.shared_memory_entry;
  123. if (controller_type == Core::HID::NpadStyleIndex::None) {
  124. controller.styleset_changed_event->GetWritableEvent().Signal();
  125. return;
  126. }
  127. shared_memory.style_tag.raw = Core::HID::NpadStyleSet::None;
  128. shared_memory.device_type.raw = 0;
  129. shared_memory.system_properties.raw = 0;
  130. switch (controller_type) {
  131. case Core::HID::NpadStyleIndex::None:
  132. UNREACHABLE();
  133. break;
  134. case Core::HID::NpadStyleIndex::ProController:
  135. shared_memory.style_tag.fullkey.Assign(1);
  136. shared_memory.device_type.fullkey.Assign(1);
  137. shared_memory.system_properties.is_vertical.Assign(1);
  138. shared_memory.system_properties.use_plus.Assign(1);
  139. shared_memory.system_properties.use_minus.Assign(1);
  140. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  141. shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
  142. break;
  143. case Core::HID::NpadStyleIndex::Handheld:
  144. shared_memory.style_tag.handheld.Assign(1);
  145. shared_memory.device_type.handheld_left.Assign(1);
  146. shared_memory.device_type.handheld_right.Assign(1);
  147. shared_memory.system_properties.is_vertical.Assign(1);
  148. shared_memory.system_properties.use_plus.Assign(1);
  149. shared_memory.system_properties.use_minus.Assign(1);
  150. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  151. shared_memory.applet_footer.type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  152. break;
  153. case Core::HID::NpadStyleIndex::JoyconDual:
  154. shared_memory.style_tag.joycon_dual.Assign(1);
  155. shared_memory.device_type.joycon_left.Assign(1);
  156. shared_memory.device_type.joycon_right.Assign(1);
  157. shared_memory.system_properties.is_vertical.Assign(1);
  158. shared_memory.system_properties.use_plus.Assign(1);
  159. shared_memory.system_properties.use_minus.Assign(1);
  160. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  161. shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
  162. break;
  163. case Core::HID::NpadStyleIndex::JoyconLeft:
  164. shared_memory.style_tag.joycon_left.Assign(1);
  165. shared_memory.device_type.joycon_left.Assign(1);
  166. shared_memory.system_properties.is_horizontal.Assign(1);
  167. shared_memory.system_properties.use_minus.Assign(1);
  168. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  169. shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
  170. break;
  171. case Core::HID::NpadStyleIndex::JoyconRight:
  172. shared_memory.style_tag.joycon_right.Assign(1);
  173. shared_memory.device_type.joycon_right.Assign(1);
  174. shared_memory.system_properties.is_horizontal.Assign(1);
  175. shared_memory.system_properties.use_plus.Assign(1);
  176. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  177. shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
  178. break;
  179. case Core::HID::NpadStyleIndex::GameCube:
  180. shared_memory.style_tag.gamecube.Assign(1);
  181. shared_memory.device_type.fullkey.Assign(1);
  182. shared_memory.system_properties.is_vertical.Assign(1);
  183. shared_memory.system_properties.use_plus.Assign(1);
  184. break;
  185. case Core::HID::NpadStyleIndex::Pokeball:
  186. shared_memory.style_tag.palma.Assign(1);
  187. shared_memory.device_type.palma.Assign(1);
  188. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  189. break;
  190. case Core::HID::NpadStyleIndex::NES:
  191. shared_memory.style_tag.lark.Assign(1);
  192. shared_memory.device_type.fullkey.Assign(1);
  193. break;
  194. case Core::HID::NpadStyleIndex::SNES:
  195. shared_memory.style_tag.lucia.Assign(1);
  196. shared_memory.device_type.fullkey.Assign(1);
  197. shared_memory.applet_footer.type = AppletFooterUiType::Lucia;
  198. break;
  199. case Core::HID::NpadStyleIndex::N64:
  200. shared_memory.style_tag.lagoon.Assign(1);
  201. shared_memory.device_type.fullkey.Assign(1);
  202. shared_memory.applet_footer.type = AppletFooterUiType::Lagon;
  203. break;
  204. case Core::HID::NpadStyleIndex::SegaGenesis:
  205. shared_memory.style_tag.lager.Assign(1);
  206. shared_memory.device_type.fullkey.Assign(1);
  207. break;
  208. default:
  209. break;
  210. }
  211. const auto& body_colors = controller.device->GetColors();
  212. shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
  213. shared_memory.fullkey_color.fullkey = body_colors.fullkey;
  214. shared_memory.joycon_color.attribute = ColorAttribute::Ok;
  215. shared_memory.joycon_color.left = body_colors.left;
  216. shared_memory.joycon_color.right = body_colors.right;
  217. // TODO: Investigate when we should report all batery types
  218. const auto& battery_level = controller.device->GetBattery();
  219. shared_memory.battery_level_dual = battery_level.dual.battery_level;
  220. shared_memory.battery_level_left = battery_level.left.battery_level;
  221. shared_memory.battery_level_right = battery_level.right.battery_level;
  222. controller.is_connected = true;
  223. controller.device->Connect();
  224. SignalStyleSetChangedEvent(npad_id);
  225. WriteEmptyEntry(controller.shared_memory_entry);
  226. }
  227. void Controller_NPad::OnInit() {
  228. if (!IsControllerActivated()) {
  229. return;
  230. }
  231. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  232. auto& controller = controller_data[i];
  233. controller.styleset_changed_event =
  234. service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
  235. }
  236. if (hid_core.GetSupportedStyleTag().raw == Core::HID::NpadStyleSet::None) {
  237. // We want to support all controllers
  238. Core::HID::NpadStyleTag style{};
  239. style.handheld.Assign(1);
  240. style.joycon_left.Assign(1);
  241. style.joycon_right.Assign(1);
  242. style.joycon_dual.Assign(1);
  243. style.fullkey.Assign(1);
  244. style.gamecube.Assign(1);
  245. style.palma.Assign(1);
  246. hid_core.SetSupportedStyleTag(style);
  247. }
  248. supported_npad_id_types.resize(npad_id_list.size());
  249. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  250. npad_id_list.size() * sizeof(Core::HID::NpadIdType));
  251. // Prefill controller buffers
  252. for (auto& controller : controller_data) {
  253. auto& npad = controller.shared_memory_entry;
  254. npad.fullkey_color = {
  255. .attribute = ColorAttribute::NoController,
  256. .fullkey = {},
  257. };
  258. npad.joycon_color = {
  259. .attribute = ColorAttribute::NoController,
  260. .left = {},
  261. .right = {},
  262. };
  263. // HW seems to initialize the first 19 entries
  264. for (std::size_t i = 0; i < 19; ++i) {
  265. WriteEmptyEntry(npad);
  266. }
  267. }
  268. // Connect controllers
  269. for (auto& controller : controller_data) {
  270. const auto& device = controller.device;
  271. if (device->IsConnected()) {
  272. AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
  273. }
  274. }
  275. }
  276. void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
  277. NPadGenericState dummy_pad_state{};
  278. NpadGcTriggerState dummy_gc_state{};
  279. dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
  280. npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
  281. dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1;
  282. npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
  283. dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
  284. npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
  285. dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
  286. npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
  287. dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
  288. npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
  289. dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1;
  290. npad.palma_lifo.WriteNextEntry(dummy_pad_state);
  291. dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
  292. npad.system_ext_lifo.WriteNextEntry(dummy_pad_state);
  293. dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
  294. npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
  295. }
  296. void Controller_NPad::OnRelease() {
  297. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  298. auto& controller = controller_data[i];
  299. service_context.CloseEvent(controller.styleset_changed_event);
  300. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  301. VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
  302. }
  303. }
  304. }
  305. void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
  306. std::lock_guard lock{mutex};
  307. auto& controller = GetControllerFromNpadIdType(npad_id);
  308. const auto controller_type = controller.device->GetNpadStyleIndex();
  309. if (!controller.device->IsConnected()) {
  310. return;
  311. }
  312. auto& pad_entry = controller.npad_pad_state;
  313. auto& trigger_entry = controller.npad_trigger_state;
  314. const auto button_state = controller.device->GetNpadButtons();
  315. const auto stick_state = controller.device->GetSticks();
  316. using btn = Core::HID::NpadButton;
  317. pad_entry.npad_buttons.raw = btn::None;
  318. if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
  319. constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
  320. btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
  321. btn::StickRRight | btn::StickRDown;
  322. pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask;
  323. pad_entry.r_stick = stick_state.right;
  324. }
  325. if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
  326. constexpr btn left_button_mask =
  327. btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
  328. btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
  329. pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
  330. pad_entry.l_stick = stick_state.left;
  331. }
  332. if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
  333. pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
  334. pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
  335. }
  336. if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
  337. pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
  338. pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
  339. }
  340. if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
  341. const auto& trigger_state = controller.device->GetTriggers();
  342. trigger_entry.l_analog = trigger_state.left;
  343. trigger_entry.r_analog = trigger_state.right;
  344. pad_entry.npad_buttons.zl.Assign(false);
  345. pad_entry.npad_buttons.zr.Assign(button_state.r);
  346. pad_entry.npad_buttons.l.Assign(button_state.zl);
  347. pad_entry.npad_buttons.r.Assign(button_state.zr);
  348. }
  349. }
  350. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  351. std::size_t data_len) {
  352. if (!IsControllerActivated()) {
  353. return;
  354. }
  355. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  356. auto& controller = controller_data[i];
  357. auto& npad = controller.shared_memory_entry;
  358. const auto& controller_type = controller.device->GetNpadStyleIndex();
  359. if (controller_type == Core::HID::NpadStyleIndex::None ||
  360. !controller.device->IsConnected()) {
  361. // Refresh shared memory
  362. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  363. &controller.shared_memory_entry, sizeof(NpadInternalState));
  364. continue;
  365. }
  366. RequestPadStateUpdate(controller.device->GetNpadIdType());
  367. auto& pad_state = controller.npad_pad_state;
  368. auto& libnx_state = controller.npad_libnx_state;
  369. auto& trigger_state = controller.npad_trigger_state;
  370. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  371. // any controllers.
  372. libnx_state.connection_status.raw = 0;
  373. libnx_state.connection_status.is_connected.Assign(1);
  374. switch (controller_type) {
  375. case Core::HID::NpadStyleIndex::None:
  376. UNREACHABLE();
  377. break;
  378. case Core::HID::NpadStyleIndex::ProController:
  379. case Core::HID::NpadStyleIndex::NES:
  380. case Core::HID::NpadStyleIndex::SNES:
  381. case Core::HID::NpadStyleIndex::N64:
  382. case Core::HID::NpadStyleIndex::SegaGenesis:
  383. pad_state.connection_status.raw = 0;
  384. pad_state.connection_status.is_connected.Assign(1);
  385. pad_state.connection_status.is_wired.Assign(1);
  386. libnx_state.connection_status.is_wired.Assign(1);
  387. pad_state.sampling_number =
  388. npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  389. npad.fullkey_lifo.WriteNextEntry(pad_state);
  390. break;
  391. case Core::HID::NpadStyleIndex::Handheld:
  392. pad_state.connection_status.raw = 0;
  393. pad_state.connection_status.is_connected.Assign(1);
  394. pad_state.connection_status.is_wired.Assign(1);
  395. pad_state.connection_status.is_left_connected.Assign(1);
  396. pad_state.connection_status.is_right_connected.Assign(1);
  397. pad_state.connection_status.is_left_wired.Assign(1);
  398. pad_state.connection_status.is_right_wired.Assign(1);
  399. libnx_state.connection_status.is_wired.Assign(1);
  400. libnx_state.connection_status.is_left_connected.Assign(1);
  401. libnx_state.connection_status.is_right_connected.Assign(1);
  402. libnx_state.connection_status.is_left_wired.Assign(1);
  403. libnx_state.connection_status.is_right_wired.Assign(1);
  404. pad_state.sampling_number =
  405. npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  406. npad.handheld_lifo.WriteNextEntry(pad_state);
  407. break;
  408. case Core::HID::NpadStyleIndex::JoyconDual:
  409. pad_state.connection_status.raw = 0;
  410. pad_state.connection_status.is_connected.Assign(1);
  411. pad_state.connection_status.is_left_connected.Assign(1);
  412. pad_state.connection_status.is_right_connected.Assign(1);
  413. libnx_state.connection_status.is_left_connected.Assign(1);
  414. libnx_state.connection_status.is_right_connected.Assign(1);
  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<u32>(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. // Hanheld 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. }
  592. Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
  593. return hid_core.GetSupportedStyleTag();
  594. }
  595. void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
  596. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  597. supported_npad_id_types.clear();
  598. supported_npad_id_types.resize(length / sizeof(u32));
  599. std::memcpy(supported_npad_id_types.data(), data, length);
  600. }
  601. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  602. ASSERT(max_length < supported_npad_id_types.size());
  603. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  604. }
  605. std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
  606. return supported_npad_id_types.size();
  607. }
  608. void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
  609. hold_type = joy_hold_type;
  610. }
  611. Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
  612. return hold_type;
  613. }
  614. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  615. handheld_activation_mode = activation_mode;
  616. }
  617. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  618. return handheld_activation_mode;
  619. }
  620. void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
  621. communication_mode = communication_mode_;
  622. }
  623. Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
  624. return communication_mode;
  625. }
  626. void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
  627. NpadJoyAssignmentMode assignment_mode) {
  628. if (!IsNpadIdValid(npad_id)) {
  629. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  630. return;
  631. }
  632. auto& controller = GetControllerFromNpadIdType(npad_id);
  633. if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
  634. controller.shared_memory_entry.assignment_mode = assignment_mode;
  635. }
  636. }
  637. bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
  638. std::size_t device_index,
  639. const Core::HID::VibrationValue& vibration_value) {
  640. auto& controller = GetControllerFromNpadIdType(npad_id);
  641. if (!controller.device->IsConnected()) {
  642. return false;
  643. }
  644. if (!controller.device->IsVibrationEnabled()) {
  645. if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
  646. controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
  647. // Send an empty vibration to stop any vibrations.
  648. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
  649. controller.device->SetVibration(device_index, vibration);
  650. // Then reset the vibration value to its default value.
  651. controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
  652. }
  653. return false;
  654. }
  655. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  656. using std::chrono::duration_cast;
  657. using std::chrono::milliseconds;
  658. using std::chrono::steady_clock;
  659. const auto now = steady_clock::now();
  660. // Filter out non-zero vibrations that are within 10ms of each other.
  661. if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
  662. duration_cast<milliseconds>(
  663. now - controller.vibration[device_index].last_vibration_timepoint) <
  664. milliseconds(10)) {
  665. return false;
  666. }
  667. controller.vibration[device_index].last_vibration_timepoint = now;
  668. }
  669. Core::HID::VibrationValue vibration{
  670. vibration_value.low_amplitude, vibration_value.low_frequency,
  671. vibration_value.high_amplitude, vibration_value.high_frequency};
  672. return controller.device->SetVibration(device_index, vibration);
  673. }
  674. void Controller_NPad::VibrateController(
  675. const Core::HID::VibrationDeviceHandle& vibration_device_handle,
  676. const Core::HID::VibrationValue& vibration_value) {
  677. if (!IsDeviceHandleValid(vibration_device_handle)) {
  678. return;
  679. }
  680. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  681. return;
  682. }
  683. auto& controller = GetControllerFromHandle(vibration_device_handle);
  684. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  685. if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
  686. return;
  687. }
  688. if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
  689. UNREACHABLE_MSG("DeviceIndex should never be None!");
  690. return;
  691. }
  692. // Some games try to send mismatched parameters in the device handle, block these.
  693. if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  694. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
  695. vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
  696. (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
  697. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
  698. vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
  699. return;
  700. }
  701. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  702. if (vibration_value.low_amplitude ==
  703. controller.vibration[device_index].latest_vibration_value.low_amplitude &&
  704. vibration_value.high_amplitude ==
  705. controller.vibration[device_index].latest_vibration_value.high_amplitude) {
  706. return;
  707. }
  708. if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
  709. vibration_value)) {
  710. controller.vibration[device_index].latest_vibration_value = vibration_value;
  711. }
  712. }
  713. void Controller_NPad::VibrateControllers(
  714. const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
  715. const std::vector<Core::HID::VibrationValue>& vibration_values) {
  716. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  717. return;
  718. }
  719. ASSERT_OR_EXECUTE_MSG(
  720. vibration_device_handles.size() == vibration_values.size(), { return; },
  721. "The amount of device handles does not match with the amount of vibration values,"
  722. "this is undefined behavior!");
  723. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  724. VibrateController(vibration_device_handles[i], vibration_values[i]);
  725. }
  726. }
  727. Core::HID::VibrationValue Controller_NPad::GetLastVibration(
  728. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  729. if (!IsDeviceHandleValid(vibration_device_handle)) {
  730. return {};
  731. }
  732. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  733. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  734. return controller.vibration[device_index].latest_vibration_value;
  735. }
  736. void Controller_NPad::InitializeVibrationDevice(
  737. const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
  738. if (!IsDeviceHandleValid(vibration_device_handle)) {
  739. return;
  740. }
  741. const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
  742. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  743. InitializeVibrationDeviceAtIndex(npad_index, device_index);
  744. }
  745. void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
  746. std::size_t device_index) {
  747. auto& controller = GetControllerFromNpadIdType(npad_id);
  748. if (!Settings::values.vibration_enabled.GetValue()) {
  749. controller.vibration[device_index].device_mounted = false;
  750. return;
  751. }
  752. controller.vibration[device_index].device_mounted =
  753. controller.device->TestVibration(device_index);
  754. }
  755. void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  756. permit_vibration_session_enabled = permit_vibration_session;
  757. }
  758. bool Controller_NPad::IsVibrationDeviceMounted(
  759. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  760. if (!IsDeviceHandleValid(vibration_device_handle)) {
  761. return false;
  762. }
  763. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  764. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  765. return controller.vibration[device_index].device_mounted;
  766. }
  767. Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
  768. if (!IsNpadIdValid(npad_id)) {
  769. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  770. // Fallback to player 1
  771. const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
  772. return controller.styleset_changed_event->GetReadableEvent();
  773. }
  774. const auto& controller = GetControllerFromNpadIdType(npad_id);
  775. return controller.styleset_changed_event->GetReadableEvent();
  776. }
  777. void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
  778. const auto& controller = GetControllerFromNpadIdType(npad_id);
  779. controller.styleset_changed_event->GetWritableEvent().Signal();
  780. }
  781. void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
  782. Core::HID::NpadIdType npad_id) {
  783. UpdateControllerAt(controller, npad_id, true);
  784. }
  785. void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
  786. Core::HID::NpadIdType npad_id, bool connected) {
  787. auto& controller = GetControllerFromNpadIdType(npad_id);
  788. if (!connected) {
  789. DisconnectNpad(npad_id);
  790. return;
  791. }
  792. controller.device->SetNpadStyleIndex(type);
  793. InitNewlyAddedController(npad_id);
  794. }
  795. void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
  796. if (!IsNpadIdValid(npad_id)) {
  797. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  798. return;
  799. }
  800. LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
  801. auto& controller = GetControllerFromNpadIdType(npad_id);
  802. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  803. // Send an empty vibration to stop any vibrations.
  804. VibrateControllerAtIndex(npad_id, device_idx, {});
  805. controller.vibration[device_idx].device_mounted = false;
  806. }
  807. auto& shared_memory_entry = controller.shared_memory_entry;
  808. shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
  809. shared_memory_entry.device_type.raw = 0;
  810. shared_memory_entry.system_properties.raw = 0;
  811. shared_memory_entry.button_properties.raw = 0;
  812. shared_memory_entry.battery_level_dual = 0;
  813. shared_memory_entry.battery_level_left = 0;
  814. shared_memory_entry.battery_level_right = 0;
  815. shared_memory_entry.fullkey_color = {
  816. .attribute = ColorAttribute::NoController,
  817. .fullkey = {},
  818. };
  819. shared_memory_entry.joycon_color = {
  820. .attribute = ColorAttribute::NoController,
  821. .left = {},
  822. .right = {},
  823. };
  824. shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
  825. shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
  826. controller.is_connected = false;
  827. controller.device->Disconnect();
  828. SignalStyleSetChangedEvent(npad_id);
  829. WriteEmptyEntry(controller.shared_memory_entry);
  830. }
  831. void Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
  832. GyroscopeZeroDriftMode drift_mode) {
  833. if (!IsDeviceHandleValid(sixaxis_handle)) {
  834. LOG_ERROR(Service_HID, "Invalid handle");
  835. return;
  836. }
  837. auto& controller = GetControllerFromHandle(sixaxis_handle);
  838. controller.gyroscope_zero_drift_mode = drift_mode;
  839. }
  840. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode(
  841. Core::HID::SixAxisSensorHandle sixaxis_handle) const {
  842. if (!IsDeviceHandleValid(sixaxis_handle)) {
  843. LOG_ERROR(Service_HID, "Invalid handle");
  844. // Return the default value
  845. return GyroscopeZeroDriftMode::Standard;
  846. }
  847. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  848. return controller.gyroscope_zero_drift_mode;
  849. }
  850. bool Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle) const {
  851. if (!IsDeviceHandleValid(sixaxis_handle)) {
  852. LOG_ERROR(Service_HID, "Invalid handle");
  853. // Return the default value
  854. return true;
  855. }
  856. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  857. return controller.sixaxis_at_rest;
  858. }
  859. void Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
  860. bool sixaxis_status) {
  861. if (!IsDeviceHandleValid(sixaxis_handle)) {
  862. LOG_ERROR(Service_HID, "Invalid handle");
  863. return;
  864. }
  865. auto& controller = GetControllerFromHandle(sixaxis_handle);
  866. controller.sixaxis_sensor_enabled = sixaxis_status;
  867. }
  868. void Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
  869. bool sixaxis_fusion_status) {
  870. if (!IsDeviceHandleValid(sixaxis_handle)) {
  871. LOG_ERROR(Service_HID, "Invalid handle");
  872. return;
  873. }
  874. auto& controller = GetControllerFromHandle(sixaxis_handle);
  875. controller.sixaxis_fusion_enabled = sixaxis_fusion_status;
  876. }
  877. void Controller_NPad::SetSixAxisFusionParameters(
  878. Core::HID::SixAxisSensorHandle sixaxis_handle,
  879. Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
  880. if (!IsDeviceHandleValid(sixaxis_handle)) {
  881. LOG_ERROR(Service_HID, "Invalid handle");
  882. return;
  883. }
  884. auto& controller = GetControllerFromHandle(sixaxis_handle);
  885. controller.sixaxis_fusion = sixaxis_fusion_parameters;
  886. }
  887. Core::HID::SixAxisSensorFusionParameters Controller_NPad::GetSixAxisFusionParameters(
  888. Core::HID::SixAxisSensorHandle sixaxis_handle) {
  889. if (!IsDeviceHandleValid(sixaxis_handle)) {
  890. LOG_ERROR(Service_HID, "Invalid handle");
  891. // Since these parameters are unknow just return zeros
  892. return {};
  893. }
  894. auto& controller = GetControllerFromHandle(sixaxis_handle);
  895. return controller.sixaxis_fusion;
  896. }
  897. void Controller_NPad::ResetSixAxisFusionParameters(Core::HID::SixAxisSensorHandle sixaxis_handle) {
  898. if (!IsDeviceHandleValid(sixaxis_handle)) {
  899. LOG_ERROR(Service_HID, "Invalid handle");
  900. return;
  901. }
  902. auto& controller = GetControllerFromHandle(sixaxis_handle);
  903. // Since these parameters are unknow just fill with zeros
  904. controller.sixaxis_fusion = {};
  905. }
  906. void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
  907. Core::HID::NpadIdType npad_id_2) {
  908. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  909. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  910. npad_id_2);
  911. return;
  912. }
  913. auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
  914. auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
  915. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  916. // Otherwise, do nothing.
  917. if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  918. controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) ||
  919. (controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  920. controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
  921. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  922. DisconnectNpad(npad_id_2);
  923. AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
  924. }
  925. }
  926. void Controller_NPad::StartLRAssignmentMode() {
  927. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  928. // controller types from boot, it doesn't really matter about showing a selection screen
  929. is_in_lr_assignment_mode = true;
  930. }
  931. void Controller_NPad::StopLRAssignmentMode() {
  932. is_in_lr_assignment_mode = false;
  933. }
  934. bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
  935. Core::HID::NpadIdType npad_id_2) {
  936. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  937. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  938. npad_id_2);
  939. return false;
  940. }
  941. if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
  942. npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
  943. npad_id_2 == Core::HID::NpadIdType::Other) {
  944. return true;
  945. }
  946. const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
  947. const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
  948. const auto type_index_1 = controller_1->GetNpadStyleIndex();
  949. const auto type_index_2 = controller_2->GetNpadStyleIndex();
  950. if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) {
  951. return false;
  952. }
  953. AddNewControllerAt(type_index_2, npad_id_1);
  954. AddNewControllerAt(type_index_1, npad_id_2);
  955. return true;
  956. }
  957. Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
  958. if (!IsNpadIdValid(npad_id)) {
  959. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  960. return Core::HID::LedPattern{0, 0, 0, 0};
  961. }
  962. const auto& controller = GetControllerFromNpadIdType(npad_id).device;
  963. return controller->GetLedPattern();
  964. }
  965. bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
  966. Core::HID::NpadIdType npad_id) const {
  967. if (!IsNpadIdValid(npad_id)) {
  968. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  969. // Return the default value
  970. return false;
  971. }
  972. const auto& controller = GetControllerFromNpadIdType(npad_id);
  973. return controller.unintended_home_button_input_protection;
  974. }
  975. void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
  976. Core::HID::NpadIdType npad_id) {
  977. if (!IsNpadIdValid(npad_id)) {
  978. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  979. return;
  980. }
  981. auto& controller = GetControllerFromNpadIdType(npad_id);
  982. controller.unintended_home_button_input_protection = is_protection_enabled;
  983. }
  984. void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
  985. analog_stick_use_center_clamp = use_center_clamp;
  986. }
  987. void Controller_NPad::ClearAllConnectedControllers() {
  988. for (auto& controller : controller_data) {
  989. if (controller.device->IsConnected() &&
  990. controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
  991. controller.device->Disconnect();
  992. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  993. }
  994. }
  995. }
  996. void Controller_NPad::DisconnectAllConnectedControllers() {
  997. for (auto& controller : controller_data) {
  998. controller.device->Disconnect();
  999. }
  1000. }
  1001. void Controller_NPad::ConnectAllDisconnectedControllers() {
  1002. for (auto& controller : controller_data) {
  1003. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
  1004. !controller.device->IsConnected()) {
  1005. controller.device->Connect();
  1006. }
  1007. }
  1008. }
  1009. void Controller_NPad::ClearAllControllers() {
  1010. for (auto& controller : controller_data) {
  1011. controller.device->Disconnect();
  1012. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1013. }
  1014. }
  1015. u32 Controller_NPad::GetAndResetPressState() {
  1016. return press_state.exchange(0);
  1017. }
  1018. bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
  1019. if (controller == Core::HID::NpadStyleIndex::Handheld) {
  1020. const bool support_handheld =
  1021. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1022. Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
  1023. // Handheld is not even a supported type, lets stop here
  1024. if (!support_handheld) {
  1025. return false;
  1026. }
  1027. // Handheld shouldn't be supported in docked mode
  1028. if (Settings::values.use_docked_mode.GetValue()) {
  1029. return false;
  1030. }
  1031. return true;
  1032. }
  1033. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1034. [](Core::HID::NpadIdType npad_id) {
  1035. return npad_id <= Core::HID::NpadIdType::Player8;
  1036. })) {
  1037. Core::HID::NpadStyleTag style = GetSupportedStyleSet();
  1038. switch (controller) {
  1039. case Core::HID::NpadStyleIndex::ProController:
  1040. return style.fullkey;
  1041. case Core::HID::NpadStyleIndex::JoyconDual:
  1042. return style.joycon_dual;
  1043. case Core::HID::NpadStyleIndex::JoyconLeft:
  1044. return style.joycon_left;
  1045. case Core::HID::NpadStyleIndex::JoyconRight:
  1046. return style.joycon_right;
  1047. case Core::HID::NpadStyleIndex::GameCube:
  1048. return style.gamecube;
  1049. case Core::HID::NpadStyleIndex::Pokeball:
  1050. return style.palma;
  1051. case Core::HID::NpadStyleIndex::NES:
  1052. return style.lark;
  1053. case Core::HID::NpadStyleIndex::SNES:
  1054. return style.lucia;
  1055. case Core::HID::NpadStyleIndex::N64:
  1056. return style.lagoon;
  1057. case Core::HID::NpadStyleIndex::SegaGenesis:
  1058. return style.lager;
  1059. default:
  1060. return false;
  1061. }
  1062. }
  1063. return false;
  1064. }
  1065. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1066. const Core::HID::SixAxisSensorHandle& device_handle) {
  1067. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1068. return GetControllerFromNpadIdType(npad_id);
  1069. }
  1070. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1071. const Core::HID::SixAxisSensorHandle& device_handle) const {
  1072. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1073. return GetControllerFromNpadIdType(npad_id);
  1074. }
  1075. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1076. const Core::HID::VibrationDeviceHandle& device_handle) {
  1077. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1078. return GetControllerFromNpadIdType(npad_id);
  1079. }
  1080. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1081. const Core::HID::VibrationDeviceHandle& device_handle) const {
  1082. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1083. return GetControllerFromNpadIdType(npad_id);
  1084. }
  1085. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1086. Core::HID::NpadIdType npad_id) {
  1087. if (!IsNpadIdValid(npad_id)) {
  1088. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1089. npad_id = Core::HID::NpadIdType::Player1;
  1090. }
  1091. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1092. return controller_data[npad_index];
  1093. }
  1094. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1095. Core::HID::NpadIdType npad_id) const {
  1096. if (!IsNpadIdValid(npad_id)) {
  1097. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1098. npad_id = Core::HID::NpadIdType::Player1;
  1099. }
  1100. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1101. return controller_data[npad_index];
  1102. }
  1103. } // namespace Service::HID