Merge pull request #8368 from german77/seventimes
Service: hid: Several improvements and implementations
This commit is contained in:
		@@ -498,6 +498,49 @@ struct SixAxisSensorFusionParameters {
 | 
			
		||||
static_assert(sizeof(SixAxisSensorFusionParameters) == 8,
 | 
			
		||||
              "SixAxisSensorFusionParameters is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::server::SixAxisSensorProperties
 | 
			
		||||
struct SixAxisSensorProperties {
 | 
			
		||||
    union {
 | 
			
		||||
        u8 raw{};
 | 
			
		||||
        BitField<0, 1, u8> is_newly_assigned;
 | 
			
		||||
        BitField<1, 1, u8> is_firmware_update_available;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(SixAxisSensorProperties) == 1, "SixAxisSensorProperties is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::SixAxisSensorCalibrationParameter
 | 
			
		||||
struct SixAxisSensorCalibrationParameter {
 | 
			
		||||
    std::array<u8, 0x744> unknown_data{};
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(SixAxisSensorCalibrationParameter) == 0x744,
 | 
			
		||||
              "SixAxisSensorCalibrationParameter is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::SixAxisSensorIcInformation
 | 
			
		||||
struct SixAxisSensorIcInformation {
 | 
			
		||||
    f32 angular_rate{2000.0f}; // dps
 | 
			
		||||
    std::array<f32, 6> unknown_gyro_data1{
 | 
			
		||||
        -10.0f, -10.0f, -10.0f, 10.0f, 10.0f, 10.0f,
 | 
			
		||||
    }; // dps
 | 
			
		||||
    std::array<f32, 9> unknown_gyro_data2{
 | 
			
		||||
        0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f,
 | 
			
		||||
    };
 | 
			
		||||
    std::array<f32, 9> unknown_gyro_data3{
 | 
			
		||||
        1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f,
 | 
			
		||||
    };
 | 
			
		||||
    f32 acceleration_range{8.0f}; // g force
 | 
			
		||||
    std::array<f32, 6> unknown_accel_data1{
 | 
			
		||||
        -0.0612f, -0.0612f, -0.0612f, 0.0612f, 0.0612f, 0.0612f,
 | 
			
		||||
    }; // g force
 | 
			
		||||
    std::array<f32, 9> unknown_accel_data2{
 | 
			
		||||
        0.95f, -0.003f, -0.003f, -0.003f, 0.95f, -0.003f, -0.003f, -0.003f, 0.95f,
 | 
			
		||||
    };
 | 
			
		||||
    std::array<f32, 9> unknown_accel_data3{
 | 
			
		||||
        1.05f, 0.003f, 0.003f, 0.003f, 1.05f, 0.003f, 0.003f, 0.003f, 1.05f,
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(SixAxisSensorIcInformation) == 0xC8,
 | 
			
		||||
              "SixAxisSensorIcInformation is an invalid size");
 | 
			
		||||
 | 
			
		||||
// This is nn::hid::VibrationDeviceHandle
 | 
			
		||||
struct VibrationDeviceHandle {
 | 
			
		||||
    NpadStyleIndex npad_type{NpadStyleIndex::None};
 | 
			
		||||
 
 | 
			
		||||
@@ -56,11 +56,22 @@ bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle
 | 
			
		||||
    return npad_id && npad_type && device_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Controller_NPad::IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle) {
 | 
			
		||||
ResultCode Controller_NPad::VerifyValidSixAxisSensorHandle(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& device_handle) {
 | 
			
		||||
    const auto npad_id = IsNpadIdValid(static_cast<Core::HID::NpadIdType>(device_handle.npad_id));
 | 
			
		||||
    const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
 | 
			
		||||
    if (!npad_id) {
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
 | 
			
		||||
    return npad_id && npad_type && device_index;
 | 
			
		||||
    if (!device_index) {
 | 
			
		||||
        return NpadDeviceIndexOutOfRange;
 | 
			
		||||
    }
 | 
			
		||||
    // This doesn't get validated on nnsdk
 | 
			
		||||
    const bool npad_type = device_handle.npad_type < Core::HID::NpadStyleIndex::MaxNpadType;
 | 
			
		||||
    if (!npad_type) {
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_, u8* raw_shared_memory_,
 | 
			
		||||
@@ -158,6 +169,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        shared_memory->system_properties.use_plus.Assign(1);
 | 
			
		||||
        shared_memory->system_properties.use_minus.Assign(1);
 | 
			
		||||
        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::SwitchProController;
 | 
			
		||||
        shared_memory->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        shared_memory->style_tag.handheld.Assign(1);
 | 
			
		||||
@@ -170,16 +182,19 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        shared_memory->assignment_mode = NpadJoyAssignmentMode::Dual;
 | 
			
		||||
        shared_memory->applet_nfc_xcd.applet_footer.type =
 | 
			
		||||
            AppletFooterUiType::HandheldJoyConLeftJoyConRight;
 | 
			
		||||
        shared_memory->sixaxis_handheld_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
        shared_memory->style_tag.joycon_dual.Assign(1);
 | 
			
		||||
        if (controller.is_dual_left_connected) {
 | 
			
		||||
            shared_memory->device_type.joycon_left.Assign(1);
 | 
			
		||||
            shared_memory->system_properties.use_minus.Assign(1);
 | 
			
		||||
            shared_memory->sixaxis_dual_left_properties.is_newly_assigned.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->sixaxis_dual_right_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        }
 | 
			
		||||
        shared_memory->system_properties.use_directional_buttons.Assign(1);
 | 
			
		||||
        shared_memory->system_properties.is_vertical.Assign(1);
 | 
			
		||||
@@ -198,6 +213,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        shared_memory->system_properties.is_horizontal.Assign(1);
 | 
			
		||||
        shared_memory->system_properties.use_minus.Assign(1);
 | 
			
		||||
        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyLeftHorizontal;
 | 
			
		||||
        shared_memory->sixaxis_left_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        shared_memory->style_tag.joycon_right.Assign(1);
 | 
			
		||||
@@ -205,6 +221,7 @@ void Controller_NPad::InitNewlyAddedController(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
        shared_memory->system_properties.is_horizontal.Assign(1);
 | 
			
		||||
        shared_memory->system_properties.use_plus.Assign(1);
 | 
			
		||||
        shared_memory->applet_nfc_xcd.applet_footer.type = AppletFooterUiType::JoyRightHorizontal;
 | 
			
		||||
        shared_memory->sixaxis_right_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
        shared_memory->style_tag.gamecube.Assign(1);
 | 
			
		||||
@@ -215,6 +232,7 @@ 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->sixaxis_fullkey_properties.is_newly_assigned.Assign(1);
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::NES:
 | 
			
		||||
        shared_memory->style_tag.lark.Assign(1);
 | 
			
		||||
@@ -582,6 +600,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
            break;
 | 
			
		||||
        case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
            set_motion_state(sixaxis_fullkey_state, motion_state[0]);
 | 
			
		||||
            break;
 | 
			
		||||
        case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
@@ -672,6 +691,12 @@ std::size_t Controller_NPad::GetSupportedNpadIdTypesSize() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::SetHoldType(NpadJoyHoldType joy_hold_type) {
 | 
			
		||||
    if (joy_hold_type != NpadJoyHoldType::Horizontal &&
 | 
			
		||||
        joy_hold_type != NpadJoyHoldType::Vertical) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Npad joy hold type needs to be valid, joy_hold_type={}",
 | 
			
		||||
                  joy_hold_type);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    hold_type = joy_hold_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -695,11 +720,12 @@ Controller_NPad::NpadCommunicationMode Controller_NPad::GetNpadCommunicationMode
 | 
			
		||||
    return communication_mode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
 | 
			
		||||
                                  NpadJoyAssignmentMode assignment_mode) {
 | 
			
		||||
ResultCode 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);
 | 
			
		||||
        return;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromNpadIdType(npad_id);
 | 
			
		||||
@@ -708,7 +734,7 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!controller.device->IsConnected()) {
 | 
			
		||||
        return;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (assignment_mode == NpadJoyAssignmentMode::Dual) {
 | 
			
		||||
@@ -717,34 +743,34 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
 | 
			
		||||
            controller.is_dual_left_connected = true;
 | 
			
		||||
            controller.is_dual_right_connected = false;
 | 
			
		||||
            UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id, true);
 | 
			
		||||
            return;
 | 
			
		||||
            return ResultSuccess;
 | 
			
		||||
        }
 | 
			
		||||
        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 ResultSuccess;
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // This is for NpadJoyAssignmentMode::Single
 | 
			
		||||
 | 
			
		||||
    // Only JoyconDual get affected by this function
 | 
			
		||||
    if (controller.device->GetNpadStyleIndex() != Core::HID::NpadStyleIndex::JoyconDual) {
 | 
			
		||||
        return;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (controller.is_dual_left_connected && !controller.is_dual_right_connected) {
 | 
			
		||||
        DisconnectNpad(npad_id);
 | 
			
		||||
        UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconLeft, npad_id, true);
 | 
			
		||||
        return;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
    if (!controller.is_dual_left_connected && controller.is_dual_right_connected) {
 | 
			
		||||
        DisconnectNpad(npad_id);
 | 
			
		||||
        UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconRight, npad_id, true);
 | 
			
		||||
        return;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We have two controllers connected to the same npad_id we need to split them
 | 
			
		||||
@@ -762,6 +788,7 @@ void Controller_NPad::SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceTy
 | 
			
		||||
        controller_2.is_dual_right_connected = false;
 | 
			
		||||
        UpdateControllerAt(Core::HID::NpadStyleIndex::JoyconDual, npad_id_2, true);
 | 
			
		||||
    }
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
 | 
			
		||||
@@ -957,10 +984,10 @@ void Controller_NPad::UpdateControllerAt(Core::HID::NpadStyleIndex type,
 | 
			
		||||
    InitNewlyAddedController(npad_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
ResultCode Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    if (!IsNpadIdValid(npad_id)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
 | 
			
		||||
        return;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_HID, "Npad disconnected {}", npad_id);
 | 
			
		||||
@@ -977,6 +1004,12 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    shared_memory->device_type.raw = 0;
 | 
			
		||||
    shared_memory->system_properties.raw = 0;
 | 
			
		||||
    shared_memory->button_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_fullkey_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_handheld_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_dual_left_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_dual_right_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_left_properties.raw = 0;
 | 
			
		||||
    shared_memory->sixaxis_right_properties.raw = 0;
 | 
			
		||||
    shared_memory->battery_level_dual = 0;
 | 
			
		||||
    shared_memory->battery_level_left = 0;
 | 
			
		||||
    shared_memory->battery_level_right = 0;
 | 
			
		||||
@@ -997,346 +1030,268 @@ void Controller_NPad::DisconnectNpad(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    controller.device->Disconnect();
 | 
			
		||||
    SignalStyleSetChangedEvent(npad_id);
 | 
			
		||||
    WriteEmptyEntry(shared_memory);
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
                                                      GyroscopeZeroDriftMode drift_mode) {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
ResultCode Controller_NPad::SetGyroscopeZeroDriftMode(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, GyroscopeZeroDriftMode drift_mode) {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        controller.sixaxis_fullkey.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        controller.sixaxis_handheld.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            controller.sixaxis_dual_left.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        controller.sixaxis_dual_right.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        controller.sixaxis_left.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        controller.sixaxis_right.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    sixaxis.gyroscope_zero_drift_mode = drift_mode;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
                                                      GyroscopeZeroDriftMode& drift_mode) const {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
ResultCode Controller_NPad::GetGyroscopeZeroDriftMode(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
    GyroscopeZeroDriftMode& drift_mode) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        drift_mode = controller.sixaxis_fullkey.gyroscope_zero_drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        drift_mode = controller.sixaxis_handheld.gyroscope_zero_drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            drift_mode = controller.sixaxis_dual_left.gyroscope_zero_drift_mode;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        drift_mode = controller.sixaxis_dual_right.gyroscope_zero_drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        drift_mode = controller.sixaxis_left.gyroscope_zero_drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        drift_mode = controller.sixaxis_right.gyroscope_zero_drift_mode;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    drift_mode = sixaxis.gyroscope_zero_drift_mode;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
                                                  bool& is_at_rest) const {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
ResultCode Controller_NPad::IsSixAxisSensorAtRest(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_at_rest) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    is_at_rest = controller.sixaxis_at_rest;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::IsFirmwareUpdateAvailableForSixAxisSensor(
 | 
			
		||||
    Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // We don't support joycon firmware updates
 | 
			
		||||
    is_firmware_available = false;
 | 
			
		||||
    const auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
 | 
			
		||||
    is_firmware_available = sixaxis_properties.is_firmware_update_available != 0;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
                                              bool sixaxis_status) {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
ResultCode Controller_NPad::EnableSixAxisSensorUnalteredPassthrough(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled) {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    sixaxis.unaltered_passtrough = is_enabled;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::IsSixAxisSensorUnalteredPassthroughEnabled(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    is_enabled = sixaxis.unaltered_passtrough;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::LoadSixAxisSensorCalibrationParameter(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
    Core::HID::SixAxisSensorCalibrationParameter& calibration) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Request this data to the controller. On error return 0xd8ca
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    calibration = sixaxis.calibration;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::GetSixAxisSensorIcInformation(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
    Core::HID::SixAxisSensorIcInformation& ic_information) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: Request this data to the controller. On error return 0xd8ca
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    ic_information = sixaxis.ic_information;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::ResetIsSixAxisSensorDeviceNewlyAssigned(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& sixaxis_properties = GetSixaxisProperties(sixaxis_handle);
 | 
			
		||||
    sixaxis_properties.is_newly_assigned.Assign(0);
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                              bool sixaxis_status) {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    controller.sixaxis_sensor_enabled = sixaxis_status;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::IsSixAxisSensorFusionEnabled(
 | 
			
		||||
    Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_fusion_enabled) const {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_fusion_enabled) const {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        is_fusion_enabled = controller.sixaxis_fullkey.is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        is_fusion_enabled = controller.sixaxis_handheld.is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            is_fusion_enabled = controller.sixaxis_dual_left.is_fusion_enabled;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        is_fusion_enabled = controller.sixaxis_dual_right.is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        is_fusion_enabled = controller.sixaxis_left.is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        is_fusion_enabled = controller.sixaxis_right.is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    is_fusion_enabled = sixaxis.is_fusion_enabled;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
ResultCode Controller_NPad::SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
                                                    bool is_fusion_enabled) {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
ResultCode Controller_NPad::SetSixAxisFusionEnabled(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_fusion_enabled) {
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        controller.sixaxis_fullkey.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        controller.sixaxis_handheld.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            controller.sixaxis_dual_left.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        controller.sixaxis_dual_right.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        controller.sixaxis_left.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        controller.sixaxis_right.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    sixaxis.is_fusion_enabled = is_fusion_enabled;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::SetSixAxisFusionParameters(
 | 
			
		||||
    Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
    Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters) {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto param1 = sixaxis_fusion_parameters.parameter1;
 | 
			
		||||
    if (param1 < 0.0f || param1 > 1.0f) {
 | 
			
		||||
        return InvalidSixAxisFusionRange;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        controller.sixaxis_fullkey.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        controller.sixaxis_handheld.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            controller.sixaxis_dual_left.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        controller.sixaxis_dual_right.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        controller.sixaxis_left.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        controller.sixaxis_right.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    sixaxis.fusion = sixaxis_fusion_parameters;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultCode Controller_NPad::GetSixAxisFusionParameters(
 | 
			
		||||
    Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
    Core::HID::SixAxisSensorFusionParameters& parameters) const {
 | 
			
		||||
    if (!IsDeviceHandleValid(sixaxis_handle)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle");
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    const auto is_valid = VerifyValidSixAxisSensorHandle(sixaxis_handle);
 | 
			
		||||
    if (is_valid.IsError()) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid handle, error_code={}", is_valid.raw);
 | 
			
		||||
        return is_valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
        parameters = controller.sixaxis_fullkey.fusion;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        parameters = controller.sixaxis_handheld.fusion;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::GameCube:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            parameters = controller.sixaxis_dual_left.fusion;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        parameters = controller.sixaxis_dual_right.fusion;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        parameters = controller.sixaxis_left.fusion;
 | 
			
		||||
        break;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        parameters = controller.sixaxis_right.fusion;
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid Npad type {}", sixaxis_handle.npad_type);
 | 
			
		||||
        return NpadInvalidHandle;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& sixaxis = GetSixaxisState(sixaxis_handle);
 | 
			
		||||
    parameters = sixaxis.fusion;
 | 
			
		||||
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
 | 
			
		||||
                                              Core::HID::NpadIdType npad_id_2) {
 | 
			
		||||
ResultCode Controller_NPad::MergeSingleJoyAsDualJoy(Core::HID::NpadIdType npad_id_1,
 | 
			
		||||
                                                    Core::HID::NpadIdType 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,
 | 
			
		||||
                  npad_id_2);
 | 
			
		||||
        return;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    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;
 | 
			
		||||
    auto controller_style_1 = controller_1.device->GetNpadStyleIndex();
 | 
			
		||||
    auto controller_style_2 = controller_2.device->GetNpadStyleIndex();
 | 
			
		||||
 | 
			
		||||
    // If the controllers at both npad indices form a pair of left and right joycons, merge them.
 | 
			
		||||
    // Otherwise, do nothing.
 | 
			
		||||
    // Simplify this code by converting dualjoycon with only a side connected to single joycons
 | 
			
		||||
    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 &&
 | 
			
		||||
        controller_style_2 == Core::HID::NpadStyleIndex::JoyconLeft) {
 | 
			
		||||
        return NpadIsSameType;
 | 
			
		||||
    }
 | 
			
		||||
    if (controller_style_1 == Core::HID::NpadStyleIndex::JoyconRight &&
 | 
			
		||||
        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;
 | 
			
		||||
        return NpadIsSameType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    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;
 | 
			
		||||
    // These exceptions are handled as if they where dual joycon
 | 
			
		||||
    if (controller_style_1 != Core::HID::NpadStyleIndex::JoyconLeft &&
 | 
			
		||||
        controller_style_1 != Core::HID::NpadStyleIndex::JoyconRight) {
 | 
			
		||||
        return NpadIsDualJoycon;
 | 
			
		||||
    }
 | 
			
		||||
    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);
 | 
			
		||||
    if (controller_style_2 != Core::HID::NpadStyleIndex::JoyconLeft &&
 | 
			
		||||
        controller_style_2 != Core::HID::NpadStyleIndex::JoyconRight) {
 | 
			
		||||
        return NpadIsDualJoycon;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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 ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::StartLRAssignmentMode() {
 | 
			
		||||
@@ -1349,17 +1304,17 @@ void Controller_NPad::StopLRAssignmentMode() {
 | 
			
		||||
    is_in_lr_assignment_mode = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
 | 
			
		||||
                                         Core::HID::NpadIdType npad_id_2) {
 | 
			
		||||
ResultCode Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
 | 
			
		||||
                                               Core::HID::NpadIdType 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,
 | 
			
		||||
                  npad_id_2);
 | 
			
		||||
        return false;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    if (npad_id_1 == Core::HID::NpadIdType::Handheld ||
 | 
			
		||||
        npad_id_2 == Core::HID::NpadIdType::Handheld || npad_id_1 == Core::HID::NpadIdType::Other ||
 | 
			
		||||
        npad_id_2 == Core::HID::NpadIdType::Other) {
 | 
			
		||||
        return true;
 | 
			
		||||
        return ResultSuccess;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& controller_1 = GetControllerFromNpadIdType(npad_id_1).device;
 | 
			
		||||
    const auto& controller_2 = GetControllerFromNpadIdType(npad_id_2).device;
 | 
			
		||||
@@ -1369,46 +1324,49 @@ bool Controller_NPad::SwapNpadAssignment(Core::HID::NpadIdType npad_id_1,
 | 
			
		||||
    const auto is_connected_2 = controller_2->IsConnected();
 | 
			
		||||
 | 
			
		||||
    if (!IsControllerSupported(type_index_1) && is_connected_1) {
 | 
			
		||||
        return false;
 | 
			
		||||
        return NpadNotConnected;
 | 
			
		||||
    }
 | 
			
		||||
    if (!IsControllerSupported(type_index_2) && is_connected_2) {
 | 
			
		||||
        return false;
 | 
			
		||||
        return NpadNotConnected;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    UpdateControllerAt(type_index_2, npad_id_1, is_connected_2);
 | 
			
		||||
    UpdateControllerAt(type_index_1, npad_id_2, is_connected_1);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Core::HID::LedPattern Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id) {
 | 
			
		||||
ResultCode Controller_NPad::GetLedPattern(Core::HID::NpadIdType npad_id,
 | 
			
		||||
                                          Core::HID::LedPattern& pattern) const {
 | 
			
		||||
    if (!IsNpadIdValid(npad_id)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
 | 
			
		||||
        return Core::HID::LedPattern{0, 0, 0, 0};
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& controller = GetControllerFromNpadIdType(npad_id).device;
 | 
			
		||||
    return controller->GetLedPattern();
 | 
			
		||||
    pattern = controller->GetLedPattern();
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
 | 
			
		||||
    Core::HID::NpadIdType npad_id) const {
 | 
			
		||||
ResultCode Controller_NPad::IsUnintendedHomeButtonInputProtectionEnabled(
 | 
			
		||||
    Core::HID::NpadIdType npad_id, bool& is_valid) const {
 | 
			
		||||
    if (!IsNpadIdValid(npad_id)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
 | 
			
		||||
        // Return the default value
 | 
			
		||||
        return false;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    const auto& controller = GetControllerFromNpadIdType(npad_id);
 | 
			
		||||
    return controller.unintended_home_button_input_protection;
 | 
			
		||||
    is_valid = controller.unintended_home_button_input_protection;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
 | 
			
		||||
                                                                    Core::HID::NpadIdType npad_id) {
 | 
			
		||||
ResultCode Controller_NPad::SetUnintendedHomeButtonInputProtectionEnabled(
 | 
			
		||||
    bool is_protection_enabled, Core::HID::NpadIdType npad_id) {
 | 
			
		||||
    if (!IsNpadIdValid(npad_id)) {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Invalid NpadIdType npad_id:{}", npad_id);
 | 
			
		||||
        return;
 | 
			
		||||
        return InvalidNpadId;
 | 
			
		||||
    }
 | 
			
		||||
    auto& controller = GetControllerFromNpadIdType(npad_id);
 | 
			
		||||
    controller.unintended_home_button_input_protection = is_protection_enabled;
 | 
			
		||||
    return ResultSuccess;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Controller_NPad::SetAnalogStickUseCenterClamp(bool use_center_clamp) {
 | 
			
		||||
@@ -1546,4 +1504,96 @@ const Controller_NPad::NpadControllerData& Controller_NPad::GetControllerFromNpa
 | 
			
		||||
    return controller_data[npad_index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        return controller.shared_memory->sixaxis_fullkey_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        return controller.shared_memory->sixaxis_handheld_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            return controller.shared_memory->sixaxis_dual_left_properties;
 | 
			
		||||
        }
 | 
			
		||||
        return controller.shared_memory->sixaxis_dual_right_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        return controller.shared_memory->sixaxis_left_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        return controller.shared_memory->sixaxis_right_properties;
 | 
			
		||||
    default:
 | 
			
		||||
        return controller.shared_memory->sixaxis_fullkey_properties;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Core::HID::SixAxisSensorProperties& Controller_NPad::GetSixaxisProperties(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
 | 
			
		||||
    const auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        return controller.shared_memory->sixaxis_fullkey_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        return controller.shared_memory->sixaxis_handheld_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            return controller.shared_memory->sixaxis_dual_left_properties;
 | 
			
		||||
        }
 | 
			
		||||
        return controller.shared_memory->sixaxis_dual_right_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        return controller.shared_memory->sixaxis_left_properties;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        return controller.shared_memory->sixaxis_right_properties;
 | 
			
		||||
    default:
 | 
			
		||||
        return controller.shared_memory->sixaxis_fullkey_properties;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle) {
 | 
			
		||||
    auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        return controller.sixaxis_fullkey;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        return controller.sixaxis_handheld;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            return controller.sixaxis_dual_left;
 | 
			
		||||
        }
 | 
			
		||||
        return controller.sixaxis_dual_right;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        return controller.sixaxis_left;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        return controller.sixaxis_right;
 | 
			
		||||
    default:
 | 
			
		||||
        return controller.sixaxis_unknown;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Controller_NPad::SixaxisParameters& Controller_NPad::GetSixaxisState(
 | 
			
		||||
    const Core::HID::SixAxisSensorHandle& sixaxis_handle) const {
 | 
			
		||||
    const auto& controller = GetControllerFromHandle(sixaxis_handle);
 | 
			
		||||
    switch (sixaxis_handle.npad_type) {
 | 
			
		||||
    case Core::HID::NpadStyleIndex::ProController:
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Pokeball:
 | 
			
		||||
        return controller.sixaxis_fullkey;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::Handheld:
 | 
			
		||||
        return controller.sixaxis_handheld;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconDual:
 | 
			
		||||
        if (sixaxis_handle.device_index == Core::HID::DeviceIndex::Left) {
 | 
			
		||||
            return controller.sixaxis_dual_left;
 | 
			
		||||
        }
 | 
			
		||||
        return controller.sixaxis_dual_right;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconLeft:
 | 
			
		||||
        return controller.sixaxis_left;
 | 
			
		||||
    case Core::HID::NpadStyleIndex::JoyconRight:
 | 
			
		||||
        return controller.sixaxis_right;
 | 
			
		||||
    default:
 | 
			
		||||
        return controller.sixaxis_unknown;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -107,8 +107,8 @@ public:
 | 
			
		||||
    void SetNpadCommunicationMode(NpadCommunicationMode communication_mode_);
 | 
			
		||||
    NpadCommunicationMode GetNpadCommunicationMode() const;
 | 
			
		||||
 | 
			
		||||
    void SetNpadMode(Core::HID::NpadIdType npad_id, NpadJoyDeviceType npad_device_type,
 | 
			
		||||
                     NpadJoyAssignmentMode assignment_mode);
 | 
			
		||||
    ResultCode 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);
 | 
			
		||||
@@ -141,50 +141,65 @@ public:
 | 
			
		||||
    void UpdateControllerAt(Core::HID::NpadStyleIndex controller, Core::HID::NpadIdType npad_id,
 | 
			
		||||
                            bool connected);
 | 
			
		||||
 | 
			
		||||
    void DisconnectNpad(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    ResultCode DisconnectNpad(Core::HID::NpadIdType npad_id);
 | 
			
		||||
 | 
			
		||||
    ResultCode SetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    ResultCode SetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                         GyroscopeZeroDriftMode drift_mode);
 | 
			
		||||
    ResultCode GetGyroscopeZeroDriftMode(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    ResultCode GetGyroscopeZeroDriftMode(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                         GyroscopeZeroDriftMode& drift_mode) const;
 | 
			
		||||
    ResultCode IsSixAxisSensorAtRest(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    ResultCode IsSixAxisSensorAtRest(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                     bool& is_at_rest) const;
 | 
			
		||||
    ResultCode IsFirmwareUpdateAvailableForSixAxisSensor(
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle, bool& is_firmware_available) const;
 | 
			
		||||
    ResultCode SetSixAxisEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_firmware_available) const;
 | 
			
		||||
    ResultCode EnableSixAxisSensorUnalteredPassthrough(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool is_enabled);
 | 
			
		||||
    ResultCode IsSixAxisSensorUnalteredPassthroughEnabled(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle, bool& is_enabled) const;
 | 
			
		||||
    ResultCode LoadSixAxisSensorCalibrationParameter(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
        Core::HID::SixAxisSensorCalibrationParameter& calibration) const;
 | 
			
		||||
    ResultCode GetSixAxisSensorIcInformation(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
        Core::HID::SixAxisSensorIcInformation& ic_information) const;
 | 
			
		||||
    ResultCode ResetIsSixAxisSensorDeviceNewlyAssigned(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle);
 | 
			
		||||
    ResultCode SetSixAxisEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                 bool sixaxis_status);
 | 
			
		||||
    ResultCode IsSixAxisSensorFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    ResultCode IsSixAxisSensorFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                            bool& is_fusion_enabled) const;
 | 
			
		||||
    ResultCode SetSixAxisFusionEnabled(Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
    ResultCode SetSixAxisFusionEnabled(const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
                                       bool is_fusion_enabled);
 | 
			
		||||
    ResultCode SetSixAxisFusionParameters(
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
        Core::HID::SixAxisSensorFusionParameters sixaxis_fusion_parameters);
 | 
			
		||||
    ResultCode GetSixAxisFusionParameters(
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle,
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& sixaxis_handle,
 | 
			
		||||
        Core::HID::SixAxisSensorFusionParameters& parameters) const;
 | 
			
		||||
    Core::HID::LedPattern GetLedPattern(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    bool IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id) const;
 | 
			
		||||
    void SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
 | 
			
		||||
                                                       Core::HID::NpadIdType npad_id);
 | 
			
		||||
    ResultCode GetLedPattern(Core::HID::NpadIdType npad_id, Core::HID::LedPattern& pattern) const;
 | 
			
		||||
    ResultCode IsUnintendedHomeButtonInputProtectionEnabled(Core::HID::NpadIdType npad_id,
 | 
			
		||||
                                                            bool& is_enabled) const;
 | 
			
		||||
    ResultCode SetUnintendedHomeButtonInputProtectionEnabled(bool is_protection_enabled,
 | 
			
		||||
                                                             Core::HID::NpadIdType npad_id);
 | 
			
		||||
    void SetAnalogStickUseCenterClamp(bool use_center_clamp);
 | 
			
		||||
    void ClearAllConnectedControllers();
 | 
			
		||||
    void DisconnectAllConnectedControllers();
 | 
			
		||||
    void ConnectAllDisconnectedControllers();
 | 
			
		||||
    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 StopLRAssignmentMode();
 | 
			
		||||
    bool 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);
 | 
			
		||||
 | 
			
		||||
    // Logical OR for all buttons presses on all controllers
 | 
			
		||||
    // Specifically for cheat engine and other features.
 | 
			
		||||
    Core::HID::NpadButton GetAndResetPressState();
 | 
			
		||||
 | 
			
		||||
    static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
 | 
			
		||||
    static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
 | 
			
		||||
    static ResultCode VerifyValidSixAxisSensorHandle(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& device_handle);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    static constexpr std::size_t NPAD_COUNT = 10;
 | 
			
		||||
@@ -451,9 +466,13 @@ private:
 | 
			
		||||
        NpadLuciaType lucia_type{};
 | 
			
		||||
        NpadLagonType lagon_type{};
 | 
			
		||||
        NpadLagerType lager_type{};
 | 
			
		||||
        // FW 13.x Investigate there is some sort of bitflag related to joycons
 | 
			
		||||
        INSERT_PADDING_BYTES(0x4);
 | 
			
		||||
        INSERT_PADDING_BYTES(0xc08); // Unknown
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_fullkey_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_handheld_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_dual_left_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_dual_right_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_left_properties;
 | 
			
		||||
        Core::HID::SixAxisSensorProperties sixaxis_right_properties;
 | 
			
		||||
        INSERT_PADDING_BYTES(0xc06); // Unknown
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(NpadInternalState) == 0x5000, "NpadInternalState is an invalid size");
 | 
			
		||||
 | 
			
		||||
@@ -465,7 +484,10 @@ private:
 | 
			
		||||
 | 
			
		||||
    struct SixaxisParameters {
 | 
			
		||||
        bool is_fusion_enabled{true};
 | 
			
		||||
        bool unaltered_passtrough{false};
 | 
			
		||||
        Core::HID::SixAxisSensorFusionParameters fusion{};
 | 
			
		||||
        Core::HID::SixAxisSensorCalibrationParameter calibration{};
 | 
			
		||||
        Core::HID::SixAxisSensorIcInformation ic_information{};
 | 
			
		||||
        GyroscopeZeroDriftMode gyroscope_zero_drift_mode{GyroscopeZeroDriftMode::Standard};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -491,6 +513,7 @@ private:
 | 
			
		||||
        SixaxisParameters sixaxis_dual_right{};
 | 
			
		||||
        SixaxisParameters sixaxis_left{};
 | 
			
		||||
        SixaxisParameters sixaxis_right{};
 | 
			
		||||
        SixaxisParameters sixaxis_unknown{};
 | 
			
		||||
 | 
			
		||||
        // Current pad state
 | 
			
		||||
        NPadGenericState npad_pad_state{};
 | 
			
		||||
@@ -522,6 +545,14 @@ private:
 | 
			
		||||
    NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
 | 
			
		||||
    const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
 | 
			
		||||
 | 
			
		||||
    Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& device_handle);
 | 
			
		||||
    const Core::HID::SixAxisSensorProperties& GetSixaxisProperties(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& device_handle) const;
 | 
			
		||||
    SixaxisParameters& GetSixaxisState(const Core::HID::SixAxisSensorHandle& device_handle);
 | 
			
		||||
    const SixaxisParameters& GetSixaxisState(
 | 
			
		||||
        const Core::HID::SixAxisSensorHandle& device_handle) const;
 | 
			
		||||
 | 
			
		||||
    std::atomic<u64> press_state{};
 | 
			
		||||
 | 
			
		||||
    std::array<NpadControllerData, NPAD_COUNT> controller_data{};
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,11 @@
 | 
			
		||||
namespace Service::HID {
 | 
			
		||||
 | 
			
		||||
constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100};
 | 
			
		||||
constexpr ResultCode NpadDeviceIndexOutOfRange{ErrorModule::HID, 107};
 | 
			
		||||
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 NpadNotConnected{ErrorModule::HID, 710};
 | 
			
		||||
 | 
			
		||||
} // namespace Service::HID
 | 
			
		||||
 
 | 
			
		||||
@@ -257,12 +257,12 @@ Hid::Hid(Core::System& system_)
 | 
			
		||||
        {81, &Hid::ResetGyroscopeZeroDriftMode, "ResetGyroscopeZeroDriftMode"},
 | 
			
		||||
        {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
 | 
			
		||||
        {83, &Hid::IsFirmwareUpdateAvailableForSixAxisSensor, "IsFirmwareUpdateAvailableForSixAxisSensor"},
 | 
			
		||||
        {84, nullptr, "EnableSixAxisSensorUnalteredPassthrough"},
 | 
			
		||||
        {85, nullptr, "IsSixAxisSensorUnalteredPassthroughEnabled"},
 | 
			
		||||
        {84, &Hid::EnableSixAxisSensorUnalteredPassthrough, "EnableSixAxisSensorUnalteredPassthrough"},
 | 
			
		||||
        {85, &Hid::IsSixAxisSensorUnalteredPassthroughEnabled, "IsSixAxisSensorUnalteredPassthroughEnabled"},
 | 
			
		||||
        {86, nullptr, "StoreSixAxisSensorCalibrationParameter"},
 | 
			
		||||
        {87, nullptr, "LoadSixAxisSensorCalibrationParameter"},
 | 
			
		||||
        {88, nullptr, "GetSixAxisSensorIcInformation"},
 | 
			
		||||
        {89, nullptr, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
 | 
			
		||||
        {87, &Hid::LoadSixAxisSensorCalibrationParameter, "LoadSixAxisSensorCalibrationParameter"},
 | 
			
		||||
        {88, &Hid::GetSixAxisSensorIcInformation, "GetSixAxisSensorIcInformation"},
 | 
			
		||||
        {89, &Hid::ResetIsSixAxisSensorDeviceNewlyAssigned, "ResetIsSixAxisSensorDeviceNewlyAssigned"},
 | 
			
		||||
        {91, &Hid::ActivateGesture, "ActivateGesture"},
 | 
			
		||||
        {100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
 | 
			
		||||
        {101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
 | 
			
		||||
@@ -694,11 +694,7 @@ void Hid::ResetSixAxisSensorFusionParameters(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
        rb.Push(result1);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (result2.IsError()) {
 | 
			
		||||
        rb.Push(result2);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(result2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -821,6 +817,144 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c
 | 
			
		||||
    rb.Push(is_firmware_available);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        bool enabled;
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle;
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.EnableSixAxisSensorUnalteredPassthrough(
 | 
			
		||||
        parameters.sixaxis_handle, parameters.enabled);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_HID,
 | 
			
		||||
                "(STUBBED) called, enabled={}, npad_type={}, npad_id={}, device_index={}, "
 | 
			
		||||
                "applet_resource_user_id={}",
 | 
			
		||||
                parameters.enabled, parameters.sixaxis_handle.npad_type,
 | 
			
		||||
                parameters.sixaxis_handle.npad_id, parameters.sixaxis_handle.device_index,
 | 
			
		||||
                parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    bool is_unaltered_sisxaxis_enabled{};
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.IsSixAxisSensorUnalteredPassthroughEnabled(
 | 
			
		||||
        parameters.sixaxis_handle, is_unaltered_sisxaxis_enabled);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(
 | 
			
		||||
        Service_HID,
 | 
			
		||||
        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
 | 
			
		||||
        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
 | 
			
		||||
        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
    rb.Push(is_unaltered_sisxaxis_enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    Core::HID::SixAxisSensorCalibrationParameter calibration{};
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result =
 | 
			
		||||
        controller.LoadSixAxisSensorCalibrationParameter(parameters.sixaxis_handle, calibration);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(
 | 
			
		||||
        Service_HID,
 | 
			
		||||
        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
 | 
			
		||||
        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
 | 
			
		||||
        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    if (result.IsSuccess()) {
 | 
			
		||||
        ctx.WriteBuffer(calibration);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    Core::HID::SixAxisSensorIcInformation ic_information{};
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result =
 | 
			
		||||
        controller.GetSixAxisSensorIcInformation(parameters.sixaxis_handle, ic_information);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(
 | 
			
		||||
        Service_HID,
 | 
			
		||||
        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
 | 
			
		||||
        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
 | 
			
		||||
        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    if (result.IsSuccess()) {
 | 
			
		||||
        ctx.WriteBuffer(ic_information);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
        Core::HID::SixAxisSensorHandle sixaxis_handle;
 | 
			
		||||
        INSERT_PADDING_WORDS_NOINIT(1);
 | 
			
		||||
        u64 applet_resource_user_id;
 | 
			
		||||
    };
 | 
			
		||||
    static_assert(sizeof(Parameters) == 0x10, "Parameters has incorrect size.");
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result =
 | 
			
		||||
        controller.ResetIsSixAxisSensorDeviceNewlyAssigned(parameters.sixaxis_handle);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(
 | 
			
		||||
        Service_HID,
 | 
			
		||||
        "(STUBBED) called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
 | 
			
		||||
        parameters.sixaxis_handle.npad_type, parameters.sixaxis_handle.npad_id,
 | 
			
		||||
        parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    struct Parameters {
 | 
			
		||||
@@ -948,27 +1082,29 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
        .DisconnectNpad(parameters.npad_id);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.DisconnectNpad(parameters.npad_id);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(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);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto npad_id{rp.PopEnum<Core::HID::NpadIdType>()};
 | 
			
		||||
 | 
			
		||||
    Core::HID::LedPattern pattern{0, 0, 0, 0};
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.GetLedPattern(npad_id, pattern);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_HID, "called, npad_id={}", npad_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
                .GetLedPattern(npad_id)
 | 
			
		||||
                .raw);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
    rb.Push(pattern.raw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1028,15 +1164,16 @@ 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::NpadJoyDeviceType::Left,
 | 
			
		||||
                     Controller_NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result =
 | 
			
		||||
        controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left,
 | 
			
		||||
                               Controller_NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1051,16 +1188,16 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
        .SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type,
 | 
			
		||||
                     Controller_NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.SetNpadMode(parameters.npad_id, parameters.npad_joy_device_type,
 | 
			
		||||
                                               Controller_NPad::NpadJoyAssignmentMode::Single);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1074,14 +1211,15 @@ 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);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.SetNpadMode(parameters.npad_id, {},
 | 
			
		||||
                                               Controller_NPad::NpadJoyAssignmentMode::Dual);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1090,14 +1228,14 @@ void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
 | 
			
		||||
    const auto applet_resource_user_id{rp.Pop<u64>()};
 | 
			
		||||
 | 
			
		||||
    applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
        .MergeSingleJoyAsDualJoy(npad_id_1, npad_id_2);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    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={}",
 | 
			
		||||
              npad_id_1, npad_id_2, applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::StartLrAssignmentMode(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1157,19 +1295,14 @@ void Hid::SwapNpadAssignment(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    const auto npad_id_2{rp.PopEnum<Core::HID::NpadIdType>()};
 | 
			
		||||
    const auto applet_resource_user_id{rp.Pop<u64>()};
 | 
			
		||||
 | 
			
		||||
    const bool res = applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
                         .SwapNpadAssignment(npad_id_1, npad_id_2);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.SwapNpadAssignment(npad_id_1, npad_id_2);
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    if (res) {
 | 
			
		||||
        rb.Push(ResultSuccess);
 | 
			
		||||
    } else {
 | 
			
		||||
        LOG_ERROR(Service_HID, "Npads are not connected!");
 | 
			
		||||
        rb.Push(NpadNotConnected);
 | 
			
		||||
    }
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1183,13 +1316,17 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(Kernel::HLERequestContext
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    bool is_enabled = false;
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result =
 | 
			
		||||
        controller.IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id, is_enabled);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_HID, "(STUBBED) called, npad_id={}, applet_resource_user_id={}",
 | 
			
		||||
                parameters.npad_id, parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
                .IsUnintendedHomeButtonInputProtectionEnabled(parameters.npad_id));
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
    rb.Push(is_enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1204,9 +1341,9 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
 | 
			
		||||
 | 
			
		||||
    const auto parameters{rp.PopRaw<Parameters>()};
 | 
			
		||||
 | 
			
		||||
    applet_resource->GetController<Controller_NPad>(HidController::NPad)
 | 
			
		||||
        .SetUnintendedHomeButtonInputProtectionEnabled(
 | 
			
		||||
            parameters.unintended_home_button_input_protection, parameters.npad_id);
 | 
			
		||||
    auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
 | 
			
		||||
    const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
 | 
			
		||||
        parameters.unintended_home_button_input_protection, parameters.npad_id);
 | 
			
		||||
 | 
			
		||||
    LOG_WARNING(Service_HID,
 | 
			
		||||
                "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={},"
 | 
			
		||||
@@ -1215,7 +1352,7 @@ void Hid::EnableUnintendedHomeButtonInputProtection(Kernel::HLERequestContext& c
 | 
			
		||||
                parameters.applet_resource_user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 2};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::SetNpadAnalogStickUseCenterClamp(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
@@ -1377,6 +1514,8 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto can_vibrate{rp.Pop<bool>()};
 | 
			
		||||
 | 
			
		||||
    // nnSDK saves this value as a float. Since it can only be 1.0f or 0.0f we simplify this value
 | 
			
		||||
    // by converting it to a bool
 | 
			
		||||
    Settings::values.vibration_enabled.SetValue(can_vibrate);
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_HID, "called, can_vibrate={}", can_vibrate);
 | 
			
		||||
@@ -1388,9 +1527,12 @@ void Hid::PermitVibration(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
void Hid::IsVibrationPermitted(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    LOG_DEBUG(Service_HID, "called");
 | 
			
		||||
 | 
			
		||||
    // nnSDK checks if a float is greater than zero. We return the bool we stored earlier
 | 
			
		||||
    const auto is_enabled = Settings::values.vibration_enabled.GetValue();
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 3};
 | 
			
		||||
    rb.Push(ResultSuccess);
 | 
			
		||||
    rb.Push(Settings::values.vibration_enabled.GetValue());
 | 
			
		||||
    rb.Push(is_enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Hid::SendVibrationValues(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
 
 | 
			
		||||
@@ -113,6 +113,11 @@ private:
 | 
			
		||||
    void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void EnableSixAxisSensorUnalteredPassthrough(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void IsSixAxisSensorUnalteredPassthroughEnabled(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void LoadSixAxisSensorCalibrationParameter(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetSixAxisSensorIcInformation(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void ResetIsSixAxisSensorDeviceNewlyAssigned(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void ActivateGesture(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user