npad.cpp 59 KB

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