npad.cpp 72 KB

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