npad_resource.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-3.0-or-later
  3. #include "core/hle/kernel/k_event.h"
  4. #include "core/hle/kernel/k_readable_event.h"
  5. #include "hid_core/hid_result.h"
  6. #include "hid_core/hid_util.h"
  7. #include "hid_core/resources/npad/npad_resource.h"
  8. #include "hid_core/resources/npad/npad_types.h"
  9. namespace Service::HID {
  10. NPadResource::NPadResource(KernelHelpers::ServiceContext& context) : service_context{context} {}
  11. NPadResource::~NPadResource() = default;
  12. Result NPadResource::RegisterAppletResourceUserId(u64 aruid) {
  13. const auto aruid_index = GetIndexFromAruid(aruid);
  14. if (aruid_index < AruidIndexMax) {
  15. return ResultAruidAlreadyRegistered;
  16. }
  17. std::size_t data_index = AruidIndexMax;
  18. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  19. if (!state[i].flag.is_initialized) {
  20. data_index = i;
  21. break;
  22. }
  23. }
  24. if (data_index == AruidIndexMax) {
  25. return ResultAruidNoAvailableEntries;
  26. }
  27. auto& aruid_data = state[data_index];
  28. aruid_data.aruid = aruid;
  29. aruid_data.flag.is_initialized.Assign(true);
  30. data_index = AruidIndexMax;
  31. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  32. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  33. if (registration_list.aruid[i] != aruid) {
  34. continue;
  35. }
  36. data_index = i;
  37. break;
  38. }
  39. // TODO: Don't Handle pending delete here
  40. if (registration_list.flag[i] == RegistrationStatus::None ||
  41. registration_list.flag[i] == RegistrationStatus::PendingDelete) {
  42. data_index = i;
  43. break;
  44. }
  45. }
  46. if (data_index == AruidIndexMax) {
  47. return ResultSuccess;
  48. }
  49. registration_list.flag[data_index] = RegistrationStatus::Initialized;
  50. registration_list.aruid[data_index] = aruid;
  51. return ResultSuccess;
  52. }
  53. void NPadResource::UnregisterAppletResourceUserId(u64 aruid) {
  54. const u64 aruid_index = GetIndexFromAruid(aruid);
  55. DestroyStyleSetUpdateEvents(aruid);
  56. if (aruid_index < AruidIndexMax) {
  57. state[aruid_index] = {};
  58. registration_list.flag[aruid_index] = RegistrationStatus::PendingDelete;
  59. }
  60. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  61. if (registration_list.flag[i] == RegistrationStatus::Initialized) {
  62. active_data_aruid = registration_list.aruid[i];
  63. }
  64. }
  65. }
  66. void NPadResource::DestroyStyleSetUpdateEvents(u64 aruid) {
  67. const u64 aruid_index = GetIndexFromAruid(aruid);
  68. if (aruid_index >= AruidIndexMax) {
  69. return;
  70. }
  71. for (auto& controller_state : state[aruid_index].controller_state) {
  72. if (!controller_state.is_styleset_update_event_initialized) {
  73. continue;
  74. }
  75. service_context.CloseEvent(controller_state.style_set_update_event);
  76. controller_state.is_styleset_update_event_initialized = false;
  77. }
  78. }
  79. Result NPadResource::Activate(u64 aruid) {
  80. const u64 aruid_index = GetIndexFromAruid(aruid);
  81. if (aruid_index >= AruidIndexMax) {
  82. return ResultSuccess;
  83. }
  84. auto& state_data = state[aruid_index];
  85. if (state_data.flag.is_assigned) {
  86. return ResultAruidAlreadyRegistered;
  87. }
  88. state_data.flag.is_assigned.Assign(true);
  89. state_data.data.ClearNpadSystemCommonPolicy();
  90. state_data.npad_revision = NpadRevision::Revision0;
  91. state_data.button_config = {};
  92. if (active_data_aruid == aruid) {
  93. default_hold_type = active_data.GetNpadJoyHoldType();
  94. active_data.SetNpadJoyHoldType(default_hold_type);
  95. }
  96. return ResultSuccess;
  97. }
  98. Result NPadResource::Activate() {
  99. if (ref_counter == std::numeric_limits<s32>::max() - 1) {
  100. return ResultAppletResourceOverflow;
  101. }
  102. if (ref_counter == 0) {
  103. RegisterAppletResourceUserId(SystemAruid);
  104. Activate(SystemAruid);
  105. }
  106. ref_counter++;
  107. return ResultSuccess;
  108. }
  109. Result NPadResource::Deactivate() {
  110. if (ref_counter == 0) {
  111. return ResultAppletResourceNotInitialized;
  112. }
  113. UnregisterAppletResourceUserId(SystemAruid);
  114. ref_counter--;
  115. return ResultSuccess;
  116. }
  117. NPadData* NPadResource::GetActiveData() {
  118. return &active_data;
  119. }
  120. u64 NPadResource::GetActiveDataAruid() {
  121. return active_data_aruid;
  122. }
  123. void NPadResource::SetAppletResourceUserId(u64 aruid) {
  124. if (active_data_aruid == aruid) {
  125. return;
  126. }
  127. active_data_aruid = aruid;
  128. default_hold_type = active_data.GetNpadJoyHoldType();
  129. const u64 aruid_index = GetIndexFromAruid(aruid);
  130. if (aruid_index >= AruidIndexMax) {
  131. return;
  132. }
  133. auto& data = state[aruid_index].data;
  134. if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) {
  135. data.SetNpadJoyHoldType(default_hold_type);
  136. }
  137. active_data = data;
  138. if (data.GetNpadStatus().is_hold_type_set) {
  139. active_data.SetNpadJoyHoldType(default_hold_type);
  140. }
  141. }
  142. std::size_t NPadResource::GetIndexFromAruid(u64 aruid) const {
  143. for (std::size_t i = 0; i < AruidIndexMax; i++) {
  144. if (registration_list.flag[i] == RegistrationStatus::Initialized &&
  145. registration_list.aruid[i] == aruid) {
  146. return i;
  147. }
  148. }
  149. return AruidIndexMax;
  150. }
  151. Result NPadResource::ApplyNpadSystemCommonPolicy(u64 aruid, bool is_full_policy) {
  152. const u64 aruid_index = GetIndexFromAruid(aruid);
  153. if (aruid_index >= AruidIndexMax) {
  154. return ResultNpadNotConnected;
  155. }
  156. auto& data = state[aruid_index].data;
  157. data.SetNpadSystemCommonPolicy(is_full_policy);
  158. data.SetNpadJoyHoldType(default_hold_type);
  159. if (active_data_aruid == aruid) {
  160. active_data.SetNpadSystemCommonPolicy(is_full_policy);
  161. active_data.SetNpadJoyHoldType(default_hold_type);
  162. }
  163. return ResultSuccess;
  164. }
  165. Result NPadResource::ClearNpadSystemCommonPolicy(u64 aruid) {
  166. const u64 aruid_index = GetIndexFromAruid(aruid);
  167. if (aruid_index >= AruidIndexMax) {
  168. return ResultNpadNotConnected;
  169. }
  170. state[aruid_index].data.ClearNpadSystemCommonPolicy();
  171. if (active_data_aruid == aruid) {
  172. active_data.ClearNpadSystemCommonPolicy();
  173. }
  174. return ResultSuccess;
  175. }
  176. Result NPadResource::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet style_set) {
  177. const u64 aruid_index = GetIndexFromAruid(aruid);
  178. if (aruid_index >= AruidIndexMax) {
  179. return ResultNpadNotConnected;
  180. }
  181. auto& data = state[aruid_index].data;
  182. data.SetSupportedNpadStyleSet(style_set);
  183. if (active_data_aruid == aruid) {
  184. active_data.SetSupportedNpadStyleSet(style_set);
  185. active_data.SetNpadJoyHoldType(data.GetNpadJoyHoldType());
  186. }
  187. return ResultSuccess;
  188. }
  189. Result NPadResource::GetSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_Set,
  190. u64 aruid) const {
  191. const u64 aruid_index = GetIndexFromAruid(aruid);
  192. if (aruid_index >= AruidIndexMax) {
  193. return ResultNpadNotConnected;
  194. }
  195. auto& data = state[aruid_index].data;
  196. if (!data.GetNpadStatus().is_supported_styleset_set) {
  197. return ResultUndefinedStyleset;
  198. }
  199. out_style_Set = data.GetSupportedNpadStyleSet();
  200. return ResultSuccess;
  201. }
  202. Result NPadResource::GetMaskedSupportedNpadStyleSet(Core::HID::NpadStyleSet& out_style_set,
  203. u64 aruid) const {
  204. if (aruid == SystemAruid) {
  205. out_style_set = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  206. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  207. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Palma |
  208. Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System;
  209. return ResultSuccess;
  210. }
  211. const u64 aruid_index = GetIndexFromAruid(aruid);
  212. if (aruid_index >= AruidIndexMax) {
  213. return ResultNpadNotConnected;
  214. }
  215. auto& data = state[aruid_index].data;
  216. if (!data.GetNpadStatus().is_supported_styleset_set) {
  217. return ResultUndefinedStyleset;
  218. }
  219. Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None};
  220. out_style_set = data.GetSupportedNpadStyleSet();
  221. switch (state[aruid_index].npad_revision) {
  222. case NpadRevision::Revision1:
  223. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  224. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  225. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  226. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt |
  227. Core::HID::NpadStyleSet::System;
  228. break;
  229. case NpadRevision::Revision2:
  230. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  231. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  232. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  233. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark |
  234. Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System;
  235. break;
  236. case NpadRevision::Revision3:
  237. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  238. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  239. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  240. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark |
  241. Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia |
  242. Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager |
  243. Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System;
  244. break;
  245. default:
  246. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  247. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  248. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt |
  249. Core::HID::NpadStyleSet::System;
  250. break;
  251. }
  252. out_style_set = out_style_set & mask;
  253. return ResultSuccess;
  254. }
  255. Result NPadResource::GetAvailableStyleset(Core::HID::NpadStyleSet& out_style_set, u64 aruid) const {
  256. const u64 aruid_index = GetIndexFromAruid(aruid);
  257. if (aruid_index >= AruidIndexMax) {
  258. return ResultNpadNotConnected;
  259. }
  260. auto& data = state[aruid_index].data;
  261. if (!data.GetNpadStatus().is_supported_styleset_set) {
  262. return ResultUndefinedStyleset;
  263. }
  264. Core::HID::NpadStyleSet mask{Core::HID::NpadStyleSet::None};
  265. out_style_set = data.GetSupportedNpadStyleSet();
  266. switch (state[aruid_index].npad_revision) {
  267. case NpadRevision::Revision1:
  268. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  269. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  270. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  271. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::SystemExt |
  272. Core::HID::NpadStyleSet::System;
  273. break;
  274. case NpadRevision::Revision2:
  275. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  276. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  277. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  278. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark |
  279. Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System;
  280. break;
  281. case NpadRevision::Revision3:
  282. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  283. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  284. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::Gc |
  285. Core::HID::NpadStyleSet::Palma | Core::HID::NpadStyleSet::Lark |
  286. Core::HID::NpadStyleSet::HandheldLark | Core::HID::NpadStyleSet::Lucia |
  287. Core::HID::NpadStyleSet::Lagoon | Core::HID::NpadStyleSet::Lager |
  288. Core::HID::NpadStyleSet::SystemExt | Core::HID::NpadStyleSet::System;
  289. break;
  290. default:
  291. mask = Core::HID::NpadStyleSet::Fullkey | Core::HID::NpadStyleSet::Handheld |
  292. Core::HID::NpadStyleSet::JoyDual | Core::HID::NpadStyleSet::JoyLeft |
  293. Core::HID::NpadStyleSet::JoyRight | Core::HID::NpadStyleSet::SystemExt |
  294. Core::HID::NpadStyleSet::System;
  295. break;
  296. }
  297. out_style_set = out_style_set & mask;
  298. return ResultSuccess;
  299. }
  300. NpadRevision NPadResource::GetNpadRevision(u64 aruid) const {
  301. const u64 aruid_index = GetIndexFromAruid(aruid);
  302. if (aruid_index >= AruidIndexMax) {
  303. return NpadRevision::Revision0;
  304. }
  305. return state[aruid_index].npad_revision;
  306. }
  307. Result NPadResource::IsSupportedNpadStyleSet(bool& is_set, u64 aruid) {
  308. const u64 aruid_index = GetIndexFromAruid(aruid);
  309. if (aruid_index >= AruidIndexMax) {
  310. return ResultNpadNotConnected;
  311. }
  312. is_set = state[aruid_index].data.GetNpadStatus().is_supported_styleset_set.Value() != 0;
  313. return ResultSuccess;
  314. }
  315. Result NPadResource::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) {
  316. const u64 aruid_index = GetIndexFromAruid(aruid);
  317. if (aruid_index >= AruidIndexMax) {
  318. return ResultNpadNotConnected;
  319. }
  320. state[aruid_index].data.SetNpadJoyHoldType(hold_type);
  321. if (active_data_aruid == aruid) {
  322. active_data.SetNpadJoyHoldType(hold_type);
  323. }
  324. return ResultSuccess;
  325. }
  326. Result NPadResource::GetNpadJoyHoldType(NpadJoyHoldType& hold_type, u64 aruid) const {
  327. const u64 aruid_index = GetIndexFromAruid(aruid);
  328. if (aruid_index >= AruidIndexMax) {
  329. return ResultNpadNotConnected;
  330. }
  331. auto& data = state[aruid_index].data;
  332. if (data.GetNpadStatus().is_policy || data.GetNpadStatus().is_full_policy) {
  333. hold_type = active_data.GetNpadJoyHoldType();
  334. return ResultSuccess;
  335. }
  336. hold_type = data.GetNpadJoyHoldType();
  337. return ResultSuccess;
  338. }
  339. Result NPadResource::SetNpadHandheldActivationMode(u64 aruid,
  340. NpadHandheldActivationMode activation_mode) {
  341. const u64 aruid_index = GetIndexFromAruid(aruid);
  342. if (aruid_index >= AruidIndexMax) {
  343. return ResultNpadNotConnected;
  344. }
  345. state[aruid_index].data.SetHandheldActivationMode(activation_mode);
  346. if (active_data_aruid == aruid) {
  347. active_data.SetHandheldActivationMode(activation_mode);
  348. }
  349. return ResultSuccess;
  350. }
  351. Result NPadResource::GetNpadHandheldActivationMode(NpadHandheldActivationMode& activation_mode,
  352. u64 aruid) const {
  353. const u64 aruid_index = GetIndexFromAruid(aruid);
  354. if (aruid_index >= AruidIndexMax) {
  355. return ResultNpadNotConnected;
  356. }
  357. activation_mode = state[aruid_index].data.GetHandheldActivationMode();
  358. return ResultSuccess;
  359. }
  360. Result NPadResource::SetSupportedNpadIdType(
  361. u64 aruid, std::span<const Core::HID::NpadIdType> supported_npad_list) {
  362. const u64 aruid_index = GetIndexFromAruid(aruid);
  363. if (aruid_index >= AruidIndexMax) {
  364. return ResultNpadNotConnected;
  365. }
  366. if (supported_npad_list.size() > MaxSupportedNpadIdTypes) {
  367. return ResultInvalidArraySize;
  368. }
  369. Result result = state[aruid_index].data.SetSupportedNpadIdType(supported_npad_list);
  370. if (result.IsSuccess() && active_data_aruid == aruid) {
  371. result = active_data.SetSupportedNpadIdType(supported_npad_list);
  372. }
  373. return result;
  374. }
  375. bool NPadResource::IsControllerSupported(u64 aruid, Core::HID::NpadStyleIndex style_index) const {
  376. const u64 aruid_index = GetIndexFromAruid(aruid);
  377. if (aruid_index >= AruidIndexMax) {
  378. return false;
  379. }
  380. return state[aruid_index].data.IsNpadStyleIndexSupported(style_index);
  381. }
  382. Result NPadResource::SetLrAssignmentMode(u64 aruid, bool is_enabled) {
  383. const u64 aruid_index = GetIndexFromAruid(aruid);
  384. if (aruid_index >= AruidIndexMax) {
  385. return ResultNpadNotConnected;
  386. }
  387. state[aruid_index].data.SetLrAssignmentMode(is_enabled);
  388. if (active_data_aruid == aruid) {
  389. active_data.SetLrAssignmentMode(is_enabled);
  390. }
  391. return ResultSuccess;
  392. }
  393. Result NPadResource::GetLrAssignmentMode(bool& is_enabled, u64 aruid) const {
  394. const u64 aruid_index = GetIndexFromAruid(aruid);
  395. if (aruid_index >= AruidIndexMax) {
  396. return ResultNpadNotConnected;
  397. }
  398. is_enabled = state[aruid_index].data.GetLrAssignmentMode();
  399. return ResultSuccess;
  400. }
  401. Result NPadResource::SetAssigningSingleOnSlSrPress(u64 aruid, bool is_enabled) {
  402. const u64 aruid_index = GetIndexFromAruid(aruid);
  403. if (aruid_index >= AruidIndexMax) {
  404. return ResultNpadNotConnected;
  405. }
  406. state[aruid_index].data.SetAssigningSingleOnSlSrPress(is_enabled);
  407. if (active_data_aruid == aruid) {
  408. active_data.SetAssigningSingleOnSlSrPress(is_enabled);
  409. }
  410. return ResultSuccess;
  411. }
  412. Result NPadResource::IsAssigningSingleOnSlSrPressEnabled(bool& is_enabled, u64 aruid) const {
  413. const u64 aruid_index = GetIndexFromAruid(aruid);
  414. if (aruid_index >= AruidIndexMax) {
  415. return ResultNpadNotConnected;
  416. }
  417. is_enabled = state[aruid_index].data.GetAssigningSingleOnSlSrPress();
  418. return ResultSuccess;
  419. }
  420. Result NPadResource::AcquireNpadStyleSetUpdateEventHandle(u64 aruid,
  421. Kernel::KReadableEvent** out_event,
  422. Core::HID::NpadIdType npad_id) {
  423. const u64 aruid_index = GetIndexFromAruid(aruid);
  424. if (aruid_index >= AruidIndexMax) {
  425. return ResultNpadNotConnected;
  426. }
  427. auto& controller_state = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)];
  428. if (!controller_state.is_styleset_update_event_initialized) {
  429. // Auto clear = true
  430. controller_state.style_set_update_event =
  431. service_context.CreateEvent("NpadResource:StylesetUpdateEvent");
  432. // Assume creating the event succeeds otherwise crash the system here
  433. controller_state.is_styleset_update_event_initialized = true;
  434. }
  435. *out_event = &controller_state.style_set_update_event->GetReadableEvent();
  436. if (controller_state.is_styleset_update_event_initialized) {
  437. controller_state.style_set_update_event->Signal();
  438. }
  439. return ResultSuccess;
  440. }
  441. Result NPadResource::SignalStyleSetUpdateEvent(u64 aruid, Core::HID::NpadIdType npad_id) {
  442. const u64 aruid_index = GetIndexFromAruid(aruid);
  443. if (aruid_index >= AruidIndexMax) {
  444. return ResultNpadNotConnected;
  445. }
  446. auto controller = state[aruid_index].controller_state[NpadIdTypeToIndex(npad_id)];
  447. if (controller.is_styleset_update_event_initialized) {
  448. controller.style_set_update_event->Signal();
  449. }
  450. return ResultSuccess;
  451. }
  452. Result NPadResource::GetHomeProtectionEnabled(bool& is_enabled, u64 aruid,
  453. Core::HID::NpadIdType npad_id) const {
  454. const u64 aruid_index = GetIndexFromAruid(aruid);
  455. if (aruid_index >= AruidIndexMax) {
  456. return ResultNpadNotConnected;
  457. }
  458. is_enabled = state[aruid_index].data.GetHomeProtectionEnabled(npad_id);
  459. return ResultSuccess;
  460. }
  461. Result NPadResource::SetHomeProtectionEnabled(u64 aruid, Core::HID::NpadIdType npad_id,
  462. bool is_enabled) {
  463. const u64 aruid_index = GetIndexFromAruid(aruid);
  464. if (aruid_index >= AruidIndexMax) {
  465. return ResultNpadNotConnected;
  466. }
  467. state[aruid_index].data.SetHomeProtectionEnabled(is_enabled, npad_id);
  468. if (active_data_aruid == aruid) {
  469. active_data.SetHomeProtectionEnabled(is_enabled, npad_id);
  470. }
  471. return ResultSuccess;
  472. }
  473. Result NPadResource::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) {
  474. const u64 aruid_index = GetIndexFromAruid(aruid);
  475. if (aruid_index >= AruidIndexMax) {
  476. return ResultNpadNotConnected;
  477. }
  478. state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled);
  479. if (active_data_aruid == aruid) {
  480. active_data.SetNpadAnalogStickUseCenterClamp(is_enabled);
  481. }
  482. return ResultSuccess;
  483. }
  484. Result NPadResource::SetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id, std::size_t index,
  485. Core::HID::NpadButton button_config) {
  486. const u64 aruid_index = GetIndexFromAruid(aruid);
  487. if (aruid_index >= AruidIndexMax) {
  488. return ResultNpadNotConnected;
  489. }
  490. state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index] = button_config;
  491. return ResultSuccess;
  492. }
  493. Core::HID::NpadButton NPadResource::GetButtonConfig(u64 aruid, Core::HID::NpadIdType npad_id,
  494. std::size_t index, Core::HID::NpadButton mask,
  495. bool is_enabled) {
  496. const u64 aruid_index = GetIndexFromAruid(aruid);
  497. if (aruid_index >= AruidIndexMax) {
  498. return Core::HID::NpadButton::None;
  499. }
  500. auto& button_config = state[aruid_index].button_config[NpadIdTypeToIndex(npad_id)][index];
  501. if (is_enabled) {
  502. button_config = button_config | mask;
  503. return button_config;
  504. }
  505. button_config = Core::HID::NpadButton::None;
  506. return Core::HID::NpadButton::None;
  507. }
  508. void NPadResource::ResetButtonConfig() {
  509. for (auto& selected_state : state) {
  510. selected_state.button_config = {};
  511. }
  512. }
  513. Result NPadResource::SetNpadCaptureButtonAssignment(u64 aruid,
  514. Core::HID::NpadStyleSet npad_style_set,
  515. Core::HID::NpadButton button_assignment) {
  516. const u64 aruid_index = GetIndexFromAruid(aruid);
  517. if (aruid_index >= AruidIndexMax) {
  518. return ResultNpadNotConnected;
  519. }
  520. // Must be a power of two
  521. const auto raw_styleset = static_cast<u32>(npad_style_set);
  522. if (raw_styleset == 0 && (raw_styleset & (raw_styleset - 1)) != 0) {
  523. return ResultMultipleStyleSetSelected;
  524. }
  525. std::size_t style_index{};
  526. Core::HID::NpadStyleSet style_selected{};
  527. for (style_index = 0; style_index < StyleIndexCount; ++style_index) {
  528. style_selected = GetStylesetByIndex(style_index);
  529. if (npad_style_set == style_selected) {
  530. break;
  531. }
  532. }
  533. if (style_selected == Core::HID::NpadStyleSet::None) {
  534. return ResultMultipleStyleSetSelected;
  535. }
  536. state[aruid_index].data.SetCaptureButtonAssignment(button_assignment, style_index);
  537. if (active_data_aruid == aruid) {
  538. active_data.SetCaptureButtonAssignment(button_assignment, style_index);
  539. }
  540. return ResultSuccess;
  541. }
  542. Result NPadResource::ClearNpadCaptureButtonAssignment(u64 aruid) {
  543. const u64 aruid_index = GetIndexFromAruid(aruid);
  544. if (aruid_index >= AruidIndexMax) {
  545. return ResultNpadNotConnected;
  546. }
  547. for (std::size_t i = 0; i < StyleIndexCount; i++) {
  548. state[aruid_index].data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i);
  549. if (active_data_aruid == aruid) {
  550. active_data.SetCaptureButtonAssignment(Core::HID::NpadButton::None, i);
  551. }
  552. }
  553. return ResultSuccess;
  554. }
  555. std::size_t NPadResource::GetNpadCaptureButtonAssignment(std::span<Core::HID::NpadButton> out_list,
  556. u64 aruid) const {
  557. const u64 aruid_index = GetIndexFromAruid(aruid);
  558. if (aruid_index >= AruidIndexMax) {
  559. return 0;
  560. }
  561. return state[aruid_index].data.GetNpadCaptureButtonAssignmentList(out_list);
  562. }
  563. void NPadResource::SetNpadRevision(u64 aruid, NpadRevision revision) {
  564. const u64 aruid_index = GetIndexFromAruid(aruid);
  565. if (aruid_index >= AruidIndexMax) {
  566. return;
  567. }
  568. state[aruid_index].npad_revision = revision;
  569. }
  570. Result NPadResource::SetNpadSystemExtStateEnabled(u64 aruid, bool is_enabled) {
  571. const u64 aruid_index = GetIndexFromAruid(aruid);
  572. if (aruid_index >= AruidIndexMax) {
  573. return ResultNpadNotConnected;
  574. }
  575. state[aruid_index].data.SetNpadAnalogStickUseCenterClamp(is_enabled);
  576. if (active_data_aruid == aruid) {
  577. active_data.SetNpadAnalogStickUseCenterClamp(is_enabled);
  578. }
  579. return ResultSuccess;
  580. }
  581. } // namespace Service::HID