hid.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <atomic>
  5. #include "common/logging/log.h"
  6. #include "core/core_timing.h"
  7. #include "core/core_timing_util.h"
  8. #include "core/frontend/emu_window.h"
  9. #include "core/frontend/input.h"
  10. #include "core/hle/ipc_helpers.h"
  11. #include "core/hle/kernel/client_port.h"
  12. #include "core/hle/kernel/client_session.h"
  13. #include "core/hle/kernel/event.h"
  14. #include "core/hle/kernel/shared_memory.h"
  15. #include "core/hle/service/hid/hid.h"
  16. #include "core/hle/service/hid/irs.h"
  17. #include "core/hle/service/hid/xcd.h"
  18. #include "core/hle/service/service.h"
  19. namespace Service::HID {
  20. // Updating period for each HID device.
  21. // TODO(shinyquagsire23): These need better values.
  22. constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  23. constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  24. constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  25. class IAppletResource final : public ServiceFramework<IAppletResource> {
  26. public:
  27. IAppletResource() : ServiceFramework("IAppletResource") {
  28. static const FunctionInfo functions[] = {
  29. {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
  30. };
  31. RegisterHandlers(functions);
  32. shared_mem = Kernel::SharedMemory::Create(
  33. nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read,
  34. 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
  35. // Register update callbacks
  36. pad_update_event = CoreTiming::RegisterEvent(
  37. "HID::UpdatePadCallback",
  38. [this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); });
  39. // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
  40. CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
  41. }
  42. ~IAppletResource() {
  43. CoreTiming::UnscheduleEvent(pad_update_event, 0);
  44. }
  45. private:
  46. void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
  47. IPC::ResponseBuilder rb{ctx, 2, 1};
  48. rb.Push(RESULT_SUCCESS);
  49. rb.PushCopyObjects(shared_mem);
  50. LOG_DEBUG(Service_HID, "called");
  51. }
  52. void LoadInputDevices() {
  53. std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  54. Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
  55. buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
  56. std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  57. Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
  58. sticks.begin(), Input::CreateDevice<Input::AnalogDevice>);
  59. touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device);
  60. // TODO(shinyquagsire23): gyro, mouse, keyboard
  61. }
  62. void UpdatePadCallback(u64 userdata, int cycles_late) {
  63. SharedMemory mem{};
  64. std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory));
  65. if (is_device_reload_pending.exchange(false))
  66. LoadInputDevices();
  67. // Set up controllers as neon red+blue Joy-Con attached to console
  68. ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header;
  69. controller_header.type = ControllerType_Handheld;
  70. controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent;
  71. controller_header.right_color_body = JOYCON_BODY_NEON_RED;
  72. controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED;
  73. controller_header.left_color_body = JOYCON_BODY_NEON_BLUE;
  74. controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE;
  75. for (size_t controller = 0; controller < mem.controllers.size(); controller++) {
  76. for (auto& layout : mem.controllers[controller].layouts) {
  77. layout.header.num_entries = HID_NUM_ENTRIES;
  78. layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
  79. // HID shared memory stores the state of the past 17 samples in a circlular buffer,
  80. // each with a timestamp in number of samples since boot.
  81. const ControllerInputEntry& last_entry = layout.entries[layout.header.latest_entry];
  82. layout.header.timestamp_ticks = CoreTiming::GetTicks();
  83. layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
  84. ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
  85. entry.timestamp = last_entry.timestamp + 1;
  86. // TODO(shinyquagsire23): Is this always identical to timestamp?
  87. entry.timestamp_2 = entry.timestamp;
  88. // TODO(shinyquagsire23): More than just handheld input
  89. if (controller != Controller_Handheld)
  90. continue;
  91. entry.connection_state = ConnectionState_Connected | ConnectionState_Wired;
  92. // TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future?
  93. // For now everything is just the default handheld layout, but split Joy-Con will
  94. // rotate the face buttons and directions for certain layouts.
  95. ControllerPadState& state = entry.buttons;
  96. using namespace Settings::NativeButton;
  97. state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
  98. state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
  99. state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
  100. state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
  101. state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
  102. state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
  103. state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
  104. state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
  105. state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
  106. state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
  107. state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
  108. state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
  109. state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  110. state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
  111. state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
  112. state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
  113. state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  114. state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  115. state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  116. state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  117. state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  118. state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  119. state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  120. state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  121. state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
  122. state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
  123. const auto [stick_l_x_f, stick_l_y_f] = sticks[Joystick_Left]->GetStatus();
  124. const auto [stick_r_x_f, stick_r_y_f] = sticks[Joystick_Right]->GetStatus();
  125. entry.joystick_left_x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  126. entry.joystick_left_y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  127. entry.joystick_right_x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  128. entry.joystick_right_y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  129. }
  130. }
  131. TouchScreen& touchscreen = mem.touchscreen;
  132. const u64 last_entry = touchscreen.header.latest_entry;
  133. const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size();
  134. const u64 timestamp = CoreTiming::GetTicks();
  135. const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1;
  136. touchscreen.header.timestamp_ticks = timestamp;
  137. touchscreen.header.num_entries = touchscreen.entries.size();
  138. touchscreen.header.latest_entry = curr_entry;
  139. touchscreen.header.max_entry_index = touchscreen.entries.size();
  140. touchscreen.header.timestamp = timestamp;
  141. touchscreen.entries[curr_entry].header.timestamp = sample_counter;
  142. TouchScreenEntryTouch touch_entry{};
  143. auto [x, y, pressed] = touch_device->GetStatus();
  144. touch_entry.timestamp = timestamp;
  145. touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width);
  146. touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height);
  147. touch_entry.touch_index = 0;
  148. // TODO(DarkLordZach): Maybe try to derive these from EmuWindow?
  149. touch_entry.diameter_x = 15;
  150. touch_entry.diameter_y = 15;
  151. touch_entry.angle = 0;
  152. // TODO(DarkLordZach): Implement multi-touch support
  153. if (pressed) {
  154. touchscreen.entries[curr_entry].header.num_touches = 1;
  155. touchscreen.entries[curr_entry].touches[0] = touch_entry;
  156. } else {
  157. touchscreen.entries[curr_entry].header.num_touches = 0;
  158. }
  159. // TODO(shinyquagsire23): Properly implement mouse
  160. Mouse& mouse = mem.mouse;
  161. const u64 last_mouse_entry = mouse.header.latest_entry;
  162. const u64 curr_mouse_entry = (mouse.header.latest_entry + 1) % mouse.entries.size();
  163. const u64 mouse_sample_counter = mouse.entries[last_mouse_entry].timestamp + 1;
  164. mouse.header.timestamp_ticks = timestamp;
  165. mouse.header.num_entries = mouse.entries.size();
  166. mouse.header.max_entry_index = mouse.entries.size();
  167. mouse.header.latest_entry = curr_mouse_entry;
  168. mouse.entries[curr_mouse_entry].timestamp = mouse_sample_counter;
  169. mouse.entries[curr_mouse_entry].timestamp_2 = mouse_sample_counter;
  170. // TODO(shinyquagsire23): Properly implement keyboard
  171. Keyboard& keyboard = mem.keyboard;
  172. const u64 last_keyboard_entry = keyboard.header.latest_entry;
  173. const u64 curr_keyboard_entry =
  174. (keyboard.header.latest_entry + 1) % keyboard.entries.size();
  175. const u64 keyboard_sample_counter = keyboard.entries[last_keyboard_entry].timestamp + 1;
  176. keyboard.header.timestamp_ticks = timestamp;
  177. keyboard.header.num_entries = keyboard.entries.size();
  178. keyboard.header.latest_entry = last_keyboard_entry;
  179. keyboard.header.max_entry_index = keyboard.entries.size();
  180. keyboard.entries[curr_keyboard_entry].timestamp = keyboard_sample_counter;
  181. keyboard.entries[curr_keyboard_entry].timestamp_2 = keyboard_sample_counter;
  182. // TODO(shinyquagsire23): Figure out what any of these are
  183. for (auto& input : mem.unk_input_1) {
  184. const u64 last_input_entry = input.header.latest_entry;
  185. const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
  186. const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
  187. input.header.timestamp_ticks = timestamp;
  188. input.header.num_entries = input.entries.size();
  189. input.header.latest_entry = last_input_entry;
  190. input.header.max_entry_index = input.entries.size();
  191. input.entries[curr_input_entry].timestamp = input_sample_counter;
  192. input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
  193. }
  194. for (auto& input : mem.unk_input_2) {
  195. input.header.timestamp_ticks = timestamp;
  196. input.header.num_entries = 17;
  197. input.header.latest_entry = 0;
  198. input.header.max_entry_index = 0;
  199. }
  200. UnkInput3& input = mem.unk_input_3;
  201. const u64 last_input_entry = input.header.latest_entry;
  202. const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
  203. const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
  204. input.header.timestamp_ticks = timestamp;
  205. input.header.num_entries = input.entries.size();
  206. input.header.latest_entry = last_input_entry;
  207. input.header.max_entry_index = input.entries.size();
  208. input.entries[curr_input_entry].timestamp = input_sample_counter;
  209. input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
  210. // TODO(shinyquagsire23): Signal events
  211. std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory));
  212. // Reschedule recurrent event
  213. CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
  214. }
  215. // Handle to shared memory region designated to HID service
  216. Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
  217. // CoreTiming update events
  218. CoreTiming::EventType* pad_update_event;
  219. // Stored input state info
  220. std::atomic<bool> is_device_reload_pending{true};
  221. std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
  222. buttons;
  223. std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks;
  224. std::unique_ptr<Input::TouchDevice> touch_device;
  225. };
  226. class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
  227. public:
  228. IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") {
  229. static const FunctionInfo functions[] = {
  230. {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"},
  231. };
  232. RegisterHandlers(functions);
  233. }
  234. private:
  235. void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
  236. IPC::ResponseBuilder rb{ctx, 2};
  237. rb.Push(RESULT_SUCCESS);
  238. LOG_WARNING(Service_HID, "(STUBBED) called");
  239. }
  240. };
  241. class Hid final : public ServiceFramework<Hid> {
  242. public:
  243. Hid() : ServiceFramework("hid") {
  244. static const FunctionInfo functions[] = {
  245. {0, &Hid::CreateAppletResource, "CreateAppletResource"},
  246. {1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
  247. {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"},
  248. {21, &Hid::ActivateMouse, "ActivateMouse"},
  249. {31, &Hid::ActivateKeyboard, "ActivateKeyboard"},
  250. {40, nullptr, "AcquireXpadIdEventHandle"},
  251. {41, nullptr, "ReleaseXpadIdEventHandle"},
  252. {51, nullptr, "ActivateXpad"},
  253. {55, nullptr, "GetXpadIds"},
  254. {56, nullptr, "ActivateJoyXpad"},
  255. {58, nullptr, "GetJoyXpadLifoHandle"},
  256. {59, nullptr, "GetJoyXpadIds"},
  257. {60, nullptr, "ActivateSixAxisSensor"},
  258. {61, nullptr, "DeactivateSixAxisSensor"},
  259. {62, nullptr, "GetSixAxisSensorLifoHandle"},
  260. {63, nullptr, "ActivateJoySixAxisSensor"},
  261. {64, nullptr, "DeactivateJoySixAxisSensor"},
  262. {65, nullptr, "GetJoySixAxisSensorLifoHandle"},
  263. {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
  264. {67, nullptr, "StopSixAxisSensor"},
  265. {68, nullptr, "IsSixAxisSensorFusionEnabled"},
  266. {69, nullptr, "EnableSixAxisSensorFusion"},
  267. {70, nullptr, "SetSixAxisSensorFusionParameters"},
  268. {71, nullptr, "GetSixAxisSensorFusionParameters"},
  269. {72, nullptr, "ResetSixAxisSensorFusionParameters"},
  270. {73, nullptr, "SetAccelerometerParameters"},
  271. {74, nullptr, "GetAccelerometerParameters"},
  272. {75, nullptr, "ResetAccelerometerParameters"},
  273. {76, nullptr, "SetAccelerometerPlayMode"},
  274. {77, nullptr, "GetAccelerometerPlayMode"},
  275. {78, nullptr, "ResetAccelerometerPlayMode"},
  276. {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
  277. {80, nullptr, "GetGyroscopeZeroDriftMode"},
  278. {81, nullptr, "ResetGyroscopeZeroDriftMode"},
  279. {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
  280. {91, nullptr, "ActivateGesture"},
  281. {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
  282. {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
  283. {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
  284. {103, &Hid::ActivateNpad, "ActivateNpad"},
  285. {104, nullptr, "DeactivateNpad"},
  286. {106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
  287. "AcquireNpadStyleSetUpdateEventHandle"},
  288. {107, nullptr, "DisconnectNpad"},
  289. {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
  290. {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
  291. {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
  292. {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
  293. "SetNpadJoyAssignmentModeSingleByDefault"},
  294. {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
  295. {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
  296. {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
  297. {126, nullptr, "StartLrAssignmentMode"},
  298. {127, nullptr, "StopLrAssignmentMode"},
  299. {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
  300. {129, nullptr, "GetNpadHandheldActivationMode"},
  301. {130, nullptr, "SwapNpadAssignment"},
  302. {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
  303. {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
  304. {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
  305. {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
  306. {201, &Hid::SendVibrationValue, "SendVibrationValue"},
  307. {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
  308. {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
  309. {204, nullptr, "PermitVibration"},
  310. {205, nullptr, "IsVibrationPermitted"},
  311. {206, &Hid::SendVibrationValues, "SendVibrationValues"},
  312. {207, nullptr, "SendVibrationGcErmCommand"},
  313. {208, nullptr, "GetActualVibrationGcErmCommand"},
  314. {209, nullptr, "BeginPermitVibrationSession"},
  315. {210, nullptr, "EndPermitVibrationSession"},
  316. {300, nullptr, "ActivateConsoleSixAxisSensor"},
  317. {301, nullptr, "StartConsoleSixAxisSensor"},
  318. {302, nullptr, "StopConsoleSixAxisSensor"},
  319. {303, nullptr, "ActivateSevenSixAxisSensor"},
  320. {304, nullptr, "StartSevenSixAxisSensor"},
  321. {305, nullptr, "StopSevenSixAxisSensor"},
  322. {306, nullptr, "InitializeSevenSixAxisSensor"},
  323. {307, nullptr, "FinalizeSevenSixAxisSensor"},
  324. {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
  325. {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
  326. {400, nullptr, "IsUsbFullKeyControllerEnabled"},
  327. {401, nullptr, "EnableUsbFullKeyController"},
  328. {402, nullptr, "IsUsbFullKeyControllerConnected"},
  329. {403, nullptr, "HasBattery"},
  330. {404, nullptr, "HasLeftRightBattery"},
  331. {405, nullptr, "GetNpadInterfaceType"},
  332. {406, nullptr, "GetNpadLeftRightInterfaceType"},
  333. {500, nullptr, "GetPalmaConnectionHandle"},
  334. {501, nullptr, "InitializePalma"},
  335. {502, nullptr, "AcquirePalmaOperationCompleteEvent"},
  336. {503, nullptr, "GetPalmaOperationInfo"},
  337. {504, nullptr, "PlayPalmaActivity"},
  338. {505, nullptr, "SetPalmaFrModeType"},
  339. {506, nullptr, "ReadPalmaStep"},
  340. {507, nullptr, "EnablePalmaStep"},
  341. {508, nullptr, "SuspendPalmaStep"},
  342. {509, nullptr, "ResetPalmaStep"},
  343. {510, nullptr, "ReadPalmaApplicationSection"},
  344. {511, nullptr, "WritePalmaApplicationSection"},
  345. {512, nullptr, "ReadPalmaUniqueCode"},
  346. {513, nullptr, "SetPalmaUniqueCodeInvalid"},
  347. {1000, nullptr, "SetNpadCommunicationMode"},
  348. {1001, nullptr, "GetNpadCommunicationMode"},
  349. };
  350. RegisterHandlers(functions);
  351. event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
  352. }
  353. ~Hid() = default;
  354. private:
  355. std::shared_ptr<IAppletResource> applet_resource;
  356. u32 joy_hold_type{0};
  357. Kernel::SharedPtr<Kernel::Event> event;
  358. void CreateAppletResource(Kernel::HLERequestContext& ctx) {
  359. if (applet_resource == nullptr) {
  360. applet_resource = std::make_shared<IAppletResource>();
  361. }
  362. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  363. rb.Push(RESULT_SUCCESS);
  364. rb.PushIpcInterface<IAppletResource>(applet_resource);
  365. LOG_DEBUG(Service_HID, "called");
  366. }
  367. void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
  368. IPC::ResponseBuilder rb{ctx, 2};
  369. rb.Push(RESULT_SUCCESS);
  370. LOG_WARNING(Service_HID, "(STUBBED) called");
  371. }
  372. void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
  373. IPC::ResponseBuilder rb{ctx, 2};
  374. rb.Push(RESULT_SUCCESS);
  375. LOG_WARNING(Service_HID, "(STUBBED) called");
  376. }
  377. void ActivateMouse(Kernel::HLERequestContext& ctx) {
  378. IPC::ResponseBuilder rb{ctx, 2};
  379. rb.Push(RESULT_SUCCESS);
  380. LOG_WARNING(Service_HID, "(STUBBED) called");
  381. }
  382. void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
  383. IPC::ResponseBuilder rb{ctx, 2};
  384. rb.Push(RESULT_SUCCESS);
  385. LOG_WARNING(Service_HID, "(STUBBED) called");
  386. }
  387. void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
  388. IPC::ResponseBuilder rb{ctx, 2};
  389. rb.Push(RESULT_SUCCESS);
  390. LOG_WARNING(Service_HID, "(STUBBED) called");
  391. }
  392. void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
  393. IPC::ResponseBuilder rb{ctx, 2};
  394. rb.Push(RESULT_SUCCESS);
  395. LOG_WARNING(Service_HID, "(STUBBED) called");
  396. }
  397. void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
  398. IPC::ResponseBuilder rb{ctx, 2};
  399. rb.Push(RESULT_SUCCESS);
  400. // TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
  401. rb.Push(true);
  402. LOG_WARNING(Service_HID, "(STUBBED) called");
  403. }
  404. void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  405. IPC::ResponseBuilder rb{ctx, 2};
  406. rb.Push(RESULT_SUCCESS);
  407. LOG_WARNING(Service_HID, "(STUBBED) called");
  408. }
  409. void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  410. IPC::ResponseBuilder rb{ctx, 3};
  411. rb.Push(RESULT_SUCCESS);
  412. rb.Push<u32>(0);
  413. LOG_WARNING(Service_HID, "(STUBBED) called");
  414. }
  415. void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
  416. IPC::ResponseBuilder rb{ctx, 2};
  417. rb.Push(RESULT_SUCCESS);
  418. LOG_WARNING(Service_HID, "(STUBBED) called");
  419. }
  420. void ActivateNpad(Kernel::HLERequestContext& ctx) {
  421. IPC::ResponseBuilder rb{ctx, 2};
  422. rb.Push(RESULT_SUCCESS);
  423. LOG_WARNING(Service_HID, "(STUBBED) called");
  424. }
  425. void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
  426. IPC::ResponseBuilder rb{ctx, 2, 1};
  427. rb.Push(RESULT_SUCCESS);
  428. rb.PushCopyObjects(event);
  429. LOG_WARNING(Service_HID, "(STUBBED) called");
  430. }
  431. void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
  432. IPC::ResponseBuilder rb{ctx, 2};
  433. rb.Push(RESULT_SUCCESS);
  434. LOG_WARNING(Service_HID, "(STUBBED) called");
  435. }
  436. void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  437. IPC::ResponseBuilder rb{ctx, 2};
  438. rb.Push(RESULT_SUCCESS);
  439. LOG_WARNING(Service_HID, "(STUBBED) called");
  440. }
  441. void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  442. IPC::ResponseBuilder rb{ctx, 3};
  443. rb.Push(RESULT_SUCCESS);
  444. rb.Push(joy_hold_type);
  445. LOG_WARNING(Service_HID, "(STUBBED) called");
  446. }
  447. void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
  448. IPC::ResponseBuilder rb{ctx, 2};
  449. rb.Push(RESULT_SUCCESS);
  450. LOG_WARNING(Service_HID, "(STUBBED) called");
  451. }
  452. void SendVibrationValue(Kernel::HLERequestContext& ctx) {
  453. IPC::ResponseBuilder rb{ctx, 2};
  454. rb.Push(RESULT_SUCCESS);
  455. LOG_WARNING(Service_HID, "(STUBBED) called");
  456. }
  457. void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
  458. IPC::ResponseBuilder rb{ctx, 2};
  459. rb.Push(RESULT_SUCCESS);
  460. LOG_WARNING(Service_HID, "(STUBBED) called");
  461. }
  462. void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
  463. IPC::ResponseBuilder rb{ctx, 2};
  464. rb.Push(RESULT_SUCCESS);
  465. LOG_WARNING(Service_HID, "(STUBBED) called");
  466. }
  467. void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
  468. IPC::ResponseBuilder rb{ctx, 2};
  469. rb.Push(RESULT_SUCCESS);
  470. LOG_WARNING(Service_HID, "(STUBBED) called");
  471. }
  472. void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
  473. IPC::ResponseBuilder rb{ctx, 2};
  474. rb.Push(RESULT_SUCCESS);
  475. LOG_WARNING(Service_HID, "(STUBBED) called");
  476. }
  477. void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
  478. IPC::ResponseBuilder rb{ctx, 4};
  479. rb.Push(RESULT_SUCCESS);
  480. rb.Push<u64>(0);
  481. LOG_WARNING(Service_HID, "(STUBBED) called");
  482. }
  483. void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
  484. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  485. rb.Push(RESULT_SUCCESS);
  486. rb.PushIpcInterface<IActiveVibrationDeviceList>();
  487. LOG_DEBUG(Service_HID, "called");
  488. }
  489. void SendVibrationValues(Kernel::HLERequestContext& ctx) {
  490. IPC::ResponseBuilder rb{ctx, 2};
  491. rb.Push(RESULT_SUCCESS);
  492. LOG_WARNING(Service_HID, "(STUBBED) called");
  493. }
  494. };
  495. class HidDbg final : public ServiceFramework<HidDbg> {
  496. public:
  497. explicit HidDbg() : ServiceFramework{"hid:dbg"} {
  498. // clang-format off
  499. static const FunctionInfo functions[] = {
  500. {0, nullptr, "DeactivateDebugPad"},
  501. {1, nullptr, "SetDebugPadAutoPilotState"},
  502. {2, nullptr, "UnsetDebugPadAutoPilotState"},
  503. {10, nullptr, "DeactivateTouchScreen"},
  504. {11, nullptr, "SetTouchScreenAutoPilotState"},
  505. {12, nullptr, "UnsetTouchScreenAutoPilotState"},
  506. {20, nullptr, "DeactivateMouse"},
  507. {21, nullptr, "SetMouseAutoPilotState"},
  508. {22, nullptr, "UnsetMouseAutoPilotState"},
  509. {30, nullptr, "DeactivateKeyboard"},
  510. {31, nullptr, "SetKeyboardAutoPilotState"},
  511. {32, nullptr, "UnsetKeyboardAutoPilotState"},
  512. {50, nullptr, "DeactivateXpad"},
  513. {51, nullptr, "SetXpadAutoPilotState"},
  514. {52, nullptr, "UnsetXpadAutoPilotState"},
  515. {60, nullptr, "DeactivateJoyXpad"},
  516. {91, nullptr, "DeactivateGesture"},
  517. {110, nullptr, "DeactivateHomeButton"},
  518. {111, nullptr, "SetHomeButtonAutoPilotState"},
  519. {112, nullptr, "UnsetHomeButtonAutoPilotState"},
  520. {120, nullptr, "DeactivateSleepButton"},
  521. {121, nullptr, "SetSleepButtonAutoPilotState"},
  522. {122, nullptr, "UnsetSleepButtonAutoPilotState"},
  523. {123, nullptr, "DeactivateInputDetector"},
  524. {130, nullptr, "DeactivateCaptureButton"},
  525. {131, nullptr, "SetCaptureButtonAutoPilotState"},
  526. {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
  527. {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
  528. {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
  529. {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
  530. {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
  531. {140, nullptr, "DeactivateConsoleSixAxisSensor"},
  532. {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
  533. {142, nullptr, "DeactivateSevenSixAxisSensor"},
  534. {201, nullptr, "ActivateFirmwareUpdate"},
  535. {202, nullptr, "DeactivateFirmwareUpdate"},
  536. {203, nullptr, "StartFirmwareUpdate"},
  537. {204, nullptr, "GetFirmwareUpdateStage"},
  538. {205, nullptr, "GetFirmwareVersion"},
  539. {206, nullptr, "GetDestinationFirmwareVersion"},
  540. {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
  541. {208, nullptr, "StartFirmwareUpdateForRevert"},
  542. {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
  543. {210, nullptr, "IsFirmwareUpdatingDevice"},
  544. {221, nullptr, "UpdateControllerColor"},
  545. {222, nullptr, "ConnectUsbPadsAsync"},
  546. {223, nullptr, "DisconnectUsbPadsAsync"},
  547. {224, nullptr, "UpdateDesignInfo"},
  548. {225, nullptr, "GetUniquePadDriverState"},
  549. {226, nullptr, "GetSixAxisSensorDriverStates"},
  550. {301, nullptr, "GetAbstractedPadHandles"},
  551. {302, nullptr, "GetAbstractedPadState"},
  552. {303, nullptr, "GetAbstractedPadsState"},
  553. {321, nullptr, "SetAutoPilotVirtualPadState"},
  554. {322, nullptr, "UnsetAutoPilotVirtualPadState"},
  555. {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
  556. {350, nullptr, "AddRegisteredDevice"},
  557. };
  558. // clang-format on
  559. RegisterHandlers(functions);
  560. }
  561. };
  562. class HidSys final : public ServiceFramework<HidSys> {
  563. public:
  564. explicit HidSys() : ServiceFramework{"hid:sys"} {
  565. // clang-format off
  566. static const FunctionInfo functions[] = {
  567. {31, nullptr, "SendKeyboardLockKeyEvent"},
  568. {101, nullptr, "AcquireHomeButtonEventHandle"},
  569. {111, nullptr, "ActivateHomeButton"},
  570. {121, nullptr, "AcquireSleepButtonEventHandle"},
  571. {131, nullptr, "ActivateSleepButton"},
  572. {141, nullptr, "AcquireCaptureButtonEventHandle"},
  573. {151, nullptr, "ActivateCaptureButton"},
  574. {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
  575. {211, nullptr, "GetNpadsWithNfc"},
  576. {212, nullptr, "AcquireNfcActivateEventHandle"},
  577. {213, nullptr, "ActivateNfc"},
  578. {214, nullptr, "GetXcdHandleForNpadWithNfc"},
  579. {215, nullptr, "IsNfcActivated"},
  580. {230, nullptr, "AcquireIrSensorEventHandle"},
  581. {231, nullptr, "ActivateIrSensor"},
  582. {301, nullptr, "ActivateNpadSystem"},
  583. {303, nullptr, "ApplyNpadSystemCommonPolicy"},
  584. {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
  585. {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
  586. {306, nullptr, "GetLastActiveNpad"},
  587. {307, nullptr, "GetNpadSystemExtStyle"},
  588. {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
  589. {309, nullptr, "GetNpadFullKeyGripColor"},
  590. {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
  591. {321, nullptr, "GetUniquePadsFromNpad"},
  592. {322, nullptr, "GetIrSensorState"},
  593. {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
  594. {500, nullptr, "SetAppletResourceUserId"},
  595. {501, nullptr, "RegisterAppletResourceUserId"},
  596. {502, nullptr, "UnregisterAppletResourceUserId"},
  597. {503, nullptr, "EnableAppletToGetInput"},
  598. {504, nullptr, "SetAruidValidForVibration"},
  599. {505, nullptr, "EnableAppletToGetSixAxisSensor"},
  600. {510, nullptr, "SetVibrationMasterVolume"},
  601. {511, nullptr, "GetVibrationMasterVolume"},
  602. {512, nullptr, "BeginPermitVibrationSession"},
  603. {513, nullptr, "EndPermitVibrationSession"},
  604. {520, nullptr, "EnableHandheldHids"},
  605. {521, nullptr, "DisableHandheldHids"},
  606. {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
  607. {541, nullptr, "GetPlayReportControllerUsages"},
  608. {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
  609. {543, nullptr, "GetRegisteredDevicesOld"},
  610. {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
  611. {545, nullptr, "SendConnectionTrigger"},
  612. {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
  613. {547, nullptr, "GetAllowedBluetoothLinksCount"},
  614. {548, nullptr, "GetRegisteredDevices"},
  615. {700, nullptr, "ActivateUniquePad"},
  616. {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
  617. {703, nullptr, "GetUniquePadIds"},
  618. {751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
  619. {800, nullptr, "ListSixAxisSensorHandles"},
  620. {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
  621. {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
  622. {803, nullptr, "StartSixAxisSensorUserCalibration"},
  623. {804, nullptr, "CancelSixAxisSensorUserCalibration"},
  624. {805, nullptr, "GetUniquePadBluetoothAddress"},
  625. {806, nullptr, "DisconnectUniquePad"},
  626. {807, nullptr, "GetUniquePadType"},
  627. {808, nullptr, "GetUniquePadInterface"},
  628. {809, nullptr, "GetUniquePadSerialNumber"},
  629. {810, nullptr, "GetUniquePadControllerNumber"},
  630. {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
  631. {821, nullptr, "StartAnalogStickManualCalibration"},
  632. {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
  633. {823, nullptr, "CancelAnalogStickManualCalibration"},
  634. {824, nullptr, "ResetAnalogStickManualCalibration"},
  635. {825, nullptr, "GetAnalogStickState"},
  636. {826, nullptr, "GetAnalogStickManualCalibrationStage"},
  637. {827, nullptr, "IsAnalogStickButtonPressed"},
  638. {828, nullptr, "IsAnalogStickInReleasePosition"},
  639. {829, nullptr, "IsAnalogStickInCircumference"},
  640. {850, nullptr, "IsUsbFullKeyControllerEnabled"},
  641. {851, nullptr, "EnableUsbFullKeyController"},
  642. {852, nullptr, "IsUsbConnected"},
  643. {900, nullptr, "ActivateInputDetector"},
  644. {901, nullptr, "NotifyInputDetector"},
  645. {1000, nullptr, "InitializeFirmwareUpdate"},
  646. {1001, nullptr, "GetFirmwareVersion"},
  647. {1002, nullptr, "GetAvailableFirmwareVersion"},
  648. {1003, nullptr, "IsFirmwareUpdateAvailable"},
  649. {1004, nullptr, "CheckFirmwareUpdateRequired"},
  650. {1005, nullptr, "StartFirmwareUpdate"},
  651. {1006, nullptr, "AbortFirmwareUpdate"},
  652. {1007, nullptr, "GetFirmwareUpdateState"},
  653. {1008, nullptr, "ActivateAudioControl"},
  654. {1009, nullptr, "AcquireAudioControlEventHandle"},
  655. {1010, nullptr, "GetAudioControlStates"},
  656. {1011, nullptr, "DeactivateAudioControl"},
  657. {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
  658. {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
  659. {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
  660. {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
  661. {1100, nullptr, "GetHidbusSystemServiceObject"},
  662. };
  663. // clang-format on
  664. RegisterHandlers(functions);
  665. }
  666. };
  667. class HidTmp final : public ServiceFramework<HidTmp> {
  668. public:
  669. explicit HidTmp() : ServiceFramework{"hid:tmp"} {
  670. // clang-format off
  671. static const FunctionInfo functions[] = {
  672. {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"},
  673. };
  674. // clang-format on
  675. RegisterHandlers(functions);
  676. }
  677. };
  678. class HidBus final : public ServiceFramework<HidBus> {
  679. public:
  680. explicit HidBus() : ServiceFramework{"hidbus"} {
  681. // clang-format off
  682. static const FunctionInfo functions[] = {
  683. {1, nullptr, "GetBusHandle"},
  684. {2, nullptr, "IsExternalDeviceConnected"},
  685. {3, nullptr, "Initialize"},
  686. {4, nullptr, "Finalize"},
  687. {5, nullptr, "EnableExternalDevice"},
  688. {6, nullptr, "GetExternalDeviceId"},
  689. {7, nullptr, "SendCommandAsync"},
  690. {8, nullptr, "GetSendCommandAsynceResult"},
  691. {9, nullptr, "SetEventForSendCommandAsycResult"},
  692. {10, nullptr, "GetSharedMemoryHandle"},
  693. {11, nullptr, "EnableJoyPollingReceiveMode"},
  694. {12, nullptr, "DisableJoyPollingReceiveMode"},
  695. {13, nullptr, "GetPollingData"},
  696. };
  697. // clang-format on
  698. RegisterHandlers(functions);
  699. }
  700. };
  701. void ReloadInputDevices() {}
  702. void InstallInterfaces(SM::ServiceManager& service_manager) {
  703. std::make_shared<Hid>()->InstallAsService(service_manager);
  704. std::make_shared<HidBus>()->InstallAsService(service_manager);
  705. std::make_shared<HidDbg>()->InstallAsService(service_manager);
  706. std::make_shared<HidSys>()->InstallAsService(service_manager);
  707. std::make_shared<HidTmp>()->InstallAsService(service_manager);
  708. std::make_shared<IRS>()->InstallAsService(service_manager);
  709. std::make_shared<IRS_SYS>()->InstallAsService(service_manager);
  710. std::make_shared<XCD_SYS>()->InstallAsService(service_manager);
  711. }
  712. } // namespace Service::HID