npad.cpp 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702
  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/hid/emulated_controller.h"
  14. #include "core/hid/hid_core.h"
  15. #include "core/hle/kernel/k_event.h"
  16. #include "core/hle/kernel/k_readable_event.h"
  17. #include "core/hle/service/hid/controllers/npad.h"
  18. #include "core/hle/service/hid/errors.h"
  19. #include "core/hle/service/kernel_helpers.h"
  20. namespace Service::HID {
  21. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  22. constexpr std::array<Core::HID::NpadIdType, 10> npad_id_list{
  23. Core::HID::NpadIdType::Player1, Core::HID::NpadIdType::Player2, Core::HID::NpadIdType::Player3,
  24. Core::HID::NpadIdType::Player4, Core::HID::NpadIdType::Player5, Core::HID::NpadIdType::Player6,
  25. Core::HID::NpadIdType::Player7, Core::HID::NpadIdType::Player8, Core::HID::NpadIdType::Other,
  26. Core::HID::NpadIdType::Handheld,
  27. };
  28. bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
  29. switch (npad_id) {
  30. case Core::HID::NpadIdType::Player1:
  31. case Core::HID::NpadIdType::Player2:
  32. case Core::HID::NpadIdType::Player3:
  33. case Core::HID::NpadIdType::Player4:
  34. case Core::HID::NpadIdType::Player5:
  35. case Core::HID::NpadIdType::Player6:
  36. case Core::HID::NpadIdType::Player7:
  37. case Core::HID::NpadIdType::Player8:
  38. case Core::HID::NpadIdType::Other:
  39. case Core::HID::NpadIdType::Handheld:
  40. return true;
  41. default:
  42. LOG_ERROR(Service_HID, "Invalid npad id {}", npad_id);
  43. return false;
  44. }
  45. }
  46. Result Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
  47. const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
  48. const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
  49. const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  50. if (!npad_type) {
  51. return VibrationInvalidStyleIndex;
  52. }
  53. if (!npad_id) {
  54. return VibrationInvalidNpadId;
  55. }
  56. if (!device_index) {
  57. return VibrationDeviceIndexOutOfRange;
  58. }
  59. return ResultSuccess;
  60. }
  61. Result Controller_NPad::VerifyValidSixAxisSensorHandle(
  62. const Core::HID::SixAxisSensorHandle& device_handle) {
  63. const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
  64. const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
  65. const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
  66. if (!npad_id) {
  67. return InvalidNpadId;
  68. }
  69. if (!device_index) {
  70. return NpadDeviceIndexOutOfRange;
  71. }
  72. // This doesn't get validated on nnsdk
  73. if (!npad_type) {
  74. return NpadInvalidHandle;
  75. }
  76. return ResultSuccess;
  77. }
  78. Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
  79. KernelHelpers::ServiceContext& service_context_)
  80. : ControllerBase{hid_core_}, service_context{service_context_} {
  81. static_assert(NPAD_OFFSET + (NPAD_COUNT * sizeof(NpadInternalState)) < shared_memory_size);
  82. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  83. auto& controller = controller_data[i];
  84. controller.shared_memory = std::construct_at(reinterpret_cast<NpadInternalState*>(
  85. raw_shared_memory_ + NPAD_OFFSET + (i * sizeof(NpadInternalState))));
  86. controller.device = hid_core.GetEmulatedControllerByIndex(i);
  87. controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
  88. Core::HID::DEFAULT_VIBRATION_VALUE;
  89. controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
  90. Core::HID::DEFAULT_VIBRATION_VALUE;
  91. Core::HID::ControllerUpdateCallback engine_callback{
  92. .on_change = [this,
  93. i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
  94. .is_npad_service = true,
  95. };
  96. controller.callback_key = controller.device->SetCallback(engine_callback);
  97. }
  98. }
  99. Controller_NPad::~Controller_NPad() {
  100. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  101. auto& controller = controller_data[i];
  102. controller.device->DeleteCallback(controller.callback_key);
  103. }
  104. OnRelease();
  105. }
  106. void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
  107. std::size_t controller_idx) {
  108. if (type == Core::HID::ControllerTriggerType::All) {
  109. ControllerUpdate(Core::HID::ControllerTriggerType::Connected, controller_idx);
  110. ControllerUpdate(Core::HID::ControllerTriggerType::Battery, controller_idx);
  111. return;
  112. }
  113. if (controller_idx >= controller_data.size()) {
  114. return;
  115. }
  116. auto& controller = controller_data[controller_idx];
  117. const auto is_connected = controller.device->IsConnected();
  118. const auto npad_type = controller.device->GetNpadStyleIndex();
  119. const auto npad_id = controller.device->GetNpadIdType();
  120. switch (type) {
  121. case Core::HID::ControllerTriggerType::Connected:
  122. case Core::HID::ControllerTriggerType::Disconnected:
  123. if (is_connected == controller.is_connected) {
  124. return;
  125. }
  126. UpdateControllerAt(npad_type, npad_id, is_connected);
  127. break;
  128. case Core::HID::ControllerTriggerType::Battery: {
  129. if (!controller.device->IsConnected()) {
  130. return;
  131. }
  132. auto* shared_memory = controller.shared_memory;
  133. const auto& battery_level = controller.device->GetBattery();
  134. shared_memory->battery_level_dual = battery_level.dual.battery_level;
  135. shared_memory->battery_level_left = battery_level.left.battery_level;
  136. shared_memory->battery_level_right = battery_level.right.battery_level;
  137. break;
  138. }
  139. default:
  140. break;
  141. }
  142. }
  143. void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
  144. auto& controller = GetControllerFromNpadIdType(npad_id);
  145. if (!IsControllerSupported(controller.device->GetNpadStyleIndex())) {
  146. return;
  147. }
  148. LOG_DEBUG(Service_HID, "Npad connected {}", npad_id);
  149. const auto controller_type = controller.device->GetNpadStyleIndex();
  150. const auto& body_colors = controller.device->GetColors();
  151. const auto& battery_level = controller.device->GetBattery();
  152. auto* shared_memory = controller.shared_memory;
  153. if (controller_type == Core::HID::NpadStyleIndex::None) {
  154. controller.styleset_changed_event->Signal();
  155. return;
  156. }
  157. // Reset memory values
  158. shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None;
  159. shared_memory->device_type.raw = 0;
  160. shared_memory->system_properties.raw = 0;
  161. shared_memory->joycon_color.attribute = ColorAttribute::NoController;
  162. shared_memory->joycon_color.attribute = ColorAttribute::NoController;
  163. shared_memory->fullkey_color = {};
  164. shared_memory->joycon_color.left = {};
  165. shared_memory->joycon_color.right = {};
  166. shared_memory->battery_level_dual = {};
  167. shared_memory->battery_level_left = {};
  168. shared_memory->battery_level_right = {};
  169. switch (controller_type) {
  170. case Core::HID::NpadStyleIndex::None:
  171. ASSERT(false);
  172. break;
  173. case Core::HID::NpadStyleIndex::ProController:
  174. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  175. shared_memory->fullkey_color.fullkey = body_colors.fullkey;
  176. shared_memory->battery_level_dual = battery_level.dual.battery_level;
  177. shared_memory->style_tag.fullkey.Assign(1);
  178. shared_memory->device_type.fullkey.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->system_properties.is_charging_joy_dual.Assign(
  183. battery_level.dual.is_charging);
  184. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
  185. shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
  186. break;
  187. case Core::HID::NpadStyleIndex::Handheld:
  188. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  189. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  190. shared_memory->fullkey_color.fullkey = body_colors.fullkey;
  191. shared_memory->joycon_color.left = body_colors.left;
  192. shared_memory->joycon_color.right = body_colors.right;
  193. shared_memory->style_tag.handheld.Assign(1);
  194. shared_memory->device_type.handheld_left.Assign(1);
  195. shared_memory->device_type.handheld_right.Assign(1);
  196. shared_memory->system_properties.is_vertical.Assign(1);
  197. shared_memory->system_properties.use_plus.Assign(1);
  198. shared_memory->system_properties.use_minus.Assign(1);
  199. shared_memory->system_properties.use_directional_buttons.Assign(1);
  200. shared_memory->system_properties.is_charging_joy_dual.Assign(
  201. battery_level.left.is_charging);
  202. shared_memory->system_properties.is_charging_joy_left.Assign(
  203. battery_level.left.is_charging);
  204. shared_memory->system_properties.is_charging_joy_right.Assign(
  205. battery_level.right.is_charging);
  206. shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
  207. shared_memory->applet_nfc_xcd.applet_footer.type =
  208. AppletFooterUiType::HandheldJoyConLeftJoyConRight;
  209. shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
  210. break;
  211. case Core::HID::NpadStyleIndex::JoyconDual:
  212. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  213. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  214. shared_memory->style_tag.joycon_dual.Assign(1);
  215. if (controller.is_dual_left_connected) {
  216. shared_memory->joycon_color.left = body_colors.left;
  217. shared_memory->battery_level_left = battery_level.left.battery_level;
  218. shared_memory->device_type.joycon_left.Assign(1);
  219. shared_memory->system_properties.use_minus.Assign(1);
  220. shared_memory->system_properties.is_charging_joy_left.Assign(
  221. battery_level.left.is_charging);
  222. shared_memory->sixaxis_dual_left_properties.is_newly_assigned.Assign(1);
  223. }
  224. if (controller.is_dual_right_connected) {
  225. shared_memory->joycon_color.right = body_colors.right;
  226. shared_memory->battery_level_right = battery_level.right.battery_level;
  227. shared_memory->device_type.joycon_right.Assign(1);
  228. shared_memory->system_properties.use_plus.Assign(1);
  229. shared_memory->system_properties.is_charging_joy_right.Assign(
  230. battery_level.right.is_charging);
  231. shared_memory->sixaxis_dual_right_properties.is_newly_assigned.Assign(1);
  232. }
  233. shared_memory->system_properties.use_directional_buttons.Assign(1);
  234. shared_memory->system_properties.is_vertical.Assign(1);
  235. shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
  236. if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
  237. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDual;
  238. shared_memory->fullkey_color.fullkey = body_colors.left;
  239. shared_memory->battery_level_dual = battery_level.left.battery_level;
  240. shared_memory->system_properties.is_charging_joy_dual.Assign(
  241. battery_level.left.is_charging);
  242. } else if (controller.is_dual_left_connected) {
  243. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
  244. shared_memory->fullkey_color.fullkey = body_colors.left;
  245. shared_memory->battery_level_dual = battery_level.left.battery_level;
  246. shared_memory->system_properties.is_charging_joy_dual.Assign(
  247. battery_level.left.is_charging);
  248. } else {
  249. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
  250. shared_memory->fullkey_color.fullkey = body_colors.right;
  251. shared_memory->battery_level_dual = battery_level.right.battery_level;
  252. shared_memory->system_properties.is_charging_joy_dual.Assign(
  253. battery_level.right.is_charging);
  254. }
  255. break;
  256. case Core::HID::NpadStyleIndex::JoyconLeft:
  257. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  258. shared_memory->fullkey_color.fullkey = body_colors.left;
  259. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  260. shared_memory->joycon_color.left = body_colors.left;
  261. shared_memory->battery_level_dual = battery_level.left.battery_level;
  262. shared_memory->style_tag.joycon_left.Assign(1);
  263. shared_memory->device_type.joycon_left.Assign(1);
  264. shared_memory->system_properties.is_horizontal.Assign(1);
  265. shared_memory->system_properties.use_minus.Assign(1);
  266. shared_memory->system_properties.is_charging_joy_left.Assign(
  267. battery_level.left.is_charging);
  268. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
  269. shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
  270. break;
  271. case Core::HID::NpadStyleIndex::JoyconRight:
  272. shared_memory->fullkey_color.attribute = ColorAttribute::Ok;
  273. shared_memory->fullkey_color.fullkey = body_colors.right;
  274. shared_memory->joycon_color.attribute = ColorAttribute::Ok;
  275. shared_memory->joycon_color.right = body_colors.right;
  276. shared_memory->battery_level_right = battery_level.right.battery_level;
  277. shared_memory->style_tag.joycon_right.Assign(1);
  278. shared_memory->device_type.joycon_right.Assign(1);
  279. shared_memory->system_properties.is_horizontal.Assign(1);
  280. shared_memory->system_properties.use_plus.Assign(1);
  281. shared_memory->system_properties.is_charging_joy_right.Assign(
  282. battery_level.right.is_charging);
  283. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
  284. shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
  285. break;
  286. case Core::HID::NpadStyleIndex::GameCube:
  287. shared_memory->style_tag.gamecube.Assign(1);
  288. shared_memory->device_type.fullkey.Assign(1);
  289. shared_memory->system_properties.is_vertical.Assign(1);
  290. shared_memory->system_properties.use_plus.Assign(1);
  291. break;
  292. case Core::HID::NpadStyleIndex::Pokeball:
  293. shared_memory->style_tag.palma.Assign(1);
  294. shared_memory->device_type.palma.Assign(1);
  295. shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
  296. break;
  297. case Core::HID::NpadStyleIndex::NES:
  298. shared_memory->style_tag.lark.Assign(1);
  299. shared_memory->device_type.fullkey.Assign(1);
  300. break;
  301. case Core::HID::NpadStyleIndex::SNES:
  302. shared_memory->style_tag.lucia.Assign(1);
  303. shared_memory->device_type.fullkey.Assign(1);
  304. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lucia;
  305. break;
  306. case Core::HID::NpadStyleIndex::N64:
  307. shared_memory->style_tag.lagoon.Assign(1);
  308. shared_memory->device_type.fullkey.Assign(1);
  309. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::Lagon;
  310. break;
  311. case Core::HID::NpadStyleIndex::SegaGenesis:
  312. shared_memory->style_tag.lager.Assign(1);
  313. shared_memory->device_type.fullkey.Assign(1);
  314. break;
  315. default:
  316. break;
  317. }
  318. controller.is_connected = true;
  319. controller.device->Connect();
  320. controller.device->SetLedPattern();
  321. if (controller_type == Core::HID::NpadStyleIndex::JoyconDual) {
  322. if (controller.is_dual_left_connected) {
  323. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::LeftIndex,
  324. Common::Input::PollingMode::Active);
  325. }
  326. if (controller.is_dual_right_connected) {
  327. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
  328. Common::Input::PollingMode::Active);
  329. }
  330. } else {
  331. controller.device->SetPollingMode(Core::HID::EmulatedDeviceIndex::AllDevices,
  332. Common::Input::PollingMode::Active);
  333. }
  334. SignalStyleSetChangedEvent(npad_id);
  335. WriteEmptyEntry(controller.shared_memory);
  336. }
  337. void Controller_NPad::OnInit() {
  338. if (!IsControllerActivated()) {
  339. return;
  340. }
  341. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  342. auto& controller = controller_data[i];
  343. controller.styleset_changed_event =
  344. service_context.CreateEvent(fmt::format("npad:NpadStyleSetChanged_{}", i));
  345. }
  346. supported_npad_id_types.resize(npad_id_list.size());
  347. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  348. npad_id_list.size() * sizeof(Core::HID::NpadIdType));
  349. // Prefill controller buffers
  350. for (auto& controller : controller_data) {
  351. auto* npad = controller.shared_memory;
  352. npad->fullkey_color = {
  353. .attribute = ColorAttribute::NoController,
  354. .fullkey = {},
  355. };
  356. npad->joycon_color = {
  357. .attribute = ColorAttribute::NoController,
  358. .left = {},
  359. .right = {},
  360. };
  361. // HW seems to initialize the first 19 entries
  362. for (std::size_t i = 0; i < 19; ++i) {
  363. WriteEmptyEntry(npad);
  364. }
  365. }
  366. }
  367. void Controller_NPad::WriteEmptyEntry(NpadInternalState* npad) {
  368. NPadGenericState dummy_pad_state{};
  369. NpadGcTriggerState dummy_gc_state{};
  370. dummy_pad_state.sampling_number = npad->fullkey_lifo.ReadCurrentEntry().sampling_number + 1;
  371. npad->fullkey_lifo.WriteNextEntry(dummy_pad_state);
  372. dummy_pad_state.sampling_number = npad->handheld_lifo.ReadCurrentEntry().sampling_number + 1;
  373. npad->handheld_lifo.WriteNextEntry(dummy_pad_state);
  374. dummy_pad_state.sampling_number = npad->joy_dual_lifo.ReadCurrentEntry().sampling_number + 1;
  375. npad->joy_dual_lifo.WriteNextEntry(dummy_pad_state);
  376. dummy_pad_state.sampling_number = npad->joy_left_lifo.ReadCurrentEntry().sampling_number + 1;
  377. npad->joy_left_lifo.WriteNextEntry(dummy_pad_state);
  378. dummy_pad_state.sampling_number = npad->joy_right_lifo.ReadCurrentEntry().sampling_number + 1;
  379. npad->joy_right_lifo.WriteNextEntry(dummy_pad_state);
  380. dummy_pad_state.sampling_number = npad->palma_lifo.ReadCurrentEntry().sampling_number + 1;
  381. npad->palma_lifo.WriteNextEntry(dummy_pad_state);
  382. dummy_pad_state.sampling_number = npad->system_ext_lifo.ReadCurrentEntry().sampling_number + 1;
  383. npad->system_ext_lifo.WriteNextEntry(dummy_pad_state);
  384. dummy_gc_state.sampling_number = npad->gc_trigger_lifo.ReadCurrentEntry().sampling_number + 1;
  385. npad->gc_trigger_lifo.WriteNextEntry(dummy_gc_state);
  386. }
  387. void Controller_NPad::OnRelease() {
  388. is_controller_initialized = false;
  389. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  390. auto& controller = controller_data[i];
  391. service_context.CloseEvent(controller.styleset_changed_event);
  392. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  393. VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_idx, {});
  394. }
  395. }
  396. }
  397. void Controller_NPad::RequestPadStateUpdate(Core::HID::NpadIdType npad_id) {
  398. std::scoped_lock lock{mutex};
  399. auto& controller = GetControllerFromNpadIdType(npad_id);
  400. const auto controller_type = controller.device->GetNpadStyleIndex();
  401. if (!controller.device->IsConnected()) {
  402. return;
  403. }
  404. // This function is unique to yuzu for the turbo buttons to work properly
  405. controller.device->TurboButtonUpdate();
  406. auto& pad_entry = controller.npad_pad_state;
  407. auto& trigger_entry = controller.npad_trigger_state;
  408. const auto button_state = controller.device->GetNpadButtons();
  409. const auto stick_state = controller.device->GetSticks();
  410. using btn = Core::HID::NpadButton;
  411. pad_entry.npad_buttons.raw = btn::None;
  412. if (controller_type != Core::HID::NpadStyleIndex::JoyconLeft) {
  413. constexpr btn right_button_mask = btn::A | btn::B | btn::X | btn::Y | btn::StickR | btn::R |
  414. btn::ZR | btn::Plus | btn::StickRLeft | btn::StickRUp |
  415. btn::StickRRight | btn::StickRDown;
  416. pad_entry.npad_buttons.raw = button_state.raw & right_button_mask;
  417. pad_entry.r_stick = stick_state.right;
  418. }
  419. if (controller_type != Core::HID::NpadStyleIndex::JoyconRight) {
  420. constexpr btn left_button_mask =
  421. btn::Left | btn::Up | btn::Right | btn::Down | btn::StickL | btn::L | btn::ZL |
  422. btn::Minus | btn::StickLLeft | btn::StickLUp | btn::StickLRight | btn::StickLDown;
  423. pad_entry.npad_buttons.raw |= button_state.raw & left_button_mask;
  424. pad_entry.l_stick = stick_state.left;
  425. }
  426. if (controller_type == Core::HID::NpadStyleIndex::JoyconLeft) {
  427. pad_entry.npad_buttons.left_sl.Assign(button_state.left_sl);
  428. pad_entry.npad_buttons.left_sr.Assign(button_state.left_sr);
  429. }
  430. if (controller_type == Core::HID::NpadStyleIndex::JoyconRight) {
  431. pad_entry.npad_buttons.right_sl.Assign(button_state.right_sl);
  432. pad_entry.npad_buttons.right_sr.Assign(button_state.right_sr);
  433. }
  434. if (controller_type == Core::HID::NpadStyleIndex::GameCube) {
  435. const auto& trigger_state = controller.device->GetTriggers();
  436. trigger_entry.l_analog = trigger_state.left;
  437. trigger_entry.r_analog = trigger_state.right;
  438. pad_entry.npad_buttons.zl.Assign(false);
  439. pad_entry.npad_buttons.zr.Assign(button_state.r);
  440. pad_entry.npad_buttons.l.Assign(button_state.zl);
  441. pad_entry.npad_buttons.r.Assign(button_state.zr);
  442. }
  443. }
  444. void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing) {
  445. if (!IsControllerActivated()) {
  446. return;
  447. }
  448. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  449. auto& controller = controller_data[i];
  450. auto* npad = controller.shared_memory;
  451. const auto& controller_type = controller.device->GetNpadStyleIndex();
  452. if (controller_type == Core::HID::NpadStyleIndex::None ||
  453. !controller.device->IsConnected()) {
  454. continue;
  455. }
  456. RequestPadStateUpdate(controller.device->GetNpadIdType());
  457. auto& pad_state = controller.npad_pad_state;
  458. auto& libnx_state = controller.npad_libnx_state;
  459. auto& trigger_state = controller.npad_trigger_state;
  460. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  461. // any controllers.
  462. libnx_state.connection_status.raw = 0;
  463. libnx_state.connection_status.is_connected.Assign(1);
  464. switch (controller_type) {
  465. case Core::HID::NpadStyleIndex::None:
  466. ASSERT(false);
  467. break;
  468. case Core::HID::NpadStyleIndex::ProController:
  469. case Core::HID::NpadStyleIndex::NES:
  470. case Core::HID::NpadStyleIndex::SNES:
  471. case Core::HID::NpadStyleIndex::N64:
  472. case Core::HID::NpadStyleIndex::SegaGenesis:
  473. pad_state.connection_status.raw = 0;
  474. pad_state.connection_status.is_connected.Assign(1);
  475. pad_state.connection_status.is_wired.Assign(1);
  476. libnx_state.connection_status.is_wired.Assign(1);
  477. pad_state.sampling_number =
  478. npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  479. npad->fullkey_lifo.WriteNextEntry(pad_state);
  480. break;
  481. case Core::HID::NpadStyleIndex::Handheld:
  482. pad_state.connection_status.raw = 0;
  483. pad_state.connection_status.is_connected.Assign(1);
  484. pad_state.connection_status.is_wired.Assign(1);
  485. pad_state.connection_status.is_left_connected.Assign(1);
  486. pad_state.connection_status.is_right_connected.Assign(1);
  487. pad_state.connection_status.is_left_wired.Assign(1);
  488. pad_state.connection_status.is_right_wired.Assign(1);
  489. libnx_state.connection_status.is_wired.Assign(1);
  490. libnx_state.connection_status.is_left_connected.Assign(1);
  491. libnx_state.connection_status.is_right_connected.Assign(1);
  492. libnx_state.connection_status.is_left_wired.Assign(1);
  493. libnx_state.connection_status.is_right_wired.Assign(1);
  494. pad_state.sampling_number =
  495. npad->handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  496. npad->handheld_lifo.WriteNextEntry(pad_state);
  497. break;
  498. case Core::HID::NpadStyleIndex::JoyconDual:
  499. pad_state.connection_status.raw = 0;
  500. pad_state.connection_status.is_connected.Assign(1);
  501. if (controller.is_dual_left_connected) {
  502. pad_state.connection_status.is_left_connected.Assign(1);
  503. libnx_state.connection_status.is_left_connected.Assign(1);
  504. }
  505. if (controller.is_dual_right_connected) {
  506. pad_state.connection_status.is_right_connected.Assign(1);
  507. libnx_state.connection_status.is_right_connected.Assign(1);
  508. }
  509. pad_state.sampling_number =
  510. npad->joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
  511. npad->joy_dual_lifo.WriteNextEntry(pad_state);
  512. break;
  513. case Core::HID::NpadStyleIndex::JoyconLeft:
  514. pad_state.connection_status.raw = 0;
  515. pad_state.connection_status.is_connected.Assign(1);
  516. pad_state.connection_status.is_left_connected.Assign(1);
  517. libnx_state.connection_status.is_left_connected.Assign(1);
  518. pad_state.sampling_number =
  519. npad->joy_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  520. npad->joy_left_lifo.WriteNextEntry(pad_state);
  521. break;
  522. case Core::HID::NpadStyleIndex::JoyconRight:
  523. pad_state.connection_status.raw = 0;
  524. pad_state.connection_status.is_connected.Assign(1);
  525. pad_state.connection_status.is_right_connected.Assign(1);
  526. libnx_state.connection_status.is_right_connected.Assign(1);
  527. pad_state.sampling_number =
  528. npad->joy_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  529. npad->joy_right_lifo.WriteNextEntry(pad_state);
  530. break;
  531. case Core::HID::NpadStyleIndex::GameCube:
  532. pad_state.connection_status.raw = 0;
  533. pad_state.connection_status.is_connected.Assign(1);
  534. pad_state.connection_status.is_wired.Assign(1);
  535. libnx_state.connection_status.is_wired.Assign(1);
  536. pad_state.sampling_number =
  537. npad->fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  538. trigger_state.sampling_number =
  539. npad->gc_trigger_lifo.ReadCurrentEntry().state.sampling_number + 1;
  540. npad->fullkey_lifo.WriteNextEntry(pad_state);
  541. npad->gc_trigger_lifo.WriteNextEntry(trigger_state);
  542. break;
  543. case Core::HID::NpadStyleIndex::Pokeball:
  544. pad_state.connection_status.raw = 0;
  545. pad_state.connection_status.is_connected.Assign(1);
  546. pad_state.sampling_number =
  547. npad->palma_lifo.ReadCurrentEntry().state.sampling_number + 1;
  548. npad->palma_lifo.WriteNextEntry(pad_state);
  549. break;
  550. default:
  551. break;
  552. }
  553. libnx_state.npad_buttons.raw = pad_state.npad_buttons.raw;
  554. libnx_state.l_stick = pad_state.l_stick;
  555. libnx_state.r_stick = pad_state.r_stick;
  556. npad->system_ext_lifo.WriteNextEntry(pad_state);
  557. press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
  558. }
  559. }
  560. void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing) {
  561. if (!IsControllerActivated()) {
  562. return;
  563. }
  564. for (std::size_t i = 0; i < controller_data.size(); ++i) {
  565. auto& controller = controller_data[i];
  566. const auto& controller_type = controller.device->GetNpadStyleIndex();
  567. if (controller_type == Core::HID::NpadStyleIndex::None ||
  568. !controller.device->IsConnected()) {
  569. continue;
  570. }
  571. auto* npad = controller.shared_memory;
  572. const auto& motion_state = controller.device->GetMotions();
  573. auto& sixaxis_fullkey_state = controller.sixaxis_fullkey_state;
  574. auto& sixaxis_handheld_state = controller.sixaxis_handheld_state;
  575. auto& sixaxis_dual_left_state = controller.sixaxis_dual_left_state;
  576. auto& sixaxis_dual_right_state = controller.sixaxis_dual_right_state;
  577. auto& sixaxis_left_lifo_state = controller.sixaxis_left_lifo_state;
  578. auto& sixaxis_right_lifo_state = controller.sixaxis_right_lifo_state;
  579. // Clear previous state
  580. sixaxis_fullkey_state = {};
  581. sixaxis_handheld_state = {};
  582. sixaxis_dual_left_state = {};
  583. sixaxis_dual_right_state = {};
  584. sixaxis_left_lifo_state = {};
  585. sixaxis_right_lifo_state = {};
  586. if (controller.sixaxis_sensor_enabled && Settings::values.motion_enabled.GetValue()) {
  587. controller.sixaxis_at_rest = true;
  588. for (std::size_t e = 0; e < motion_state.size(); ++e) {
  589. controller.sixaxis_at_rest =
  590. controller.sixaxis_at_rest && motion_state[e].is_at_rest;
  591. }
  592. }
  593. const auto set_motion_state = [&](SixAxisSensorState& state,
  594. const Core::HID::ControllerMotion& hid_state) {
  595. using namespace std::literals::chrono_literals;
  596. static constexpr SixAxisSensorState default_motion_state = {
  597. .delta_time = std::chrono::nanoseconds(5ms).count(),
  598. .accel = {0, 0, -1.0f},
  599. .orientation =
  600. {
  601. Common::Vec3f{1.0f, 0, 0},
  602. Common::Vec3f{0, 1.0f, 0},
  603. Common::Vec3f{0, 0, 1.0f},
  604. },
  605. .attribute = {1},
  606. };
  607. if (!controller.sixaxis_sensor_enabled) {
  608. state = default_motion_state;
  609. return;
  610. }
  611. if (!Settings::values.motion_enabled.GetValue()) {
  612. state = default_motion_state;
  613. return;
  614. }
  615. state.attribute.is_connected.Assign(1);
  616. state.delta_time = std::chrono::nanoseconds(5ms).count();
  617. state.accel = hid_state.accel;
  618. state.gyro = hid_state.gyro;
  619. state.rotation = hid_state.rotation;
  620. state.orientation = hid_state.orientation;
  621. };
  622. switch (controller_type) {
  623. case Core::HID::NpadStyleIndex::None:
  624. ASSERT(false);
  625. break;
  626. case Core::HID::NpadStyleIndex::ProController:
  627. set_motion_state(sixaxis_fullkey_state, motion_state[0]);
  628. break;
  629. case Core::HID::NpadStyleIndex::Handheld:
  630. set_motion_state(sixaxis_handheld_state, motion_state[0]);
  631. break;
  632. case Core::HID::NpadStyleIndex::JoyconDual:
  633. set_motion_state(sixaxis_dual_left_state, motion_state[0]);
  634. set_motion_state(sixaxis_dual_right_state, motion_state[1]);
  635. break;
  636. case Core::HID::NpadStyleIndex::JoyconLeft:
  637. set_motion_state(sixaxis_left_lifo_state, motion_state[0]);
  638. break;
  639. case Core::HID::NpadStyleIndex::JoyconRight:
  640. set_motion_state(sixaxis_right_lifo_state, motion_state[1]);
  641. break;
  642. case Core::HID::NpadStyleIndex::Pokeball:
  643. using namespace std::literals::chrono_literals;
  644. set_motion_state(sixaxis_fullkey_state, motion_state[0]);
  645. sixaxis_fullkey_state.delta_time = std::chrono::nanoseconds(15ms).count();
  646. break;
  647. default:
  648. break;
  649. }
  650. sixaxis_fullkey_state.sampling_number =
  651. npad->sixaxis_fullkey_lifo.ReadCurrentEntry().state.sampling_number + 1;
  652. sixaxis_handheld_state.sampling_number =
  653. npad->sixaxis_handheld_lifo.ReadCurrentEntry().state.sampling_number + 1;
  654. sixaxis_dual_left_state.sampling_number =
  655. npad->sixaxis_dual_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  656. sixaxis_dual_right_state.sampling_number =
  657. npad->sixaxis_dual_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  658. sixaxis_left_lifo_state.sampling_number =
  659. npad->sixaxis_left_lifo.ReadCurrentEntry().state.sampling_number + 1;
  660. sixaxis_right_lifo_state.sampling_number =
  661. npad->sixaxis_right_lifo.ReadCurrentEntry().state.sampling_number + 1;
  662. if (Core::HID::IndexToNpadIdType(i) == Core::HID::NpadIdType::Handheld) {
  663. // This buffer only is updated on handheld on HW
  664. npad->sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
  665. } else {
  666. // Handheld doesn't update this buffer on HW
  667. npad->sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
  668. }
  669. npad->sixaxis_dual_left_lifo.WriteNextEntry(sixaxis_dual_left_state);
  670. npad->sixaxis_dual_right_lifo.WriteNextEntry(sixaxis_dual_right_state);
  671. npad->sixaxis_left_lifo.WriteNextEntry(sixaxis_left_lifo_state);
  672. npad->sixaxis_right_lifo.WriteNextEntry(sixaxis_right_lifo_state);
  673. }
  674. }
  675. void Controller_NPad::SetSupportedStyleSet(Core::HID::NpadStyleTag style_set) {
  676. hid_core.SetSupportedStyleTag(style_set);
  677. if (is_controller_initialized) {
  678. return;
  679. }
  680. // Once SetSupportedStyleSet is called controllers are fully initialized
  681. is_controller_initialized = true;
  682. // Connect all active controllers
  683. for (auto& controller : controller_data) {
  684. const auto& device = controller.device;
  685. if (device->IsConnected()) {
  686. AddNewControllerAt(device->GetNpadStyleIndex(), device->GetNpadIdType());
  687. }
  688. }
  689. }
  690. Core::HID::NpadStyleTag Controller_NPad::GetSupportedStyleSet() const {
  691. if (!is_controller_initialized) {
  692. return {Core::HID::NpadStyleSet::None};
  693. }
  694. return hid_core.GetSupportedStyleTag();
  695. }
  696. Result Controller_NPad::SetSupportedNpadIdTypes(std::span<const u8> data) {
  697. constexpr std::size_t max_number_npad_ids = 0xa;
  698. const auto length = data.size();
  699. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  700. const std::size_t elements = length / sizeof(u32);
  701. if (elements > max_number_npad_ids) {
  702. return InvalidArraySize;
  703. }
  704. supported_npad_id_types.clear();
  705. supported_npad_id_types.resize(elements);
  706. std::memcpy(supported_npad_id_types.data(), data.data(), length);
  707. return ResultSuccess;
  708. }
  709. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  710. const auto copy_amount = supported_npad_id_types.size() * sizeof(u32);
  711. ASSERT(max_length <= copy_amount);
  712. std::memcpy(data, supported_npad_id_types.data(), copy_amount);
  713. }
  714. std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
  715. return supported_npad_id_types.size();
  716. }
  717. void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
  718. if (joy_hold_type != NpadJoyHoldType::Horizontal &&
  719. joy_hold_type != NpadJoyHoldType::Vertical) {
  720. LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
  721. joy_hold_type);
  722. return;
  723. }
  724. hold_type = joy_hold_type;
  725. }
  726. Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
  727. return hold_type;
  728. }
  729. void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
  730. if (activation_mode >= NpadHandheldActivationMode::MaxActivationMode) {
  731. ASSERT_MSG(false, "Activation mode should be always None, Single or Dual");
  732. return;
  733. }
  734. handheld_activation_mode = activation_mode;
  735. }
  736. Controller_NPad::NpadHandheldActivationMode Controller_NPad::GetNpadHandheldActivationMode() const {
  737. return handheld_activation_mode;
  738. }
  739. void Controller_NPad::SetNpadCommunicationMode(NpadCommunicationMode communication_mode_) {
  740. communication_mode = communication_mode_;
  741. }
  742. Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode() const {
  743. return communication_mode;
  744. }
  745. bool Controller_NPad::SetNpadMode(Core::HID::NpadIdType& new_npad_id, Core::HID::NpadIdType npad_id,
  746. NpadJoyDeviceType npad_device_type,
  747. NpadJoyAssignmentMode assignment_mode) {
  748. if (!IsNpadIdValid(npad_id)) {
  749. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  750. return false;
  751. }
  752. auto& controller = GetControllerFromNpadIdType(npad_id);
  753. if (controller.shared_memory->assignment_mode != assignment_mode) {
  754. controller.shared_memory->assignment_mode = assignment_mode;
  755. }
  756. if (!controller.device->IsConnected()) {
  757. return false;
  758. }
  759. if (assignment_mode == NpadJoyAssignmentMode::Dual) {
  760. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) {
  761. DisconnectNpad(npad_id);
  762. controller.is_dual_left_connected = true;
  763. controller.is_dual_right_connected = false;
  764. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  765. return false;
  766. }
  767. if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
  768. DisconnectNpad(npad_id);
  769. controller.is_dual_left_connected = false;
  770. controller.is_dual_right_connected = true;
  771. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
  772. return false;
  773. }
  774. return false;
  775. }
  776. // This is for NpadJoyAssignmentMode::Single
  777. // Only JoyconDual get affected by this function
  778. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
  779. return false;
  780. }
  781. if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
  782. DisconnectNpad(npad_id);
  783. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  784. return false;
  785. }
  786. if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
  787. DisconnectNpad(npad_id);
  788. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  789. return false;
  790. }
  791. // We have two controllers connected to the same npad_id we need to split them
  792. new_npad_id = hid_core.GetFirstDisconnectedNpadId();
  793. auto& controller_2 = GetControllerFromNpadIdType(new_npad_id);
  794. DisconnectNpad(npad_id);
  795. if (npad_device_type == NpadJoyDeviceType::Left) {
  796. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
  797. controller_2.is_dual_left_connected = false;
  798. controller_2.is_dual_right_connected = true;
  799. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
  800. } else {
  801. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
  802. controller_2.is_dual_left_connected = true;
  803. controller_2.is_dual_right_connected = false;
  804. UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, new_npad_id, true);
  805. }
  806. return true;
  807. }
  808. bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
  809. std::size_t device_index,
  810. const Core::HID::VibrationValue& vibration_value) {
  811. auto& controller = GetControllerFromNpadIdType(npad_id);
  812. if (!controller.device->IsConnected()) {
  813. return false;
  814. }
  815. if (!controller.device->IsVibrationEnabled(device_index)) {
  816. if (controller.vibration[device_index].latest_vibration_value.low_amplitude != 0.0f ||
  817. controller.vibration[device_index].latest_vibration_value.high_amplitude != 0.0f) {
  818. // Send an empty vibration to stop any vibrations.
  819. Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
  820. controller.device->SetVibration(device_index, vibration);
  821. // Then reset the vibration value to its default value.
  822. controller.vibration[device_index].latest_vibration_value =
  823. Core::HID::DEFAULT_VIBRATION_VALUE;
  824. }
  825. return false;
  826. }
  827. if (!Settings::values.enable_accurate_vibrations.GetValue()) {
  828. using std::chrono::duration_cast;
  829. using std::chrono::milliseconds;
  830. using std::chrono::steady_clock;
  831. const auto now = steady_clock::now();
  832. // Filter out non-zero vibrations that are within 15ms of each other.
  833. if ((vibration_value.low_amplitude != 0.0f || vibration_value.high_amplitude != 0.0f) &&
  834. duration_cast<milliseconds>(
  835. now - controller.vibration[device_index].last_vibration_timepoint) <
  836. milliseconds(15)) {
  837. return false;
  838. }
  839. controller.vibration[device_index].last_vibration_timepoint = now;
  840. }
  841. Core::HID::VibrationValue vibration{
  842. vibration_value.low_amplitude, vibration_value.low_frequency,
  843. vibration_value.high_amplitude, vibration_value.high_frequency};
  844. return controller.device->SetVibration(device_index, vibration);
  845. }
  846. void Controller_NPad::VibrateController(
  847. const Core::HID::VibrationDeviceHandle& vibration_device_handle,
  848. const Core::HID::VibrationValue& vibration_value) {
  849. if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
  850. return;
  851. }
  852. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  853. return;
  854. }
  855. auto& controller = GetControllerFromHandle(vibration_device_handle);
  856. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  857. if (!controller.vibration[device_index].device_mounted || !controller.device->IsConnected()) {
  858. return;
  859. }
  860. if (vibration_device_handle.device_index == Core::HID::DeviceIndex::None) {
  861. ASSERT_MSG(false, "DeviceIndex should never be None!");
  862. return;
  863. }
  864. // Some games try to send mismatched parameters in the device handle, block these.
  865. if ((controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
  866. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconRight ||
  867. vibration_device_handle.device_index == Core::HID::DeviceIndex::Right)) ||
  868. (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight &&
  869. (vibration_device_handle.npad_type == Core::HID::NpadStyleIndex::JoyconLeft ||
  870. vibration_device_handle.device_index == Core::HID::DeviceIndex::Left))) {
  871. return;
  872. }
  873. // Filter out vibrations with equivalent values to reduce unnecessary state changes.
  874. if (vibration_value.low_amplitude ==
  875. controller.vibration[device_index].latest_vibration_value.low_amplitude &&
  876. vibration_value.high_amplitude ==
  877. controller.vibration[device_index].latest_vibration_value.high_amplitude) {
  878. return;
  879. }
  880. if (VibrateControllerAtIndex(controller.device->GetNpadIdType(), device_index,
  881. vibration_value)) {
  882. controller.vibration[device_index].latest_vibration_value = vibration_value;
  883. }
  884. }
  885. void Controller_NPad::VibrateControllers(
  886. const std::vector<Core::HID::VibrationDeviceHandle>& vibration_device_handles,
  887. const std::vector<Core::HID::VibrationValue>& vibration_values) {
  888. if (!Settings::values.vibration_enabled.GetValue() && !permit_vibration_session_enabled) {
  889. return;
  890. }
  891. ASSERT_OR_EXECUTE_MSG(
  892. vibration_device_handles.size() == vibration_values.size(), { return; },
  893. "The amount of device handles does not match with the amount of vibration values,"
  894. "this is undefined behavior!");
  895. for (std::size_t i = 0; i < vibration_device_handles.size(); ++i) {
  896. VibrateController(vibration_device_handles[i], vibration_values[i]);
  897. }
  898. }
  899. Core::HID::VibrationValue Controller_NPad::GetLastVibration(
  900. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  901. if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
  902. return {};
  903. }
  904. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  905. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  906. return controller.vibration[device_index].latest_vibration_value;
  907. }
  908. void Controller_NPad::InitializeVibrationDevice(
  909. const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
  910. if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
  911. return;
  912. }
  913. const auto npad_index = static_cast<Core::HID::NpadIdType>(vibration_device_handle.npad_id);
  914. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  915. InitializeVibrationDeviceAtIndex(npad_index, device_index);
  916. }
  917. void Controller_NPad::InitializeVibrationDeviceAtIndex(Core::HID::NpadIdType npad_id,
  918. std::size_t device_index) {
  919. auto& controller = GetControllerFromNpadIdType(npad_id);
  920. if (!Settings::values.vibration_enabled.GetValue()) {
  921. controller.vibration[device_index].device_mounted = false;
  922. return;
  923. }
  924. controller.vibration[device_index].device_mounted =
  925. controller.device->IsVibrationEnabled(device_index);
  926. }
  927. void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
  928. permit_vibration_session_enabled = permit_vibration_session;
  929. }
  930. bool Controller_NPad::IsVibrationDeviceMounted(
  931. const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
  932. if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
  933. return false;
  934. }
  935. const auto& controller = GetControllerFromHandle(vibration_device_handle);
  936. const auto device_index = static_cast<std::size_t>(vibration_device_handle.device_index);
  937. return controller.vibration[device_index].device_mounted;
  938. }
  939. Kernel::KReadableEvent& Controller_NPad::GetStyleSetChangedEvent(Core::HID::NpadIdType npad_id) {
  940. if (!IsNpadIdValid(npad_id)) {
  941. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  942. // Fallback to player 1
  943. const auto& controller = GetControllerFromNpadIdType(Core::HID::NpadIdType::Player1);
  944. return controller.styleset_changed_event->GetReadableEvent();
  945. }
  946. const auto& controller = GetControllerFromNpadIdType(npad_id);
  947. return controller.styleset_changed_event->GetReadableEvent();
  948. }
  949. void Controller_NPad::SignalStyleSetChangedEvent(Core::HID::NpadIdType npad_id) const {
  950. const auto& controller = GetControllerFromNpadIdType(npad_id);
  951. controller.styleset_changed_event->Signal();
  952. }
  953. void Controller_NPad::AddNewControllerAt(Core::HID::NpadStyleIndex controller,
  954. Core::HID::NpadIdType npad_id) {
  955. UpdateControllerAt(controller, npad_id, true);
  956. }
  957. void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
  958. Core::HID::NpadIdType npad_id, bool connected) {
  959. auto& controller = GetControllerFromNpadIdType(npad_id);
  960. if (!connected) {
  961. DisconnectNpad(npad_id);
  962. return;
  963. }
  964. controller.device->SetNpadStyleIndex(type);
  965. InitNewlyAddedController(npad_id);
  966. }
  967. Result Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
  968. if (!IsNpadIdValid(npad_id)) {
  969. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  970. return InvalidNpadId;
  971. }
  972. LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
  973. auto& controller = GetControllerFromNpadIdType(npad_id);
  974. for (std::size_t device_idx = 0; device_idx < controller.vibration.size(); ++device_idx) {
  975. // Send an empty vibration to stop any vibrations.
  976. VibrateControllerAtIndex(npad_id, device_idx, {});
  977. controller.vibration[device_idx].device_mounted = false;
  978. }
  979. auto* shared_memory = controller.shared_memory;
  980. // Don't reset shared_memory->assignment_mode this value is persistent
  981. shared_memory->style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
  982. shared_memory->device_type.raw = 0;
  983. shared_memory->system_properties.raw = 0;
  984. shared_memory->button_properties.raw = 0;
  985. shared_memory->sixaxis_fullkey_properties.raw = 0;
  986. shared_memory->sixaxis_handheld_properties.raw = 0;
  987. shared_memory->sixaxis_dual_left_properties.raw = 0;
  988. shared_memory->sixaxis_dual_right_properties.raw = 0;
  989. shared_memory->sixaxis_left_properties.raw = 0;
  990. shared_memory->sixaxis_right_properties.raw = 0;
  991. shared_memory->battery_level_dual = 0;
  992. shared_memory->battery_level_left = 0;
  993. shared_memory->battery_level_right = 0;
  994. shared_memory->fullkey_color = {
  995. .attribute = ColorAttribute::NoController,
  996. .fullkey = {},
  997. };
  998. shared_memory->joycon_color = {
  999. .attribute = ColorAttribute::NoController,
  1000. .left = {},
  1001. .right = {},
  1002. };
  1003. shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::None;
  1004. controller.is_dual_left_connected = true;
  1005. controller.is_dual_right_connected = true;
  1006. controller.is_connected = false;
  1007. controller.device->Disconnect();
  1008. SignalStyleSetChangedEvent(npad_id);
  1009. WriteEmptyEntry(shared_memory);
  1010. return ResultSuccess;
  1011. }
  1012. Result Controller_NPad::SetGyroscopeZeroDriftMode(
  1013. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1014. Core::HID::GyroscopeZeroDriftMode drift_mode) {
  1015. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1016. if (is_valid.IsError()) {
  1017. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1018. return is_valid;
  1019. }
  1020. auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1021. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1022. sixaxis.gyroscope_zero_drift_mode = drift_mode;
  1023. controller.device->SetGyroscopeZeroDriftMode(drift_mode);
  1024. return ResultSuccess;
  1025. }
  1026. Result Controller_NPad::GetGyroscopeZeroDriftMode(
  1027. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1028. Core::HID::GyroscopeZeroDriftMode& drift_mode) const {
  1029. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1030. if (is_valid.IsError()) {
  1031. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1032. return is_valid;
  1033. }
  1034. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1035. drift_mode = sixaxis.gyroscope_zero_drift_mode;
  1036. return ResultSuccess;
  1037. }
  1038. Result Controller_NPad::IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1039. bool& is_at_rest) const {
  1040. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1041. if (is_valid.IsError()) {
  1042. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1043. return is_valid;
  1044. }
  1045. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  1046. is_at_rest = controller.sixaxis_at_rest;
  1047. return ResultSuccess;
  1048. }
  1049. Result Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
  1050. const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
  1051. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1052. if (is_valid.IsError()) {
  1053. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1054. return is_valid;
  1055. }
  1056. const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
  1057. is_firmware_available = sixaxis_properties.is_firmware_update_available != 0;
  1058. return ResultSuccess;
  1059. }
  1060. Result Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
  1061. const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
  1062. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1063. if (is_valid.IsError()) {
  1064. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1065. return is_valid;
  1066. }
  1067. auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1068. sixaxis.unaltered_passtrough = is_enabled;
  1069. return ResultSuccess;
  1070. }
  1071. Result Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
  1072. const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
  1073. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1074. if (is_valid.IsError()) {
  1075. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1076. return is_valid;
  1077. }
  1078. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1079. is_enabled = sixaxis.unaltered_passtrough;
  1080. return ResultSuccess;
  1081. }
  1082. Result Controller_NPad::LoadSixAxisSensorCalibrationParameter(
  1083. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1084. Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
  1085. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1086. if (is_valid.IsError()) {
  1087. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1088. return is_valid;
  1089. }
  1090. // TODO: Request this data to the controller. On error return 0xd8ca
  1091. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1092. calibration = sixaxis.calibration;
  1093. return ResultSuccess;
  1094. }
  1095. Result Controller_NPad::GetSixAxisSensorIcInformation(
  1096. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1097. Core::HID::SixAxisSensorIcInformation& ic_information) const {
  1098. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1099. if (is_valid.IsError()) {
  1100. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1101. return is_valid;
  1102. }
  1103. // TODO: Request this data to the controller. On error return 0xd8ca
  1104. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1105. ic_information = sixaxis.ic_information;
  1106. return ResultSuccess;
  1107. }
  1108. Result Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
  1109. const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
  1110. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1111. if (is_valid.IsError()) {
  1112. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1113. return is_valid;
  1114. }
  1115. auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
  1116. sixaxis_properties.is_newly_assigned.Assign(0);
  1117. return ResultSuccess;
  1118. }
  1119. Result Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1120. bool sixaxis_status) {
  1121. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1122. if (is_valid.IsError()) {
  1123. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1124. return is_valid;
  1125. }
  1126. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1127. controller.sixaxis_sensor_enabled = sixaxis_status;
  1128. return ResultSuccess;
  1129. }
  1130. Result Controller_NPad::IsSixAxisSensorFusionEnabled(
  1131. const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
  1132. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1133. if (is_valid.IsError()) {
  1134. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1135. return is_valid;
  1136. }
  1137. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1138. is_fusion_enabled = sixaxis.is_fusion_enabled;
  1139. return ResultSuccess;
  1140. }
  1141. Result Controller_NPad::SetSixAxisFusionEnabled(
  1142. const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
  1143. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1144. if (is_valid.IsError()) {
  1145. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1146. return is_valid;
  1147. }
  1148. auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1149. sixaxis.is_fusion_enabled = is_fusion_enabled;
  1150. return ResultSuccess;
  1151. }
  1152. Result Controller_NPad::SetSixAxisFusionParameters(
  1153. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1154. Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
  1155. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1156. if (is_valid.IsError()) {
  1157. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1158. return is_valid;
  1159. }
  1160. const auto param1 = sixaxis_fusion_parameters.parameter1;
  1161. if (param1 < 0.0f || param1 > 1.0f) {
  1162. return InvalidSixAxisFusionRange;
  1163. }
  1164. auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1165. sixaxis.fusion = sixaxis_fusion_parameters;
  1166. return ResultSuccess;
  1167. }
  1168. Result Controller_NPad::GetSixAxisFusionParameters(
  1169. const Core::HID::SixAxisSensorHandle& sixaxis_handle,
  1170. Core::HID::SixAxisSensorFusionParameters& parameters) const {
  1171. const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
  1172. if (is_valid.IsError()) {
  1173. LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
  1174. return is_valid;
  1175. }
  1176. const auto& sixaxis = GetSixaxisState(sixaxis_handle);
  1177. parameters = sixaxis.fusion;
  1178. return ResultSuccess;
  1179. }
  1180. Result Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
  1181. Core::HID::NpadIdType npad_id_2) {
  1182. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  1183. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  1184. npad_id_2);
  1185. return InvalidNpadId;
  1186. }
  1187. auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
  1188. auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
  1189. auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
  1190. auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
  1191. // Simplify this code by converting dualjoycon with only a side connected to single joycons
  1192. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) {
  1193. if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
  1194. controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft;
  1195. }
  1196. if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
  1197. controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight;
  1198. }
  1199. }
  1200. if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
  1201. if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
  1202. controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft;
  1203. }
  1204. if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
  1205. controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight;
  1206. }
  1207. }
  1208. // Invalid merge errors
  1209. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual ||
  1210. controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
  1211. return NpadIsDualJoycon;
  1212. }
  1213. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
  1214. controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) {
  1215. return NpadIsSameType;
  1216. }
  1217. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
  1218. controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
  1219. return NpadIsSameType;
  1220. }
  1221. // These exceptions are handled as if they where dual joycon
  1222. if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft &&
  1223. controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) {
  1224. return NpadIsDualJoycon;
  1225. }
  1226. if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft &&
  1227. controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) {
  1228. return NpadIsDualJoycon;
  1229. }
  1230. // Disconnect the joycons and connect them as dual joycon at the first index.
  1231. DisconnectNpad(npad_id_1);
  1232. DisconnectNpad(npad_id_2);
  1233. controller_1.is_dual_left_connected = true;
  1234. controller_1.is_dual_right_connected = true;
  1235. AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
  1236. return ResultSuccess;
  1237. }
  1238. void Controller_NPad::StartLRAssignmentMode() {
  1239. // Nothing internally is used for lr assignment mode. Since we have the ability to set the
  1240. // controller types from boot, it doesn't really matter about showing a selection screen
  1241. is_in_lr_assignment_mode = true;
  1242. }
  1243. void Controller_NPad::StopLRAssignmentMode() {
  1244. is_in_lr_assignment_mode = false;
  1245. }
  1246. Result Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
  1247. Core::HID::NpadIdType npad_id_2) {
  1248. if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
  1249. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
  1250. npad_id_2);
  1251. return InvalidNpadId;
  1252. }
  1253. if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
  1254. npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
  1255. npad_id_2 == Core::HID::NpadIdType::Other) {
  1256. return ResultSuccess;
  1257. }
  1258. const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
  1259. const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
  1260. const auto type_index_1 = controller_1->GetNpadStyleIndex();
  1261. const auto type_index_2 = controller_2->GetNpadStyleIndex();
  1262. const auto is_connected_1 = controller_1->IsConnected();
  1263. const auto is_connected_2 = controller_2->IsConnected();
  1264. if (!IsControllerSupported(type_index_1) && is_connected_1) {
  1265. return NpadNotConnected;
  1266. }
  1267. if (!IsControllerSupported(type_index_2) && is_connected_2) {
  1268. return NpadNotConnected;
  1269. }
  1270. UpdateControllerAt(type_index_2, npad_id_1, is_connected_2);
  1271. UpdateControllerAt(type_index_1, npad_id_2, is_connected_1);
  1272. return ResultSuccess;
  1273. }
  1274. Result Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
  1275. Core::HID::LedPattern& pattern) const {
  1276. if (!IsNpadIdValid(npad_id)) {
  1277. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1278. return InvalidNpadId;
  1279. }
  1280. const auto& controller = GetControllerFromNpadIdType(npad_id).device;
  1281. pattern = controller->GetLedPattern();
  1282. return ResultSuccess;
  1283. }
  1284. Result Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
  1285. bool& is_valid) const {
  1286. if (!IsNpadIdValid(npad_id)) {
  1287. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1288. return InvalidNpadId;
  1289. }
  1290. const auto& controller = GetControllerFromNpadIdType(npad_id);
  1291. is_valid = controller.unintended_home_button_input_protection;
  1292. return ResultSuccess;
  1293. }
  1294. Result Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
  1295. bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
  1296. if (!IsNpadIdValid(npad_id)) {
  1297. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1298. return InvalidNpadId;
  1299. }
  1300. auto& controller = GetControllerFromNpadIdType(npad_id);
  1301. controller.unintended_home_button_input_protection = is_protection_enabled;
  1302. return ResultSuccess;
  1303. }
  1304. void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
  1305. analog_stick_use_center_clamp = use_center_clamp;
  1306. }
  1307. void Controller_NPad::ClearAllConnectedControllers() {
  1308. for (auto& controller : controller_data) {
  1309. if (controller.device->IsConnected() &&
  1310. controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None) {
  1311. controller.device->Disconnect();
  1312. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1313. }
  1314. }
  1315. }
  1316. void Controller_NPad::DisconnectAllConnectedControllers() {
  1317. for (auto& controller : controller_data) {
  1318. controller.device->Disconnect();
  1319. }
  1320. }
  1321. void Controller_NPad::ConnectAllDisconnectedControllers() {
  1322. for (auto& controller : controller_data) {
  1323. if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::None &&
  1324. !controller.device->IsConnected()) {
  1325. controller.device->Connect();
  1326. }
  1327. }
  1328. }
  1329. void Controller_NPad::ClearAllControllers() {
  1330. for (auto& controller : controller_data) {
  1331. controller.device->Disconnect();
  1332. controller.device->SetNpadStyleIndex(Core::HID::NpadStyleIndex::None);
  1333. }
  1334. }
  1335. Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
  1336. return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
  1337. }
  1338. bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
  1339. if (controller == Core::HID::NpadStyleIndex::Handheld) {
  1340. const bool support_handheld =
  1341. std::find(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1342. Core::HID::NpadIdType::Handheld) != supported_npad_id_types.end();
  1343. // Handheld is not even a supported type, lets stop here
  1344. if (!support_handheld) {
  1345. return false;
  1346. }
  1347. // Handheld shouldn't be supported in docked mode
  1348. if (Settings::values.use_docked_mode.GetValue()) {
  1349. return false;
  1350. }
  1351. return true;
  1352. }
  1353. if (std::any_of(supported_npad_id_types.begin(), supported_npad_id_types.end(),
  1354. [](Core::HID::NpadIdType npad_id) {
  1355. return npad_id <= Core::HID::NpadIdType::Player8;
  1356. })) {
  1357. Core::HID::NpadStyleTag style = GetSupportedStyleSet();
  1358. switch (controller) {
  1359. case Core::HID::NpadStyleIndex::ProController:
  1360. return style.fullkey.As<bool>();
  1361. case Core::HID::NpadStyleIndex::JoyconDual:
  1362. return style.joycon_dual.As<bool>();
  1363. case Core::HID::NpadStyleIndex::JoyconLeft:
  1364. return style.joycon_left.As<bool>();
  1365. case Core::HID::NpadStyleIndex::JoyconRight:
  1366. return style.joycon_right.As<bool>();
  1367. case Core::HID::NpadStyleIndex::GameCube:
  1368. return style.gamecube.As<bool>();
  1369. case Core::HID::NpadStyleIndex::Pokeball:
  1370. return style.palma.As<bool>();
  1371. case Core::HID::NpadStyleIndex::NES:
  1372. return style.lark.As<bool>();
  1373. case Core::HID::NpadStyleIndex::SNES:
  1374. return style.lucia.As<bool>();
  1375. case Core::HID::NpadStyleIndex::N64:
  1376. return style.lagoon.As<bool>();
  1377. case Core::HID::NpadStyleIndex::SegaGenesis:
  1378. return style.lager.As<bool>();
  1379. default:
  1380. return false;
  1381. }
  1382. }
  1383. return false;
  1384. }
  1385. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1386. const Core::HID::SixAxisSensorHandle& device_handle) {
  1387. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1388. return GetControllerFromNpadIdType(npad_id);
  1389. }
  1390. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1391. const Core::HID::SixAxisSensorHandle& device_handle) const {
  1392. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1393. return GetControllerFromNpadIdType(npad_id);
  1394. }
  1395. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1396. const Core::HID::VibrationDeviceHandle& device_handle) {
  1397. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1398. return GetControllerFromNpadIdType(npad_id);
  1399. }
  1400. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromHandle(
  1401. const Core::HID::VibrationDeviceHandle& device_handle) const {
  1402. const auto npad_id = static_cast<Core::HID::NpadIdType>(device_handle.npad_id);
  1403. return GetControllerFromNpadIdType(npad_id);
  1404. }
  1405. Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1406. Core::HID::NpadIdType npad_id) {
  1407. if (!IsNpadIdValid(npad_id)) {
  1408. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1409. npad_id = Core::HID::NpadIdType::Player1;
  1410. }
  1411. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1412. return controller_data[npad_index];
  1413. }
  1414. const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpadIdType(
  1415. Core::HID::NpadIdType npad_id) const {
  1416. if (!IsNpadIdValid(npad_id)) {
  1417. LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
  1418. npad_id = Core::HID::NpadIdType::Player1;
  1419. }
  1420. const auto npad_index = Core::HID::NpadIdTypeToIndex(npad_id);
  1421. return controller_data[npad_index];
  1422. }
  1423. Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
  1424. const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
  1425. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1426. switch (sixaxis_handle.npad_type) {
  1427. case Core::HID::NpadStyleIndex::ProController:
  1428. case Core::HID::NpadStyleIndex::Pokeball:
  1429. return controller.shared_memory->sixaxis_fullkey_properties;
  1430. case Core::HID::NpadStyleIndex::Handheld:
  1431. return controller.shared_memory->sixaxis_handheld_properties;
  1432. case Core::HID::NpadStyleIndex::JoyconDual:
  1433. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1434. return controller.shared_memory->sixaxis_dual_left_properties;
  1435. }
  1436. return controller.shared_memory->sixaxis_dual_right_properties;
  1437. case Core::HID::NpadStyleIndex::JoyconLeft:
  1438. return controller.shared_memory->sixaxis_left_properties;
  1439. case Core::HID::NpadStyleIndex::JoyconRight:
  1440. return controller.shared_memory->sixaxis_right_properties;
  1441. default:
  1442. return controller.shared_memory->sixaxis_fullkey_properties;
  1443. }
  1444. }
  1445. const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
  1446. const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
  1447. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  1448. switch (sixaxis_handle.npad_type) {
  1449. case Core::HID::NpadStyleIndex::ProController:
  1450. case Core::HID::NpadStyleIndex::Pokeball:
  1451. return controller.shared_memory->sixaxis_fullkey_properties;
  1452. case Core::HID::NpadStyleIndex::Handheld:
  1453. return controller.shared_memory->sixaxis_handheld_properties;
  1454. case Core::HID::NpadStyleIndex::JoyconDual:
  1455. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1456. return controller.shared_memory->sixaxis_dual_left_properties;
  1457. }
  1458. return controller.shared_memory->sixaxis_dual_right_properties;
  1459. case Core::HID::NpadStyleIndex::JoyconLeft:
  1460. return controller.shared_memory->sixaxis_left_properties;
  1461. case Core::HID::NpadStyleIndex::JoyconRight:
  1462. return controller.shared_memory->sixaxis_right_properties;
  1463. default:
  1464. return controller.shared_memory->sixaxis_fullkey_properties;
  1465. }
  1466. }
  1467. Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
  1468. const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
  1469. auto& controller = GetControllerFromHandle(sixaxis_handle);
  1470. switch (sixaxis_handle.npad_type) {
  1471. case Core::HID::NpadStyleIndex::ProController:
  1472. case Core::HID::NpadStyleIndex::Pokeball:
  1473. return controller.sixaxis_fullkey;
  1474. case Core::HID::NpadStyleIndex::Handheld:
  1475. return controller.sixaxis_handheld;
  1476. case Core::HID::NpadStyleIndex::JoyconDual:
  1477. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1478. return controller.sixaxis_dual_left;
  1479. }
  1480. return controller.sixaxis_dual_right;
  1481. case Core::HID::NpadStyleIndex::JoyconLeft:
  1482. return controller.sixaxis_left;
  1483. case Core::HID::NpadStyleIndex::JoyconRight:
  1484. return controller.sixaxis_right;
  1485. default:
  1486. return controller.sixaxis_unknown;
  1487. }
  1488. }
  1489. const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
  1490. const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
  1491. const auto& controller = GetControllerFromHandle(sixaxis_handle);
  1492. switch (sixaxis_handle.npad_type) {
  1493. case Core::HID::NpadStyleIndex::ProController:
  1494. case Core::HID::NpadStyleIndex::Pokeball:
  1495. return controller.sixaxis_fullkey;
  1496. case Core::HID::NpadStyleIndex::Handheld:
  1497. return controller.sixaxis_handheld;
  1498. case Core::HID::NpadStyleIndex::JoyconDual:
  1499. if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
  1500. return controller.sixaxis_dual_left;
  1501. }
  1502. return controller.sixaxis_dual_right;
  1503. case Core::HID::NpadStyleIndex::JoyconLeft:
  1504. return controller.sixaxis_left;
  1505. case Core::HID::NpadStyleIndex::JoyconRight:
  1506. return controller.sixaxis_right;
  1507. default:
  1508. return controller.sixaxis_unknown;
  1509. }
  1510. }
  1511. } // namespace Service::HID