npad.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084
  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.h"
  13. #include "core/core_timing.h"
  14. #include "core/hle/kernel/k_event.h"
  15. #include "core/hle/kernel/k_readable_event.h"
  16. #include "core/hle/kernel/k_writable_event.h"
  17. #include "core/hle/service/hid/controllers/npad.h"
  18. #include "core/hle/service/kernel_helpers.h"
  19. namespace Service::HID {
  20. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  21. constexpr u32 MAX_NPAD_ID = 7;
  22. constexpr std::size_t HANDHELD_INDEX = 8;
  23. constexpr std::array<u32, 10> npad_id_list{
  24. 0, 1, 2, 3, 4, 5, 6, 7, NPAD_HANDHELD, NPAD_UNKNOWN,
  25. };
  26. std::size_t Controller_NPad::NPadIdToIndex(u32 npad_id) {
  27. switch (npad_id) {
  28. case 0:
  29. case 1:
  30. case 2:
  31. case 3:
  32. case 4:
  33. case 5:
  34. case 6:
  35. case 7:
  36. return npad_id;
  37. case HANDHELD_INDEX:
  38. case NPAD_HANDHELD:
  39. return HANDHELD_INDEX;
  40. case 9:
  41. case NPAD_UNKNOWN:
  42. return 9;
  43. default:
  44. UNIMPLEMENTED_MSG("Unknown npad id {}", npad_id);
  45. return 0;
  46. }
  47. }
  48. u32 Controller_NPad::IndexToNPad(std::size_t index) {
  49. switch (index) {
  50. case 0:
  51. case 1:
  52. case 2:
  53. case 3:
  54. case 4:
  55. case 5:
  56. case 6:
  57. case 7:
  58. return static_cast<u32>(index);
  59. case HANDHELD_INDEX:
  60. return NPAD_HANDHELD;
  61. case 9:
  62. return NPAD_UNKNOWN;
  63. default:
  64. UNIMPLEMENTED_MSG("Unknown npad index {}", index);
  65. return 0;
  66. }
  67. }
  68. bool Controller_NPad::IsNpadIdValid(u32 npad_id) {
  69. switch (npad_id) {
  70. case 0:
  71. case 1:
  72. case 2:
  73. case 3:
  74. case 4:
  75. case 5:
  76. case 6:
  77. case 7:
  78. case NPAD_UNKNOWN:
  79. case NPAD_HANDHELD:
  80. return true;
  81. default:
  82. LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
  83. return false;
  84. }
  85. }
  86. bool Controller_NPad::IsDeviceHandleValid(const DeviceHandle& device_handle) {
  87. return IsNpadIdValid(device_handle.npad_id) &&
  88. device_handle.npad_type < Core::HID::NpadType::MaxNpadType &&
  89. device_handle.device_index < DeviceIndex::MaxDeviceIndex;
  90. }
  91. Controller_NPad::Controller_NPad(Core::System& system_,
  92. KernelHelpers::ServiceContext& service_context_)
  93. : ControllerBase{system_}, service_context{service_context_} {
  94. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  95. auto& controller = controller_data[i];
  96. controller.device = system.HIDCore().GetEmulatedControllerByIndex(i);
  97. controller.vibration[0].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
  98. controller.vibration[1].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
  99. Core::HID::ControllerUpdateCallback engine_callback{
  100. [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }};
  101. controller.callback_key = controller.device->SetCallback(engine_callback);
  102. }
  103. }
  104. Controller_NPad::~Controller_NPad() {
  105. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  106. auto& controller = controller_data[i];
  107. controller.device->DeleteCallback(controller.callback_key);
  108. }
  109. OnRelease();
  110. }
  111. void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
  112. std::size_t controller_idx) {
  113. if (type == Core::HID::ControllerTriggerType::All) {
  114. ControllerUpdate(Core::HID::ControllerTriggerType::Type, controller_idx);
  115. ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
  116. return;
  117. }
  118. auto& controller = controller_data[controller_idx];
  119. const auto is_connected = controller.device->IsConnected();
  120. const auto npad_type = controller.device->GetNpadType();
  121. switch (type) {
  122. case Core::HID::ControllerTriggerType::Connected:
  123. case Core::HID::ControllerTriggerType::Disconnected:
  124. if (is_connected == controller.is_connected) {
  125. return;
  126. }
  127. UpdateControllerAt(npad_type, controller_idx, is_connected);
  128. break;
  129. case Core::HID::ControllerTriggerType::Type: {
  130. if (npad_type == controller.npad_type) {
  131. return;
  132. }
  133. // UpdateControllerAt(npad_type, controller_idx, is_connected);
  134. break;
  135. }
  136. default:
  137. break;
  138. }
  139. }
  140. void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
  141. auto& controller = controller_data[controller_idx];
  142. LOG_ERROR(Service_HID, "Connect {} {}", controller_idx, controller.is_connected);
  143. const auto controller_type = controller.device->GetNpadType();
  144. auto& shared_memory = controller.shared_memory_entry;
  145. if (controller_type == Core::HID::NpadType::None) {
  146. controller.styleset_changed_event->GetWritableEvent().Signal();
  147. return;
  148. }
  149. shared_memory.style_set.raw = 0; // Zero out
  150. shared_memory.device_type.raw = 0;
  151. shared_memory.system_properties.raw = 0;
  152. switch (controller_type) {
  153. case Core::HID::NpadType::None:
  154. UNREACHABLE();
  155. break;
  156. case Core::HID::NpadType::ProController:
  157. shared_memory.style_set.fullkey.Assign(1);
  158. shared_memory.device_type.fullkey.Assign(1);
  159. shared_memory.system_properties.is_vertical.Assign(1);
  160. shared_memory.system_properties.use_plus.Assign(1);
  161. shared_memory.system_properties.use_minus.Assign(1);
  162. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  163. shared_memory.footer_type = AppletFooterUiType::SwitchProController;
  164. break;
  165. case Core::HID::NpadType::Handheld:
  166. shared_memory.style_set.handheld.Assign(1);
  167. shared_memory.device_type.handheld_left.Assign(1);
  168. shared_memory.device_type.handheld_right.Assign(1);
  169. shared_memory.system_properties.is_vertical.Assign(1);
  170. shared_memory.system_properties.use_plus.Assign(1);
  171. shared_memory.system_properties.use_minus.Assign(1);
  172. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  173. shared_memory.footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  174. break;
  175. case Core::HID::NpadType::JoyconDual:
  176. shared_memory.style_set.joycon_dual.Assign(1);
  177. shared_memory.device_type.joycon_left.Assign(1);
  178. shared_memory.device_type.joycon_right.Assign(1);
  179. shared_memory.system_properties.is_vertical.Assign(1);
  180. shared_memory.system_properties.use_plus.Assign(1);
  181. shared_memory.system_properties.use_minus.Assign(1);
  182. shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
  183. shared_memory.footer_type = AppletFooterUiType::JoyDual;
  184. break;
  185. case Core::HID::NpadType::JoyconLeft:
  186. shared_memory.style_set.joycon_left.Assign(1);
  187. shared_memory.device_type.joycon_left.Assign(1);
  188. shared_memory.system_properties.is_horizontal.Assign(1);
  189. shared_memory.system_properties.use_minus.Assign(1);
  190. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  191. shared_memory.footer_type = AppletFooterUiType::JoyLeftHorizontal;
  192. break;
  193. case Core::HID::NpadType::JoyconRight:
  194. shared_memory.style_set.joycon_right.Assign(1);
  195. shared_memory.device_type.joycon_right.Assign(1);
  196. shared_memory.system_properties.is_horizontal.Assign(1);
  197. shared_memory.system_properties.use_plus.Assign(1);
  198. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  199. shared_memory.footer_type = AppletFooterUiType::JoyRightHorizontal;
  200. break;
  201. case Core::HID::NpadType::GameCube:
  202. shared_memory.style_set.gamecube.Assign(1);
  203. // The GC Controller behaves like a wired Pro Controller
  204. shared_memory.device_type.fullkey.Assign(1);
  205. shared_memory.system_properties.is_vertical.Assign(1);
  206. shared_memory.system_properties.use_plus.Assign(1);
  207. break;
  208. case Core::HID::NpadType::Pokeball:
  209. shared_memory.style_set.palma.Assign(1);
  210. shared_memory.device_type.palma.Assign(1);
  211. shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
  212. break;
  213. default:
  214. break;
  215. }
  216. const auto& body_colors = controller.device->GetColors();
  217. shared_memory.fullkey_color.attribute = ColorAttribute::Ok;
  218. shared_memory.fullkey_color.fullkey = body_colors.fullkey;
  219. shared_memory.joycon_color.attribute = ColorAttribute::Ok;
  220. shared_memory.joycon_color.left = body_colors.left;
  221. shared_memory.joycon_color.right = body_colors.right;
  222. // TODO: Investigate when we should report all batery types
  223. const auto& battery_level = controller.device->GetBattery();
  224. shared_memory.battery_level_dual = battery_level.dual.battery_level;
  225. shared_memory.battery_level_left = battery_level.left.battery_level;
  226. shared_memory.battery_level_right = battery_level.right.battery_level;
  227. controller.is_connected = true;
  228. controller.device->Connect();
  229. SignalStyleSetChangedEvent(IndexToNPad(controller_idx));
  230. WriteEmptyEntry(controller.shared_memory_entry);
  231. }
  232. void Controller_NPad::OnInit() {
  233. if (!IsControllerActivated()) {
  234. return;
  235. }
  236. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  237. auto& controller = controller_data[i];
  238. controller.styleset_changed_event =
  239. service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
  240. }
  241. if (system.HIDCore().GetSupportedStyleTag().raw == 0) {
  242. // We want to support all controllers
  243. Core::HID::NpadStyleTag style{};
  244. style.handheld.Assign(1);
  245. style.joycon_left.Assign(1);
  246. style.joycon_right.Assign(1);
  247. style.joycon_dual.Assign(1);
  248. style.fullkey.Assign(1);
  249. style.gamecube.Assign(1);
  250. style.palma.Assign(1);
  251. system.HIDCore().SetSupportedStyleTag(style);
  252. }
  253. supported_npad_id_types.resize(npad_id_list.size());
  254. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  255. npad_id_list.size() * sizeof(u32));
  256. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  257. auto& controller = controller_data[i].device;
  258. if (controller->IsConnected()) {
  259. AddNewControllerAt(controller->GetNpadType(), i);
  260. }
  261. }
  262. // Prefill controller buffers
  263. for (auto& controller : controller_data) {
  264. NPadGenericState dummy_pad_state{};
  265. auto& npad = controller.shared_memory_entry;
  266. for (std::size_t i = 0; i < 19; ++i) {
  267. WriteEmptyEntry(npad);
  268. }
  269. }
  270. }
  271. void Controller_NPad::WriteEmptyEntry(NpadInternalState& npad) {
  272. NPadGenericState dummy_pad_state{};
  273. NpadGcTriggerState dummy_gc_state{};
  274. dummy_pad_state.sampling_number = npad.fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
  275. npad.fullkey_lifo.WriteNextEntry(dummy_pad_state);
  276. dummy_pad_state.sampling_number = npad.handheld_lifo.ReadCurrentEntry().sampling_number + 1;
  277. npad.handheld_lifo.WriteNextEntry(dummy_pad_state);
  278. dummy_pad_state.sampling_number = npad.joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
  279. npad.joy_dual_lifo.WriteNextEntry(dummy_pad_state);
  280. dummy_pad_state.sampling_number = npad.joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
  281. npad.joy_left_lifo.WriteNextEntry(dummy_pad_state);
  282. dummy_pad_state.sampling_number = npad.joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
  283. npad.joy_right_lifo.WriteNextEntry(dummy_pad_state);
  284. dummy_pad_state.sampling_number = npad.palma_lifo.ReadCurrentEntry().sampling_number + 1;
  285. npad.palma_lifo.WriteNextEntry(dummy_pad_state);
  286. dummy_pad_state.sampling_number = npad.system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
  287. npad.system_ext_lifo.WriteNextEntry(dummy_pad_state);
  288. dummy_gc_state.sampling_number = npad.gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
  289. npad.gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
  290. }
  291. void Controller_NPad::OnRelease() {
  292. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  293. auto& controller = controller_data[i];
  294. service_context.CloseEvent(controller.styleset_changed_event);
  295. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  296. VibrateControllerAtIndex(i, device_idx, {});
  297. }
  298. }
  299. }
  300. void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
  301. std::lock_guard lock{mutex};
  302. const auto controller_idx = NPadIdToIndex(npad_id);
  303. auto& controller = controller_data[controller_idx];
  304. const auto controller_type = controller.device->GetNpadType();
  305. if (!controller.device->IsConnected()) {
  306. return;
  307. }
  308. auto& pad_entry = controller.npad_pad_state;
  309. auto& trigger_entry = controller.npad_trigger_state;
  310. const auto button_state = controller.device->GetNpadButtons();
  311. const auto stick_state = controller.device->GetSticks();
  312. using btn = Core::HID::NpadButton;
  313. pad_entry.npad_buttons.raw = btn::None;
  314. if (controller_type != Core::HID::NpadType::JoyconLeft) {
  315. constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
  316. btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
  317. btn::StickRRight | btn::StickRDown;
  318. pad_entry.npad_buttons.raw |= button_state.raw & right_button_mask;
  319. pad_entry.r_stick = stick_state.right;
  320. }
  321. if (controller_type != Core::HID::NpadType::JoyconRight) {
  322. constexpr btn left_button_mask =
  323. btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
  324. btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
  325. pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
  326. pad_entry.l_stick = stick_state.left;
  327. }
  328. if (controller_type == Core::HID::NpadType::JoyconLeft) {
  329. pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
  330. pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
  331. }
  332. if (controller_type == Core::HID::NpadType::JoyconRight) {
  333. pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
  334. pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
  335. }
  336. if (controller_type == Core::HID::NpadType::GameCube) {
  337. const auto& trigger_state = controller.device->GetTriggers();
  338. trigger_entry.l_analog = trigger_state.left;
  339. trigger_entry.r_analog = trigger_state.right;
  340. pad_entry.npad_buttons.zl.Assign(false);
  341. pad_entry.npad_buttons.zr.Assign(button_state.r);
  342. pad_entry.npad_buttons.l.Assign(button_state.zl);
  343. pad_entry.npad_buttons.r.Assign(button_state.zr);
  344. }
  345. }
  346. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  347. std::size_t data_len) {
  348. if (!IsControllerActivated()) {
  349. return;
  350. }
  351. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  352. auto& controller = controller_data[i];
  353. auto& npad = controller.shared_memory_entry;
  354. const auto& controller_type = controller.device->GetNpadType();
  355. if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
  356. // Refresh shared memory
  357. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  358. &controller.shared_memory_entry, sizeof(NpadInternalState));
  359. continue;
  360. }
  361. const u32 npad_index = static_cast<u32>(i);
  362. RequestPadStateUpdate(npad_index);
  363. auto& pad_state = controller.npad_pad_state;
  364. auto& libnx_state = controller.npad_libnx_state;
  365. auto& trigger_state = controller.npad_trigger_state;
  366. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  367. // any controllers.
  368. libnx_state.connection_status.raw = 0;
  369. libnx_state.connection_status.is_connected.Assign(1);
  370. switch (controller_type) {
  371. case Core::HID::NpadType::None:
  372. UNREACHABLE();
  373. break;
  374. case Core::HID::NpadType::ProController:
  375. pad_state.connection_status.raw = 0;
  376. pad_state.connection_status.is_connected.Assign(1);
  377. pad_state.connection_status.is_wired.Assign(1);
  378. libnx_state.connection_status.is_wired.Assign(1);
  379. pad_state.sampling_number =
  380. npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  381. npad.fullkey_lifo.WriteNextEntry(pad_state);
  382. break;
  383. case Core::HID::NpadType::Handheld:
  384. pad_state.connection_status.raw = 0;
  385. pad_state.connection_status.is_connected.Assign(1);
  386. pad_state.connection_status.is_wired.Assign(1);
  387. pad_state.connection_status.is_left_connected.Assign(1);
  388. pad_state.connection_status.is_right_connected.Assign(1);
  389. pad_state.connection_status.is_left_wired.Assign(1);
  390. pad_state.connection_status.is_right_wired.Assign(1);
  391. libnx_state.connection_status.is_wired.Assign(1);
  392. libnx_state.connection_status.is_left_connected.Assign(1);
  393. libnx_state.connection_status.is_right_connected.Assign(1);
  394. libnx_state.connection_status.is_left_wired.Assign(1);
  395. libnx_state.connection_status.is_right_wired.Assign(1);
  396. pad_state.sampling_number =
  397. npad.handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  398. npad.handheld_lifo.WriteNextEntry(pad_state);
  399. break;
  400. case Core::HID::NpadType::JoyconDual:
  401. pad_state.connection_status.raw = 0;
  402. pad_state.connection_status.is_connected.Assign(1);
  403. pad_state.connection_status.is_left_connected.Assign(1);
  404. pad_state.connection_status.is_right_connected.Assign(1);
  405. libnx_state.connection_status.is_left_connected.Assign(1);
  406. libnx_state.connection_status.is_right_connected.Assign(1);
  407. pad_state.sampling_number =
  408. npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
  409. npad.joy_dual_lifo.WriteNextEntry(pad_state);
  410. break;
  411. case Core::HID::NpadType::JoyconLeft:
  412. pad_state.connection_status.raw = 0;
  413. pad_state.connection_status.is_connected.Assign(1);
  414. pad_state.connection_status.is_left_connected.Assign(1);
  415. libnx_state.connection_status.is_left_connected.Assign(1);
  416. pad_state.sampling_number =
  417. npad.joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  418. npad.joy_left_lifo.WriteNextEntry(pad_state);
  419. break;
  420. case Core::HID::NpadType::JoyconRight:
  421. pad_state.connection_status.raw = 0;
  422. pad_state.connection_status.is_connected.Assign(1);
  423. pad_state.connection_status.is_right_connected.Assign(1);
  424. libnx_state.connection_status.is_right_connected.Assign(1);
  425. pad_state.sampling_number =
  426. npad.joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  427. npad.joy_right_lifo.WriteNextEntry(pad_state);
  428. break;
  429. case Core::HID::NpadType::GameCube:
  430. pad_state.connection_status.raw = 0;
  431. pad_state.connection_status.is_connected.Assign(1);
  432. pad_state.connection_status.is_wired.Assign(1);
  433. libnx_state.connection_status.is_wired.Assign(1);
  434. pad_state.sampling_number =
  435. npad.fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  436. trigger_state.sampling_number =
  437. npad.gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
  438. npad.fullkey_lifo.WriteNextEntry(pad_state);
  439. npad.gc_trigger_lifo.WriteNextEntry(trigger_state);
  440. break;
  441. case Core::HID::NpadType::Pokeball:
  442. pad_state.connection_status.raw = 0;
  443. pad_state.connection_status.is_connected.Assign(1);
  444. pad_state.sampling_number =
  445. npad.palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
  446. npad.palma_lifo.WriteNextEntry(pad_state);
  447. break;
  448. default:
  449. break;
  450. }
  451. libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
  452. libnx_state.l_stick = pad_state.l_stick;
  453. libnx_state.r_stick = pad_state.r_stick;
  454. npad.system_ext_lifo.WriteNextEntry(pad_state);
  455. press_state |= static_cast<u32>(pad_state.npad_buttons.raw);
  456. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  457. &controller.shared_memory_entry, sizeof(NpadInternalState));
  458. }
  459. }
  460. void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing, u8* data,
  461. std::size_t data_len) {
  462. if (!IsControllerActivated()) {
  463. return;
  464. }
  465. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  466. auto& controller = controller_data[i];
  467. const auto& controller_type = controller.device->GetNpadType();
  468. if (controller_type == Core::HID::NpadType::None || !controller.device->IsConnected()) {
  469. continue;
  470. }
  471. auto& npad = controller.shared_memory_entry;
  472. const auto& motion_state = controller.device->GetMotions();
  473. auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
  474. auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
  475. auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
  476. auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
  477. auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
  478. auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
  479. if (sixaxis_sensors_enabled && Settings::values.motion_enabled.GetValue()) {
  480. sixaxis_at_rest = true;
  481. for (std::size_t e = 0; e < motion_state.size(); ++e) {
  482. sixaxis_at_rest = sixaxis_at_rest && motion_state[e].is_at_rest;
  483. }
  484. }
  485. switch (controller_type) {
  486. case Core::HID::NpadType::None:
  487. UNREACHABLE();
  488. break;
  489. case Core::HID::NpadType::ProController:
  490. sixaxis_fullkey_state.attribute.raw = 0;
  491. if (sixaxis_sensors_enabled) {
  492. sixaxis_fullkey_state.attribute.is_connected.Assign(1);
  493. sixaxis_fullkey_state.accel = motion_state[0].accel;
  494. sixaxis_fullkey_state.gyro = motion_state[0].gyro;
  495. sixaxis_fullkey_state.rotation = motion_state[0].rotation;
  496. sixaxis_fullkey_state.orientation = motion_state[0].orientation;
  497. }
  498. break;
  499. case Core::HID::NpadType::Handheld:
  500. sixaxis_handheld_state.attribute.raw = 0;
  501. if (sixaxis_sensors_enabled) {
  502. sixaxis_handheld_state.attribute.is_connected.Assign(1);
  503. sixaxis_handheld_state.accel = motion_state[0].accel;
  504. sixaxis_handheld_state.gyro = motion_state[0].gyro;
  505. sixaxis_handheld_state.rotation = motion_state[0].rotation;
  506. sixaxis_handheld_state.orientation = motion_state[0].orientation;
  507. }
  508. break;
  509. case Core::HID::NpadType::JoyconDual:
  510. sixaxis_dual_left_state.attribute.raw = 0;
  511. sixaxis_dual_right_state.attribute.raw = 0;
  512. if (sixaxis_sensors_enabled) {
  513. // Set motion for the left joycon
  514. sixaxis_dual_left_state.attribute.is_connected.Assign(1);
  515. sixaxis_dual_left_state.accel = motion_state[0].accel;
  516. sixaxis_dual_left_state.gyro = motion_state[0].gyro;
  517. sixaxis_dual_left_state.rotation = motion_state[0].rotation;
  518. sixaxis_dual_left_state.orientation = motion_state[0].orientation;
  519. }
  520. if (sixaxis_sensors_enabled) {
  521. // Set motion for the right joycon
  522. sixaxis_dual_right_state.attribute.is_connected.Assign(1);
  523. sixaxis_dual_right_state.accel = motion_state[1].accel;
  524. sixaxis_dual_right_state.gyro = motion_state[1].gyro;
  525. sixaxis_dual_right_state.rotation = motion_state[1].rotation;
  526. sixaxis_dual_right_state.orientation = motion_state[1].orientation;
  527. }
  528. break;
  529. case Core::HID::NpadType::JoyconLeft:
  530. sixaxis_left_lifo_state.attribute.raw = 0;
  531. if (sixaxis_sensors_enabled) {
  532. sixaxis_left_lifo_state.attribute.is_connected.Assign(1);
  533. sixaxis_left_lifo_state.accel = motion_state[0].accel;
  534. sixaxis_left_lifo_state.gyro = motion_state[0].gyro;
  535. sixaxis_left_lifo_state.rotation = motion_state[0].rotation;
  536. sixaxis_left_lifo_state.orientation = motion_state[0].orientation;
  537. }
  538. break;
  539. case Core::HID::NpadType::JoyconRight:
  540. sixaxis_right_lifo_state.attribute.raw = 0;
  541. if (sixaxis_sensors_enabled) {
  542. sixaxis_right_lifo_state.attribute.is_connected.Assign(1);
  543. sixaxis_right_lifo_state.accel = motion_state[1].accel;
  544. sixaxis_right_lifo_state.gyro = motion_state[1].gyro;
  545. sixaxis_right_lifo_state.rotation = motion_state[1].rotation;
  546. sixaxis_right_lifo_state.orientation = motion_state[1].orientation;
  547. }
  548. break;
  549. default:
  550. break;
  551. }
  552. sixaxis_fullkey_state.sampling_number =
  553. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  554. sixaxis_handheld_state.sampling_number =
  555. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  556. sixaxis_dual_left_state.sampling_number =
  557. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  558. sixaxis_dual_right_state.sampling_number =
  559. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  560. sixaxis_left_lifo_state.sampling_number =
  561. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  562. sixaxis_right_lifo_state.sampling_number =
  563. npad.sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  564. npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
  565. npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
  566. npad.sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
  567. npad.sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
  568. npad.sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
  569. npad.sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
  570. std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
  571. &controller.shared_memory_entry, sizeof(NpadInternalState));
  572. }
  573. }
  574. void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
  575. system.HIDCore().SetSupportedStyleTag(style_set);
  576. }
  577. Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
  578. return system.HIDCore().GetSupportedStyleTag();
  579. }
  580. void Controller_NPad::SetSupportedNpadIdTypes(u8* data, std::size_t length) {
  581. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  582. supported_npad_id_types.clear();
  583. supported_npad_id_types.resize(length / sizeof(u32));
  584. std::memcpy(supported_npad_id_types.data(), data, length);
  585. }
  586. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  587. ASSERT(max_length < supported_npad_id_types.size());
  588. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  589. }
  590. std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
  591. return supported_npad_id_types.size();
  592. }
  593. void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
  594. hold_type = joy_hold_type;
  595. }
  596. Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
  597. return hold_type;
  598. }
  599. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  600. handheld_activation_mode = activation_mode;
  601. }
  602. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  603. return handheld_activation_mode;
  604. }
  605. void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
  606. communication_mode = communication_mode_;
  607. }
  608. Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
  609. return communication_mode;
  610. }
  611. void Controller_NPad::SetNpadMode(u32 npad_id, NpadJoyAssignmentMode assignment_mode) {
  612. const std::size_t npad_index = NPadIdToIndex(npad_id);
  613. ASSERT(npad_index < controller_data.size());
  614. auto& controller = controller_data[npad_index];
  615. if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
  616. controller.shared_memory_entry.assignment_mode = assignment_mode;
  617. }
  618. }
  619. bool Controller_NPad::VibrateControllerAtIndex(std::size_t npad_index, std::size_t device_index,
  620. const VibrationValue& vibration_value) {
  621. auto& controller = controller_data[npad_index];
  622. if (!controller.device->IsConnected()) {
  623. return false;
  624. }
  625. if (!controller.device->IsVibrationEnabled()) {
  626. if (controller.vibration[device_index].latest_vibration_value.amp_low != 0.0f ||
  627. controller.vibration[device_index].latest_vibration_value.amp_high != 0.0f) {
  628. // Send an empty vibration to stop any vibrations.
  629. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
  630. controller.device->SetVibration(device_index, vibration);
  631. // Then reset the vibration value to its default value.
  632. controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE;
  633. }
  634. return false;
  635. }
  636. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  637. using std::chrono::duration_cast;
  638. using std::chrono::milliseconds;
  639. using std::chrono::steady_clock;
  640. const auto now = steady_clock::now();
  641. // Filter out non-zero vibrations that are within 10ms of each other.
  642. if ((vibration_value.amp_low != 0.0f || vibration_value.amp_high != 0.0f) &&
  643. duration_cast<milliseconds>(
  644. now - controller.vibration[device_index].last_vibration_timepoint) <
  645. milliseconds(10)) {
  646. return false;
  647. }
  648. controller.vibration[device_index].last_vibration_timepoint = now;
  649. }
  650. Core::HID::VibrationValue vibration{vibration_value.amp_low, vibration_value.freq_low,
  651. vibration_value.amp_high, vibration_value.freq_high};
  652. return controller.device->SetVibration(device_index, vibration);
  653. }
  654. void Controller_NPad::VibrateController(const DeviceHandle& vibration_device_handle,
  655. const VibrationValue& vibration_value) {
  656. if (!IsDeviceHandleValid(vibration_device_handle)) {
  657. return;
  658. }
  659. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  660. return;
  661. }
  662. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  663. auto& controller = controller_data[npad_index];
  664. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  665. if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
  666. return;
  667. }
  668. if (vibration_device_handle.device_index == DeviceIndex::None) {
  669. UNREACHABLE_MSG("DeviceIndex should never be None!");
  670. return;
  671. }
  672. // Some games try to send mismatched parameters in the device handle, block these.
  673. if ((controller.device->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
  674. (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconRight ||
  675. vibration_device_handle.device_index == DeviceIndex::Right)) ||
  676. (controller.device->GetNpadType() == Core::HID::NpadType::JoyconRight &&
  677. (vibration_device_handle.npad_type == Core::HID::NpadType::JoyconLeft ||
  678. vibration_device_handle.device_index == DeviceIndex::Left))) {
  679. return;
  680. }
  681. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  682. if (vibration_value.amp_low ==
  683. controller.vibration[device_index].latest_vibration_value.amp_low &&
  684. vibration_value.amp_high ==
  685. controller.vibration[device_index].latest_vibration_value.amp_high) {
  686. return;
  687. }
  688. if (VibrateControllerAtIndex(npad_index, device_index, vibration_value)) {
  689. controller.vibration[device_index].latest_vibration_value = vibration_value;
  690. }
  691. }
  692. void Controller_NPad::VibrateControllers(const std::vector<DeviceHandle>& vibration_device_handles,
  693. const std::vector<VibrationValue>& vibration_values) {
  694. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  695. return;
  696. }
  697. ASSERT_OR_EXECUTE_MSG(
  698. vibration_device_handles.size() == vibration_values.size(), { return; },
  699. "The amount of device handles does not match with the amount of vibration values,"
  700. "this is undefined behavior!");
  701. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  702. VibrateController(vibration_device_handles[i], vibration_values[i]);
  703. }
  704. }
  705. Controller_NPad::VibrationValue Controller_NPad::GetLastVibration(
  706. const DeviceHandle& vibration_device_handle) const {
  707. if (!IsDeviceHandleValid(vibration_device_handle)) {
  708. return {};
  709. }
  710. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  711. const auto& controller = controller_data[npad_index];
  712. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  713. return controller.vibration[device_index].latest_vibration_value;
  714. }
  715. void Controller_NPad::InitializeVibrationDevice(const DeviceHandle& vibration_device_handle) {
  716. if (!IsDeviceHandleValid(vibration_device_handle)) {
  717. return;
  718. }
  719. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  720. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  721. InitializeVibrationDeviceAtIndex(npad_index, device_index);
  722. }
  723. void Controller_NPad::InitializeVibrationDeviceAtIndex(std::size_t npad_index,
  724. std::size_t device_index) {
  725. auto& controller = controller_data[npad_index];
  726. if (!Settings::values.vibration_enabled.GetValue()) {
  727. controller.vibration[device_index].device_mounted = false;
  728. return;
  729. }
  730. controller.vibration[device_index].device_mounted =
  731. controller.device->TestVibration(device_index);
  732. }
  733. void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  734. permit_vibration_session_enabled = permit_vibration_session;
  735. }
  736. bool Controller_NPad::IsVibrationDeviceMounted(const DeviceHandle& vibration_device_handle) const {
  737. if (!IsDeviceHandleValid(vibration_device_handle)) {
  738. return false;
  739. }
  740. const auto npad_index = NPadIdToIndex(vibration_device_handle.npad_id);
  741. const auto& controller = controller_data[npad_index];
  742. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  743. return controller.vibration[device_index].device_mounted;
  744. }
  745. Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(u32 npad_id) {
  746. const auto& controller = controller_data[NPadIdToIndex(npad_id)];
  747. return controller.styleset_changed_event->GetReadableEvent();
  748. }
  749. void Controller_NPad::SignalStyleSetChangedEvent(u32 npad_id) const {
  750. const auto& controller = controller_data[NPadIdToIndex(npad_id)];
  751. controller.styleset_changed_event->GetWritableEvent().Signal();
  752. }
  753. void Controller_NPad::AddNewControllerAt(Core::HID::NpadType controller, std::size_t npad_index) {
  754. UpdateControllerAt(controller, npad_index, true);
  755. }
  756. void Controller_NPad::UpdateControllerAt(Core::HID::NpadType type, std::size_t npad_index,
  757. bool connected) {
  758. auto& controller = controller_data[npad_index];
  759. if (!connected) {
  760. DisconnectNpadAtIndex(npad_index);
  761. return;
  762. }
  763. controller.device->SetNpadType(type);
  764. controller.device->Connect();
  765. InitNewlyAddedController(npad_index);
  766. }
  767. void Controller_NPad::DisconnectNpad(u32 npad_id) {
  768. DisconnectNpadAtIndex(NPadIdToIndex(npad_id));
  769. }
  770. void Controller_NPad::DisconnectNpadAtIndex(std::size_t npad_index) {
  771. auto& controller = controller_data[npad_index];
  772. LOG_ERROR(Service_HID, "Disconnect {} {}", npad_index, controller.is_connected);
  773. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  774. // Send an empty vibration to stop any vibrations.
  775. VibrateControllerAtIndex(npad_index, device_idx, {});
  776. controller.vibration[device_idx].device_mounted = false;
  777. }
  778. auto& shared_memory_entry = controller.shared_memory_entry;
  779. shared_memory_entry.style_set.raw = 0; // Zero out
  780. shared_memory_entry.device_type.raw = 0;
  781. shared_memory_entry.system_properties.raw = 0;
  782. shared_memory_entry.button_properties.raw = 0;
  783. shared_memory_entry.battery_level_dual = 0;
  784. shared_memory_entry.battery_level_left = 0;
  785. shared_memory_entry.battery_level_right = 0;
  786. shared_memory_entry.fullkey_color = {};
  787. shared_memory_entry.joycon_color = {};
  788. shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
  789. shared_memory_entry.footer_type = AppletFooterUiType::None;
  790. controller.is_connected = false;
  791. controller.device->Disconnect();
  792. SignalStyleSetChangedEvent(IndexToNPad(npad_index));
  793. WriteEmptyEntry(controller.shared_memory_entry);
  794. }
  795. void Controller_NPad::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode drift_mode) {
  796. gyroscope_zero_drift_mode = drift_mode;
  797. }
  798. Controller_NPad::GyroscopeZeroDriftMode Controller_NPad::GetGyroscopeZeroDriftMode() const {
  799. return gyroscope_zero_drift_mode;
  800. }
  801. bool Controller_NPad::IsSixAxisSensorAtRest() const {
  802. return sixaxis_at_rest;
  803. }
  804. void Controller_NPad::SetSixAxisEnabled(bool six_axis_status) {
  805. sixaxis_sensors_enabled = six_axis_status;
  806. }
  807. void Controller_NPad::SetSixAxisFusionParameters(f32 parameter1, f32 parameter2) {
  808. sixaxis_fusion_parameter1 = parameter1;
  809. sixaxis_fusion_parameter2 = parameter2;
  810. }
  811. std::pair<f32, f32> Controller_NPad::GetSixAxisFusionParameters() {
  812. return {
  813. sixaxis_fusion_parameter1,
  814. sixaxis_fusion_parameter2,
  815. };
  816. }
  817. void Controller_NPad::ResetSixAxisFusionParameters() {
  818. sixaxis_fusion_parameter1 = 0.0f;
  819. sixaxis_fusion_parameter2 = 0.0f;
  820. }
  821. void Controller_NPad::MergeSingleJoyAsDualJoy(u32 npad_id_1, u32 npad_id_2) {
  822. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  823. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  824. const auto& controller_1 = controller_data[npad_index_1].device;
  825. const auto& controller_2 = controller_data[npad_index_2].device;
  826. // If the controllers at both npad indices form a pair of left and right joycons, merge them.
  827. // Otherwise, do nothing.
  828. if ((controller_1->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
  829. controller_2->GetNpadType() == Core::HID::NpadType::JoyconRight) ||
  830. (controller_2->GetNpadType() == Core::HID::NpadType::JoyconLeft &&
  831. controller_1->GetNpadType() == Core::HID::NpadType::JoyconRight)) {
  832. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
  833. DisconnectNpad(npad_id_2);
  834. AddNewControllerAt(Core::HID::NpadType::JoyconDual, npad_index_1);
  835. }
  836. }
  837. void Controller_NPad::StartLRAssignmentMode() {
  838. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  839. // controller types from boot, it doesn't really matter about showing a selection screen
  840. is_in_lr_assignment_mode = true;
  841. }
  842. void Controller_NPad::StopLRAssignmentMode() {
  843. is_in_lr_assignment_mode = false;
  844. }
  845. bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
  846. if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
  847. npad_id_2 == NPAD_UNKNOWN) {
  848. return true;
  849. }
  850. const auto npad_index_1 = NPadIdToIndex(npad_id_1);
  851. const auto npad_index_2 = NPadIdToIndex(npad_id_2);
  852. const auto& controller_1 = controller_data[npad_index_1].device;
  853. const auto& controller_2 = controller_data[npad_index_2].device;
  854. const auto type_index_1 = controller_1->GetNpadType();
  855. const auto type_index_2 = controller_2->GetNpadType();
  856. if (!IsControllerSupported(type_index_1) || !IsControllerSupported(type_index_2)) {
  857. return false;
  858. }
  859. AddNewControllerAt(type_index_2, npad_index_1);
  860. AddNewControllerAt(type_index_1, npad_index_2);
  861. return true;
  862. }
  863. Core::HID::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  864. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  865. // These are controllers without led patterns
  866. return Core::HID::LedPattern{0, 0, 0, 0};
  867. }
  868. return controller_data[npad_id].device->GetLedPattern();
  869. }
  870. bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(u32 npad_id) const {
  871. auto& controller = controller_data[NPadIdToIndex(npad_id)];
  872. return controller.unintended_home_button_input_protection;
  873. }
  874. void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
  875. u32 npad_id) {
  876. auto& controller = controller_data[NPadIdToIndex(npad_id)];
  877. controller.unintended_home_button_input_protection = is_protection_enabled;
  878. }
  879. void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
  880. analog_stick_use_center_clamp = use_center_clamp;
  881. }
  882. void Controller_NPad::ClearAllConnectedControllers() {
  883. for (auto& controller : controller_data) {
  884. if (controller.device->IsConnected() &&
  885. controller.device->GetNpadType() != Core::HID::NpadType::None) {
  886. controller.device->SetNpadType(Core::HID::NpadType::None);
  887. controller.device->Disconnect();
  888. }
  889. }
  890. }
  891. void Controller_NPad::DisconnectAllConnectedControllers() {
  892. for (auto& controller : controller_data) {
  893. controller.device->Disconnect();
  894. }
  895. }
  896. void Controller_NPad::ConnectAllDisconnectedControllers() {
  897. for (auto& controller : controller_data) {
  898. if (controller.device->GetNpadType() != Core::HID::NpadType::None &&
  899. !controller.device->IsConnected()) {
  900. controller.device->Connect();
  901. }
  902. }
  903. }
  904. void Controller_NPad::ClearAllControllers() {
  905. for (auto& controller : controller_data) {
  906. controller.device->SetNpadType(Core::HID::NpadType::None);
  907. controller.device->Disconnect();
  908. }
  909. }
  910. u32 Controller_NPad::GetAndResetPressState() {
  911. return press_state.exchange(0);
  912. }
  913. bool Controller_NPad::IsControllerSupported(Core::HID::NpadType controller) const {
  914. if (controller == Core::HID::NpadType::Handheld) {
  915. const bool support_handheld =
  916. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  917. NPAD_HANDHELD) != supported_npad_id_types.end();
  918. // Handheld is not even a supported type, lets stop here
  919. if (!support_handheld) {
  920. return false;
  921. }
  922. // Handheld shouldn't be supported in docked mode
  923. if (Settings::values.use_docked_mode.GetValue()) {
  924. return false;
  925. }
  926. return true;
  927. }
  928. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  929. [](u32 npad_id) { return npad_id <= MAX_NPAD_ID; })) {
  930. Core::HID::NpadStyleTag style = GetSupportedStyleSet();
  931. switch (controller) {
  932. case Core::HID::NpadType::ProController:
  933. return style.fullkey;
  934. case Core::HID::NpadType::JoyconDual:
  935. return style.joycon_dual;
  936. case Core::HID::NpadType::JoyconLeft:
  937. return style.joycon_left;
  938. case Core::HID::NpadType::JoyconRight:
  939. return style.joycon_right;
  940. case Core::HID::NpadType::GameCube:
  941. return style.gamecube;
  942. case Core::HID::NpadType::Pokeball:
  943. return style.palma;
  944. default:
  945. return false;
  946. }
  947. }
  948. return false;
  949. }
  950. } // namespace Service::HID