early-access version 2799
This commit is contained in:
@@ -234,7 +234,7 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
|
||||
|
||||
ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement, s64 timeout) {
|
||||
// Prepare to wait.
|
||||
KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
|
||||
|
||||
{
|
||||
@@ -287,7 +287,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
|
||||
|
||||
ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
|
||||
// Prepare to wait.
|
||||
KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
ThreadQueueImplForKAddressArbiter wait_queue(kernel, std::addressof(thread_tree));
|
||||
|
||||
{
|
||||
|
@@ -106,7 +106,7 @@ KConditionVariable::KConditionVariable(Core::System& system_)
|
||||
KConditionVariable::~KConditionVariable() = default;
|
||||
|
||||
ResultCode KConditionVariable::SignalToAddress(VAddr addr) {
|
||||
KThread* owner_thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
KThread* owner_thread = GetCurrentThreadPointer(kernel);
|
||||
|
||||
// Signal the address.
|
||||
{
|
||||
@@ -147,7 +147,7 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) {
|
||||
}
|
||||
|
||||
ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value) {
|
||||
KThread* cur_thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
KThread* cur_thread = GetCurrentThreadPointer(kernel);
|
||||
ThreadQueueImplForKConditionVariableWaitForAddress wait_queue(kernel);
|
||||
|
||||
// Wait for the address.
|
||||
|
@@ -15,8 +15,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto& scheduler = kernel.Scheduler(core_id);
|
||||
auto& current_thread = *scheduler.GetCurrentThread();
|
||||
auto& current_thread = GetCurrentThread(kernel);
|
||||
|
||||
// If the user disable count is set, we may need to pin the current thread.
|
||||
if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
|
||||
@@ -26,7 +25,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
|
||||
process->PinCurrentThread(core_id);
|
||||
|
||||
// Set the interrupt flag for the thread.
|
||||
scheduler.GetCurrentThread()->SetInterruptFlag();
|
||||
GetCurrentThread(kernel).SetInterruptFlag();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -176,7 +176,8 @@ void KProcess::PinCurrentThread(s32 core_id) {
|
||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||
|
||||
// Get the current thread.
|
||||
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
|
||||
KThread* cur_thread =
|
||||
kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread();
|
||||
|
||||
// If the thread isn't terminated, pin it.
|
||||
if (!cur_thread->IsTerminationRequested()) {
|
||||
@@ -193,7 +194,8 @@ void KProcess::UnpinCurrentThread(s32 core_id) {
|
||||
ASSERT(kernel.GlobalSchedulerContext().IsLocked());
|
||||
|
||||
// Get the current thread.
|
||||
KThread* cur_thread = kernel.Scheduler(static_cast<std::size_t>(core_id)).GetCurrentThread();
|
||||
KThread* cur_thread =
|
||||
kernel.Scheduler(static_cast<std::size_t>(core_id)).GetSchedulerCurrentThread();
|
||||
|
||||
// Unpin it.
|
||||
cur_thread->Unpin();
|
||||
@@ -420,11 +422,11 @@ void KProcess::PrepareForTermination() {
|
||||
ChangeStatus(ProcessStatus::Exiting);
|
||||
|
||||
const auto stop_threads = [this](const std::vector<KThread*>& in_thread_list) {
|
||||
for (auto& thread : in_thread_list) {
|
||||
for (auto* thread : in_thread_list) {
|
||||
if (thread->GetOwnerProcess() != this)
|
||||
continue;
|
||||
|
||||
if (thread == kernel.CurrentScheduler()->GetCurrentThread())
|
||||
if (thread == GetCurrentThreadPointer(kernel))
|
||||
continue;
|
||||
|
||||
// TODO(Subv): When are the other running/ready threads terminated?
|
||||
|
@@ -317,7 +317,7 @@ void KScheduler::RotateScheduledQueue(s32 cpu_core_id, s32 priority) {
|
||||
|
||||
{
|
||||
KThread* best_thread = priority_queue.GetScheduledFront(cpu_core_id);
|
||||
if (best_thread == GetCurrentThread()) {
|
||||
if (best_thread == GetCurrentThreadPointer(kernel)) {
|
||||
best_thread = priority_queue.GetScheduledNext(cpu_core_id, best_thread);
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
|
||||
ASSERT(kernel.CurrentProcess() != nullptr);
|
||||
|
||||
// Get the current thread and process.
|
||||
KThread& cur_thread = Kernel::GetCurrentThread(kernel);
|
||||
KThread& cur_thread = GetCurrentThread(kernel);
|
||||
KProcess& cur_process = *kernel.CurrentProcess();
|
||||
|
||||
// If the thread's yield count matches, there's nothing for us to do.
|
||||
@@ -463,7 +463,7 @@ void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
|
||||
ASSERT(kernel.CurrentProcess() != nullptr);
|
||||
|
||||
// Get the current thread and process.
|
||||
KThread& cur_thread = Kernel::GetCurrentThread(kernel);
|
||||
KThread& cur_thread = GetCurrentThread(kernel);
|
||||
KProcess& cur_process = *kernel.CurrentProcess();
|
||||
|
||||
// If the thread's yield count matches, there's nothing for us to do.
|
||||
@@ -551,7 +551,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) {
|
||||
ASSERT(kernel.CurrentProcess() != nullptr);
|
||||
|
||||
// Get the current thread and process.
|
||||
KThread& cur_thread = Kernel::GetCurrentThread(kernel);
|
||||
KThread& cur_thread = GetCurrentThread(kernel);
|
||||
KProcess& cur_process = *kernel.CurrentProcess();
|
||||
|
||||
// If the thread's yield count matches, there's nothing for us to do.
|
||||
@@ -642,7 +642,7 @@ KScheduler::~KScheduler() {
|
||||
ASSERT(!idle_thread);
|
||||
}
|
||||
|
||||
KThread* KScheduler::GetCurrentThread() const {
|
||||
KThread* KScheduler::GetSchedulerCurrentThread() const {
|
||||
if (auto result = current_thread.load(); result) {
|
||||
return result;
|
||||
}
|
||||
@@ -654,7 +654,7 @@ u64 KScheduler::GetLastContextSwitchTicks() const {
|
||||
}
|
||||
|
||||
void KScheduler::RescheduleCurrentCore() {
|
||||
ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1);
|
||||
ASSERT(GetCurrentThread(system.Kernel()).GetDisableDispatchCount() == 1);
|
||||
|
||||
auto& phys_core = system.Kernel().PhysicalCore(core_id);
|
||||
if (phys_core.IsInterrupted()) {
|
||||
@@ -665,7 +665,7 @@ void KScheduler::RescheduleCurrentCore() {
|
||||
if (state.needs_scheduling.load()) {
|
||||
Schedule();
|
||||
} else {
|
||||
GetCurrentThread()->EnableDispatch();
|
||||
GetCurrentThread(system.Kernel()).EnableDispatch();
|
||||
guard.Unlock();
|
||||
}
|
||||
}
|
||||
@@ -718,13 +718,18 @@ void KScheduler::Reload(KThread* thread) {
|
||||
|
||||
void KScheduler::SwitchContextStep2() {
|
||||
// Load context of new thread
|
||||
Reload(GetCurrentThread());
|
||||
Reload(GetCurrentThreadPointer(system.Kernel()));
|
||||
|
||||
RescheduleCurrentCore();
|
||||
}
|
||||
|
||||
void KScheduler::Schedule() {
|
||||
ASSERT(GetCurrentThread(system.Kernel()).GetDisableDispatchCount() == 1);
|
||||
this->ScheduleImpl();
|
||||
}
|
||||
|
||||
void KScheduler::ScheduleImpl() {
|
||||
KThread* previous_thread = GetCurrentThread();
|
||||
KThread* previous_thread = GetCurrentThreadPointer(system.Kernel());
|
||||
KThread* next_thread = state.highest_priority_thread;
|
||||
|
||||
state.needs_scheduling.store(false);
|
||||
@@ -762,6 +767,7 @@ void KScheduler::ScheduleImpl() {
|
||||
old_context = &previous_thread->GetHostContext();
|
||||
|
||||
// Set the new thread.
|
||||
SetCurrentThread(system.Kernel(), next_thread);
|
||||
current_thread.store(next_thread);
|
||||
|
||||
guard.Unlock();
|
||||
@@ -805,6 +811,7 @@ void KScheduler::SwitchToCurrent() {
|
||||
}
|
||||
}
|
||||
auto thread = next_thread ? next_thread : idle_thread;
|
||||
SetCurrentThread(system.Kernel(), thread);
|
||||
Common::Fiber::YieldTo(switch_fiber, *thread->GetHostContext());
|
||||
} while (!is_switch_pending());
|
||||
}
|
||||
|
@@ -48,18 +48,13 @@ public:
|
||||
void Reload(KThread* thread);
|
||||
|
||||
/// Gets the current running thread
|
||||
[[nodiscard]] KThread* GetCurrentThread() const;
|
||||
[[nodiscard]] KThread* GetSchedulerCurrentThread() const;
|
||||
|
||||
/// Gets the idle thread
|
||||
[[nodiscard]] KThread* GetIdleThread() const {
|
||||
return idle_thread;
|
||||
}
|
||||
|
||||
/// Returns true if the scheduler is idle
|
||||
[[nodiscard]] bool IsIdle() const {
|
||||
return GetCurrentThread() == idle_thread;
|
||||
}
|
||||
|
||||
/// Gets the timestamp for the last context switch in ticks.
|
||||
[[nodiscard]] u64 GetLastContextSwitchTicks() const;
|
||||
|
||||
@@ -149,10 +144,7 @@ private:
|
||||
|
||||
void RotateScheduledQueue(s32 cpu_core_id, s32 priority);
|
||||
|
||||
void Schedule() {
|
||||
ASSERT(GetCurrentThread()->GetDisableDispatchCount() == 1);
|
||||
this->ScheduleImpl();
|
||||
}
|
||||
void Schedule();
|
||||
|
||||
/// Switches the CPU's active thread context to that of the specified thread
|
||||
void ScheduleImpl();
|
||||
|
@@ -382,7 +382,7 @@ void KThread::FinishTermination() {
|
||||
for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
||||
KThread* core_thread{};
|
||||
do {
|
||||
core_thread = kernel.Scheduler(i).GetCurrentThread();
|
||||
core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread();
|
||||
} while (core_thread == this);
|
||||
}
|
||||
}
|
||||
@@ -631,7 +631,7 @@ ResultCode KThread::SetCoreMask(s32 core_id_, u64 v_affinity_mask) {
|
||||
s32 thread_core;
|
||||
for (thread_core = 0; thread_core < static_cast<s32>(Core::Hardware::NUM_CPU_CORES);
|
||||
++thread_core) {
|
||||
if (kernel.Scheduler(thread_core).GetCurrentThread() == this) {
|
||||
if (kernel.Scheduler(thread_core).GetSchedulerCurrentThread() == this) {
|
||||
thread_is_current = true;
|
||||
break;
|
||||
}
|
||||
@@ -756,7 +756,7 @@ void KThread::WaitUntilSuspended() {
|
||||
for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
||||
KThread* core_thread{};
|
||||
do {
|
||||
core_thread = kernel.Scheduler(i).GetCurrentThread();
|
||||
core_thread = kernel.Scheduler(i).GetSchedulerCurrentThread();
|
||||
} while (core_thread == this);
|
||||
}
|
||||
}
|
||||
@@ -822,7 +822,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||
// Check if the thread is currently running.
|
||||
// If it is, we'll need to retry.
|
||||
for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
||||
if (kernel.Scheduler(i).GetCurrentThread() == this) {
|
||||
if (kernel.Scheduler(i).GetSchedulerCurrentThread() == this) {
|
||||
thread_is_current = true;
|
||||
break;
|
||||
}
|
||||
@@ -1175,6 +1175,10 @@ std::shared_ptr<Common::Fiber>& KThread::GetHostContext() {
|
||||
return host_context;
|
||||
}
|
||||
|
||||
void SetCurrentThread(KernelCore& kernel, KThread* thread) {
|
||||
kernel.SetCurrentEmuThread(thread);
|
||||
}
|
||||
|
||||
KThread* GetCurrentThreadPointer(KernelCore& kernel) {
|
||||
return kernel.GetCurrentEmuThread();
|
||||
}
|
||||
|
@@ -106,6 +106,7 @@ enum class StepState : u32 {
|
||||
StepPerformed, ///< Thread has stepped, waiting to be scheduled again
|
||||
};
|
||||
|
||||
void SetCurrentThread(KernelCore& kernel, KThread* thread);
|
||||
[[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel);
|
||||
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
|
||||
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
|
||||
|
@@ -331,6 +331,8 @@ struct KernelCore::Impl {
|
||||
return is_shutting_down.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
static inline thread_local KThread* current_thread{nullptr};
|
||||
|
||||
KThread* GetCurrentEmuThread() {
|
||||
// If we are shutting down the kernel, none of this is relevant anymore.
|
||||
if (IsShuttingDown()) {
|
||||
@@ -341,7 +343,12 @@ struct KernelCore::Impl {
|
||||
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
|
||||
return GetHostDummyThread();
|
||||
}
|
||||
return schedulers[thread_id]->GetCurrentThread();
|
||||
|
||||
return current_thread;
|
||||
}
|
||||
|
||||
void SetCurrentEmuThread(KThread* thread) {
|
||||
current_thread = thread;
|
||||
}
|
||||
|
||||
void DeriveInitialMemoryLayout() {
|
||||
@@ -1024,6 +1031,10 @@ KThread* KernelCore::GetCurrentEmuThread() const {
|
||||
return impl->GetCurrentEmuThread();
|
||||
}
|
||||
|
||||
void KernelCore::SetCurrentEmuThread(KThread* thread) {
|
||||
impl->SetCurrentEmuThread(thread);
|
||||
}
|
||||
|
||||
KMemoryManager& KernelCore::MemoryManager() {
|
||||
return *impl->memory_manager;
|
||||
}
|
||||
|
@@ -226,6 +226,9 @@ public:
|
||||
/// Gets the current host_thread/guest_thread pointer.
|
||||
KThread* GetCurrentEmuThread() const;
|
||||
|
||||
/// Sets the current guest_thread pointer.
|
||||
void SetCurrentEmuThread(KThread* thread);
|
||||
|
||||
/// Gets the current host_thread handle.
|
||||
u32 GetCurrentHostThreadID() const;
|
||||
|
||||
|
@@ -327,7 +327,6 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
|
||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
||||
|
||||
auto thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
{
|
||||
KScopedSchedulerLock lock(kernel);
|
||||
|
||||
@@ -337,7 +336,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||
session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming());
|
||||
}
|
||||
|
||||
return thread->GetWaitResult();
|
||||
return GetCurrentThread(kernel).GetWaitResult();
|
||||
}
|
||||
|
||||
static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
|
||||
@@ -624,7 +623,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
|
||||
|
||||
handle_debug_buffer(info1, info2);
|
||||
|
||||
auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
|
||||
auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
|
||||
const auto thread_processor_id = current_thread->GetActiveCore();
|
||||
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
|
||||
}
|
||||
@@ -884,7 +883,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle
|
||||
|
||||
const auto& core_timing = system.CoreTiming();
|
||||
const auto& scheduler = *system.Kernel().CurrentScheduler();
|
||||
const auto* const current_thread = scheduler.GetCurrentThread();
|
||||
const auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
|
||||
const bool same_thread = current_thread == thread.GetPointerUnsafe();
|
||||
|
||||
const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
|
||||
@@ -1103,7 +1102,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
|
||||
if (thread->GetRawState() != ThreadState::Runnable) {
|
||||
bool current = false;
|
||||
for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
|
||||
if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetCurrentThread()) {
|
||||
if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetSchedulerCurrentThread()) {
|
||||
current = true;
|
||||
break;
|
||||
}
|
||||
@@ -1851,7 +1850,7 @@ static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
|
||||
static void ExitThread(Core::System& system) {
|
||||
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
|
||||
|
||||
auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
|
||||
auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
|
||||
system.GlobalSchedulerContext().RemoveThread(current_thread);
|
||||
current_thread->Exit();
|
||||
system.Kernel().UnregisterInUseObject(current_thread);
|
||||
@@ -2993,7 +2992,7 @@ void Call(Core::System& system, u32 immediate) {
|
||||
auto& kernel = system.Kernel();
|
||||
kernel.EnterSVCProfile();
|
||||
|
||||
auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
|
||||
auto* thread = GetCurrentThreadPointer(kernel);
|
||||
thread->SetIsCallingSvc();
|
||||
|
||||
const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
|
||||
|
@@ -49,28 +49,42 @@ bool Controller_NPad::IsNpadIdValid(Core::HID::NpadIdType npad_id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle) {
|
||||
ResultCode Controller_NPad::IsDeviceHandleValid(
|
||||
const Core::HID::VibrationDeviceHandle& 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;
|
||||
const bool device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
|
||||
return npad_id && npad_type && device_index;
|
||||
|
||||
if (npad_type) {
|
||||
return VibrationInvalidStyleIndex;
|
||||
}
|
||||
if (npad_id) {
|
||||
return VibrationInvalidNpadId;
|
||||
}
|
||||
if (device_index) {
|
||||
return VibrationDeviceIndexOutOfRange;
|
||||
}
|
||||
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
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 device_index = device_handle.device_index < Core::HID::DeviceIndex::MaxDeviceIndex;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -705,6 +719,12 @@ Controller_NPad::NpadJoyHoldType Controller_NPad::GetHoldType() const {
|
||||
}
|
||||
|
||||
void Controller_NPad::SetNpadHandheldActivationMode(NpadHandheldActivationMode activation_mode) {
|
||||
if (activation_mode != NpadHandheldActivationMode::None &&
|
||||
activation_mode != NpadHandheldActivationMode::Single) {
|
||||
ASSERT_MSG(false, "Activation mode should be always None or Single");
|
||||
return;
|
||||
}
|
||||
|
||||
handheld_activation_mode = activation_mode;
|
||||
}
|
||||
|
||||
@@ -840,7 +860,7 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
|
||||
void Controller_NPad::VibrateController(
|
||||
const Core::HID::VibrationDeviceHandle& vibration_device_handle,
|
||||
const Core::HID::VibrationValue& vibration_value) {
|
||||
if (!IsDeviceHandleValid(vibration_device_handle)) {
|
||||
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -903,7 +923,7 @@ void Controller_NPad::VibrateControllers(
|
||||
|
||||
Core::HID::VibrationValue Controller_NPad::GetLastVibration(
|
||||
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
|
||||
if (!IsDeviceHandleValid(vibration_device_handle)) {
|
||||
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -914,7 +934,7 @@ Core::HID::VibrationValue Controller_NPad::GetLastVibration(
|
||||
|
||||
void Controller_NPad::InitializeVibrationDevice(
|
||||
const Core::HID::VibrationDeviceHandle& vibration_device_handle) {
|
||||
if (!IsDeviceHandleValid(vibration_device_handle)) {
|
||||
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -941,7 +961,7 @@ void Controller_NPad::SetPermitVibrationSession(bool permit_vibration_session) {
|
||||
|
||||
bool Controller_NPad::IsVibrationDeviceMounted(
|
||||
const Core::HID::VibrationDeviceHandle& vibration_device_handle) const {
|
||||
if (!IsDeviceHandleValid(vibration_device_handle)) {
|
||||
if (IsDeviceHandleValid(vibration_device_handle).IsError()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -197,7 +197,7 @@ public:
|
||||
Core::HID::NpadButton GetAndResetPressState();
|
||||
|
||||
static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
|
||||
static bool IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
|
||||
static ResultCode IsDeviceHandleValid(const Core::HID::VibrationDeviceHandle& device_handle);
|
||||
static ResultCode VerifyValidSixAxisSensorHandle(
|
||||
const Core::HID::SixAxisSensorHandle& device_handle);
|
||||
|
||||
|
@@ -9,6 +9,9 @@ namespace Service::HID {
|
||||
|
||||
constexpr ResultCode NpadInvalidHandle{ErrorModule::HID, 100};
|
||||
constexpr ResultCode NpadDeviceIndexOutOfRange{ErrorModule::HID, 107};
|
||||
constexpr ResultCode VibrationInvalidStyleIndex{ErrorModule::HID, 122};
|
||||
constexpr ResultCode VibrationInvalidNpadId{ErrorModule::HID, 123};
|
||||
constexpr ResultCode VibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
||||
constexpr ResultCode InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
||||
constexpr ResultCode NpadIsDualJoycon{ErrorModule::HID, 601};
|
||||
constexpr ResultCode NpadIsSameType{ErrorModule::HID, 602};
|
||||
|
@@ -778,7 +778,7 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
|
||||
|
||||
bool is_at_rest{};
|
||||
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
const auto result = controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
|
||||
controller.IsSixAxisSensorAtRest(parameters.sixaxis_handle, is_at_rest);
|
||||
|
||||
LOG_DEBUG(Service_HID,
|
||||
"called, npad_type={}, npad_id={}, device_index={}, applet_resource_user_id={}",
|
||||
@@ -786,7 +786,7 @@ void Hid::IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
|
||||
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_at_rest);
|
||||
}
|
||||
|
||||
@@ -803,8 +803,8 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c
|
||||
|
||||
bool is_firmware_available{};
|
||||
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
const auto result = controller.IsFirmwareUpdateAvailableForSixAxisSensor(
|
||||
parameters.sixaxis_handle, is_firmware_available);
|
||||
controller.IsFirmwareUpdateAvailableForSixAxisSensor(parameters.sixaxis_handle,
|
||||
is_firmware_available);
|
||||
|
||||
LOG_WARNING(
|
||||
Service_HID,
|
||||
@@ -813,7 +813,7 @@ void Hid::IsFirmwareUpdateAvailableForSixAxisSensor(Kernel::HLERequestContext& c
|
||||
parameters.sixaxis_handle.device_index, parameters.applet_resource_user_id);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(result);
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(is_firmware_available);
|
||||
}
|
||||
|
||||
@@ -1083,13 +1083,13 @@ void Hid::DisconnectNpad(Kernel::HLERequestContext& ctx) {
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
const auto result = controller.DisconnectNpad(parameters.npad_id);
|
||||
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(result);
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Hid::GetPlayerLedPattern(Kernel::HLERequestContext& ctx) {
|
||||
@@ -1165,15 +1165,14 @@ void Hid::SetNpadJoyAssignmentModeSingleByDefault(Kernel::HLERequestContext& ctx
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
const auto result =
|
||||
controller.SetNpadMode(parameters.npad_id, Controller_NPad::NpadJoyDeviceType::Left,
|
||||
Controller_NPad::NpadJoyAssignmentMode::Single);
|
||||
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(result);
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
|
||||
@@ -1189,15 +1188,15 @@ void Hid::SetNpadJoyAssignmentModeSingle(Kernel::HLERequestContext& ctx) {
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
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);
|
||||
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(result);
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
|
||||
@@ -1212,14 +1211,13 @@ void Hid::SetNpadJoyAssignmentModeDual(Kernel::HLERequestContext& ctx) {
|
||||
const auto parameters{rp.PopRaw<Parameters>()};
|
||||
|
||||
auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
const auto result = controller.SetNpadMode(parameters.npad_id, {},
|
||||
Controller_NPad::NpadJoyAssignmentMode::Dual);
|
||||
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(result);
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Hid::MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
|
||||
@@ -1412,8 +1410,11 @@ void Hid::ClearNpadCaptureButtonAssignment(Kernel::HLERequestContext& ctx) {
|
||||
void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto vibration_device_handle{rp.PopRaw<Core::HID::VibrationDeviceHandle>()};
|
||||
const auto& controller =
|
||||
GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
|
||||
|
||||
Core::HID::VibrationDeviceInfo vibration_device_info;
|
||||
bool check_device_index = false;
|
||||
|
||||
switch (vibration_device_handle.npad_type) {
|
||||
case Core::HID::NpadStyleIndex::ProController:
|
||||
@@ -1421,34 +1422,46 @@ void Hid::GetVibrationDeviceInfo(Kernel::HLERequestContext& ctx) {
|
||||
case Core::HID::NpadStyleIndex::JoyconDual:
|
||||
case Core::HID::NpadStyleIndex::JoyconLeft:
|
||||
case Core::HID::NpadStyleIndex::JoyconRight:
|
||||
default:
|
||||
vibration_device_info.type = Core::HID::VibrationDeviceType::LinearResonantActuator;
|
||||
check_device_index = true;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::GameCube:
|
||||
vibration_device_info.type = Core::HID::VibrationDeviceType::GcErm;
|
||||
break;
|
||||
case Core::HID::NpadStyleIndex::Pokeball:
|
||||
case Core::HID::NpadStyleIndex::N64:
|
||||
vibration_device_info.type = Core::HID::VibrationDeviceType::N64;
|
||||
break;
|
||||
default:
|
||||
vibration_device_info.type = Core::HID::VibrationDeviceType::Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (vibration_device_handle.device_index) {
|
||||
case Core::HID::DeviceIndex::Left:
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
|
||||
break;
|
||||
case Core::HID::DeviceIndex::Right:
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
|
||||
break;
|
||||
case Core::HID::DeviceIndex::None:
|
||||
default:
|
||||
ASSERT_MSG(false, "DeviceIndex should never be None!");
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
|
||||
break;
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::None;
|
||||
if (check_device_index) {
|
||||
switch (vibration_device_handle.device_index) {
|
||||
case Core::HID::DeviceIndex::Left:
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::Left;
|
||||
break;
|
||||
case Core::HID::DeviceIndex::Right:
|
||||
vibration_device_info.position = Core::HID::VibrationDevicePosition::Right;
|
||||
break;
|
||||
case Core::HID::DeviceIndex::None:
|
||||
default:
|
||||
ASSERT_MSG(false, "DeviceIndex should never be None!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_HID, "called, vibration_device_type={}, vibration_device_position={}",
|
||||
vibration_device_info.type, vibration_device_info.position);
|
||||
|
||||
const auto result = controller.IsDeviceHandleValid(vibration_device_handle);
|
||||
if (result.IsError()) {
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(result);
|
||||
return;
|
||||
}
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(vibration_device_info);
|
||||
|
Reference in New Issue
Block a user