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 From 5857aea94ef52186f64a6794adf418ba92329329 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 6 Oct 2018 13:14:42 +1000 Subject: Addressed changes for better hid --- src/core/hle/service/hid/hid.cpp | 67 ++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 37 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 757b3b770..ba4aefa6c 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -38,8 +38,8 @@ 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 { +constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000; +enum class HidController : std::size_t { DebugPad, Touchscreen, Mouse, @@ -52,7 +52,7 @@ enum class HidController : size_t { NPad, Gesture, - MaxControllers + MaxControllers, }; class IAppletResource final : public ServiceFramework { @@ -68,33 +68,21 @@ public: 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(); + MakeController(HidController::DebugPad); + MakeController(HidController::Touchscreen); + MakeController(HidController::Mouse); + MakeController(HidController::Keyboard); + MakeController(HidController::XPad); + MakeController(HidController::Unknown1); + MakeController(HidController::Unknown2); + MakeController(HidController::Unknown3); + MakeController(HidController::SixAxisSensor); + MakeController(HidController::NPad); + MakeController(HidController::Gesture); // 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::NPad).ActivateController(); + GetController(HidController::Touchscreen).ActivateController(); GetController(HidController::Unknown1).SetCommonHeaderOffset(0x4c00); GetController(HidController::Unknown2).SetCommonHeaderOffset(0x4e00); @@ -118,6 +106,11 @@ public: controllers[static_cast(controller)]->DeactivateController(); } + template + void MakeController(HidController controller) { + controllers[static_cast(controller)] = std::make_unique(); + } + template T& GetController(HidController controller) { return static_cast(*controllers[static_cast(controller)]); @@ -136,7 +129,7 @@ private: } void UpdateControllers(u64 userdata, int cycles_late) { - bool should_reload = Settings::values.is_device_reload_pending.exchange(false); + const bool should_reload = Settings::values.is_device_reload_pending.exchange(false); for (const auto& controller : controllers) { if (should_reload) { controller->OnLoadInputDevices(); @@ -386,7 +379,6 @@ private: } void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) { - std::string blah = ctx.Description(); auto& controller = applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 3}; @@ -434,7 +426,7 @@ private: void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { auto& controller = applet_resource->GetController(HidController::NPad); IPC::RequestParser rp{ctx}; - auto hold_type = rp.PopRaw(); + const auto hold_type = rp.PopRaw(); controller.SetHoldType(Controller_NPad::NpadHoldType{hold_type}); IPC::ResponseBuilder rb{ctx, 2}; @@ -443,7 +435,8 @@ private: } void GetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { - auto& controller = applet_resource->GetController(HidController::NPad); + const auto& controller = + applet_resource->GetController(HidController::NPad); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push(static_cast(controller.GetHoldType())); @@ -458,8 +451,8 @@ private: void SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto controller_id = rp.PopRaw(); - auto vibration_values = rp.PopRaw(); + const auto controller_id = rp.PopRaw(); + const auto vibration_values = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -470,8 +463,8 @@ private: } void SendVibrationValues(Kernel::HLERequestContext& ctx) { - auto controllers = ctx.ReadBuffer(0); - auto vibrations = ctx.ReadBuffer(1); + const auto controllers = ctx.ReadBuffer(0); + const auto vibrations = ctx.ReadBuffer(1); std::vector controller_list(controllers.size() / sizeof(u32)); std::vector vibration_list(vibrations.size() / @@ -501,7 +494,7 @@ private: void SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto npad_id = rp.PopRaw(); + const auto npad_id = rp.PopRaw(); auto& controller = applet_resource->GetController(HidController::NPad); controller.SetNpadMode(npad_id, Controller_NPad::NPadAssignments::Dual); -- cgit v1.2.3 From f43815af5d59bb1b31696f317c2e2ce243445cb5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sun, 7 Oct 2018 20:17:04 +1100 Subject: Added the ability to "disconnect" individual npads Fixes arms --- src/core/hle/service/hid/hid.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (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 ba4aefa6c..dfee289d2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -411,7 +411,10 @@ private: } void DisconnectNpad(Kernel::HLERequestContext& ctx) { - applet_resource->DeactivateController(HidController::NPad); + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + applet_resource->GetController(HidController::NPad) + .DisconnectNPad(npad_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_HID, "called"); -- cgit v1.2.3 From 3d75c9cd7a75f7ef97e2e14fc2eb15e4bba92934 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Wed, 10 Oct 2018 21:38:43 +1100 Subject: Added GetLedPattern and HandheldVariant HandheldVariant is for specific games which expect handheld controllers to be at position 8(kirby), however this doesn't fix all games as some games require handhelds to be at position 0(snipperclips) --- src/core/hle/service/hid/hid.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 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 dfee289d2..4c0d96cc2 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -421,9 +421,14 @@ private: } void GetPlayerLedPattern(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2}; + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - LOG_WARNING(Service_HID, "(STUBBED) called"); + rb.PushRaw(applet_resource->GetController(HidController::NPad) + .GetLedPattern(npad_id) + .raw); + LOG_DEBUG(Service_HID, "called"); } void SetNpadJoyHoldType(Kernel::HLERequestContext& ctx) { @@ -513,6 +518,8 @@ private: } void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto mode = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); -- cgit v1.2.3 From 9e924f2ef2add0f351df6addc01c356b52c8d7be Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 11 Oct 2018 00:58:47 +1100 Subject: Added BeginPermitVibrationSession and EndPermitVibrationSession Used by Mario Party --- src/core/hle/service/hid/hid.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 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 4c0d96cc2..65ee1d9bb 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -240,8 +240,8 @@ public: {206, &Hid::SendVibrationValues, "SendVibrationValues"}, {207, nullptr, "SendVibrationGcErmCommand"}, {208, nullptr, "GetActualVibrationGcErmCommand"}, - {209, nullptr, "BeginPermitVibrationSession"}, - {210, nullptr, "EndPermitVibrationSession"}, + {209, &Hid::BeginPermitVibrationSession, "BeginPermitVibrationSession"}, + {210, &Hid::EndPermitVibrationSession, "EndPermitVibrationSession"}, {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, {302, nullptr, "StopConsoleSixAxisSensor"}, @@ -457,6 +457,22 @@ private: LOG_WARNING(Service_HID, "(STUBBED) called"); } + void BeginPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetVibrationEnabled(true); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + + void EndPermitVibrationSession(Kernel::HLERequestContext& ctx) { + applet_resource->GetController(HidController::NPad) + .SetVibrationEnabled(false); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_HID, "called"); + } + void SendVibrationValue(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto controller_id = rp.PopRaw(); -- cgit v1.2.3 From 85b0d9a7be05eeec2fc230003341f9b444a17bf5 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 02:56:49 +1100 Subject: Dynamically decide handheld variant based on supported npad id priority Kirby input still doesn't work, should fix a lot of other games --- src/core/hle/service/hid/hid.cpp | 4 ++++ 1 file changed, 4 insertions(+) (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 65ee1d9bb..e5cbd2ef6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -347,6 +347,8 @@ private: } void StartSixAxisSensor(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto handle = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); @@ -539,6 +541,8 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); + applet_resource->GetController(HidController::NPad) + .SetHandheldActiviationMode(mode); } void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3 From 98b760c645088ef690c7fe5941bdebeed34a3012 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 16:28:00 +1100 Subject: Wip --- src/core/hle/service/hid/hid.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (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 e5cbd2ef6..db1537b40 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -284,7 +284,7 @@ public: private: std::shared_ptr applet_resource; - +#pragma optimize("", off) void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { applet_resource = std::make_shared(); @@ -405,6 +405,8 @@ private: } void AcquireNpadStyleSetUpdateEventHandle(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(applet_resource->GetController(HidController::NPad) @@ -454,6 +456,8 @@ private: } void SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + auto npad_id = rp.PopRaw(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); -- cgit v1.2.3 From 8144fa42bdeb96524f506f935109df128f961847 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 18 Oct 2018 00:11:47 +1100 Subject: Using dual joycons as the default controller Reason for the change is to allow both docked and undocked mode to work --- src/core/hle/service/hid/hid.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 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 db1537b40..8aca0f197 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -284,7 +284,7 @@ public: private: std::shared_ptr applet_resource; -#pragma optimize("", off) + void CreateAppletResource(Kernel::HLERequestContext& ctx) { if (applet_resource == nullptr) { applet_resource = std::make_shared(); @@ -545,8 +545,6 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); - applet_resource->GetController(HidController::NPad) - .SetHandheldActiviationMode(mode); } void GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) { -- cgit v1.2.3