From 56f35ab2629c3753dbb624799bd8aaff2a179f58 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 00:23:21 +1000 Subject: "Better Hid" rework part 1 --- src/core/hle/service/hid/hid.cpp | 433 +++++++++++++++++---------------------- 1 file changed, 189 insertions(+), 244 deletions(-) (limited to 'src/core/hle/service/hid/hid.cpp') diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 7c6b0a4e6..757b3b770 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include +#include "common/common_types.h" #include "common/logging/log.h" #include "core/core.h" #include "core/core_timing.h" @@ -19,6 +21,16 @@ #include "core/hle/service/service.h" #include "core/settings.h" +#include "core/hle/service/hid/controllers/controller_base.h" +#include "core/hle/service/hid/controllers/debug_pad.h" +#include "core/hle/service/hid/controllers/gesture.h" +#include "core/hle/service/hid/controllers/keyboard.h" +#include "core/hle/service/hid/controllers/mouse.h" +#include "core/hle/service/hid/controllers/npad.h" +#include "core/hle/service/hid/controllers/stubbed.h" +#include "core/hle/service/hid/controllers/touchscreen.h" +#include "core/hle/service/hid/controllers/xpad.h" + namespace Service::HID { // Updating period for each HID device. @@ -26,6 +38,22 @@ namespace Service::HID { constexpr u64 pad_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 accelerometer_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; constexpr u64 gyroscope_update_ticks = CoreTiming::BASE_CLOCK_RATE / 100; +constexpr size_t SHARED_MEMORY_SIZE = 0x40000; +enum class HidController : size_t { + DebugPad, + Touchscreen, + Mouse, + Keyboard, + XPad, + Unknown1, + Unknown2, + Unknown3, + SixAxisSensor, + NPad, + Gesture, + + MaxControllers +}; class IAppletResource final : public ServiceFramework { public: @@ -37,19 +65,64 @@ public: auto& kernel = Core::System::GetInstance().Kernel(); shared_mem = Kernel::SharedMemory::Create( - kernel, nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, + kernel, nullptr, SHARED_MEMORY_SIZE, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); + controllers[static_cast(HidController::DebugPad)] = + std::make_unique(); + controllers[static_cast(HidController::Touchscreen)] = + std::make_unique(); + controllers[static_cast(HidController::Mouse)] = + std::make_unique(); + controllers[static_cast(HidController::Keyboard)] = + std::make_unique(); + controllers[static_cast(HidController::XPad)] = std::make_unique(); + + controllers[static_cast(HidController::Unknown1)] = + std::make_unique(); + controllers[static_cast(HidController::Unknown2)] = + std::make_unique(); + controllers[static_cast(HidController::Unknown3)] = + std::make_unique(); + + controllers[static_cast(HidController::SixAxisSensor)] = + std::make_unique(); + + controllers[static_cast(HidController::NPad)] = std::make_unique(); + controllers[static_cast(HidController::Gesture)] = + std::make_unique(); + + // Homebrew doesn't try to activate some controllers, so we activate them by default + controllers[static_cast(HidController::NPad)]->ActivateController(); + controllers[static_cast(HidController::Touchscreen)]->ActivateController(); + + GetController(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); + GetController(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); + GetController(HidController::Unknown3).SetCommonHeaderOffset(0x5000); + // Register update callbacks pad_update_event = CoreTiming::RegisterEvent( "HID::UpdatePadCallback", - [this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); }); + [this](u64 userdata, int cycles_late) { UpdateControllers(userdata, cycles_late); }); // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); } + void ActivateController(HidController controller) { + controllers[static_cast(controller)]->ActivateController(); + } + + void DeactivateController(HidController controller) { + controllers[static_cast(controller)]->DeactivateController(); + } + + template + T& GetController(HidController controller) { + return static_cast(*controllers[static_cast(controller)]); + } + ~IAppletResource() { CoreTiming::UnscheduleEvent(pad_update_event, 0); } @@ -62,200 +135,15 @@ private: LOG_DEBUG(Service_HID, "called"); } - void LoadInputDevices() { - std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, - Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, - buttons.begin(), Input::CreateDevice); - std::transform(Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, - Settings::values.analogs.begin() + Settings::NativeAnalog::STICK_HID_END, - sticks.begin(), Input::CreateDevice); - touch_device = Input::CreateDevice(Settings::values.touch_device); - // TODO(shinyquagsire23): gyro, mouse, keyboard - } - - void UpdatePadCallback(u64 userdata, int cycles_late) { - SharedMemory mem{}; - std::memcpy(&mem, shared_mem->GetPointer(), sizeof(SharedMemory)); - - if (Settings::values.is_device_reload_pending.exchange(false)) - LoadInputDevices(); - - // Set up controllers as neon red+blue Joy-Con attached to console - ControllerHeader& controller_header = mem.controllers[Controller_Handheld].header; - controller_header.type = ControllerType_Handheld; - controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent; - controller_header.right_color_body = JOYCON_BODY_NEON_RED; - controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED; - controller_header.left_color_body = JOYCON_BODY_NEON_BLUE; - controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE; - - for (std::size_t controller = 0; controller < mem.controllers.size(); controller++) { - for (auto& layout : mem.controllers[controller].layouts) { - layout.header.num_entries = HID_NUM_ENTRIES; - layout.header.max_entry_index = HID_NUM_ENTRIES - 1; - - // HID shared memory stores the state of the past 17 samples in a circlular buffer, - // each with a timestamp in number of samples since boot. - const ControllerInputEntry& last_entry = layout.entries[layout.header.latest_entry]; - - layout.header.timestamp_ticks = CoreTiming::GetTicks(); - layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES; - - ControllerInputEntry& entry = layout.entries[layout.header.latest_entry]; - entry.timestamp = last_entry.timestamp + 1; - // TODO(shinyquagsire23): Is this always identical to timestamp? - entry.timestamp_2 = entry.timestamp; - - // TODO(shinyquagsire23): More than just handheld input - if (controller != Controller_Handheld) - continue; - - entry.connection_state = ConnectionState_Connected | ConnectionState_Wired; - - // TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future? - // For now everything is just the default handheld layout, but split Joy-Con will - // rotate the face buttons and directions for certain layouts. - ControllerPadState& state = entry.buttons; - using namespace Settings::NativeButton; - state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); - state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); - state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); - state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); - state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); - state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); - state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); - state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); - state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); - state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); - - state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); - state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); - state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); - state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); - - state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); - state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); - - state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); - state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); - - const auto [stick_l_x_f, stick_l_y_f] = sticks[Joystick_Left]->GetStatus(); - const auto [stick_r_x_f, stick_r_y_f] = sticks[Joystick_Right]->GetStatus(); - entry.joystick_left_x = static_cast(stick_l_x_f * HID_JOYSTICK_MAX); - entry.joystick_left_y = static_cast(stick_l_y_f * HID_JOYSTICK_MAX); - entry.joystick_right_x = static_cast(stick_r_x_f * HID_JOYSTICK_MAX); - entry.joystick_right_y = static_cast(stick_r_y_f * HID_JOYSTICK_MAX); + void UpdateControllers(u64 userdata, int cycles_late) { + bool should_reload = Settings::values.is_device_reload_pending.exchange(false); + for (const auto& controller : controllers) { + if (should_reload) { + controller->OnLoadInputDevices(); } + controller->OnUpdate(shared_mem->GetPointer(), SHARED_MEMORY_SIZE); } - TouchScreen& touchscreen = mem.touchscreen; - const u64 last_entry = touchscreen.header.latest_entry; - const u64 curr_entry = (last_entry + 1) % touchscreen.entries.size(); - const u64 timestamp = CoreTiming::GetTicks(); - const u64 sample_counter = touchscreen.entries[last_entry].header.timestamp + 1; - touchscreen.header.timestamp_ticks = timestamp; - touchscreen.header.num_entries = touchscreen.entries.size(); - touchscreen.header.latest_entry = curr_entry; - touchscreen.header.max_entry_index = touchscreen.entries.size(); - touchscreen.header.timestamp = timestamp; - touchscreen.entries[curr_entry].header.timestamp = sample_counter; - - TouchScreenEntryTouch touch_entry{}; - auto [x, y, pressed] = touch_device->GetStatus(); - touch_entry.timestamp = timestamp; - touch_entry.x = static_cast(x * Layout::ScreenUndocked::Width); - touch_entry.y = static_cast(y * Layout::ScreenUndocked::Height); - touch_entry.touch_index = 0; - - // TODO(DarkLordZach): Maybe try to derive these from EmuWindow? - touch_entry.diameter_x = 15; - touch_entry.diameter_y = 15; - touch_entry.angle = 0; - - // TODO(DarkLordZach): Implement multi-touch support - if (pressed) { - touchscreen.entries[curr_entry].header.num_touches = 1; - touchscreen.entries[curr_entry].touches[0] = touch_entry; - } else { - touchscreen.entries[curr_entry].header.num_touches = 0; - } - - // TODO(shinyquagsire23): Properly implement mouse - Mouse& mouse = mem.mouse; - const u64 last_mouse_entry = mouse.header.latest_entry; - const u64 curr_mouse_entry = (mouse.header.latest_entry + 1) % mouse.entries.size(); - const u64 mouse_sample_counter = mouse.entries[last_mouse_entry].timestamp + 1; - mouse.header.timestamp_ticks = timestamp; - mouse.header.num_entries = mouse.entries.size(); - mouse.header.max_entry_index = mouse.entries.size(); - mouse.header.latest_entry = curr_mouse_entry; - - mouse.entries[curr_mouse_entry].timestamp = mouse_sample_counter; - mouse.entries[curr_mouse_entry].timestamp_2 = mouse_sample_counter; - - // TODO(shinyquagsire23): Properly implement keyboard - Keyboard& keyboard = mem.keyboard; - const u64 last_keyboard_entry = keyboard.header.latest_entry; - const u64 curr_keyboard_entry = - (keyboard.header.latest_entry + 1) % keyboard.entries.size(); - const u64 keyboard_sample_counter = keyboard.entries[last_keyboard_entry].timestamp + 1; - keyboard.header.timestamp_ticks = timestamp; - keyboard.header.num_entries = keyboard.entries.size(); - keyboard.header.latest_entry = last_keyboard_entry; - keyboard.header.max_entry_index = keyboard.entries.size(); - - keyboard.entries[curr_keyboard_entry].timestamp = keyboard_sample_counter; - keyboard.entries[curr_keyboard_entry].timestamp_2 = keyboard_sample_counter; - - // TODO(shinyquagsire23): Figure out what any of these are - for (auto& input : mem.unk_input_1) { - const u64 last_input_entry = input.header.latest_entry; - const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size(); - const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1; - - input.header.timestamp_ticks = timestamp; - input.header.num_entries = input.entries.size(); - input.header.latest_entry = last_input_entry; - input.header.max_entry_index = input.entries.size(); - - input.entries[curr_input_entry].timestamp = input_sample_counter; - input.entries[curr_input_entry].timestamp_2 = input_sample_counter; - } - - for (auto& input : mem.unk_input_2) { - input.header.timestamp_ticks = timestamp; - input.header.num_entries = 17; - input.header.latest_entry = 0; - input.header.max_entry_index = 0; - } - - UnkInput3& input = mem.unk_input_3; - const u64 last_input_entry = input.header.latest_entry; - const u64 curr_input_entry = (input.header.latest_entry + 1) % input.entries.size(); - const u64 input_sample_counter = input.entries[last_input_entry].timestamp + 1; - - input.header.timestamp_ticks = timestamp; - input.header.num_entries = input.entries.size(); - input.header.latest_entry = last_input_entry; - input.header.max_entry_index = input.entries.size(); - - input.entries[curr_input_entry].timestamp = input_sample_counter; - input.entries[curr_input_entry].timestamp_2 = input_sample_counter; - - // TODO(shinyquagsire23): Signal events - - std::memcpy(shared_mem->GetPointer(), &mem, sizeof(SharedMemory)); - - // Reschedule recurrent event CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); } @@ -265,11 +153,8 @@ private: // CoreTiming update events CoreTiming::EventType* pad_update_event; - // Stored input state info - std::array, Settings::NativeButton::NUM_BUTTONS_HID> - buttons; - std::array, Settings::NativeAnalog::NUM_STICKS_HID> sticks; - std::unique_ptr touch_device; + std::array, static_cast(HidController::MaxControllers)> + controllers{}; }; class IActiveVibrationDeviceList final : public ServiceFramework { @@ -301,7 +186,7 @@ public: {31, &Hid::ActivateKeyboard, "ActivateKeyboard"}, {40, nullptr, "AcquireXpadIdEventHandle"}, {41, nullptr, "ReleaseXpadIdEventHandle"}, - {51, nullptr, "ActivateXpad"}, + {51, &Hid::ActivateXpad, "ActivateXpad"}, {55, nullptr, "GetXpadIds"}, {56, nullptr, "ActivateJoyXpad"}, {58, nullptr, "GetJoyXpadLifoHandle"}, @@ -401,16 +286,11 @@ public: // clang-format on RegisterHandlers(functions); - - auto& kernel = Core::System::GetInstance().Kernel(); - event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "hid:EventHandle"); } ~Hid() = default; private: std::shared_ptr applet_resource; - u32 joy_hold_type{0}; - Kernel::SharedPtr event; void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { @@ -423,28 +303,54 @@ private: LOG_DEBUG(Service_HID, "called"); } + void ActivateXpad(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::XPad); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + void ActivateDebugPad(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::DebugPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateTouchScreen(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Touchscreen); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateMouse(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Mouse); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateKeyboard(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Keyboard); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); + } + + void ActivateGesture(Kernel::HLERequestContext& ctx) { + applet_resource->ActivateController(HidController::Gesture); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + + void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { + // Should have no effect with how our npad sets up the data + applet_resource->ActivateController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); } void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { @@ -468,41 +374,55 @@ private: } void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto supported_styleset = rp.PopRaw(); + applet_resource->GetController(HidController::NPad) + .SetSupportedStyleSet({supported_styleset}); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + + LOG_DEBUG(Service_HID, "called"); } void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { + std::string blah = ctx.Description(); + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push(0); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(controller.GetSupportedStyleSet().raw); + LOG_DEBUG(Service_HID, "called"); } void SetSupportedNpadIdType(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetSupportedNPadIdTypes(ctx.ReadBuffer().data(), ctx.GetReadBufferSize()); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void ActivateNpad(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + applet_resource->ActivateController(HidController::NPad); + LOG_DEBUG(Service_HID, "called"); } void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(event); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.PushCopyObjects(applet_resource->GetController(HidController::NPad) + .GetStyleSetChangedEvent()); + LOG_DEBUG(Service_HID, "called"); } void DisconnectNpad(Kernel::HLERequestContext& ctx) { + applet_resource->DeactivateController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { @@ -512,16 +432,22 @@ private: } void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::RequestParser rp{ctx}; + auto hold_type = rp.PopRaw(); + controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 3}; + auto& controller = applet_resource->GetController(HidController::NPad); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(joy_hold_type); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(static_cast(controller.GetHoldType())); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { @@ -531,21 +457,57 @@ private: } void SendVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto controller_id = rp.PopRaw(); + auto vibration_values = rp.PopRaw(); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + + applet_resource->GetController(HidController::NPad) + .VibrateController({controller_id}, {vibration_values}); + LOG_DEBUG(Service_HID, "called"); } - void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { + void SendVibrationValues(Kernel::HLERequestContext& ctx) { + auto controllers = ctx.ReadBuffer(0); + auto vibrations = ctx.ReadBuffer(1); + + std::vector controller_list(controllers.size() / sizeof(u32)); + std::vector vibration_list(vibrations.size() / + sizeof(Controller_NPad::Vibration)); + + std::memcpy(controller_list.data(), controllers.data(), controllers.size()); + std::memcpy(vibration_list.data(), vibrations.data(), vibrations.size()); + std::transform(controller_list.begin(), controller_list.end(), controller_list.begin(), + [](u32 controller_id) { return controller_id - 3; }); + + applet_resource->GetController(HidController::NPad) + .VibrateController(controller_list, vibration_list); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); + } + + void GetActualVibrationValue(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw( + applet_resource->GetController(HidController::NPad) + .GetLastVibration()); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + auto& controller = applet_resource->GetController(HidController::NPad); + controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + LOG_DEBUG(Service_HID, "called"); } void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) { @@ -563,8 +525,9 @@ private: void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push(0); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.Push(1); + rb.Push(0); + LOG_DEBUG(Service_HID, "called"); } void CreateActiveVibrationDeviceList(Kernel::HLERequestContext& ctx) { @@ -574,12 +537,6 @@ private: LOG_DEBUG(Service_HID, "called"); } - void SendVibrationValues(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } - void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -597,18 +554,6 @@ private: rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); } - - void ActivateGesture(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } - - void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); - } }; class HidDbg final : public ServiceFramework { -- cgit v1.2.3