npad.cpp 58 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <array>
  5. #include <chrono>
  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/hle/kernel/k_event.h"
  14. #include "core/hle/kernel/k_readable_event.h"
  15. #include "core/hle/service/kernel_helpers.h"
  16. #include "hid_core/frontend/emulated_controller.h"
  17. #include "hid_core/hid_core.h"
  18. #include "hid_core/hid_result.h"
  19. #include "hid_core/hid_util.h"
  20. #include "hid_core/resources/applet_resource.h"
  21. #include "hid_core/resources/npad/npad.h"
  22. #include "hid_core/resources/shared_memory_format.h"
  23. namespace Service::HID {
  24. NPad::NPad(Core::HID::HIDCore& hid_core_, KernelHelpers::ServiceContext& service_context_)
  25. : hid_core{hid_core_}, service_context{service_context_}, npad_resource{service_context} {
  26. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
  27. for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
  28. auto& controller = controller_data[aruid_index][i];
  29. controller.device = hid_core.GetEmulatedControllerByIndex(i);
  30. controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
  31. Core::HID::DEFAULT_VIBRATION_VALUE;
  32. controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex]
  33. .latest_vibration_value = Core::HID::DEFAULT_VIBRATION_VALUE;
  34. Core::HID::ControllerUpdateCallback engine_callback{
  35. .on_change =
  36. [this, i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
  37. .is_npad_service = true,
  38. };
  39. controller.callback_key = controller.device->SetCallback(engine_callback);
  40. }
  41. }
  42. }
  43. NPad::~NPad() {
  44. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
  45. for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
  46. auto& controller = controller_data[aruid_index][i];
  47. controller.device->DeleteCallback(controller.callback_key);
  48. }
  49. }
  50. }
  51. Result NPad::Activate() {
  52. if (ref_counter == std::numeric_limits<s32>::max() - 1) {
  53. return ResultNpadResourceOverflow;
  54. }
  55. if (ref_counter == 0) {
  56. std::scoped_lock lock{mutex};
  57. // TODO: Activate handlers and AbstractedPad
  58. }
  59. ref_counter++;
  60. return ResultSuccess;
  61. }
  62. Result NPad::Activate(u64 aruid) {
  63. std::scoped_lock lock{mutex};
  64. std::scoped_lock shared_lock{*applet_resource_holder.shared_mutex};
  65. auto* data = applet_resource_holder.applet_resource->GetAruidData(aruid);
  66. const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid);
  67. if (data == nullptr || !data->flag.is_assigned) {
  68. return ResultSuccess;
  69. }
  70. for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
  71. auto& controller = controller_data[aruid_index][i];
  72. controller.shared_memory = &data->shared_memory_format->npad.npad_entry[i].internal_state;
  73. }
  74. // Prefill controller buffers
  75. for (auto& controller : controller_data[aruid_index]) {
  76. auto* npad = controller.shared_memory;
  77. npad->fullkey_color = {
  78. .attribute = ColorAttribute::NoController,
  79. .fullkey = {},
  80. };
  81. npad->joycon_color = {
  82. .attribute = ColorAttribute::NoController,
  83. .left = {},
  84. .right = {},
  85. };
  86. // HW seems to initialize the first 19 entries
  87. for (std::size_t i = 0; i < 19; ++i) {
  88. WriteEmptyEntry(npad);
  89. }
  90. }
  91. return ResultSuccess;
  92. }
  93. Result NPad::ActivateNpadResource() {
  94. return npad_resource.Activate();
  95. }
  96. Result NPad::ActivateNpadResource(u64 aruid) {
  97. return npad_resource.Activate(aruid);
  98. }
  99. void NPad::ControllerUpdate(Core::HID::ControllerTriggerType type, std::size_t controller_idx) {
  100. if (type == Core::HID::ControllerTriggerType::All) {
  101. ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
  102. ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
  103. return;
  104. }
  105. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
  106. if (controller_idx >= controller_data[aruid_index].size()) {
  107. return;
  108. }
  109. auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index);
  110. if (!data->flag.is_assigned) {
  111. continue;
  112. }
  113. auto& controller = controller_data[aruid_index][controller_idx];
  114. const auto is_connected = controller.device->IsConnected();
  115. const auto npad_type = controller.device->GetNpadStyleIndex();
  116. const auto npad_id = controller.device->GetNpadIdType();
  117. switch (type) {
  118. case Core::HID::ControllerTriggerType::Connected:
  119. case Core::HID::ControllerTriggerType::Disconnected:
  120. if (is_connected == controller.is_connected) {
  121. return;
  122. }
  123. UpdateControllerAt(data->aruid, npad_type, npad_id, is_connected);
  124. break;
  125. case Core::HID::ControllerTriggerType::Battery: {
  126. if (!controller.device->IsConnected()) {
  127. return;
  128. }
  129. auto* shared_memory = controller.shared_memory;
  130. const auto& battery_level = controller.device->GetBattery();
  131. shared_memory->battery_level_dual = battery_level.dual.battery_level;
  132. shared_memory->battery_level_left = battery_level.left.battery_level;
  133. shared_memory->battery_level_right = battery_level.right.battery_level;
  134. break;
  135. }
  136. default:
  137. break;
  138. }
  139. }
  140. }
  141. void NPad::InitNewlyAddedController(u64 aruid, Core::HID::NpadIdType npad_id) {
  142. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  143. if (!npad_resource.IsControllerSupported(aruid, controller.device->GetNpadStyleIndex())) {
  144. return;
  145. }
  146. LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
  147. const auto controller_type = controller.device->GetNpadStyleIndex();
  148. const auto& body_colors = controller.device->GetColors();
  149. const auto& battery_level = controller.device->GetBattery();
  150. auto* shared_memory = controller.shared_memory;
  151. if (controller_type == Core::HID::NpadStyleIndex::None) {
  152. npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id);
  153. return;
  154. }
  155. // Reset memory values
  156. shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None;
  157. shared_memory->device_type.raw = 0;
  158. shared_memory->system_properties.raw = 0;
  159. shared_memory->joycon_color.attribute = ColorAttribute::NoController;
  160. shared_memory->joycon_color.attribute = ColorAttribute::NoController;
  161. shared_memory->fullkey_color = {};
  162. shared_memory->joycon_color.left = {};
  163. shared_memory->joycon_color.right = {};
  164. shared_memory->battery_level_dual = {};
  165. shared_memory->battery_level_left = {};
  166. shared_memory->battery_level_right = {};
  167. switch (controller_type) {
  168. case Core::HID::NpadStyleIndex::None:
  169. ASSERT(false);
  170. break;
  171. case Core::HID::NpadStyleIndex::ProController:
  172. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  173. shared_memory->fullkey_color.fullkey = body_colors.fullkey;
  174. shared_memory->battery_level_dual = battery_level.dual.battery_level;
  175. shared_memory->style_tag.fullkey.Assign(1);
  176. shared_memory->device_type.fullkey.Assign(1);
  177. shared_memory->system_properties.is_vertical.Assign(1);
  178. shared_memory->system_properties.use_plus.Assign(1);
  179. shared_memory->system_properties.use_minus.Assign(1);
  180. shared_memory->system_properties.is_charging_joy_dual.Assign(
  181. battery_level.dual.is_charging);
  182. shared_memory->applet_footer_type = AppletFooterUiType::SwitchProController;
  183. shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
  184. break;
  185. case Core::HID::NpadStyleIndex::Handheld:
  186. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  187. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  188. shared_memory->fullkey_color.fullkey = body_colors.fullkey;
  189. shared_memory->joycon_color.left = body_colors.left;
  190. shared_memory->joycon_color.right = body_colors.right;
  191. shared_memory->style_tag.handheld.Assign(1);
  192. shared_memory->device_type.handheld_left.Assign(1);
  193. shared_memory->device_type.handheld_right.Assign(1);
  194. shared_memory->system_properties.is_vertical.Assign(1);
  195. shared_memory->system_properties.use_plus.Assign(1);
  196. shared_memory->system_properties.use_minus.Assign(1);
  197. shared_memory->system_properties.use_directional_buttons.Assign(1);
  198. shared_memory->system_properties.is_charging_joy_dual.Assign(
  199. battery_level.left.is_charging);
  200. shared_memory->system_properties.is_charging_joy_left.Assign(
  201. battery_level.left.is_charging);
  202. shared_memory->system_properties.is_charging_joy_right.Assign(
  203. battery_level.right.is_charging);
  204. shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
  205. shared_memory->applet_footer_type = AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  206. shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
  207. break;
  208. case Core::HID::NpadStyleIndex::JoyconDual:
  209. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  210. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  211. shared_memory->style_tag.joycon_dual.Assign(1);
  212. if (controller.is_dual_left_connected) {
  213. shared_memory->joycon_color.left = body_colors.left;
  214. shared_memory->battery_level_left = battery_level.left.battery_level;
  215. shared_memory->device_type.joycon_left.Assign(1);
  216. shared_memory->system_properties.use_minus.Assign(1);
  217. shared_memory->system_properties.is_charging_joy_left.Assign(
  218. battery_level.left.is_charging);
  219. shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1);
  220. }
  221. if (controller.is_dual_right_connected) {
  222. shared_memory->joycon_color.right = body_colors.right;
  223. shared_memory->battery_level_right = battery_level.right.battery_level;
  224. shared_memory->device_type.joycon_right.Assign(1);
  225. shared_memory->system_properties.use_plus.Assign(1);
  226. shared_memory->system_properties.is_charging_joy_right.Assign(
  227. battery_level.right.is_charging);
  228. shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1);
  229. }
  230. shared_memory->system_properties.use_directional_buttons.Assign(1);
  231. shared_memory->system_properties.is_vertical.Assign(1);
  232. shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
  233. if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
  234. shared_memory->applet_footer_type = AppletFooterUiType::JoyDual;
  235. shared_memory->fullkey_color.fullkey = body_colors.left;
  236. shared_memory->battery_level_dual = battery_level.left.battery_level;
  237. shared_memory->system_properties.is_charging_joy_dual.Assign(
  238. battery_level.left.is_charging);
  239. } else if (controller.is_dual_left_connected) {
  240. shared_memory->applet_footer_type = AppletFooterUiType::JoyDualLeftOnly;
  241. shared_memory->fullkey_color.fullkey = body_colors.left;
  242. shared_memory->battery_level_dual = battery_level.left.battery_level;
  243. shared_memory->system_properties.is_charging_joy_dual.Assign(
  244. battery_level.left.is_charging);
  245. } else {
  246. shared_memory->applet_footer_type = AppletFooterUiType::JoyDualRightOnly;
  247. shared_memory->fullkey_color.fullkey = body_colors.right;
  248. shared_memory->battery_level_dual = battery_level.right.battery_level;
  249. shared_memory->system_properties.is_charging_joy_dual.Assign(
  250. battery_level.right.is_charging);
  251. }
  252. break;
  253. case Core::HID::NpadStyleIndex::JoyconLeft:
  254. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  255. shared_memory->fullkey_color.fullkey = body_colors.left;
  256. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  257. shared_memory->joycon_color.left = body_colors.left;
  258. shared_memory->battery_level_dual = battery_level.left.battery_level;
  259. shared_memory->style_tag.joycon_left.Assign(1);
  260. shared_memory->device_type.joycon_left.Assign(1);
  261. shared_memory->system_properties.is_horizontal.Assign(1);
  262. shared_memory->system_properties.use_minus.Assign(1);
  263. shared_memory->system_properties.is_charging_joy_left.Assign(
  264. battery_level.left.is_charging);
  265. shared_memory->applet_footer_type = AppletFooterUiType::JoyLeftHorizontal;
  266. shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
  267. break;
  268. case Core::HID::NpadStyleIndex::JoyconRight:
  269. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  270. shared_memory->fullkey_color.fullkey = body_colors.right;
  271. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  272. shared_memory->joycon_color.right = body_colors.right;
  273. shared_memory->battery_level_right = battery_level.right.battery_level;
  274. shared_memory->style_tag.joycon_right.Assign(1);
  275. shared_memory->device_type.joycon_right.Assign(1);
  276. shared_memory->system_properties.is_horizontal.Assign(1);
  277. shared_memory->system_properties.use_plus.Assign(1);
  278. shared_memory->system_properties.is_charging_joy_right.Assign(
  279. battery_level.right.is_charging);
  280. shared_memory->applet_footer_type = AppletFooterUiType::JoyRightHorizontal;
  281. shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
  282. break;
  283. case Core::HID::NpadStyleIndex::GameCube:
  284. shared_memory->style_tag.gamecube.Assign(1);
  285. shared_memory->device_type.fullkey.Assign(1);
  286. shared_memory->system_properties.is_vertical.Assign(1);
  287. shared_memory->system_properties.use_plus.Assign(1);
  288. break;
  289. case Core::HID::NpadStyleIndex::Pokeball:
  290. shared_memory->style_tag.palma.Assign(1);
  291. shared_memory->device_type.palma.Assign(1);
  292. shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
  293. break;
  294. case Core::HID::NpadStyleIndex::NES:
  295. shared_memory->style_tag.lark.Assign(1);
  296. shared_memory->device_type.fullkey.Assign(1);
  297. break;
  298. case Core::HID::NpadStyleIndex::SNES:
  299. shared_memory->style_tag.lucia.Assign(1);
  300. shared_memory->device_type.fullkey.Assign(1);
  301. shared_memory->applet_footer_type = AppletFooterUiType::Lucia;
  302. break;
  303. case Core::HID::NpadStyleIndex::N64:
  304. shared_memory->style_tag.lagoon.Assign(1);
  305. shared_memory->device_type.fullkey.Assign(1);
  306. shared_memory->applet_footer_type = AppletFooterUiType::Lagon;
  307. break;
  308. case Core::HID::NpadStyleIndex::SegaGenesis:
  309. shared_memory->style_tag.lager.Assign(1);
  310. shared_memory->device_type.fullkey.Assign(1);
  311. break;
  312. default:
  313. break;
  314. }
  315. controller.is_connected = true;
  316. controller.device->Connect();
  317. controller.device->SetLedPattern();
  318. if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
  319. if (controller.is_dual_left_connected) {
  320. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex,
  321. Common::Input::PollingMode::Active);
  322. }
  323. if (controller.is_dual_right_connected) {
  324. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
  325. Common::Input::PollingMode::Active);
  326. }
  327. } else {
  328. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices,
  329. Common::Input::PollingMode::Active);
  330. }
  331. npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id);
  332. WriteEmptyEntry(controller.shared_memory);
  333. hid_core.SetLastActiveController(npad_id);
  334. }
  335. void NPad::WriteEmptyEntry(NpadInternalState* npad) {
  336. NPadGenericState dummy_pad_state{};
  337. NpadGcTriggerState dummy_gc_state{};
  338. dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
  339. npad->fullkey_lifo.WriteNextEntry(dummy_pad_state);
  340. dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1;
  341. npad->handheld_lifo.WriteNextEntry(dummy_pad_state);
  342. dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
  343. npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state);
  344. dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
  345. npad->joy_left_lifo.WriteNextEntry(dummy_pad_state);
  346. dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
  347. npad->joy_right_lifo.WriteNextEntry(dummy_pad_state);
  348. dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1;
  349. npad->palma_lifo.WriteNextEntry(dummy_pad_state);
  350. dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
  351. npad->system_ext_lifo.WriteNextEntry(dummy_pad_state);
  352. dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
  353. npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
  354. }
  355. void NPad::RequestPadStateUpdate(u64 aruid, Core::HID::NpadIdType npad_id) {
  356. std::scoped_lock lock{*applet_resource_holder.shared_mutex};
  357. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  358. const auto controller_type = controller.device->GetNpadStyleIndex();
  359. if (!controller.device->IsConnected() && controller.is_connected) {
  360. DisconnectNpad(aruid, npad_id);
  361. return;
  362. }
  363. if (!controller.device->IsConnected()) {
  364. return;
  365. }
  366. if (controller.device->IsConnected() && !controller.is_connected) {
  367. InitNewlyAddedController(aruid, npad_id);
  368. }
  369. // This function is unique to yuzu for the turbo buttons and motion to work properly
  370. controller.device->StatusUpdate();
  371. auto& pad_entry = controller.npad_pad_state;
  372. auto& trigger_entry = controller.npad_trigger_state;
  373. const auto button_state = controller.device->GetNpadButtons();
  374. const auto stick_state = controller.device->GetSticks();
  375. using btn = Core::HID::NpadButton;
  376. pad_entry.npad_buttons.raw = btn::None;
  377. if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
  378. constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
  379. btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
  380. btn::StickRRight | btn::StickRDown;
  381. pad_entry.npad_buttons.raw = button_state.raw & right_button_mask;
  382. pad_entry.r_stick = stick_state.right;
  383. }
  384. if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
  385. constexpr btn left_button_mask =
  386. btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
  387. btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
  388. pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
  389. pad_entry.l_stick = stick_state.left;
  390. }
  391. if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft ||
  392. controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
  393. pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
  394. pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
  395. }
  396. if (controller_type == Core::HID::NpadStyleIndex::JoyconRight ||
  397. controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
  398. pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
  399. pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
  400. }
  401. if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
  402. const auto& trigger_state = controller.device->GetTriggers();
  403. trigger_entry.l_analog = trigger_state.left;
  404. trigger_entry.r_analog = trigger_state.right;
  405. pad_entry.npad_buttons.zl.Assign(false);
  406. pad_entry.npad_buttons.zr.Assign(button_state.r);
  407. pad_entry.npad_buttons.l.Assign(button_state.zl);
  408. pad_entry.npad_buttons.r.Assign(button_state.zr);
  409. }
  410. if (pad_entry.npad_buttons.raw != Core::HID::NpadButton::None) {
  411. hid_core.SetLastActiveController(npad_id);
  412. }
  413. }
  414. void NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
  415. if (ref_counter == 0) {
  416. return;
  417. }
  418. std::scoped_lock lock{*applet_resource_holder.shared_mutex};
  419. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; ++aruid_index) {
  420. const auto* data = applet_resource_holder.applet_resource->GetAruidDataByIndex(aruid_index);
  421. const auto aruid = data->aruid;
  422. if (!data->flag.is_assigned) {
  423. continue;
  424. }
  425. for (std::size_t i = 0; i < controller_data[aruid_index].size(); ++i) {
  426. auto& controller = controller_data[aruid_index][i];
  427. controller.shared_memory =
  428. &data->shared_memory_format->npad.npad_entry[i].internal_state;
  429. auto* npad = controller.shared_memory;
  430. const auto& controller_type = controller.device->GetNpadStyleIndex();
  431. if (controller_type == Core::HID::NpadStyleIndex::None ||
  432. !controller.device->IsConnected()) {
  433. continue;
  434. }
  435. RequestPadStateUpdate(aruid, controller.device->GetNpadIdType());
  436. auto& pad_state = controller.npad_pad_state;
  437. auto& libnx_state = controller.npad_libnx_state;
  438. auto& trigger_state = controller.npad_trigger_state;
  439. // LibNX exclusively uses this section, so we always update it since LibNX doesn't
  440. // activate any controllers.
  441. libnx_state.connection_status.raw = 0;
  442. libnx_state.connection_status.is_connected.Assign(1);
  443. switch (controller_type) {
  444. case Core::HID::NpadStyleIndex::None:
  445. ASSERT(false);
  446. break;
  447. case Core::HID::NpadStyleIndex::ProController:
  448. case Core::HID::NpadStyleIndex::NES:
  449. case Core::HID::NpadStyleIndex::SNES:
  450. case Core::HID::NpadStyleIndex::N64:
  451. case Core::HID::NpadStyleIndex::SegaGenesis:
  452. pad_state.connection_status.raw = 0;
  453. pad_state.connection_status.is_connected.Assign(1);
  454. pad_state.connection_status.is_wired.Assign(1);
  455. libnx_state.connection_status.is_wired.Assign(1);
  456. pad_state.sampling_number =
  457. npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  458. npad->fullkey_lifo.WriteNextEntry(pad_state);
  459. break;
  460. case Core::HID::NpadStyleIndex::Handheld:
  461. pad_state.connection_status.raw = 0;
  462. pad_state.connection_status.is_connected.Assign(1);
  463. pad_state.connection_status.is_wired.Assign(1);
  464. pad_state.connection_status.is_left_connected.Assign(1);
  465. pad_state.connection_status.is_right_connected.Assign(1);
  466. pad_state.connection_status.is_left_wired.Assign(1);
  467. pad_state.connection_status.is_right_wired.Assign(1);
  468. libnx_state.connection_status.is_wired.Assign(1);
  469. libnx_state.connection_status.is_left_connected.Assign(1);
  470. libnx_state.connection_status.is_right_connected.Assign(1);
  471. libnx_state.connection_status.is_left_wired.Assign(1);
  472. libnx_state.connection_status.is_right_wired.Assign(1);
  473. pad_state.sampling_number =
  474. npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  475. npad->handheld_lifo.WriteNextEntry(pad_state);
  476. break;
  477. case Core::HID::NpadStyleIndex::JoyconDual:
  478. pad_state.connection_status.raw = 0;
  479. pad_state.connection_status.is_connected.Assign(1);
  480. if (controller.is_dual_left_connected) {
  481. pad_state.connection_status.is_left_connected.Assign(1);
  482. libnx_state.connection_status.is_left_connected.Assign(1);
  483. }
  484. if (controller.is_dual_right_connected) {
  485. pad_state.connection_status.is_right_connected.Assign(1);
  486. libnx_state.connection_status.is_right_connected.Assign(1);
  487. }
  488. pad_state.sampling_number =
  489. npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
  490. npad->joy_dual_lifo.WriteNextEntry(pad_state);
  491. break;
  492. case Core::HID::NpadStyleIndex::JoyconLeft:
  493. pad_state.connection_status.raw = 0;
  494. pad_state.connection_status.is_connected.Assign(1);
  495. pad_state.connection_status.is_left_connected.Assign(1);
  496. libnx_state.connection_status.is_left_connected.Assign(1);
  497. pad_state.sampling_number =
  498. npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  499. npad->joy_left_lifo.WriteNextEntry(pad_state);
  500. break;
  501. case Core::HID::NpadStyleIndex::JoyconRight:
  502. pad_state.connection_status.raw = 0;
  503. pad_state.connection_status.is_connected.Assign(1);
  504. pad_state.connection_status.is_right_connected.Assign(1);
  505. libnx_state.connection_status.is_right_connected.Assign(1);
  506. pad_state.sampling_number =
  507. npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  508. npad->joy_right_lifo.WriteNextEntry(pad_state);
  509. break;
  510. case Core::HID::NpadStyleIndex::GameCube:
  511. pad_state.connection_status.raw = 0;
  512. pad_state.connection_status.is_connected.Assign(1);
  513. pad_state.connection_status.is_wired.Assign(1);
  514. libnx_state.connection_status.is_wired.Assign(1);
  515. pad_state.sampling_number =
  516. npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  517. trigger_state.sampling_number =
  518. npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
  519. npad->fullkey_lifo.WriteNextEntry(pad_state);
  520. npad->gc_trigger_lifo.WriteNextEntry(trigger_state);
  521. break;
  522. case Core::HID::NpadStyleIndex::Pokeball:
  523. pad_state.connection_status.raw = 0;
  524. pad_state.connection_status.is_connected.Assign(1);
  525. pad_state.sampling_number =
  526. npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
  527. npad->palma_lifo.WriteNextEntry(pad_state);
  528. break;
  529. default:
  530. break;
  531. }
  532. libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
  533. libnx_state.l_stick = pad_state.l_stick;
  534. libnx_state.r_stick = pad_state.r_stick;
  535. npad->system_ext_lifo.WriteNextEntry(pad_state);
  536. press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
  537. }
  538. }
  539. }
  540. Result NPad::SetSupportedNpadStyleSet(u64 aruid, Core::HID::NpadStyleSet supported_style_set) {
  541. std::scoped_lock lock{mutex};
  542. hid_core.SetSupportedStyleTag({supported_style_set});
  543. const Result result = npad_resource.SetSupportedNpadStyleSet(aruid, supported_style_set);
  544. if (result.IsSuccess()) {
  545. OnUpdate({});
  546. }
  547. return result;
  548. }
  549. Result NPad::GetSupportedNpadStyleSet(u64 aruid,
  550. Core::HID::NpadStyleSet& out_supported_style_set) const {
  551. std::scoped_lock lock{mutex};
  552. const Result result = npad_resource.GetSupportedNpadStyleSet(out_supported_style_set, aruid);
  553. if (result == ResultUndefinedStyleset) {
  554. out_supported_style_set = Core::HID::NpadStyleSet::None;
  555. return ResultSuccess;
  556. }
  557. return result;
  558. }
  559. Result NPad::GetMaskedSupportedNpadStyleSet(
  560. u64 aruid, Core::HID::NpadStyleSet& out_supported_style_set) const {
  561. std::scoped_lock lock{mutex};
  562. const Result result =
  563. npad_resource.GetMaskedSupportedNpadStyleSet(out_supported_style_set, aruid);
  564. if (result == ResultUndefinedStyleset) {
  565. out_supported_style_set = Core::HID::NpadStyleSet::None;
  566. return ResultSuccess;
  567. }
  568. return result;
  569. }
  570. Result NPad::SetSupportedNpadIdType(u64 aruid,
  571. std::span<const Core::HID::NpadIdType> supported_npad_list) {
  572. std::scoped_lock lock{mutex};
  573. if (supported_npad_list.size() > MaxSupportedNpadIdTypes) {
  574. return ResultInvalidArraySize;
  575. }
  576. Result result = npad_resource.SetSupportedNpadIdType(aruid, supported_npad_list);
  577. if (result.IsSuccess()) {
  578. OnUpdate({});
  579. }
  580. return result;
  581. }
  582. Result NPad::SetNpadJoyHoldType(u64 aruid, NpadJoyHoldType hold_type) {
  583. std::scoped_lock lock{mutex};
  584. return npad_resource.SetNpadJoyHoldType(aruid, hold_type);
  585. }
  586. Result NPad::GetNpadJoyHoldType(u64 aruid, NpadJoyHoldType& out_hold_type) const {
  587. std::scoped_lock lock{mutex};
  588. return npad_resource.GetNpadJoyHoldType(out_hold_type, aruid);
  589. }
  590. Result NPad::SetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode mode) {
  591. std::scoped_lock lock{mutex};
  592. Result result = npad_resource.SetNpadHandheldActivationMode(aruid, mode);
  593. if (result.IsSuccess()) {
  594. OnUpdate({});
  595. }
  596. return result;
  597. }
  598. Result NPad::GetNpadHandheldActivationMode(u64 aruid, NpadHandheldActivationMode& out_mode) const {
  599. std::scoped_lock lock{mutex};
  600. return npad_resource.GetNpadHandheldActivationMode(out_mode, aruid);
  601. }
  602. bool NPad::SetNpadMode(u64 aruid, Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
  603. NpadJoyDeviceType npad_device_type, NpadJoyAssignmentMode assignment_mode) {
  604. if (!IsNpadIdValid(npad_id)) {
  605. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  606. return false;
  607. }
  608. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  609. if (controller.shared_memory->assignment_mode != assignment_mode) {
  610. controller.shared_memory->assignment_mode = assignment_mode;
  611. }
  612. if (!controller.device->IsConnected()) {
  613. return false;
  614. }
  615. if (assignment_mode == NpadJoyAssignmentMode::Dual) {
  616. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) {
  617. DisconnectNpad(aruid, npad_id);
  618. controller.is_dual_left_connected = true;
  619. controller.is_dual_right_connected = false;
  620. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  621. return false;
  622. }
  623. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
  624. DisconnectNpad(aruid, npad_id);
  625. controller.is_dual_left_connected = false;
  626. controller.is_dual_right_connected = true;
  627. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  628. return false;
  629. }
  630. return false;
  631. }
  632. // This is for NpadJoyAssignmentMode::Single
  633. // Only JoyconDual get affected by this function
  634. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
  635. return false;
  636. }
  637. if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
  638. DisconnectNpad(aruid, npad_id);
  639. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  640. return false;
  641. }
  642. if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
  643. DisconnectNpad(aruid, npad_id);
  644. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  645. return false;
  646. }
  647. // We have two controllers connected to the same npad_id we need to split them
  648. new_npad_id = hid_core.GetFirstDisconnectedNpadId();
  649. auto& controller_2 = GetControllerFromNpadIdType(aruid, new_npad_id);
  650. DisconnectNpad(aruid, npad_id);
  651. if (npad_device_type == NpadJoyDeviceType::Left) {
  652. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  653. controller_2.is_dual_left_connected = false;
  654. controller_2.is_dual_right_connected = true;
  655. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
  656. } else {
  657. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  658. controller_2.is_dual_left_connected = true;
  659. controller_2.is_dual_right_connected = false;
  660. UpdateControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
  661. }
  662. return true;
  663. }
  664. bool NPad::VibrateControllerAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
  665. std::size_t device_index,
  666. const Core::HID::VibrationValue& vibration_value) {
  667. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  668. if (!controller.device->IsConnected()) {
  669. return false;
  670. }
  671. if (!controller.device->IsVibrationEnabled(device_index)) {
  672. if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
  673. controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
  674. // Send an empty vibration to stop any vibrations.
  675. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
  676. controller.device->SetVibration(device_index, vibration);
  677. // Then reset the vibration value to its default value.
  678. controller.vibration[device_index].latest_vibration_value =
  679. Core::HID::DEFAULT_VIBRATION_VALUE;
  680. }
  681. return false;
  682. }
  683. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  684. using std::chrono::duration_cast;
  685. using std::chrono::milliseconds;
  686. using std::chrono::steady_clock;
  687. const auto now = steady_clock::now();
  688. // Filter out non-zero vibrations that are within 15ms of each other.
  689. if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
  690. duration_cast<milliseconds>(
  691. now - controller.vibration[device_index].last_vibration_timepoint) <
  692. milliseconds(15)) {
  693. return false;
  694. }
  695. controller.vibration[device_index].last_vibration_timepoint = now;
  696. }
  697. Core::HID::VibrationValue vibration{
  698. vibration_value.low_amplitude, vibration_value.low_frequency,
  699. vibration_value.high_amplitude, vibration_value.high_frequency};
  700. return controller.device->SetVibration(device_index, vibration);
  701. }
  702. void NPad::VibrateController(u64 aruid,
  703. const Core::HID::VibrationDeviceHandle& vibration_device_handle,
  704. const Core::HID::VibrationValue& vibration_value) {
  705. if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
  706. return;
  707. }
  708. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  709. return;
  710. }
  711. auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
  712. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  713. if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
  714. return;
  715. }
  716. if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
  717. ASSERT_MSG(false, "DeviceIndex should never be None!");
  718. return;
  719. }
  720. // Some games try to send mismatched parameters in the device handle, block these.
  721. if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  722. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
  723. vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
  724. (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
  725. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
  726. vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
  727. return;
  728. }
  729. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  730. if (vibration_value.low_amplitude ==
  731. controller.vibration[device_index].latest_vibration_value.low_amplitude &&
  732. vibration_value.high_amplitude ==
  733. controller.vibration[device_index].latest_vibration_value.high_amplitude) {
  734. return;
  735. }
  736. if (VibrateControllerAtIndex(aruid, controller.device->GetNpadIdType(), device_index,
  737. vibration_value)) {
  738. controller.vibration[device_index].latest_vibration_value = vibration_value;
  739. }
  740. }
  741. void NPad::VibrateControllers(
  742. u64 aruid, std::span<const Core::HID::VibrationDeviceHandle> vibration_device_handles,
  743. std::span<const Core::HID::VibrationValue> vibration_values) {
  744. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  745. return;
  746. }
  747. ASSERT_OR_EXECUTE_MSG(
  748. vibration_device_handles.size() == vibration_values.size(), { return; },
  749. "The amount of device handles does not match with the amount of vibration values,"
  750. "this is undefined behavior!");
  751. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  752. VibrateController(aruid, vibration_device_handles[i], vibration_values[i]);
  753. }
  754. }
  755. Core::HID::VibrationValue NPad::GetLastVibration(
  756. u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  757. if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
  758. return {};
  759. }
  760. const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
  761. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  762. return controller.vibration[device_index].latest_vibration_value;
  763. }
  764. void NPad::InitializeVibrationDevice(
  765. const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
  766. if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
  767. return;
  768. }
  769. const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
  770. const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
  771. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  772. InitializeVibrationDeviceAtIndex(aruid, npad_index, device_index);
  773. }
  774. void NPad::InitializeVibrationDeviceAtIndex(u64 aruid, Core::HID::NpadIdType npad_id,
  775. std::size_t device_index) {
  776. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  777. if (!Settings::values.vibration_enabled.GetValue()) {
  778. controller.vibration[device_index].device_mounted = false;
  779. return;
  780. }
  781. controller.vibration[device_index].device_mounted =
  782. controller.device->IsVibrationEnabled(device_index);
  783. }
  784. void NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  785. permit_vibration_session_enabled = permit_vibration_session;
  786. }
  787. bool NPad::IsVibrationDeviceMounted(
  788. u64 aruid, const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  789. if (IsVibrationHandleValid(vibration_device_handle).IsError()) {
  790. return false;
  791. }
  792. const auto& controller = GetControllerFromHandle(aruid, vibration_device_handle);
  793. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  794. return controller.vibration[device_index].device_mounted;
  795. }
  796. Result NPad::AcquireNpadStyleSetUpdateEventHandle(u64 aruid, Kernel::KReadableEvent** out_event,
  797. Core::HID::NpadIdType npad_id) {
  798. std::scoped_lock lock{mutex};
  799. return npad_resource.AcquireNpadStyleSetUpdateEventHandle(aruid, out_event, npad_id);
  800. }
  801. void NPad::AddNewControllerAt(u64 aruid, Core::HID::NpadStyleIndex controller,
  802. Core::HID::NpadIdType npad_id) {
  803. UpdateControllerAt(aruid, controller, npad_id, true);
  804. }
  805. void NPad::UpdateControllerAt(u64 aruid, Core::HID::NpadStyleIndex type,
  806. Core::HID::NpadIdType npad_id, bool connected) {
  807. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  808. if (!connected) {
  809. DisconnectNpad(aruid, npad_id);
  810. return;
  811. }
  812. controller.device->SetNpadStyleIndex(type);
  813. InitNewlyAddedController(aruid, npad_id);
  814. }
  815. Result NPad::DisconnectNpad(u64 aruid, Core::HID::NpadIdType npad_id) {
  816. if (!IsNpadIdValid(npad_id)) {
  817. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  818. return ResultInvalidNpadId;
  819. }
  820. LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
  821. auto& controller = GetControllerFromNpadIdType(aruid, npad_id);
  822. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  823. // Send an empty vibration to stop any vibrations.
  824. VibrateControllerAtIndex(aruid, npad_id, device_idx, {});
  825. controller.vibration[device_idx].device_mounted = false;
  826. }
  827. auto* shared_memory = controller.shared_memory;
  828. // Don't reset shared_memory->assignment_mode this value is persistent
  829. shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
  830. shared_memory->device_type.raw = 0;
  831. shared_memory->system_properties.raw = 0;
  832. shared_memory->button_properties.raw = 0;
  833. shared_memory->sixaxis_fullkey_properties.raw = 0;
  834. shared_memory->sixaxis_handheld_properties.raw = 0;
  835. shared_memory->sixaxis_dual_left_properties.raw = 0;
  836. shared_memory->sixaxis_dual_right_properties.raw = 0;
  837. shared_memory->sixaxis_left_properties.raw = 0;
  838. shared_memory->sixaxis_right_properties.raw = 0;
  839. shared_memory->battery_level_dual = Core::HID::NpadBatteryLevel::Empty;
  840. shared_memory->battery_level_left = Core::HID::NpadBatteryLevel::Empty;
  841. shared_memory->battery_level_right = Core::HID::NpadBatteryLevel::Empty;
  842. shared_memory->fullkey_color = {
  843. .attribute = ColorAttribute::NoController,
  844. .fullkey = {},
  845. };
  846. shared_memory->joycon_color = {
  847. .attribute = ColorAttribute::NoController,
  848. .left = {},
  849. .right = {},
  850. };
  851. shared_memory->applet_footer_type = AppletFooterUiType::None;
  852. controller.is_dual_left_connected = true;
  853. controller.is_dual_right_connected = true;
  854. controller.is_connected = false;
  855. controller.device->Disconnect();
  856. npad_resource.SignalStyleSetUpdateEvent(aruid, npad_id);
  857. WriteEmptyEntry(shared_memory);
  858. return ResultSuccess;
  859. }
  860. Result NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
  861. u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  862. bool& is_firmware_available) const {
  863. const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
  864. if (is_valid.IsError()) {
  865. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  866. return is_valid;
  867. }
  868. const auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle);
  869. is_firmware_available = sixaxis_properties.is_firmware_update_available != 0;
  870. return ResultSuccess;
  871. }
  872. Result NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
  873. u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
  874. const auto is_valid = IsSixaxisHandleValid(sixaxis_handle);
  875. if (is_valid.IsError()) {
  876. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  877. return is_valid;
  878. }
  879. auto& sixaxis_properties = GetSixaxisProperties(aruid, sixaxis_handle);
  880. sixaxis_properties.is_newly_assigned.Assign(0);
  881. return ResultSuccess;
  882. }
  883. Result NPad::MergeSingleJoyAsDualJoy(u64 aruid, Core::HID::NpadIdType npad_id_1,
  884. Core::HID::NpadIdType npad_id_2) {
  885. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  886. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  887. npad_id_2);
  888. return ResultInvalidNpadId;
  889. }
  890. auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1);
  891. auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2);
  892. auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
  893. auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
  894. // Simplify this code by converting dualjoycon with only a side connected to single joycons
  895. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) {
  896. if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
  897. controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft;
  898. }
  899. if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
  900. controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight;
  901. }
  902. }
  903. if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
  904. if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
  905. controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft;
  906. }
  907. if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
  908. controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight;
  909. }
  910. }
  911. // Invalid merge errors
  912. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual ||
  913. controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
  914. return NpadIsDualJoycon;
  915. }
  916. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
  917. controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) {
  918. return NpadIsSameType;
  919. }
  920. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
  921. controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
  922. return NpadIsSameType;
  923. }
  924. // These exceptions are handled as if they where dual joycon
  925. if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft &&
  926. controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) {
  927. return NpadIsDualJoycon;
  928. }
  929. if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft &&
  930. controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) {
  931. return NpadIsDualJoycon;
  932. }
  933. // Disconnect the joycons and connect them as dual joycon at the first index.
  934. DisconnectNpad(aruid, npad_id_1);
  935. DisconnectNpad(aruid, npad_id_2);
  936. controller_1.is_dual_left_connected = true;
  937. controller_1.is_dual_right_connected = true;
  938. AddNewControllerAt(aruid, Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
  939. return ResultSuccess;
  940. }
  941. Result NPad::StartLrAssignmentMode(u64 aruid) {
  942. std::scoped_lock lock{mutex};
  943. bool is_enabled{};
  944. Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid);
  945. if (result.IsSuccess() && is_enabled == false) {
  946. result = npad_resource.SetLrAssignmentMode(aruid, true);
  947. }
  948. return result;
  949. }
  950. Result NPad::StopLrAssignmentMode(u64 aruid) {
  951. std::scoped_lock lock{mutex};
  952. bool is_enabled{};
  953. Result result = npad_resource.GetLrAssignmentMode(is_enabled, aruid);
  954. if (result.IsSuccess() && is_enabled == true) {
  955. result = npad_resource.SetLrAssignmentMode(aruid, false);
  956. }
  957. return result;
  958. }
  959. Result NPad::SwapNpadAssignment(u64 aruid, Core::HID::NpadIdType npad_id_1,
  960. Core::HID::NpadIdType npad_id_2) {
  961. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  962. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  963. npad_id_2);
  964. return ResultInvalidNpadId;
  965. }
  966. if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
  967. npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
  968. npad_id_2 == Core::HID::NpadIdType::Other) {
  969. return ResultSuccess;
  970. }
  971. const auto& controller_1 = GetControllerFromNpadIdType(aruid, npad_id_1).device;
  972. const auto& controller_2 = GetControllerFromNpadIdType(aruid, npad_id_2).device;
  973. const auto type_index_1 = controller_1->GetNpadStyleIndex();
  974. const auto type_index_2 = controller_2->GetNpadStyleIndex();
  975. const auto is_connected_1 = controller_1->IsConnected();
  976. const auto is_connected_2 = controller_2->IsConnected();
  977. if (!npad_resource.IsControllerSupported(aruid, type_index_1) && is_connected_1) {
  978. return ResultNpadNotConnected;
  979. }
  980. if (!npad_resource.IsControllerSupported(aruid, type_index_2) && is_connected_2) {
  981. return ResultNpadNotConnected;
  982. }
  983. UpdateControllerAt(aruid, type_index_2, npad_id_1, is_connected_2);
  984. UpdateControllerAt(aruid, type_index_1, npad_id_2, is_connected_1);
  985. return ResultSuccess;
  986. }
  987. Result NPad::GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const {
  988. if (!IsNpadIdValid(npad_id)) {
  989. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  990. return ResultInvalidNpadId;
  991. }
  992. const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
  993. const auto& controller = GetControllerFromNpadIdType(aruid, npad_id).device;
  994. pattern = controller->GetLedPattern();
  995. return ResultSuccess;
  996. }
  997. Result NPad::IsUnintendedHomeButtonInputProtectionEnabled(bool& out_is_enabled, u64 aruid,
  998. Core::HID::NpadIdType npad_id) const {
  999. std::scoped_lock lock{mutex};
  1000. return npad_resource.GetHomeProtectionEnabled(out_is_enabled, aruid, npad_id);
  1001. }
  1002. Result NPad::EnableUnintendedHomeButtonInputProtection(u64 aruid, Core::HID::NpadIdType npad_id,
  1003. bool is_enabled) {
  1004. std::scoped_lock lock{mutex};
  1005. return npad_resource.SetHomeProtectionEnabled(aruid, npad_id, is_enabled);
  1006. }
  1007. void NPad::SetNpadAnalogStickUseCenterClamp(u64 aruid, bool is_enabled) {
  1008. std::scoped_lock lock{mutex};
  1009. npad_resource.SetNpadAnalogStickUseCenterClamp(aruid, is_enabled);
  1010. }
  1011. void NPad::ClearAllConnectedControllers() {
  1012. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
  1013. for (auto& controller : controller_data[aruid_index]) {
  1014. if (controller.device->IsConnected() &&
  1015. controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
  1016. controller.device->Disconnect();
  1017. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1018. }
  1019. }
  1020. }
  1021. }
  1022. void NPad::DisconnectAllConnectedControllers() {
  1023. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
  1024. for (auto& controller : controller_data[aruid_index]) {
  1025. controller.device->Disconnect();
  1026. }
  1027. }
  1028. }
  1029. void NPad::ConnectAllDisconnectedControllers() {
  1030. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
  1031. for (auto& controller : controller_data[aruid_index]) {
  1032. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
  1033. !controller.device->IsConnected()) {
  1034. controller.device->Connect();
  1035. }
  1036. }
  1037. }
  1038. }
  1039. void NPad::ClearAllControllers() {
  1040. for (std::size_t aruid_index = 0; aruid_index < AruidIndexMax; aruid_index++) {
  1041. for (auto& controller : controller_data[aruid_index]) {
  1042. controller.device->Disconnect();
  1043. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1044. }
  1045. }
  1046. }
  1047. Core::HID::NpadButton NPad::GetAndResetPressState() {
  1048. return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
  1049. }
  1050. Result NPad::ApplyNpadSystemCommonPolicy(u64 aruid) {
  1051. std::scoped_lock lock{mutex};
  1052. const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, false);
  1053. if (result.IsSuccess()) {
  1054. OnUpdate({});
  1055. }
  1056. return result;
  1057. }
  1058. Result NPad::ApplyNpadSystemCommonPolicyFull(u64 aruid) {
  1059. std::scoped_lock lock{mutex};
  1060. const Result result = npad_resource.ApplyNpadSystemCommonPolicy(aruid, true);
  1061. if (result.IsSuccess()) {
  1062. OnUpdate({});
  1063. }
  1064. return result;
  1065. }
  1066. Result NPad::ClearNpadSystemCommonPolicy(u64 aruid) {
  1067. std::scoped_lock lock{mutex};
  1068. const Result result = npad_resource.ClearNpadSystemCommonPolicy(aruid);
  1069. if (result.IsSuccess()) {
  1070. OnUpdate({});
  1071. }
  1072. return result;
  1073. }
  1074. void NPad::SetRevision(u64 aruid, NpadRevision revision) {
  1075. npad_resource.SetNpadRevision(aruid, revision);
  1076. }
  1077. NpadRevision NPad::GetRevision(u64 aruid) {
  1078. return npad_resource.GetNpadRevision(aruid);
  1079. }
  1080. Result NPad::RegisterAppletResourceUserId(u64 aruid) {
  1081. return npad_resource.RegisterAppletResourceUserId(aruid);
  1082. }
  1083. void NPad::UnregisterAppletResourceUserId(u64 aruid) {
  1084. npad_resource.UnregisterAppletResourceUserId(aruid);
  1085. }
  1086. void NPad::SetNpadExternals(std::shared_ptr<AppletResource> resource,
  1087. std::recursive_mutex* shared_mutex) {
  1088. applet_resource_holder.applet_resource = resource;
  1089. applet_resource_holder.shared_mutex = shared_mutex;
  1090. applet_resource_holder.shared_npad_resource = &npad_resource;
  1091. }
  1092. NPad::NpadControllerData& NPad::GetControllerFromHandle(
  1093. u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) {
  1094. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1095. return GetControllerFromNpadIdType(aruid, npad_id);
  1096. }
  1097. const NPad::NpadControllerData& NPad::GetControllerFromHandle(
  1098. u64 aruid, const Core::HID::VibrationDeviceHandle& device_handle) const {
  1099. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1100. return GetControllerFromNpadIdType(aruid, npad_id);
  1101. }
  1102. NPad::NpadControllerData& NPad::GetControllerFromHandle(
  1103. u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) {
  1104. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1105. return GetControllerFromNpadIdType(aruid, npad_id);
  1106. }
  1107. const NPad::NpadControllerData& NPad::GetControllerFromHandle(
  1108. u64 aruid, const Core::HID::SixAxisSensorHandle& device_handle) const {
  1109. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1110. return GetControllerFromNpadIdType(aruid, npad_id);
  1111. }
  1112. NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(u64 aruid,
  1113. Core::HID::NpadIdType npad_id) {
  1114. if (!IsNpadIdValid(npad_id)) {
  1115. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1116. npad_id = Core::HID::NpadIdType::Player1;
  1117. }
  1118. const auto npad_index = NpadIdTypeToIndex(npad_id);
  1119. const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid);
  1120. return controller_data[aruid_index][npad_index];
  1121. }
  1122. const NPad::NpadControllerData& NPad::GetControllerFromNpadIdType(
  1123. u64 aruid, Core::HID::NpadIdType npad_id) const {
  1124. if (!IsNpadIdValid(npad_id)) {
  1125. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1126. npad_id = Core::HID::NpadIdType::Player1;
  1127. }
  1128. const auto npad_index = NpadIdTypeToIndex(npad_id);
  1129. const auto aruid_index = applet_resource_holder.applet_resource->GetIndexFromAruid(aruid);
  1130. return controller_data[aruid_index][npad_index];
  1131. }
  1132. Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
  1133. u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
  1134. auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
  1135. switch (sixaxis_handle.npad_type) {
  1136. case Core::HID::NpadStyleIndex::ProController:
  1137. case Core::HID::NpadStyleIndex::Pokeball:
  1138. return controller.shared_memory->sixaxis_fullkey_properties;
  1139. case Core::HID::NpadStyleIndex::Handheld:
  1140. return controller.shared_memory->sixaxis_handheld_properties;
  1141. case Core::HID::NpadStyleIndex::JoyconDual:
  1142. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1143. return controller.shared_memory->sixaxis_dual_left_properties;
  1144. }
  1145. return controller.shared_memory->sixaxis_dual_right_properties;
  1146. case Core::HID::NpadStyleIndex::JoyconLeft:
  1147. return controller.shared_memory->sixaxis_left_properties;
  1148. case Core::HID::NpadStyleIndex::JoyconRight:
  1149. return controller.shared_memory->sixaxis_right_properties;
  1150. default:
  1151. return controller.shared_memory->sixaxis_fullkey_properties;
  1152. }
  1153. }
  1154. const Core::HID::SixAxisSensorProperties& NPad::GetSixaxisProperties(
  1155. u64 aruid, const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
  1156. const auto& controller = GetControllerFromHandle(aruid, sixaxis_handle);
  1157. switch (sixaxis_handle.npad_type) {
  1158. case Core::HID::NpadStyleIndex::ProController:
  1159. case Core::HID::NpadStyleIndex::Pokeball:
  1160. return controller.shared_memory->sixaxis_fullkey_properties;
  1161. case Core::HID::NpadStyleIndex::Handheld:
  1162. return controller.shared_memory->sixaxis_handheld_properties;
  1163. case Core::HID::NpadStyleIndex::JoyconDual:
  1164. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1165. return controller.shared_memory->sixaxis_dual_left_properties;
  1166. }
  1167. return controller.shared_memory->sixaxis_dual_right_properties;
  1168. case Core::HID::NpadStyleIndex::JoyconLeft:
  1169. return controller.shared_memory->sixaxis_left_properties;
  1170. case Core::HID::NpadStyleIndex::JoyconRight:
  1171. return controller.shared_memory->sixaxis_right_properties;
  1172. default:
  1173. return controller.shared_memory->sixaxis_fullkey_properties;
  1174. }
  1175. }
  1176. AppletDetailedUiType NPad::GetAppletDetailedUiType(Core::HID::NpadIdType npad_id) {
  1177. const auto aruid = applet_resource_holder.applet_resource->GetActiveAruid();
  1178. const auto& shared_memory = GetControllerFromNpadIdType(aruid, npad_id).shared_memory;
  1179. return {
  1180. .ui_variant = 0,
  1181. .footer = shared_memory->applet_footer_type,
  1182. };
  1183. }
  1184. } // namespace Service::HID