service/hid: Implement SetNpadJoyAssignmentMode
This commit is contained in:
parent
fae07919af
commit
d6ae9c68f8
5 changed files with 174 additions and 38 deletions
|
@ -145,6 +145,16 @@ NpadIdType HIDCore::GetFirstNpadId() const {
|
|||
return NpadIdType::Player1;
|
||||
}
|
||||
|
||||
NpadIdType HIDCore::GetFirstDisconnectedNpadId() const {
|
||||
for (std::size_t player_index = 0; player_index < available_controllers; ++player_index) {
|
||||
const auto* const controller = GetEmulatedControllerByIndex(player_index);
|
||||
if (!controller->IsConnected()) {
|
||||
return controller->GetNpadIdType();
|
||||
}
|
||||
}
|
||||
return NpadIdType::Player1;
|
||||
}
|
||||
|
||||
void HIDCore::EnableAllControllerConfiguration() {
|
||||
player_1->EnableConfiguration();
|
||||
player_2->EnableConfiguration();
|
||||
|
|
|
@ -45,6 +45,9 @@ public:
|
|||
/// Returns the first connected npad id
|
||||
NpadIdType GetFirstNpadId() const;
|
||||
|
||||
/// Returns the first disconnected npad id
|
||||
NpadIdType GetFirstDisconnectedNpadId() const;
|
||||
|
||||
/// Sets all emulated controllers into configuring mode.
|
||||
void EnableAllControllerConfiguration();
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ void Controller_NPad::ControllerUpdate(Core::HID::ControllerTriggerType type,
|
|||
UpdateControllerAt(npad_type, npad_id, is_connected);
|
||||
break;
|
||||
case Core::HID::ControllerTriggerType::Battery: {
|
||||
if (!controller.is_connected) {
|
||||
if (!controller.device->IsConnected()) {
|
||||
return;
|
||||
}
|
||||
auto& shared_memory = controller.shared_memory_entry;
|
||||
|
@ -150,7 +150,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
|
|||
shared_memory.system_properties.is_vertical.Assign(1);
|
||||
shared_memory.system_properties.use_plus.Assign(1);
|
||||
shared_memory.system_properties.use_minus.Assign(1);
|
||||
shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::SwitchProController;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::Handheld:
|
||||
|
@ -166,21 +165,30 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
|
|||
break;
|
||||
case Core::HID::NpadStyleIndex::JoyconDual:
|
||||
shared_memory.style_tag.joycon_dual.Assign(1);
|
||||
shared_memory.device_type.joycon_left.Assign(1);
|
||||
shared_memory.device_type.joycon_right.Assign(1);
|
||||
shared_memory.system_properties.is_vertical.Assign(1);
|
||||
shared_memory.system_properties.use_plus.Assign(1);
|
||||
shared_memory.system_properties.use_minus.Assign(1);
|
||||
if (controller.is_dual_left_connected) {
|
||||
shared_memory.device_type.joycon_left.Assign(1);
|
||||
shared_memory.system_properties.use_minus.Assign(1);
|
||||
}
|
||||
if (controller.is_dual_right_connected) {
|
||||
shared_memory.device_type.joycon_right.Assign(1);
|
||||
shared_memory.system_properties.use_plus.Assign(1);
|
||||
}
|
||||
shared_memory.system_properties.use_directional_buttons.Assign(1);
|
||||
shared_memory.system_properties.is_vertical.Assign(1);
|
||||
shared_memory.assignment_mode = NpadJoyAssignmentMode::Dual;
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
|
||||
if (controller.is_dual_left_connected && controller.is_dual_right_connected) {
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyDual;
|
||||
} else if (controller.is_dual_left_connected) {
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyDualLeftOnly;
|
||||
} else {
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyDualRightOnly;
|
||||
}
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::JoyconLeft:
|
||||
shared_memory.style_tag.joycon_left.Assign(1);
|
||||
shared_memory.device_type.joycon_left.Assign(1);
|
||||
shared_memory.system_properties.is_horizontal.Assign(1);
|
||||
shared_memory.system_properties.use_minus.Assign(1);
|
||||
shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::JoyconRight:
|
||||
|
@ -188,7 +196,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
|
|||
shared_memory.device_type.joycon_right.Assign(1);
|
||||
shared_memory.system_properties.is_horizontal.Assign(1);
|
||||
shared_memory.system_properties.use_plus.Assign(1);
|
||||
shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
|
||||
shared_memory.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::GameCube:
|
||||
|
@ -200,7 +207,6 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
|
|||
case Core::HID::NpadStyleIndex::Pokeball:
|
||||
shared_memory.style_tag.palma.Assign(1);
|
||||
shared_memory.device_type.palma.Assign(1);
|
||||
shared_memory.assignment_mode = NpadJoyAssignmentMode::Single;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::NES:
|
||||
shared_memory.style_tag.lark.Assign(1);
|
||||
|
@ -443,11 +449,15 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
|||
case Core::HID::NpadStyleIndex::JoyconDual:
|
||||
pad_state.connection_status.raw = 0;
|
||||
pad_state.connection_status.is_connected.Assign(1);
|
||||
pad_state.connection_status.is_left_connected.Assign(1);
|
||||
pad_state.connection_status.is_right_connected.Assign(1);
|
||||
if (controller.is_dual_left_connected) {
|
||||
pad_state.connection_status.is_left_connected.Assign(1);
|
||||
libnx_state.connection_status.is_left_connected.Assign(1);
|
||||
}
|
||||
if (controller.is_dual_right_connected) {
|
||||
pad_state.connection_status.is_right_connected.Assign(1);
|
||||
libnx_state.connection_status.is_right_connected.Assign(1);
|
||||
}
|
||||
|
||||
libnx_state.connection_status.is_left_connected.Assign(1);
|
||||
libnx_state.connection_status.is_right_connected.Assign(1);
|
||||
pad_state.sampling_number =
|
||||
npad.joy_dual_lifo.ReadCurrentEntry().state.sampling_number + 1;
|
||||
npad.joy_dual_lifo.WriteNextEntry(pad_state);
|
||||
|
@ -687,7 +697,7 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
|
|||
return communication_mode;
|
||||
}
|
||||
|
||||
void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
|
||||
void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
|
||||
NpadJoyAssignmentMode assignment_mode) {
|
||||
if (!IsNpadIdValid(npad_id)) {
|
||||
LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
|
||||
|
@ -698,6 +708,62 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id,
|
|||
if (controller.shared_memory_entry.assignment_mode != assignment_mode) {
|
||||
controller.shared_memory_entry.assignment_mode = assignment_mode;
|
||||
}
|
||||
|
||||
if (!controller.device->IsConnected()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (assignment_mode == NpadJoyAssignmentMode::Dual) {
|
||||
if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft) {
|
||||
DisconnectNpad(npad_id);
|
||||
controller.is_dual_left_connected = true;
|
||||
controller.is_dual_right_connected = false;
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
|
||||
return;
|
||||
}
|
||||
if (controller.device->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) {
|
||||
DisconnectNpad(npad_id);
|
||||
controller.is_dual_left_connected = false;
|
||||
controller.is_dual_right_connected = true;
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// This is for NpadJoyAssignmentMode::Single
|
||||
|
||||
// Only JoyconDual get affected by this function
|
||||
if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
|
||||
DisconnectNpad(npad_id);
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
|
||||
return;
|
||||
}
|
||||
if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
|
||||
DisconnectNpad(npad_id);
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have two controllers connected to the same npad_id we need to split them
|
||||
const auto npad_id_2 = hid_core.GetFirstDisconnectedNpadId();
|
||||
auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
|
||||
DisconnectNpad(npad_id);
|
||||
if (npad_device_type == NpadJoyDeviceType::Left) {
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
|
||||
controller_2.is_dual_left_connected = false;
|
||||
controller_2.is_dual_right_connected = true;
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
|
||||
} else {
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
|
||||
controller_2.is_dual_left_connected = true;
|
||||
controller_2.is_dual_right_connected = false;
|
||||
UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
|
||||
|
@ -907,6 +973,7 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
|
|||
}
|
||||
|
||||
auto& shared_memory_entry = controller.shared_memory_entry;
|
||||
// Don't reset shared_memory_entry.assignment_mode this value is persistent
|
||||
shared_memory_entry.style_tag.raw = Core::HID::NpadStyleSet::None; // Zero out
|
||||
shared_memory_entry.device_type.raw = 0;
|
||||
shared_memory_entry.system_properties.raw = 0;
|
||||
|
@ -923,9 +990,10 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
|
|||
.left = {},
|
||||
.right = {},
|
||||
};
|
||||
shared_memory_entry.assignment_mode = NpadJoyAssignmentMode::Dual;
|
||||
shared_memory_entry.applet_footer.type = AppletFooterUiType::None;
|
||||
|
||||
controller.is_dual_left_connected = true;
|
||||
controller.is_dual_right_connected = true;
|
||||
controller.is_connected = false;
|
||||
controller.device->Disconnect();
|
||||
SignalStyleSetChangedEvent(npad_id);
|
||||
|
@ -1022,19 +1090,70 @@ void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
|
|||
npad_id_2);
|
||||
return;
|
||||
}
|
||||
auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
|
||||
auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
|
||||
auto& controller_1 = GetControllerFromNpadIdType(npad_id_1);
|
||||
auto& controller_2 = GetControllerFromNpadIdType(npad_id_2);
|
||||
const auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
|
||||
const 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.
|
||||
// Otherwise, do nothing.
|
||||
if ((controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
|
||||
controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight) ||
|
||||
(controller_2->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconLeft &&
|
||||
controller_1->GetNpadStyleIndex() == Core::HID::NpadStyleIndex::JoyconRight)) {
|
||||
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconLeft &&
|
||||
controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight) {
|
||||
merge_controllers = true;
|
||||
}
|
||||
if (controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft &&
|
||||
controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight) {
|
||||
merge_controllers = true;
|
||||
}
|
||||
if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconDual &&
|
||||
controller_style_2 == Core::HID::NpadStyleIndex::JoyconRight &&
|
||||
controller_1.is_dual_left_connected && !controller_1.is_dual_right_connected) {
|
||||
merge_controllers = true;
|
||||
}
|
||||
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.
|
||||
DisconnectNpad(npad_id_2);
|
||||
controller_1.is_dual_left_connected = true;
|
||||
controller_1.is_dual_right_connected = true;
|
||||
AddNewControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_1);
|
||||
return;
|
||||
}
|
||||
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() {
|
||||
|
|
|
@ -113,7 +113,8 @@ public:
|
|||
void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
|
||||
NpadCommunicationMode GetNpadCommunicationMode() const;
|
||||
|
||||
void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyAssignmentMode assignment_mode);
|
||||
void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
|
||||
NpadJoyAssignmentMode assignment_mode);
|
||||
|
||||
bool VibrateControllerAtIndex(Core::HID::NpadIdType npad_id, std::size_t device_index,
|
||||
const Core::HID::VibrationValue& vibration_value);
|
||||
|
@ -464,7 +465,10 @@ private:
|
|||
std::array<VibrationData, 2> vibration{};
|
||||
bool unintended_home_button_input_protection{};
|
||||
bool is_connected{};
|
||||
Core::HID::NpadStyleIndex npad_type{Core::HID::NpadStyleIndex::None};
|
||||
|
||||
// Dual joycons can have only one side connected
|
||||
bool is_dual_left_connected{true};
|
||||
bool is_dual_right_connected{true};
|
||||
|
||||
// Motion parameters
|
||||
bool sixaxis_at_rest{true};
|
||||
|
|
|
@ -975,35 +975,35 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
|
|||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
|
||||
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left,
|
||||
Controller_NPad::NpadJoyAssignmentMode::Single);
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.applet_resource_user_id);
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
||||
parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
|
||||
// TODO: Check the differences between this and SetNpadJoyAssignmentModeSingleByDefault
|
||||
IPC::RequestParser rp{ctx};
|
||||
struct Parameters {
|
||||
Core::HID::NpadIdType npad_id;
|
||||
INSERT_PADDING_WORDS_NOINIT(1);
|
||||
u64 applet_resource_user_id;
|
||||
u64 npad_joy_device_type;
|
||||
Controller_NPad::NpadJoyDeviceType npad_joy_device_type;
|
||||
};
|
||||
static_assert(sizeof(Parameters) == 0x18, "Parameters has incorrect size.");
|
||||
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Single);
|
||||
.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type,
|
||||
Controller_NPad::NpadJoyAssignmentMode::Single);
|
||||
|
||||
LOG_WARNING(Service_HID,
|
||||
"(STUBBED) called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
||||
parameters.npad_id, parameters.applet_resource_user_id,
|
||||
parameters.npad_joy_device_type);
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}, npad_joy_device_type={}",
|
||||
parameters.npad_id, parameters.applet_resource_user_id,
|
||||
parameters.npad_joy_device_type);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
@ -1021,10 +1021,10 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
|
|||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
applet_resource->GetController<Controller_NPad>(HidController::NPad)
|
||||
.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyAssignmentMode::Dual);
|
||||
.SetNpadMode(parameters.npad_id, {}, Controller_NPad::NpadJoyAssignmentMode::Dual);
|
||||
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
|
||||
parameters.npad_id, parameters.applet_resource_user_id);
|
||||
LOG_INFO(Service_HID, "called, npad_id={}, applet_resource_user_id={}", parameters.npad_id,
|
||||
parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
|
|
Loading…
Reference in a new issue