hid.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  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/service.h"
  17. namespace Service::HID {
  18. // Updating period for each HID device.
  19. // TODO(shinyquagsire23): These need better values.
  20. constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  21. constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  22. constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100;
  23. class IAppletResource final : public ServiceFramework<IAppletResource> {
  24. public:
  25. IAppletResource() : ServiceFramework("IAppletResource") {
  26. static const FunctionInfo functions[] = {
  27. {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"},
  28. };
  29. RegisterHandlers(functions);
  30. shared_mem = Kernel::SharedMemory::Create(
  31. nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read,
  32. 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
  33. // Register update callbacks
  34. pad_update_event = CoreTiming::RegisterEvent(
  35. "HID::UpdatePadCallback",
  36. [this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); });
  37. // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
  38. CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event);
  39. }
  40. ~IAppletResource() {
  41. CoreTiming::UnscheduleEvent(pad_update_event, 0);
  42. }
  43. private:
  44. void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) {
  45. IPC::ResponseBuilder rb{ctx, 2, 1};
  46. rb.Push(RESULT_SUCCESS);
  47. rb.PushCopyObjects(shared_mem);
  48. LOG_DEBUG(Service_HID, "called");
  49. }
  50. void LoadInputDevices() {
  51. std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN,
  52. Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END,
  53. buttons.begin(), Input::CreateDevice<Input::ButtonDevice>);
  54. std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN,
  55. Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END,
  56. sticks.begin(), Input::CreateDevice<Input::AnalogDevice>);
  57. touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touch_device);
  58. // TODO(shinyquagsire23): gyro, mouse, keyboard
  59. }
  60. void UpdatePadCallback(u64 userdata, int cycles_late) {
  61. SharedMemory mem{};
  62. std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory));
  63. if (is_device_reload_pending.exchange(false))
  64. LoadInputDevices();
  65. // Set up controllers as neon red+blue Joy-Con attached to console
  66. ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header;
  67. controller_header.type = ControllerType_Handheld;
  68. controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent;
  69. controller_header.right_color_body = JOYCON_BODY_NEON_RED;
  70. controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED;
  71. controller_header.left_color_body = JOYCON_BODY_NEON_BLUE;
  72. controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE;
  73. for (size_t controller = 0; controller < mem.controllers.size(); controller++) {
  74. for (auto& layout : mem.controllers[controller].layouts) {
  75. layout.header.num_entries = HID_NUM_ENTRIES;
  76. layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
  77. // HID shared memory stores the state of the past 17 samples in a circlular buffer,
  78. // each with a timestamp in number of samples since boot.
  79. const ControllerInputEntry& last_entry = layout.entries[layout.header.latest_entry];
  80. layout.header.timestamp_ticks = CoreTiming::GetTicks();
  81. layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
  82. ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
  83. entry.timestamp = last_entry.timestamp + 1;
  84. // TODO(shinyquagsire23): Is this always identical to timestamp?
  85. entry.timestamp_2 = entry.timestamp;
  86. // TODO(shinyquagsire23): More than just handheld input
  87. if (controller != Controller_Handheld)
  88. continue;
  89. entry.connection_state = ConnectionState_Connected | ConnectionState_Wired;
  90. // TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future?
  91. // For now everything is just the default handheld layout, but split Joy-Con will
  92. // rotate the face buttons and directions for certain layouts.
  93. ControllerPadState& state = entry.buttons;
  94. using namespace Settings::NativeButton;
  95. state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus());
  96. state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus());
  97. state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus());
  98. state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus());
  99. state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus());
  100. state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus());
  101. state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus());
  102. state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus());
  103. state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus());
  104. state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus());
  105. state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus());
  106. state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus());
  107. state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus());
  108. state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus());
  109. state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus());
  110. state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus());
  111. state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  112. state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  113. state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  114. state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  115. state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus());
  116. state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus());
  117. state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus());
  118. state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus());
  119. state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
  120. state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus());
  121. const auto [stick_l_x_f, stick_l_y_f] = sticks[Joystick_Left]->GetStatus();
  122. const auto [stick_r_x_f, stick_r_y_f] = sticks[Joystick_Right]->GetStatus();
  123. entry.joystick_left_x = static_cast<s32>(stick_l_x_f * HID_JOYSTICK_MAX);
  124. entry.joystick_left_y = static_cast<s32>(stick_l_y_f * HID_JOYSTICK_MAX);
  125. entry.joystick_right_x = static_cast<s32>(stick_r_x_f * HID_JOYSTICK_MAX);
  126. entry.joystick_right_y = static_cast<s32>(stick_r_y_f * HID_JOYSTICK_MAX);
  127. }
  128. }
  129. TouchScreen& touchscreen = mem.touchscreen;
  130. const u64 last_entry = touchscreen.header.latest_entry;
  131. const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size();
  132. const u64 timestamp = CoreTiming::GetTicks();
  133. const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1;
  134. touchscreen.header.timestamp_ticks = timestamp;
  135. touchscreen.header.num_entries = touchscreen.entries.size();
  136. touchscreen.header.latest_entry = curr_entry;
  137. touchscreen.header.max_entry_index = touchscreen.entries.size();
  138. touchscreen.header.timestamp = timestamp;
  139. touchscreen.entries[curr_entry].header.timestamp = sample_counter;
  140. TouchScreenEntryTouch touch_entry{};
  141. auto [x, y, pressed] = touch_device->GetStatus();
  142. touch_entry.timestamp = timestamp;
  143. touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width);
  144. touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height);
  145. touch_entry.touch_index = 0;
  146. // TODO(DarkLordZach): Maybe try to derive these from EmuWindow?
  147. touch_entry.diameter_x = 15;
  148. touch_entry.diameter_y = 15;
  149. touch_entry.angle = 0;
  150. // TODO(DarkLordZach): Implement multi-touch support
  151. if (pressed) {
  152. touchscreen.entries[curr_entry].header.num_touches = 1;
  153. touchscreen.entries[curr_entry].touches[0] = touch_entry;
  154. } else {
  155. touchscreen.entries[curr_entry].header.num_touches = 0;
  156. }
  157. // TODO(shinyquagsire23): Properly implement mouse
  158. Mouse& mouse = mem.mouse;
  159. const u64 last_mouse_entry = mouse.header.latest_entry;
  160. const u64 curr_mouse_entry = (mouse.header.latest_entry + 1) % mouse.entries.size();
  161. const u64 mouse_sample_counter = mouse.entries[last_mouse_entry].timestamp + 1;
  162. mouse.header.timestamp_ticks = timestamp;
  163. mouse.header.num_entries = mouse.entries.size();
  164. mouse.header.max_entry_index = mouse.entries.size();
  165. mouse.header.latest_entry = curr_mouse_entry;
  166. mouse.entries[curr_mouse_entry].timestamp = mouse_sample_counter;
  167. mouse.entries[curr_mouse_entry].timestamp_2 = mouse_sample_counter;
  168. // TODO(shinyquagsire23): Properly implement keyboard
  169. Keyboard& keyboard = mem.keyboard;
  170. const u64 last_keyboard_entry = keyboard.header.latest_entry;
  171. const u64 curr_keyboard_entry =
  172. (keyboard.header.latest_entry + 1) % keyboard.entries.size();
  173. const u64 keyboard_sample_counter = keyboard.entries[last_keyboard_entry].timestamp + 1;
  174. keyboard.header.timestamp_ticks = timestamp;
  175. keyboard.header.num_entries = keyboard.entries.size();
  176. keyboard.header.latest_entry = last_keyboard_entry;
  177. keyboard.header.max_entry_index = keyboard.entries.size();
  178. keyboard.entries[curr_keyboard_entry].timestamp = keyboard_sample_counter;
  179. keyboard.entries[curr_keyboard_entry].timestamp_2 = keyboard_sample_counter;
  180. // TODO(shinyquagsire23): Figure out what any of these are
  181. for (auto& input : mem.unk_input_1) {
  182. const u64 last_input_entry = input.header.latest_entry;
  183. const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
  184. const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
  185. input.header.timestamp_ticks = timestamp;
  186. input.header.num_entries = input.entries.size();
  187. input.header.latest_entry = last_input_entry;
  188. input.header.max_entry_index = input.entries.size();
  189. input.entries[curr_input_entry].timestamp = input_sample_counter;
  190. input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
  191. }
  192. for (auto& input : mem.unk_input_2) {
  193. input.header.timestamp_ticks = timestamp;
  194. input.header.num_entries = 17;
  195. input.header.latest_entry = 0;
  196. input.header.max_entry_index = 0;
  197. }
  198. UnkInput3& input = mem.unk_input_3;
  199. const u64 last_input_entry = input.header.latest_entry;
  200. const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size();
  201. const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1;
  202. input.header.timestamp_ticks = timestamp;
  203. input.header.num_entries = input.entries.size();
  204. input.header.latest_entry = last_input_entry;
  205. input.header.max_entry_index = input.entries.size();
  206. input.entries[curr_input_entry].timestamp = input_sample_counter;
  207. input.entries[curr_input_entry].timestamp_2 = input_sample_counter;
  208. // TODO(shinyquagsire23): Signal events
  209. std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory));
  210. // Reschedule recurrent event
  211. CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event);
  212. }
  213. // Handle to shared memory region designated to HID service
  214. Kernel::SharedPtr<Kernel::SharedMemory> shared_mem;
  215. // CoreTiming update events
  216. CoreTiming::EventType* pad_update_event;
  217. // Stored input state info
  218. std::atomic<bool> is_device_reload_pending{true};
  219. std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID>
  220. buttons;
  221. std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID> sticks;
  222. std::unique_ptr<Input::TouchDevice> touch_device;
  223. };
  224. class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
  225. public:
  226. IActiveVibrationDeviceList() : ServiceFramework("IActiveVibrationDeviceList") {
  227. static const FunctionInfo functions[] = {
  228. {0, &IActiveVibrationDeviceList::ActivateVibrationDevice, "ActivateVibrationDevice"},
  229. };
  230. RegisterHandlers(functions);
  231. }
  232. private:
  233. void ActivateVibrationDevice(Kernel::HLERequestContext& ctx) {
  234. IPC::ResponseBuilder rb{ctx, 2};
  235. rb.Push(RESULT_SUCCESS);
  236. LOG_WARNING(Service_HID, "(STUBBED) called");
  237. }
  238. };
  239. class Hid final : public ServiceFramework<Hid> {
  240. public:
  241. Hid() : ServiceFramework("hid") {
  242. static const FunctionInfo functions[] = {
  243. {0, &Hid::CreateAppletResource, "CreateAppletResource"},
  244. {1, &Hid::ActivateDebugPad, "ActivateDebugPad"},
  245. {11, &Hid::ActivateTouchScreen, "ActivateTouchScreen"},
  246. {21, &Hid::ActivateMouse, "ActivateMouse"},
  247. {31, &Hid::ActivateKeyboard, "ActivateKeyboard"},
  248. {40, nullptr, "AcquireXpadIdEventHandle"},
  249. {41, nullptr, "ReleaseXpadIdEventHandle"},
  250. {51, nullptr, "ActivateXpad"},
  251. {55, nullptr, "GetXpadIds"},
  252. {56, nullptr, "ActivateJoyXpad"},
  253. {58, nullptr, "GetJoyXpadLifoHandle"},
  254. {59, nullptr, "GetJoyXpadIds"},
  255. {60, nullptr, "ActivateSixAxisSensor"},
  256. {61, nullptr, "DeactivateSixAxisSensor"},
  257. {62, nullptr, "GetSixAxisSensorLifoHandle"},
  258. {63, nullptr, "ActivateJoySixAxisSensor"},
  259. {64, nullptr, "DeactivateJoySixAxisSensor"},
  260. {65, nullptr, "GetJoySixAxisSensorLifoHandle"},
  261. {66, &Hid::StartSixAxisSensor, "StartSixAxisSensor"},
  262. {67, nullptr, "StopSixAxisSensor"},
  263. {68, nullptr, "IsSixAxisSensorFusionEnabled"},
  264. {69, nullptr, "EnableSixAxisSensorFusion"},
  265. {70, nullptr, "SetSixAxisSensorFusionParameters"},
  266. {71, nullptr, "GetSixAxisSensorFusionParameters"},
  267. {72, nullptr, "ResetSixAxisSensorFusionParameters"},
  268. {73, nullptr, "SetAccelerometerParameters"},
  269. {74, nullptr, "GetAccelerometerParameters"},
  270. {75, nullptr, "ResetAccelerometerParameters"},
  271. {76, nullptr, "SetAccelerometerPlayMode"},
  272. {77, nullptr, "GetAccelerometerPlayMode"},
  273. {78, nullptr, "ResetAccelerometerPlayMode"},
  274. {79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
  275. {80, nullptr, "GetGyroscopeZeroDriftMode"},
  276. {81, nullptr, "ResetGyroscopeZeroDriftMode"},
  277. {82, nullptr, "IsSixAxisSensorAtRest"},
  278. {91, nullptr, "ActivateGesture"},
  279. {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
  280. {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
  281. {102, &Hid::SetSupportedNpadIdType, "SetSupportedNpadIdType"},
  282. {103, &Hid::ActivateNpad, "ActivateNpad"},
  283. {104, nullptr, "DeactivateNpad"},
  284. {106, &Hid::AcquireNpadStyleSetUpdateEventHandle,
  285. "AcquireNpadStyleSetUpdateEventHandle"},
  286. {107, nullptr, "DisconnectNpad"},
  287. {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
  288. {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
  289. {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
  290. {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
  291. "SetNpadJoyAssignmentModeSingleByDefault"},
  292. {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
  293. {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
  294. {125, nullptr, "MergeSingleJoyAsDualJoy"},
  295. {126, nullptr, "StartLrAssignmentMode"},
  296. {127, nullptr, "StopLrAssignmentMode"},
  297. {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
  298. {129, nullptr, "GetNpadHandheldActivationMode"},
  299. {130, nullptr, "SwapNpadAssignment"},
  300. {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
  301. {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
  302. {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
  303. {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
  304. {201, &Hid::SendVibrationValue, "SendVibrationValue"},
  305. {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
  306. {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
  307. {204, nullptr, "PermitVibration"},
  308. {205, nullptr, "IsVibrationPermitted"},
  309. {206, &Hid::SendVibrationValues, "SendVibrationValues"},
  310. {207, nullptr, "SendVibrationGcErmCommand"},
  311. {208, nullptr, "GetActualVibrationGcErmCommand"},
  312. {209, nullptr, "BeginPermitVibrationSession"},
  313. {210, nullptr, "EndPermitVibrationSession"},
  314. {300, nullptr, "ActivateConsoleSixAxisSensor"},
  315. {301, nullptr, "StartConsoleSixAxisSensor"},
  316. {302, nullptr, "StopConsoleSixAxisSensor"},
  317. {303, nullptr, "ActivateSevenSixAxisSensor"},
  318. {304, nullptr, "StartSevenSixAxisSensor"},
  319. {305, nullptr, "StopSevenSixAxisSensor"},
  320. {306, nullptr, "InitializeSevenSixAxisSensor"},
  321. {307, nullptr, "FinalizeSevenSixAxisSensor"},
  322. {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
  323. {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
  324. {400, nullptr, "IsUsbFullKeyControllerEnabled"},
  325. {401, nullptr, "EnableUsbFullKeyController"},
  326. {402, nullptr, "IsUsbFullKeyControllerConnected"},
  327. {403, nullptr, "HasBattery"},
  328. {404, nullptr, "HasLeftRightBattery"},
  329. {405, nullptr, "GetNpadInterfaceType"},
  330. {406, nullptr, "GetNpadLeftRightInterfaceType"},
  331. {500, nullptr, "GetPalmaConnectionHandle"},
  332. {501, nullptr, "InitializePalma"},
  333. {502, nullptr, "AcquirePalmaOperationCompleteEvent"},
  334. {503, nullptr, "GetPalmaOperationInfo"},
  335. {504, nullptr, "PlayPalmaActivity"},
  336. {505, nullptr, "SetPalmaFrModeType"},
  337. {506, nullptr, "ReadPalmaStep"},
  338. {507, nullptr, "EnablePalmaStep"},
  339. {508, nullptr, "SuspendPalmaStep"},
  340. {509, nullptr, "ResetPalmaStep"},
  341. {510, nullptr, "ReadPalmaApplicationSection"},
  342. {511, nullptr, "WritePalmaApplicationSection"},
  343. {512, nullptr, "ReadPalmaUniqueCode"},
  344. {513, nullptr, "SetPalmaUniqueCodeInvalid"},
  345. {1000, nullptr, "SetNpadCommunicationMode"},
  346. {1001, nullptr, "GetNpadCommunicationMode"},
  347. };
  348. RegisterHandlers(functions);
  349. event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
  350. }
  351. ~Hid() = default;
  352. private:
  353. std::shared_ptr<IAppletResource> applet_resource;
  354. u32 joy_hold_type{0};
  355. Kernel::SharedPtr<Kernel::Event> event;
  356. void CreateAppletResource(Kernel::HLERequestContext& ctx) {
  357. if (applet_resource == nullptr) {
  358. applet_resource = std::make_shared<IAppletResource>();
  359. }
  360. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  361. rb.Push(RESULT_SUCCESS);
  362. rb.PushIpcInterface<IAppletResource>(applet_resource);
  363. LOG_DEBUG(Service_HID, "called");
  364. }
  365. void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
  366. IPC::ResponseBuilder rb{ctx, 2};
  367. rb.Push(RESULT_SUCCESS);
  368. LOG_WARNING(Service_HID, "(STUBBED) called");
  369. }
  370. void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
  371. IPC::ResponseBuilder rb{ctx, 2};
  372. rb.Push(RESULT_SUCCESS);
  373. LOG_WARNING(Service_HID, "(STUBBED) called");
  374. }
  375. void ActivateMouse(Kernel::HLERequestContext& ctx) {
  376. IPC::ResponseBuilder rb{ctx, 2};
  377. rb.Push(RESULT_SUCCESS);
  378. LOG_WARNING(Service_HID, "(STUBBED) called");
  379. }
  380. void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
  381. IPC::ResponseBuilder rb{ctx, 2};
  382. rb.Push(RESULT_SUCCESS);
  383. LOG_WARNING(Service_HID, "(STUBBED) called");
  384. }
  385. void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
  386. IPC::ResponseBuilder rb{ctx, 2};
  387. rb.Push(RESULT_SUCCESS);
  388. LOG_WARNING(Service_HID, "(STUBBED) called");
  389. }
  390. void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
  391. IPC::ResponseBuilder rb{ctx, 2};
  392. rb.Push(RESULT_SUCCESS);
  393. LOG_WARNING(Service_HID, "(STUBBED) called");
  394. }
  395. void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  396. IPC::ResponseBuilder rb{ctx, 2};
  397. rb.Push(RESULT_SUCCESS);
  398. LOG_WARNING(Service_HID, "(STUBBED) called");
  399. }
  400. void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  401. IPC::ResponseBuilder rb{ctx, 3};
  402. rb.Push(RESULT_SUCCESS);
  403. rb.Push<u32>(0);
  404. LOG_WARNING(Service_HID, "(STUBBED) called");
  405. }
  406. void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
  407. IPC::ResponseBuilder rb{ctx, 2};
  408. rb.Push(RESULT_SUCCESS);
  409. LOG_WARNING(Service_HID, "(STUBBED) called");
  410. }
  411. void ActivateNpad(Kernel::HLERequestContext& ctx) {
  412. IPC::ResponseBuilder rb{ctx, 2};
  413. rb.Push(RESULT_SUCCESS);
  414. LOG_WARNING(Service_HID, "(STUBBED) called");
  415. }
  416. void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
  417. IPC::ResponseBuilder rb{ctx, 2, 1};
  418. rb.Push(RESULT_SUCCESS);
  419. rb.PushCopyObjects(event);
  420. LOG_WARNING(Service_HID, "(STUBBED) called");
  421. }
  422. void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
  423. IPC::ResponseBuilder rb{ctx, 2};
  424. rb.Push(RESULT_SUCCESS);
  425. LOG_WARNING(Service_HID, "(STUBBED) called");
  426. }
  427. void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  428. IPC::ResponseBuilder rb{ctx, 2};
  429. rb.Push(RESULT_SUCCESS);
  430. LOG_WARNING(Service_HID, "(STUBBED) called");
  431. }
  432. void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  433. IPC::ResponseBuilder rb{ctx, 3};
  434. rb.Push(RESULT_SUCCESS);
  435. rb.Push(joy_hold_type);
  436. LOG_WARNING(Service_HID, "(STUBBED) called");
  437. }
  438. void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
  439. IPC::ResponseBuilder rb{ctx, 2};
  440. rb.Push(RESULT_SUCCESS);
  441. LOG_WARNING(Service_HID, "(STUBBED) called");
  442. }
  443. void SendVibrationValue(Kernel::HLERequestContext& ctx) {
  444. IPC::ResponseBuilder rb{ctx, 2};
  445. rb.Push(RESULT_SUCCESS);
  446. LOG_WARNING(Service_HID, "(STUBBED) called");
  447. }
  448. void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
  449. IPC::ResponseBuilder rb{ctx, 2};
  450. rb.Push(RESULT_SUCCESS);
  451. LOG_WARNING(Service_HID, "(STUBBED) called");
  452. }
  453. void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
  454. IPC::ResponseBuilder rb{ctx, 2};
  455. rb.Push(RESULT_SUCCESS);
  456. LOG_WARNING(Service_HID, "(STUBBED) called");
  457. }
  458. void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
  459. IPC::ResponseBuilder rb{ctx, 2};
  460. rb.Push(RESULT_SUCCESS);
  461. LOG_WARNING(Service_HID, "(STUBBED) called");
  462. }
  463. void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
  464. IPC::ResponseBuilder rb{ctx, 4};
  465. rb.Push(RESULT_SUCCESS);
  466. rb.Push<u64>(0);
  467. LOG_WARNING(Service_HID, "(STUBBED) called");
  468. }
  469. void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
  470. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  471. rb.Push(RESULT_SUCCESS);
  472. rb.PushIpcInterface<IActiveVibrationDeviceList>();
  473. LOG_DEBUG(Service_HID, "called");
  474. }
  475. void SendVibrationValues(Kernel::HLERequestContext& ctx) {
  476. IPC::ResponseBuilder rb{ctx, 2};
  477. rb.Push(RESULT_SUCCESS);
  478. LOG_WARNING(Service_HID, "(STUBBED) called");
  479. }
  480. };
  481. void ReloadInputDevices() {}
  482. void InstallInterfaces(SM::ServiceManager& service_manager) {
  483. std::make_shared<Hid>()->InstallAsService(service_manager);
  484. }
  485. } // namespace Service::HID