summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt1
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp30
-rw-r--r--src/core/hle/service/hid/controllers/npad.h5
-rw-r--r--src/core/hle/service/hid/errors.h13
-rw-r--r--src/core/hle/service/hid/hid.cpp50
-rw-r--r--src/core/hle/service/hid/hid.h3
6 files changed, 99 insertions, 3 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index cb77b99ee..7439018d9 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -291,6 +291,7 @@ add_library(core STATIC
hle/service/hid/irs.h
hle/service/hid/xcd.cpp
hle/service/hid/xcd.h
+ hle/service/hid/errors.h
hle/service/hid/controllers/controller_base.cpp
hle/service/hid/controllers/controller_base.h
hle/service/hid/controllers/debug_pad.cpp
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index fdd6d79a2..99af0469d 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -548,6 +548,36 @@ void Controller_NPad::DisconnectNPad(u32 npad_id) {
connected_controllers[NPadIdToIndex(npad_id)].is_connected = false;
}
+void Controller_NPad::StartLRAssignmentMode() {
+ // Nothing internally is used for lr assignment mode. Since we have the ability to set the
+ // controller types from boot, it doesn't really matter about showing a selection screen
+ is_in_lr_assignment_mode = true;
+}
+
+void Controller_NPad::StopLRAssignmentMode() {
+ is_in_lr_assignment_mode = false;
+}
+
+bool Controller_NPad::SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2) {
+ if (npad_id_1 == NPAD_HANDHELD || npad_id_2 == NPAD_HANDHELD || npad_id_1 == NPAD_UNKNOWN ||
+ npad_id_2 == NPAD_UNKNOWN) {
+ return true;
+ }
+
+ if (!IsControllerSupported(connected_controllers[NPadIdToIndex(npad_id_1)].type) ||
+ !IsControllerSupported(connected_controllers[NPadIdToIndex(npad_id_2)].type)) {
+ return false;
+ }
+
+ std::swap(connected_controllers[NPadIdToIndex(npad_id_1)].type,
+ connected_controllers[NPadIdToIndex(npad_id_2)].type);
+
+ InitNewlyAddedControler(NPadIdToIndex(npad_id_1));
+ InitNewlyAddedControler(NPadIdToIndex(npad_id_2));
+
+ return true;
+}
+
bool Controller_NPad::IsControllerSupported(NPadControllerType controller) {
if (controller == NPadControllerType::Handheld) {
// Handheld is not even a supported type, lets stop here
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 4ff50b3cd..4b6c1083f 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -124,6 +124,10 @@ public:
void ConnectAllDisconnectedControllers();
void ClearAllControllers();
+ void StartLRAssignmentMode();
+ void StopLRAssignmentMode();
+ bool SwapNpadAssignment(u32 npad_id_1, u32 npad_id_2);
+
// Logical OR for all buttons presses on all controllers
// Specifically for cheat engine and other features.
u32 GetAndResetPressState();
@@ -321,5 +325,6 @@ private:
void RequestPadStateUpdate(u32 npad_id);
std::array<ControllerPad, 10> npad_pad_states{};
bool IsControllerSupported(NPadControllerType controller);
+ bool is_in_lr_assignment_mode{false};
};
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/errors.h b/src/core/hle/service/hid/errors.h
new file mode 100644
index 000000000..3583642e7
--- /dev/null
+++ b/src/core/hle/service/hid/errors.h
@@ -0,0 +1,13 @@
+// Copyright 2019 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/result.h"
+
+namespace Service::HID {
+
+constexpr ResultCode ERR_NPAD_NOT_CONNECTED{ErrorModule::HID, 710};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index a4ad95d96..0bd24b8eb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -16,6 +16,7 @@
#include "core/hle/kernel/readable_event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/kernel/writable_event.h"
+#include "core/hle/service/hid/errors.h"
#include "core/hle/service/hid/hid.h"
#include "core/hle/service/hid/irs.h"
#include "core/hle/service/hid/xcd.h"
@@ -202,11 +203,11 @@ Hid::Hid() : ServiceFramework("hid") {
{123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
{125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
- {126, nullptr, "StartLrAssignmentMode"},
- {127, nullptr, "StopLrAssignmentMode"},
+ {126, &Hid::StartLrAssignmentMode, "StartLrAssignmentMode"},
+ {127, &Hid::StopLrAssignmentMode, "StopLrAssignmentMode"},
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
{129, nullptr, "GetNpadHandheldActivationMode"},
- {130, nullptr, "SwapNpadAssignment"},
+ {130, &Hid::SwapNpadAssignment, "SwapNpadAssignment"},
{131, nullptr, "IsUnintendedHomeButtonInputProtectionEnabled"},
{132, nullptr, "EnableUnintendedHomeButtonInputProtection"},
{133, nullptr, "SetNpadJoyAssignmentModeSingleWithDestination"},
@@ -733,6 +734,49 @@ void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) {
rb.Push(RESULT_SUCCESS);
}
+void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.StartLRAssignmentMode();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::StopLrAssignmentMode(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}", applet_resource_user_id);
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ controller.StopLRAssignmentMode();
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+}
+
+void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const auto npad_1{rp.Pop<u32>()};
+ const auto npad_2{rp.Pop<u32>()};
+ const auto applet_resource_user_id{rp.Pop<u64>()};
+
+ LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, npad_1={}, npad_2={}",
+ applet_resource_user_id, npad_1, npad_2);
+
+ auto& controller = applet_resource->GetController<Controller_NPad>(HidController::NPad);
+ IPC::ResponseBuilder rb{ctx, 2};
+ if (controller.SwapNpadAssignment(npad_1, npad_2)) {
+ rb.Push(RESULT_SUCCESS);
+ } else {
+ LOG_ERROR(Service_HID, "Npads are not connected!");
+ rb.Push(ERR_NPAD_NOT_CONNECTED);
+ }
+}
+
class HidDbg final : public ServiceFramework<HidDbg> {
public:
explicit HidDbg() : ServiceFramework{"hid:dbg"} {
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h
index d3660cad2..28260ef1b 100644
--- a/src/core/hle/service/hid/hid.h
+++ b/src/core/hle/service/hid/hid.h
@@ -119,6 +119,9 @@ private:
void StopSixAxisSensor(Kernel::HLERequestContext& ctx);
void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx);
void SetPalmaBoostMode(Kernel::HLERequestContext& ctx);
+ void StartLrAssignmentMode(Kernel::HLERequestContext& ctx);
+ void StopLrAssignmentMode(Kernel::HLERequestContext& ctx);
+ void SwapNpadAssignment(Kernel::HLERequestContext& ctx);
std::shared_ptr<IAppletResource> applet_resource;
};