npad.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <algorithm>
  6. #include <array>
  7. #include <cstring>
  8. #include "common/assert.h"
  9. #include "common/bit_field.h"
  10. #include "common/common_types.h"
  11. #include "common/logging/log.h"
  12. #include "common/swap.h"
  13. #include "core/core.h"
  14. #include "core/core_timing.h"
  15. #include "core/frontend/input.h"
  16. #include "core/hle/kernel/event.h"
  17. #include "core/hle/service/hid/controllers/npad.h"
  18. #include "core/settings.h"
  19. namespace Service::HID {
  20. constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
  21. constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
  22. constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
  23. constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
  24. constexpr s32 HID_JOYSTICK_MAX = 0x7fff;
  25. constexpr s32 HID_JOYSTICK_MIN = -0x7fff;
  26. constexpr std::size_t NPAD_OFFSET = 0x9A00;
  27. constexpr u32 BATTERY_FULL = 2;
  28. enum class JoystickId : std::size_t { Joystick_Left, Joystick_Right };
  29. Controller_NPad::Controller_NPad() = default;
  30. Controller_NPad::~Controller_NPad() = default;
  31. void Controller_NPad::InitNewlyAddedControler(std::size_t controller_idx) {
  32. const auto controller_type = connected_controllers[controller_idx].type;
  33. auto& controller = shared_memory_entries[controller_idx];
  34. if (controller_type == NPadControllerType::None) {
  35. return;
  36. }
  37. controller.joy_styles.raw = 0; // Zero out
  38. controller.device_type.raw = 0;
  39. switch (controller_type) {
  40. case NPadControllerType::Handheld:
  41. controller.joy_styles.handheld.Assign(1);
  42. controller.device_type.handheld.Assign(1);
  43. controller.pad_assignment = NPadAssignments::Dual;
  44. break;
  45. case NPadControllerType::JoyDual:
  46. controller.joy_styles.joycon_dual.Assign(1);
  47. controller.device_type.joycon_left.Assign(1);
  48. controller.device_type.joycon_right.Assign(1);
  49. controller.pad_assignment = NPadAssignments::Dual;
  50. break;
  51. case NPadControllerType::JoyLeft:
  52. controller.joy_styles.joycon_left.Assign(1);
  53. controller.device_type.joycon_left.Assign(1);
  54. controller.pad_assignment = NPadAssignments::Dual;
  55. break;
  56. case NPadControllerType::JoyRight:
  57. controller.joy_styles.joycon_right.Assign(1);
  58. controller.device_type.joycon_right.Assign(1);
  59. controller.pad_assignment = NPadAssignments::Dual;
  60. break;
  61. case NPadControllerType::Pokeball:
  62. controller.joy_styles.pokeball.Assign(1);
  63. controller.device_type.pokeball.Assign(1);
  64. controller.pad_assignment = NPadAssignments::Single;
  65. break;
  66. case NPadControllerType::ProController:
  67. controller.joy_styles.pro_controller.Assign(1);
  68. controller.device_type.pro_controller.Assign(1);
  69. controller.pad_assignment = NPadAssignments::Single;
  70. break;
  71. }
  72. controller.single_color_error = ColorReadError::ReadOk;
  73. controller.single_color.body_color = 0;
  74. controller.single_color.button_color = 0;
  75. controller.dual_color_error = ColorReadError::ReadOk;
  76. controller.left_color.body_color = JOYCON_BODY_NEON_BLUE;
  77. controller.left_color.button_color = JOYCON_BUTTONS_NEON_BLUE;
  78. controller.right_color.body_color = JOYCON_BODY_NEON_RED;
  79. controller.right_color.button_color = JOYCON_BUTTONS_NEON_RED;
  80. controller.properties.is_vertical.Assign(1); // TODO(ogniK): Swap joycons orientations
  81. controller.properties.use_plus.Assign(1);
  82. controller.properties.use_minus.Assign(1);
  83. controller.battery_level[0] = BATTERY_FULL;
  84. controller.battery_level[1] = BATTERY_FULL;
  85. controller.battery_level[2] = BATTERY_FULL;
  86. }
  87. void Controller_NPad::OnInit() {
  88. auto& kernel = Core::System::GetInstance().Kernel();
  89. styleset_changed_event =
  90. Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "npad:NpadStyleSetChanged");
  91. if (!IsControllerActivated())
  92. return;
  93. std::size_t controller{};
  94. if (style.raw == 0) {
  95. // We want to support all controllers
  96. style.handheld.Assign(1);
  97. style.joycon_left.Assign(1);
  98. style.joycon_right.Assign(1);
  99. style.joycon_dual.Assign(1);
  100. style.pro_controller.Assign(1);
  101. style.pokeball.Assign(1);
  102. }
  103. if (std::none_of(connected_controllers.begin(), connected_controllers.end(),
  104. [](const ControllerHolder& controller) { return controller.is_connected; })) {
  105. supported_npad_id_types.resize(npad_id_list.size());
  106. std::memcpy(supported_npad_id_types.data(), npad_id_list.data(),
  107. npad_id_list.size() * sizeof(u32));
  108. AddNewController(NPadControllerType::JoyDual);
  109. }
  110. }
  111. void Controller_NPad::OnLoadInputDevices() {
  112. std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  113. Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
  114. buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
  115. std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  116. Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
  117. sticks.begin(), Input::CreateDevice<Input::AnalogDevice>);
  118. }
  119. void Controller_NPad::OnRelease() {}
  120. void Controller_NPad::OnUpdate(u8* data, std::size_t data_len) {
  121. if (!IsControllerActivated())
  122. return;
  123. for (std::size_t i = 0; i < shared_memory_entries.size(); i++) {
  124. auto& npad = shared_memory_entries[i];
  125. const std::array<NPadGeneric*, 7> controller_npads{&npad.main_controller_states,
  126. &npad.handheld_states,
  127. &npad.dual_states,
  128. &npad.left_joy_states,
  129. &npad.right_joy_states,
  130. &npad.pokeball_states,
  131. &npad.libnx};
  132. for (auto* main_controller : controller_npads) {
  133. main_controller->common.entry_count = 16;
  134. main_controller->common.total_entry_count = 17;
  135. const auto& last_entry =
  136. main_controller->npad[main_controller->common.last_entry_index];
  137. main_controller->common.timestamp = CoreTiming::GetTicks();
  138. main_controller->common.last_entry_index =
  139. (main_controller->common.last_entry_index + 1) % 17;
  140. auto& cur_entry = main_controller->npad[main_controller->common.last_entry_index];
  141. cur_entry.timestamp = last_entry.timestamp + 1;
  142. cur_entry.timestamp2 = cur_entry.timestamp;
  143. }
  144. const auto& controller_type = connected_controllers[i].type;
  145. if (controller_type == NPadControllerType::None || !connected_controllers[i].is_connected) {
  146. continue;
  147. }
  148. // Pad states
  149. ControllerPadState pad_state{};
  150. using namespace Settings::NativeButton;
  151. pad_state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
  152. pad_state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
  153. pad_state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
  154. pad_state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
  155. pad_state.l_stick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
  156. pad_state.r_stick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
  157. pad_state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
  158. pad_state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
  159. pad_state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
  160. pad_state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
  161. pad_state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
  162. pad_state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
  163. pad_state.d_left.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  164. pad_state.d_up.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
  165. pad_state.d_right.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
  166. pad_state.d_down.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
  167. pad_state.l_stick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  168. pad_state.l_stick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  169. pad_state.l_stick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  170. pad_state.l_stick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  171. pad_state.r_stick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  172. pad_state.r_stick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  173. pad_state.r_stick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  174. pad_state.r_stick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  175. pad_state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
  176. pad_state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
  177. AnalogPosition lstick_entry{};
  178. AnalogPosition rstick_entry{};
  179. const auto [stick_l_x_f, stick_l_y_f] =
  180. sticks[static_cast<std::size_t>(JoystickId::Joystick_Left)]->GetStatus();
  181. const auto [stick_r_x_f, stick_r_y_f] =
  182. sticks[static_cast<std::size_t>(JoystickId::Joystick_Right)]->GetStatus();
  183. lstick_entry.x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  184. lstick_entry.y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  185. rstick_entry.x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  186. rstick_entry.y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  187. auto& main_controller =
  188. npad.main_controller_states.npad[npad.main_controller_states.common.last_entry_index];
  189. auto& handheld_entry =
  190. npad.handheld_states.npad[npad.handheld_states.common.last_entry_index];
  191. auto& dual_entry = npad.dual_states.npad[npad.dual_states.common.last_entry_index];
  192. auto& left_entry = npad.left_joy_states.npad[npad.left_joy_states.common.last_entry_index];
  193. auto& right_entry =
  194. npad.right_joy_states.npad[npad.right_joy_states.common.last_entry_index];
  195. auto& pokeball_entry =
  196. npad.pokeball_states.npad[npad.pokeball_states.common.last_entry_index];
  197. auto& libnx_entry = npad.libnx.npad[npad.libnx.common.last_entry_index];
  198. if (hold_type == NpadHoldType::Horizontal) {
  199. // TODO(ogniK): Remap buttons for different orientations
  200. }
  201. libnx_entry.connection_status.raw = 0;
  202. switch (controller_type) {
  203. case NPadControllerType::Handheld:
  204. handheld_entry.connection_status.raw = 0;
  205. handheld_entry.connection_status.IsConnected.Assign(1);
  206. if (!Settings::values.use_docked_mode) {
  207. handheld_entry.connection_status.IsWired.Assign(1);
  208. }
  209. handheld_entry.pad_states.raw = pad_state.raw;
  210. handheld_entry.l_stick = lstick_entry;
  211. handheld_entry.r_stick = rstick_entry;
  212. break;
  213. case NPadControllerType::JoyDual:
  214. dual_entry.connection_status.raw = 0;
  215. dual_entry.connection_status.IsLeftJoyConnected.Assign(1);
  216. dual_entry.connection_status.IsRightJoyConnected.Assign(1);
  217. dual_entry.connection_status.IsConnected.Assign(1);
  218. libnx_entry.connection_status.IsLeftJoyConnected.Assign(1);
  219. libnx_entry.connection_status.IsRightJoyConnected.Assign(1);
  220. libnx_entry.connection_status.IsConnected.Assign(1);
  221. dual_entry.pad_states.raw = pad_state.raw;
  222. dual_entry.l_stick = lstick_entry;
  223. dual_entry.r_stick = rstick_entry;
  224. case NPadControllerType::JoyLeft:
  225. left_entry.connection_status.raw = 0;
  226. left_entry.connection_status.IsConnected.Assign(1);
  227. left_entry.pad_states.raw = pad_state.raw;
  228. left_entry.l_stick = lstick_entry;
  229. left_entry.r_stick = rstick_entry;
  230. break;
  231. case NPadControllerType::JoyRight:
  232. right_entry.connection_status.raw = 0;
  233. right_entry.connection_status.IsConnected.Assign(1);
  234. right_entry.pad_states.raw = pad_state.raw;
  235. right_entry.l_stick = lstick_entry;
  236. right_entry.r_stick = rstick_entry;
  237. break;
  238. case NPadControllerType::Pokeball:
  239. pokeball_entry.connection_status.raw = 0;
  240. pokeball_entry.connection_status.IsConnected.Assign(1);
  241. pokeball_entry.connection_status.IsWired.Assign(1);
  242. pokeball_entry.pad_states.raw = pad_state.raw;
  243. pokeball_entry.l_stick = lstick_entry;
  244. pokeball_entry.r_stick = rstick_entry;
  245. break;
  246. case NPadControllerType::ProController:
  247. main_controller.connection_status.raw = 0;
  248. main_controller.connection_status.IsConnected.Assign(1);
  249. main_controller.connection_status.IsWired.Assign(1);
  250. main_controller.pad_states.raw = pad_state.raw;
  251. main_controller.l_stick = lstick_entry;
  252. main_controller.r_stick = rstick_entry;
  253. break;
  254. }
  255. // LibNX exclusively uses this section, so we always update it since LibNX doesn't activate
  256. // any controllers.
  257. libnx_entry.pad_states.raw = pad_state.raw;
  258. libnx_entry.l_stick = lstick_entry;
  259. libnx_entry.r_stick = rstick_entry;
  260. }
  261. std::memcpy(data + NPAD_OFFSET, shared_memory_entries.data(),
  262. shared_memory_entries.size() * sizeof(NPadEntry));
  263. } // namespace Service::HID
  264. void Controller_NPad::SetSupportedStyleSet(NPadType style_set) {
  265. style.raw = style_set.raw;
  266. }
  267. Controller_NPad::NPadType Controller_NPad::GetSupportedStyleSet() const {
  268. return style;
  269. }
  270. void Controller_NPad::SetSupportedNPadIdTypes(u8* data, std::size_t length) {
  271. ASSERT(length > 0 && (length % sizeof(u32)) == 0);
  272. supported_npad_id_types.clear();
  273. supported_npad_id_types.resize(length / sizeof(u32));
  274. std::memcpy(supported_npad_id_types.data(), data, length);
  275. }
  276. void Controller_NPad::GetSupportedNpadIdTypes(u32* data, std::size_t max_length) {
  277. ASSERT(max_length < supported_npad_id_types.size());
  278. std::memcpy(data, supported_npad_id_types.data(), supported_npad_id_types.size());
  279. }
  280. std::size_t Controller_NPad::GetSupportedNPadIdTypesSize() const {
  281. return supported_npad_id_types.size();
  282. }
  283. void Controller_NPad::SetHoldType(NpadHoldType joy_hold_type) {
  284. hold_type = joy_hold_type;
  285. }
  286. Controller_NPad::NpadHoldType Controller_NPad::GetHoldType() const {
  287. return hold_type;
  288. }
  289. void Controller_NPad::SetNpadMode(u32 npad_id, NPadAssignments assignment_mode) {
  290. ASSERT(npad_id < shared_memory_entries.size());
  291. shared_memory_entries[npad_id].pad_assignment = assignment_mode;
  292. }
  293. void Controller_NPad::VibrateController(const std::vector<u32>& controller_ids,
  294. const std::vector<Vibration>& vibrations) {
  295. if (!can_controllers_vibrate) {
  296. return;
  297. }
  298. for (std::size_t i = 0; i < controller_ids.size(); i++) {
  299. std::size_t controller_pos = i;
  300. // Handheld controller conversion
  301. if (controller_pos == 32) {
  302. controller_pos = 8;
  303. }
  304. // Unknown controller conversion
  305. if (controller_pos == 16) {
  306. controller_pos = 9;
  307. }
  308. if (connected_controllers[controller_pos].is_connected) {
  309. // TODO(ogniK): Vibrate the physical controller
  310. }
  311. }
  312. LOG_WARNING(Service_HID, "(STUBBED) called");
  313. last_processed_vibration = vibrations.back();
  314. }
  315. Kernel::SharedPtr<Kernel::Event> Controller_NPad::GetStyleSetChangedEvent() const {
  316. return styleset_changed_event;
  317. }
  318. Controller_NPad::Vibration Controller_NPad::GetLastVibration() const {
  319. return last_processed_vibration;
  320. }
  321. void Controller_NPad::AddNewController(NPadControllerType controller) {
  322. if (controller == NPadControllerType::Handheld) {
  323. connected_controllers[8] = {controller, true};
  324. InitNewlyAddedControler(8);
  325. return;
  326. }
  327. const auto pos =
  328. std::find_if(connected_controllers.begin(), connected_controllers.end() - 2,
  329. [](const ControllerHolder& holder) { return !holder.is_connected; });
  330. if (pos == connected_controllers.end() - 2) {
  331. LOG_ERROR(Service_HID, "Cannot connect any more controllers!");
  332. return;
  333. }
  334. const auto controller_id = std::distance(connected_controllers.begin(), pos);
  335. connected_controllers[controller_id] = {controller, true};
  336. InitNewlyAddedControler(controller_id);
  337. }
  338. void Controller_NPad::ConnectNPad(u32 npad_id) {
  339. if (npad_id >= connected_controllers.size())
  340. return;
  341. connected_controllers[npad_id].is_connected = true;
  342. }
  343. void Controller_NPad::DisconnectNPad(u32 npad_id) {
  344. if (npad_id >= connected_controllers.size())
  345. return;
  346. connected_controllers[npad_id].is_connected = false;
  347. }
  348. Controller_NPad::LedPattern Controller_NPad::GetLedPattern(u32 npad_id) {
  349. if (npad_id == npad_id_list.back() || npad_id == npad_id_list[npad_id_list.size() - 2]) {
  350. // These are controllers without led patterns
  351. return LedPattern{0, 0, 0, 0};
  352. }
  353. switch (npad_id) {
  354. case 0:
  355. return LedPattern{1, 0, 0, 0};
  356. case 1:
  357. return LedPattern{0, 1, 0, 0};
  358. case 2:
  359. return LedPattern{0, 0, 1, 0};
  360. case 3:
  361. return LedPattern{0, 0, 0, 1};
  362. case 4:
  363. return LedPattern{1, 0, 0, 1};
  364. case 5:
  365. return LedPattern{1, 0, 1, 0};
  366. case 6:
  367. return LedPattern{1, 0, 1, 1};
  368. case 7:
  369. return LedPattern{0, 1, 1, 0};
  370. default:
  371. UNIMPLEMENTED_MSG("Unhandled npad_id {}", npad_id);
  372. return LedPattern{0, 0, 0, 0};
  373. };
  374. }
  375. void Controller_NPad::SetVibrationEnabled(bool can_vibrate) {
  376. can_controllers_vibrate = can_vibrate;
  377. }
  378. } // namespace Service::HID