hid.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  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, &Hid::DisconnectNpad, "DisconnectNpad"},
  289. {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"},
  290. {109, nullptr, "ActivateNpadWithRevision"},
  291. {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"},
  292. {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"},
  293. {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault,
  294. "SetNpadJoyAssignmentModeSingleByDefault"},
  295. {123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
  296. {124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
  297. {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
  298. {126, nullptr, "StartLrAssignmentMode"},
  299. {127, nullptr, "StopLrAssignmentMode"},
  300. {128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
  301. {129, nullptr, "GetNpadHandheldActivationMode"},
  302. {130, nullptr, "SwapNpadAssignment"},
  303. {131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
  304. {132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
  305. {133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
  306. {200, &Hid::GetVibrationDeviceInfo, "GetVibrationDeviceInfo"},
  307. {201, &Hid::SendVibrationValue, "SendVibrationValue"},
  308. {202, &Hid::GetActualVibrationValue, "GetActualVibrationValue"},
  309. {203, &Hid::CreateActiveVibrationDeviceList, "CreateActiveVibrationDeviceList"},
  310. {204, nullptr, "PermitVibration"},
  311. {205, nullptr, "IsVibrationPermitted"},
  312. {206, &Hid::SendVibrationValues, "SendVibrationValues"},
  313. {207, nullptr, "SendVibrationGcErmCommand"},
  314. {208, nullptr, "GetActualVibrationGcErmCommand"},
  315. {209, nullptr, "BeginPermitVibrationSession"},
  316. {210, nullptr, "EndPermitVibrationSession"},
  317. {300, nullptr, "ActivateConsoleSixAxisSensor"},
  318. {301, nullptr, "StartConsoleSixAxisSensor"},
  319. {302, nullptr, "StopConsoleSixAxisSensor"},
  320. {303, nullptr, "ActivateSevenSixAxisSensor"},
  321. {304, nullptr, "StartSevenSixAxisSensor"},
  322. {305, nullptr, "StopSevenSixAxisSensor"},
  323. {306, nullptr, "InitializeSevenSixAxisSensor"},
  324. {307, nullptr, "FinalizeSevenSixAxisSensor"},
  325. {308, nullptr, "SetSevenSixAxisSensorFusionStrength"},
  326. {309, nullptr, "GetSevenSixAxisSensorFusionStrength"},
  327. {400, nullptr, "IsUsbFullKeyControllerEnabled"},
  328. {401, nullptr, "EnableUsbFullKeyController"},
  329. {402, nullptr, "IsUsbFullKeyControllerConnected"},
  330. {403, nullptr, "HasBattery"},
  331. {404, nullptr, "HasLeftRightBattery"},
  332. {405, nullptr, "GetNpadInterfaceType"},
  333. {406, nullptr, "GetNpadLeftRightInterfaceType"},
  334. {500, nullptr, "GetPalmaConnectionHandle"},
  335. {501, nullptr, "InitializePalma"},
  336. {502, nullptr, "AcquirePalmaOperationCompleteEvent"},
  337. {503, nullptr, "GetPalmaOperationInfo"},
  338. {504, nullptr, "PlayPalmaActivity"},
  339. {505, nullptr, "SetPalmaFrModeType"},
  340. {506, nullptr, "ReadPalmaStep"},
  341. {507, nullptr, "EnablePalmaStep"},
  342. {508, nullptr, "SuspendPalmaStep"},
  343. {509, nullptr, "ResetPalmaStep"},
  344. {510, nullptr, "ReadPalmaApplicationSection"},
  345. {511, nullptr, "WritePalmaApplicationSection"},
  346. {512, nullptr, "ReadPalmaUniqueCode"},
  347. {513, nullptr, "SetPalmaUniqueCodeInvalid"},
  348. {1000, nullptr, "SetNpadCommunicationMode"},
  349. {1001, nullptr, "GetNpadCommunicationMode"},
  350. };
  351. RegisterHandlers(functions);
  352. event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
  353. }
  354. ~Hid() = default;
  355. private:
  356. std::shared_ptr<IAppletResource> applet_resource;
  357. u32 joy_hold_type{0};
  358. Kernel::SharedPtr<Kernel::Event> event;
  359. void CreateAppletResource(Kernel::HLERequestContext& ctx) {
  360. if (applet_resource == nullptr) {
  361. applet_resource = std::make_shared<IAppletResource>();
  362. }
  363. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  364. rb.Push(RESULT_SUCCESS);
  365. rb.PushIpcInterface<IAppletResource>(applet_resource);
  366. LOG_DEBUG(Service_HID, "called");
  367. }
  368. void ActivateDebugPad(Kernel::HLERequestContext& ctx) {
  369. IPC::ResponseBuilder rb{ctx, 2};
  370. rb.Push(RESULT_SUCCESS);
  371. LOG_WARNING(Service_HID, "(STUBBED) called");
  372. }
  373. void ActivateTouchScreen(Kernel::HLERequestContext& ctx) {
  374. IPC::ResponseBuilder rb{ctx, 2};
  375. rb.Push(RESULT_SUCCESS);
  376. LOG_WARNING(Service_HID, "(STUBBED) called");
  377. }
  378. void ActivateMouse(Kernel::HLERequestContext& ctx) {
  379. IPC::ResponseBuilder rb{ctx, 2};
  380. rb.Push(RESULT_SUCCESS);
  381. LOG_WARNING(Service_HID, "(STUBBED) called");
  382. }
  383. void ActivateKeyboard(Kernel::HLERequestContext& ctx) {
  384. IPC::ResponseBuilder rb{ctx, 2};
  385. rb.Push(RESULT_SUCCESS);
  386. LOG_WARNING(Service_HID, "(STUBBED) called");
  387. }
  388. void StartSixAxisSensor(Kernel::HLERequestContext& ctx) {
  389. IPC::ResponseBuilder rb{ctx, 2};
  390. rb.Push(RESULT_SUCCESS);
  391. LOG_WARNING(Service_HID, "(STUBBED) called");
  392. }
  393. void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
  394. IPC::ResponseBuilder rb{ctx, 2};
  395. rb.Push(RESULT_SUCCESS);
  396. LOG_WARNING(Service_HID, "(STUBBED) called");
  397. }
  398. void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
  399. IPC::ResponseBuilder rb{ctx, 3};
  400. rb.Push(RESULT_SUCCESS);
  401. // TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
  402. rb.Push(true);
  403. LOG_WARNING(Service_HID, "(STUBBED) called");
  404. }
  405. void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  406. IPC::ResponseBuilder rb{ctx, 2};
  407. rb.Push(RESULT_SUCCESS);
  408. LOG_WARNING(Service_HID, "(STUBBED) called");
  409. }
  410. void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
  411. IPC::ResponseBuilder rb{ctx, 3};
  412. rb.Push(RESULT_SUCCESS);
  413. rb.Push<u32>(0);
  414. LOG_WARNING(Service_HID, "(STUBBED) called");
  415. }
  416. void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) {
  417. IPC::ResponseBuilder rb{ctx, 2};
  418. rb.Push(RESULT_SUCCESS);
  419. LOG_WARNING(Service_HID, "(STUBBED) called");
  420. }
  421. void ActivateNpad(Kernel::HLERequestContext& ctx) {
  422. IPC::ResponseBuilder rb{ctx, 2};
  423. rb.Push(RESULT_SUCCESS);
  424. LOG_WARNING(Service_HID, "(STUBBED) called");
  425. }
  426. void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) {
  427. IPC::ResponseBuilder rb{ctx, 2, 1};
  428. rb.Push(RESULT_SUCCESS);
  429. rb.PushCopyObjects(event);
  430. LOG_WARNING(Service_HID, "(STUBBED) called");
  431. }
  432. void DisconnectNpad(Kernel::HLERequestContext& ctx) {
  433. IPC::ResponseBuilder rb{ctx, 2};
  434. rb.Push(RESULT_SUCCESS);
  435. LOG_WARNING(Service_HID, "(STUBBED) called");
  436. }
  437. void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
  438. IPC::ResponseBuilder rb{ctx, 2};
  439. rb.Push(RESULT_SUCCESS);
  440. LOG_WARNING(Service_HID, "(STUBBED) called");
  441. }
  442. void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  443. IPC::ResponseBuilder rb{ctx, 2};
  444. rb.Push(RESULT_SUCCESS);
  445. LOG_WARNING(Service_HID, "(STUBBED) called");
  446. }
  447. void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) {
  448. IPC::ResponseBuilder rb{ctx, 3};
  449. rb.Push(RESULT_SUCCESS);
  450. rb.Push(joy_hold_type);
  451. LOG_WARNING(Service_HID, "(STUBBED) called");
  452. }
  453. void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) {
  454. IPC::ResponseBuilder rb{ctx, 2};
  455. rb.Push(RESULT_SUCCESS);
  456. LOG_WARNING(Service_HID, "(STUBBED) called");
  457. }
  458. void SendVibrationValue(Kernel::HLERequestContext& ctx) {
  459. IPC::ResponseBuilder rb{ctx, 2};
  460. rb.Push(RESULT_SUCCESS);
  461. LOG_WARNING(Service_HID, "(STUBBED) called");
  462. }
  463. void GetActualVibrationValue(Kernel::HLERequestContext& ctx) {
  464. IPC::ResponseBuilder rb{ctx, 2};
  465. rb.Push(RESULT_SUCCESS);
  466. LOG_WARNING(Service_HID, "(STUBBED) called");
  467. }
  468. void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
  469. IPC::ResponseBuilder rb{ctx, 2};
  470. rb.Push(RESULT_SUCCESS);
  471. LOG_WARNING(Service_HID, "(STUBBED) called");
  472. }
  473. void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
  474. IPC::ResponseBuilder rb{ctx, 2};
  475. rb.Push(RESULT_SUCCESS);
  476. LOG_WARNING(Service_HID, "(STUBBED) called");
  477. }
  478. void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
  479. IPC::ResponseBuilder rb{ctx, 2};
  480. rb.Push(RESULT_SUCCESS);
  481. LOG_WARNING(Service_HID, "(STUBBED) called");
  482. }
  483. void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
  484. IPC::ResponseBuilder rb{ctx, 4};
  485. rb.Push(RESULT_SUCCESS);
  486. rb.Push<u64>(0);
  487. LOG_WARNING(Service_HID, "(STUBBED) called");
  488. }
  489. void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) {
  490. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  491. rb.Push(RESULT_SUCCESS);
  492. rb.PushIpcInterface<IActiveVibrationDeviceList>();
  493. LOG_DEBUG(Service_HID, "called");
  494. }
  495. void SendVibrationValues(Kernel::HLERequestContext& ctx) {
  496. IPC::ResponseBuilder rb{ctx, 2};
  497. rb.Push(RESULT_SUCCESS);
  498. LOG_WARNING(Service_HID, "(STUBBED) called");
  499. }
  500. };
  501. class HidDbg final : public ServiceFramework<HidDbg> {
  502. public:
  503. explicit HidDbg() : ServiceFramework{"hid:dbg"} {
  504. // clang-format off
  505. static const FunctionInfo functions[] = {
  506. {0, nullptr, "DeactivateDebugPad"},
  507. {1, nullptr, "SetDebugPadAutoPilotState"},
  508. {2, nullptr, "UnsetDebugPadAutoPilotState"},
  509. {10, nullptr, "DeactivateTouchScreen"},
  510. {11, nullptr, "SetTouchScreenAutoPilotState"},
  511. {12, nullptr, "UnsetTouchScreenAutoPilotState"},
  512. {20, nullptr, "DeactivateMouse"},
  513. {21, nullptr, "SetMouseAutoPilotState"},
  514. {22, nullptr, "UnsetMouseAutoPilotState"},
  515. {30, nullptr, "DeactivateKeyboard"},
  516. {31, nullptr, "SetKeyboardAutoPilotState"},
  517. {32, nullptr, "UnsetKeyboardAutoPilotState"},
  518. {50, nullptr, "DeactivateXpad"},
  519. {51, nullptr, "SetXpadAutoPilotState"},
  520. {52, nullptr, "UnsetXpadAutoPilotState"},
  521. {60, nullptr, "DeactivateJoyXpad"},
  522. {91, nullptr, "DeactivateGesture"},
  523. {110, nullptr, "DeactivateHomeButton"},
  524. {111, nullptr, "SetHomeButtonAutoPilotState"},
  525. {112, nullptr, "UnsetHomeButtonAutoPilotState"},
  526. {120, nullptr, "DeactivateSleepButton"},
  527. {121, nullptr, "SetSleepButtonAutoPilotState"},
  528. {122, nullptr, "UnsetSleepButtonAutoPilotState"},
  529. {123, nullptr, "DeactivateInputDetector"},
  530. {130, nullptr, "DeactivateCaptureButton"},
  531. {131, nullptr, "SetCaptureButtonAutoPilotState"},
  532. {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
  533. {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
  534. {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
  535. {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
  536. {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
  537. {140, nullptr, "DeactivateConsoleSixAxisSensor"},
  538. {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
  539. {142, nullptr, "DeactivateSevenSixAxisSensor"},
  540. {201, nullptr, "ActivateFirmwareUpdate"},
  541. {202, nullptr, "DeactivateFirmwareUpdate"},
  542. {203, nullptr, "StartFirmwareUpdate"},
  543. {204, nullptr, "GetFirmwareUpdateStage"},
  544. {205, nullptr, "GetFirmwareVersion"},
  545. {206, nullptr, "GetDestinationFirmwareVersion"},
  546. {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
  547. {208, nullptr, "StartFirmwareUpdateForRevert"},
  548. {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
  549. {210, nullptr, "IsFirmwareUpdatingDevice"},
  550. {221, nullptr, "UpdateControllerColor"},
  551. {222, nullptr, "ConnectUsbPadsAsync"},
  552. {223, nullptr, "DisconnectUsbPadsAsync"},
  553. {224, nullptr, "UpdateDesignInfo"},
  554. {225, nullptr, "GetUniquePadDriverState"},
  555. {226, nullptr, "GetSixAxisSensorDriverStates"},
  556. {301, nullptr, "GetAbstractedPadHandles"},
  557. {302, nullptr, "GetAbstractedPadState"},
  558. {303, nullptr, "GetAbstractedPadsState"},
  559. {321, nullptr, "SetAutoPilotVirtualPadState"},
  560. {322, nullptr, "UnsetAutoPilotVirtualPadState"},
  561. {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
  562. {350, nullptr, "AddRegisteredDevice"},
  563. };
  564. // clang-format on
  565. RegisterHandlers(functions);
  566. }
  567. };
  568. class HidSys final : public ServiceFramework<HidSys> {
  569. public:
  570. explicit HidSys() : ServiceFramework{"hid:sys"} {
  571. // clang-format off
  572. static const FunctionInfo functions[] = {
  573. {31, nullptr, "SendKeyboardLockKeyEvent"},
  574. {101, nullptr, "AcquireHomeButtonEventHandle"},
  575. {111, nullptr, "ActivateHomeButton"},
  576. {121, nullptr, "AcquireSleepButtonEventHandle"},
  577. {131, nullptr, "ActivateSleepButton"},
  578. {141, nullptr, "AcquireCaptureButtonEventHandle"},
  579. {151, nullptr, "ActivateCaptureButton"},
  580. {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
  581. {211, nullptr, "GetNpadsWithNfc"},
  582. {212, nullptr, "AcquireNfcActivateEventHandle"},
  583. {213, nullptr, "ActivateNfc"},
  584. {214, nullptr, "GetXcdHandleForNpadWithNfc"},
  585. {215, nullptr, "IsNfcActivated"},
  586. {230, nullptr, "AcquireIrSensorEventHandle"},
  587. {231, nullptr, "ActivateIrSensor"},
  588. {301, nullptr, "ActivateNpadSystem"},
  589. {303, nullptr, "ApplyNpadSystemCommonPolicy"},
  590. {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
  591. {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
  592. {306, nullptr, "GetLastActiveNpad"},
  593. {307, nullptr, "GetNpadSystemExtStyle"},
  594. {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
  595. {309, nullptr, "GetNpadFullKeyGripColor"},
  596. {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
  597. {321, nullptr, "GetUniquePadsFromNpad"},
  598. {322, nullptr, "GetIrSensorState"},
  599. {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
  600. {500, nullptr, "SetAppletResourceUserId"},
  601. {501, nullptr, "RegisterAppletResourceUserId"},
  602. {502, nullptr, "UnregisterAppletResourceUserId"},
  603. {503, nullptr, "EnableAppletToGetInput"},
  604. {504, nullptr, "SetAruidValidForVibration"},
  605. {505, nullptr, "EnableAppletToGetSixAxisSensor"},
  606. {510, nullptr, "SetVibrationMasterVolume"},
  607. {511, nullptr, "GetVibrationMasterVolume"},
  608. {512, nullptr, "BeginPermitVibrationSession"},
  609. {513, nullptr, "EndPermitVibrationSession"},
  610. {520, nullptr, "EnableHandheldHids"},
  611. {521, nullptr, "DisableHandheldHids"},
  612. {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
  613. {541, nullptr, "GetPlayReportControllerUsages"},
  614. {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
  615. {543, nullptr, "GetRegisteredDevicesOld"},
  616. {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
  617. {545, nullptr, "SendConnectionTrigger"},
  618. {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
  619. {547, nullptr, "GetAllowedBluetoothLinksCount"},
  620. {548, nullptr, "GetRegisteredDevices"},
  621. {700, nullptr, "ActivateUniquePad"},
  622. {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
  623. {703, nullptr, "GetUniquePadIds"},
  624. {751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
  625. {800, nullptr, "ListSixAxisSensorHandles"},
  626. {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
  627. {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
  628. {803, nullptr, "StartSixAxisSensorUserCalibration"},
  629. {804, nullptr, "CancelSixAxisSensorUserCalibration"},
  630. {805, nullptr, "GetUniquePadBluetoothAddress"},
  631. {806, nullptr, "DisconnectUniquePad"},
  632. {807, nullptr, "GetUniquePadType"},
  633. {808, nullptr, "GetUniquePadInterface"},
  634. {809, nullptr, "GetUniquePadSerialNumber"},
  635. {810, nullptr, "GetUniquePadControllerNumber"},
  636. {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
  637. {821, nullptr, "StartAnalogStickManualCalibration"},
  638. {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
  639. {823, nullptr, "CancelAnalogStickManualCalibration"},
  640. {824, nullptr, "ResetAnalogStickManualCalibration"},
  641. {825, nullptr, "GetAnalogStickState"},
  642. {826, nullptr, "GetAnalogStickManualCalibrationStage"},
  643. {827, nullptr, "IsAnalogStickButtonPressed"},
  644. {828, nullptr, "IsAnalogStickInReleasePosition"},
  645. {829, nullptr, "IsAnalogStickInCircumference"},
  646. {850, nullptr, "IsUsbFullKeyControllerEnabled"},
  647. {851, nullptr, "EnableUsbFullKeyController"},
  648. {852, nullptr, "IsUsbConnected"},
  649. {900, nullptr, "ActivateInputDetector"},
  650. {901, nullptr, "NotifyInputDetector"},
  651. {1000, nullptr, "InitializeFirmwareUpdate"},
  652. {1001, nullptr, "GetFirmwareVersion"},
  653. {1002, nullptr, "GetAvailableFirmwareVersion"},
  654. {1003, nullptr, "IsFirmwareUpdateAvailable"},
  655. {1004, nullptr, "CheckFirmwareUpdateRequired"},
  656. {1005, nullptr, "StartFirmwareUpdate"},
  657. {1006, nullptr, "AbortFirmwareUpdate"},
  658. {1007, nullptr, "GetFirmwareUpdateState"},
  659. {1008, nullptr, "ActivateAudioControl"},
  660. {1009, nullptr, "AcquireAudioControlEventHandle"},
  661. {1010, nullptr, "GetAudioControlStates"},
  662. {1011, nullptr, "DeactivateAudioControl"},
  663. {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
  664. {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
  665. {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
  666. {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
  667. {1100, nullptr, "GetHidbusSystemServiceObject"},
  668. };
  669. // clang-format on
  670. RegisterHandlers(functions);
  671. }
  672. };
  673. class HidTmp final : public ServiceFramework<HidTmp> {
  674. public:
  675. explicit HidTmp() : ServiceFramework{"hid:tmp"} {
  676. // clang-format off
  677. static const FunctionInfo functions[] = {
  678. {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"},
  679. };
  680. // clang-format on
  681. RegisterHandlers(functions);
  682. }
  683. };
  684. class HidBus final : public ServiceFramework<HidBus> {
  685. public:
  686. explicit HidBus() : ServiceFramework{"hidbus"} {
  687. // clang-format off
  688. static const FunctionInfo functions[] = {
  689. {1, nullptr, "GetBusHandle"},
  690. {2, nullptr, "IsExternalDeviceConnected"},
  691. {3, nullptr, "Initialize"},
  692. {4, nullptr, "Finalize"},
  693. {5, nullptr, "EnableExternalDevice"},
  694. {6, nullptr, "GetExternalDeviceId"},
  695. {7, nullptr, "SendCommandAsync"},
  696. {8, nullptr, "GetSendCommandAsynceResult"},
  697. {9, nullptr, "SetEventForSendCommandAsycResult"},
  698. {10, nullptr, "GetSharedMemoryHandle"},
  699. {11, nullptr, "EnableJoyPollingReceiveMode"},
  700. {12, nullptr, "DisableJoyPollingReceiveMode"},
  701. {13, nullptr, "GetPollingData"},
  702. };
  703. // clang-format on
  704. RegisterHandlers(functions);
  705. }
  706. };
  707. void ReloadInputDevices() {}
  708. void InstallInterfaces(SM::ServiceManager& service_manager) {
  709. std::make_shared<Hid>()->InstallAsService(service_manager);
  710. std::make_shared<HidBus>()->InstallAsService(service_manager);
  711. std::make_shared<HidDbg>()->InstallAsService(service_manager);
  712. std::make_shared<HidSys>()->InstallAsService(service_manager);
  713. std::make_shared<HidTmp>()->InstallAsService(service_manager);
  714. std::make_shared<IRS>()->InstallAsService(service_manager);
  715. std::make_shared<IRS_SYS>()->InstallAsService(service_manager);
  716. std::make_shared<XCD_SYS>()->InstallAsService(service_manager);
  717. }
  718. } // namespace Service::HID