summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/svc/svc_ipc.cpp37
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp41
-rw-r--r--src/core/hle/service/nfc/common/device.cpp32
4 files changed, 73 insertions, 47 deletions
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index dd662b3f8..d178c2453 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -338,6 +338,15 @@ public:
return m_parent != nullptr;
}
+ std::span<KSynchronizationObject*> GetSynchronizationObjectBuffer() {
+ return m_sync_object_buffer.sync_objects;
+ }
+
+ std::span<Handle> GetHandleBuffer() {
+ return {m_sync_object_buffer.handles.data() + Svc::ArgumentHandleCountMax,
+ Svc::ArgumentHandleCountMax};
+ }
+
u16 GetUserDisableCount() const;
void SetInterruptFlag();
void ClearInterruptFlag();
@@ -855,6 +864,7 @@ private:
u32* m_light_ipc_data{};
KProcessAddress m_tls_address{};
KLightLock m_activity_pause_lock;
+ SyncObjectBuffer m_sync_object_buffer{};
s64 m_schedule_count{};
s64 m_last_scheduled_tick{};
std::array<QueueEntry, Core::Hardware::NUM_CPU_CORES> m_per_core_priority_queue_entry{};
diff --git a/src/core/hle/kernel/svc/svc_ipc.cpp b/src/core/hle/kernel/svc/svc_ipc.cpp
index 60247df2e..bb94f6934 100644
--- a/src/core/hle/kernel/svc/svc_ipc.cpp
+++ b/src/core/hle/kernel/svc/svc_ipc.cpp
@@ -38,22 +38,31 @@ Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_ha
Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) {
+ // Ensure number of handles is valid.
+ R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+
+ // Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
-
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
- R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
- handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
- ResultInvalidPointer);
-
- std::array<Handle, Svc::ArgumentHandleCountMax> handles;
- GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
-
- // Convert handle list to object table.
- std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
- R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),
- num_handles),
- ResultInvalidHandle);
+ auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
+ auto handles = GetCurrentThread(kernel).GetHandleBuffer();
+
+ // Copy user handles.
+ if (num_handles > 0) {
+ // Ensure we can try to get the handles.
+ R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
+ handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
+ ResultInvalidPointer);
+
+ // Get the handles.
+ GetCurrentMemory(kernel).ReadBlock(handles_addr, handles.data(),
+ sizeof(Handle) * num_handles);
+
+ // Convert the handles to objects.
+ R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
+ objs.data(), handles.data(), num_handles),
+ ResultInvalidHandle);
+ }
// Ensure handles are closed when we're done.
SCOPE_EXIT({
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 53df5bcd8..f02d03f30 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -47,21 +47,35 @@ Result ResetSignal(Core::System& system, Handle handle) {
R_THROW(ResultInvalidHandle);
}
-static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
- int32_t num_handles, int64_t timeout_ns) {
+/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
+Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
+ int32_t num_handles, int64_t timeout_ns) {
+ LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
+ num_handles, timeout_ns);
+
// Ensure number of handles is valid.
R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
// Get the synchronization context.
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> objs;
+ auto objs = GetCurrentThread(kernel).GetSynchronizationObjectBuffer();
+ auto handles = GetCurrentThread(kernel).GetHandleBuffer();
// Copy user handles.
if (num_handles > 0) {
+ // Ensure we can try to get the handles.
+ R_UNLESS(GetCurrentMemory(kernel).IsValidVirtualAddressRange(
+ user_handles, static_cast<u64>(sizeof(Handle) * num_handles)),
+ ResultInvalidPointer);
+
+ // Get the handles.
+ GetCurrentMemory(kernel).ReadBlock(user_handles, handles.data(),
+ sizeof(Handle) * num_handles);
+
// Convert the handles to objects.
- R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
- num_handles),
+ R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(
+ objs.data(), handles.data(), num_handles),
ResultInvalidHandle);
}
@@ -80,23 +94,6 @@ static Result WaitSynchronization(Core::System& system, int32_t* out_index, cons
R_RETURN(res);
}
-/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_handles,
- int32_t num_handles, int64_t timeout_ns) {
- LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
- num_handles, timeout_ns);
-
- // Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
- std::array<Handle, Svc::ArgumentHandleCountMax> handles;
- if (num_handles > 0) {
- GetCurrentMemory(system.Kernel())
- .ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
- }
-
- R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
-}
-
/// Resumes a thread waiting on WaitSynchronization
Result CancelSynchronization(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);
diff --git a/src/core/hle/service/nfc/common/device.cpp b/src/core/hle/service/nfc/common/device.cpp
index 5bf289818..2d633b03f 100644
--- a/src/core/hle/service/nfc/common/device.cpp
+++ b/src/core/hle/service/nfc/common/device.cpp
@@ -66,10 +66,6 @@ NfcDevice::~NfcDevice() {
};
void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
- if (!is_initalized) {
- return;
- }
-
if (type == Core::HID::ControllerTriggerType::Connected) {
Initialize();
availability_change_event->Signal();
@@ -77,12 +73,12 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
}
if (type == Core::HID::ControllerTriggerType::Disconnected) {
- device_state = DeviceState::Unavailable;
+ Finalize();
availability_change_event->Signal();
return;
}
- if (type != Core::HID::ControllerTriggerType::Nfc) {
+ if (!is_initalized) {
return;
}
@@ -90,6 +86,17 @@ void NfcDevice::NpadUpdate(Core::HID::ControllerTriggerType type) {
return;
}
+ // Ensure nfc mode is always active
+ if (npad_device->GetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex) ==
+ Common::Input::PollingMode::Active) {
+ npad_device->SetPollingMode(Core::HID::EmulatedDeviceIndex::RightIndex,
+ Common::Input::PollingMode::NFC);
+ }
+
+ if (type != Core::HID::ControllerTriggerType::Nfc) {
+ return;
+ }
+
const auto nfc_status = npad_device->GetNfc();
switch (nfc_status.state) {
case Common::Input::NfcState::NewAmiibo:
@@ -207,11 +214,14 @@ void NfcDevice::Initialize() {
}
void NfcDevice::Finalize() {
- if (device_state == DeviceState::TagMounted) {
- Unmount();
- }
- if (device_state == DeviceState::SearchingForTag || device_state == DeviceState::TagRemoved) {
- StopDetection();
+ if (npad_device->IsConnected()) {
+ if (device_state == DeviceState::TagMounted) {
+ Unmount();
+ }
+ if (device_state == DeviceState::SearchingForTag ||
+ device_state == DeviceState::TagRemoved) {
+ StopDetection();
+ }
}
if (device_state != DeviceState::Unavailable) {