service: hid: Implement MergeSingleJoyAsDualJoy according to RE

This commit is contained in:
german77 2022-05-21 16:40:11 -05:00 committed by Narr the Reg
parent 7aa1d10655
commit 3cf15af31e
4 changed files with 55 additions and 63 deletions

View File

@ -1275,77 +1275,66 @@ ResultCode Controller_NPad::GetSixAxisFusionParameters(
return ResultSuccess; return ResultSuccess;
} }
void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2) { Core::HID::NpadIdType npad_id_2) {
if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) { if (!IsNpadIdValid(npad_id_1) || !IsNpadIdValid(npad_id_2)) {
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1, LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id_1:{}, npad_id_2:{}", npad_id_1,
npad_id_2); npad_id_2);
return; return InvalidNpadId;
} }
auto& controller_1 = GetControllerFromNpadIdType(npad_id_1); auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
auto& controller_2 = GetControllerFromNpadIdType(npad_id_2); auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
const auto controller_style_1 = controller_1.device->GetNpadStyleIndex(); auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
const auto controller_style_2 = controller_2.device->GetNpadStyleIndex(); auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
bool merge_controllers = false;
// If the controllers at both npad indices form a pair of left and right joycons, merge them. // Simplify this code by converting dualjoycon with only a side connected to single joycons
// Otherwise, do nothing. if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual) {
if (controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
controller_style_1 = Core::HID::NpadStyleIndex::JoyconLeft;
}
if (!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
controller_style_1 = Core::HID::NpadStyleIndex::JoyconRight;
}
}
if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
if (controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
controller_style_2 = Core::HID::NpadStyleIndex::JoyconLeft;
}
if (!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
controller_style_2 = Core::HID::NpadStyleIndex::JoyconRight;
}
}
// Invalid merge errors
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual ||
controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual) {
return NpadIsDualJoycon;
}
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft && if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) {
return NpadIsSameType;
}
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) { controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
merge_controllers = true; return NpadIsSameType;
} }
if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) { // These exceptions are handled as if they where dual joycon
merge_controllers = true; if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft &&
} controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) {
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual && return NpadIsDualJoycon;
controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight && }
controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) { if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft &&
merge_controllers = true; controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) {
} return NpadIsDualJoycon;
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected) {
merge_controllers = true;
}
if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
merge_controllers = true;
}
if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
merge_controllers = true;
}
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected &&
!controller_2.is_dual_left_connected && controller_2.is_dual_right_connected) {
merge_controllers = true;
}
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
controller_style_2 == Core::HID::NpadStyleIndex::JoyconDual &&
!controller_1.is_dual_left_connected && controller_1.is_dual_right_connected &&
controller_2.is_dual_left_connected && !controller_2.is_dual_right_connected) {
merge_controllers = true;
} }
if (merge_controllers) {
// Disconnect the joycon at the second id and connect the dual joycon at the first index. // Disconnect the joycon at the second id and connect the dual joycon at the first index.
DisconnectNpad(npad_id_2); DisconnectNpad(npad_id_2);
controller_1.is_dual_left_connected = true; controller_1.is_dual_left_connected = true;
controller_1.is_dual_right_connected = true; controller_1.is_dual_right_connected = true;
AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1); AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
return; return ResultSuccess;
}
LOG_WARNING(Service_HID,
"Controllers can't be merged npad_id_1:{}, npad_id_2:{}, type_1:{}, type_2:{}, "
"dual_1(left/right):{}/{}, dual_2(left/right):{}/{}",
npad_id_1, npad_id_2, controller_1.device->GetNpadStyleIndex(),
controller_2.device->GetNpadStyleIndex(), controller_1.is_dual_left_connected,
controller_1.is_dual_right_connected, controller_2.is_dual_left_connected,
controller_2.is_dual_right_connected);
} }
void Controller_NPad::StartLRAssignmentMode() { void Controller_NPad::StartLRAssignmentMode() {

View File

@ -174,7 +174,8 @@ public:
void ConnectAllDisconnectedControllers(); void ConnectAllDisconnectedControllers();
void ClearAllControllers(); void ClearAllControllers();
void MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); ResultCode MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
Core::HID::NpadIdType npad_id_2);
void StartLRAssignmentMode(); void StartLRAssignmentMode();
void StopLRAssignmentMode(); void StopLRAssignmentMode();
ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2); ResultCode SwapNpadAssignment(Core::HID::NpadIdType npad_id_1, Core::HID::NpadIdType npad_id_2);

View File

@ -9,6 +9,8 @@ namespace Service::HID {
constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100}; constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100};
constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423}; constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423};
constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601};
constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602};
constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709}; constexpr ResultCode InvalidNpadId{ErrorModule::HID, 709};
constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710}; constexpr ResultCode NpadNotConnected{ErrorModule::HID, 710};

View File

@ -1090,14 +1090,14 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()}; const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
const auto applet_resource_user_id{rp.Pop<u64>()}; const auto applet_resource_user_id{rp.Pop<u64>()};
applet_resource->GetController<Controller_NPad>(HidController::NPad) auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2); const auto result = controller.MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}", LOG_DEBUG(Service_HID, "called, npad_id_1={}, npad_id_2={}, applet_resource_user_id={}",
npad_id_1, npad_id_2, applet_resource_user_id); npad_id_1, npad_id_2, applet_resource_user_id);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(result);
} }
void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) { void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {