mirror of
https://git.citron-emu.org/citron/emulator
synced 2025-12-21 11:33:35 +00:00
Merge branch 'tma-add-new-functions-services' into 'master'
core/hle: Implement TMA (Target Manager Agent) service See merge request citron/rewrite!28
This commit is contained in:
@@ -134,6 +134,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Service, SSL) \
|
||||
SUB(Service, TCAP) \
|
||||
SUB(Service, Time) \
|
||||
SUB(Service, TMA) \
|
||||
SUB(Service, USB) \
|
||||
SUB(Service, VI) \
|
||||
SUB(Service, WLAN) \
|
||||
|
||||
@@ -102,6 +102,7 @@ enum class Class : u8 {
|
||||
Service_SSL, ///< The SSL service
|
||||
Service_TCAP, ///< The TCAP service.
|
||||
Service_Time, ///< The time service
|
||||
Service_TMA, ///< The TMA (Target Manager Agent) service
|
||||
Service_USB, ///< The USB (Universal Serial Bus) service
|
||||
Service_VI, ///< The VI (Video interface) service
|
||||
Service_WLAN, ///< The WLAN (Wireless local area network) service
|
||||
|
||||
@@ -1102,6 +1102,16 @@ add_library(core STATIC
|
||||
hle/service/ssl/ssl.h
|
||||
hle/service/ssl/ssl_backend.h
|
||||
hle/service/ssl/ssl_types.h
|
||||
hle/service/tma/file_io.cpp
|
||||
hle/service/tma/file_io.h
|
||||
hle/service/tma/htc.cpp
|
||||
hle/service/tma/htc.h
|
||||
hle/service/tma/htc_tenv.cpp
|
||||
hle/service/tma/htc_tenv.h
|
||||
hle/service/tma/htcs.cpp
|
||||
hle/service/tma/htcs.h
|
||||
hle/service/tma/tma.cpp
|
||||
hle/service/tma/tma.h
|
||||
hle/service/usb/usb.cpp
|
||||
hle/service/usb/usb.h
|
||||
hle/service/vi/application_display_service.cpp
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/services.h"
|
||||
@@ -59,6 +60,7 @@
|
||||
#include "core/hle/service/sockets/sockets.h"
|
||||
#include "core/hle/service/spl/spl_module.h"
|
||||
#include "core/hle/service/ssl/ssl.h"
|
||||
#include "core/hle/service/tma/tma.h"
|
||||
#include "core/hle/service/usb/usb.h"
|
||||
#include "core/hle/service/vi/vi.h"
|
||||
|
||||
@@ -127,6 +129,7 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
|
||||
kernel.RunOnGuestCoreProcess("ro", [&] { RO::LoopProcess(system); });
|
||||
kernel.RunOnGuestCoreProcess("spl", [&] { SPL::LoopProcess(system); });
|
||||
kernel.RunOnGuestCoreProcess("ssl", [&] { SSL::LoopProcess(system); });
|
||||
kernel.RunOnGuestCoreProcess("tma", [&] { TMA::LoopProcess(system); });
|
||||
kernel.RunOnGuestCoreProcess("usb", [&] { USB::LoopProcess(system); });
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
271
src/core/hle/service/tma/file_io.cpp
Normal file
271
src/core/hle/service/tma/file_io.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/tma/file_io.h"
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
IFileAccessor::IFileAccessor(Core::System& system_) : ServiceFramework{system_, "IFileAccessor"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IFileAccessor::ReadFile>, "ReadFile"},
|
||||
{1, D<&IFileAccessor::WriteFile>, "WriteFile"},
|
||||
{2, D<&IFileAccessor::GetFileSize>, "GetFileSize"},
|
||||
{3, D<&IFileAccessor::SetFileSize>, "SetFileSize"},
|
||||
{4, D<&IFileAccessor::FlushFile>, "FlushFile"},
|
||||
{5, D<&IFileAccessor::SetPriorityForFile>, "SetPriorityForFile"},
|
||||
{6, D<&IFileAccessor::GetPriorityForFile>, "GetPriorityForFile"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IFileAccessor::~IFileAccessor() = default;
|
||||
|
||||
Result IFileAccessor::ReadFile(u32 read_option, Out<s64> out_bytes_read, s64 offset,
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, read_option={}, offset={}", read_option, offset);
|
||||
|
||||
// No actual file data to read
|
||||
*out_bytes_read = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::WriteFile(u32 write_option, s64 offset, InBuffer<BufferAttr_HipcMapAlias> buffer) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, write_option={}, offset={}, size={}",
|
||||
write_option, offset, buffer.size());
|
||||
|
||||
// Update file size if writing beyond current size
|
||||
if (offset + static_cast<s64>(buffer.size()) > file_size) {
|
||||
file_size = offset + static_cast<s64>(buffer.size());
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::GetFileSize(Out<s64> out_file_size) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
*out_file_size = file_size;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::SetFileSize(s64 file_size_new) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, file_size={}", file_size_new);
|
||||
|
||||
file_size = file_size_new;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::FlushFile() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::SetPriorityForFile(s32 priority_new) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, priority={}", priority_new);
|
||||
|
||||
priority = priority_new;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileAccessor::GetPriorityForFile(Out<s32> out_priority) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
*out_priority = priority;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
IDirectoryAccessor::IDirectoryAccessor(Core::System& system_) : ServiceFramework{system_, "IDirectoryAccessor"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IDirectoryAccessor::GetEntryCount>, "GetEntryCount"},
|
||||
{1, D<&IDirectoryAccessor::ReadDirectory>, "ReadDirectory"},
|
||||
{2, D<&IDirectoryAccessor::SetPriorityForDirectory>, "SetPriorityForDirectory"},
|
||||
{3, D<&IDirectoryAccessor::GetPriorityForDirectory>, "GetPriorityForDirectory"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IDirectoryAccessor::~IDirectoryAccessor() = default;
|
||||
|
||||
Result IDirectoryAccessor::GetEntryCount(Out<s64> out_entry_count) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return 0 entries
|
||||
*out_entry_count = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDirectoryAccessor::ReadDirectory(Out<s64> out_entries_read, OutBuffer<BufferAttr_HipcMapAlias> out_entry_buffer) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// No entries to read
|
||||
*out_entries_read = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDirectoryAccessor::SetPriorityForDirectory(s32 priority_new) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, priority={}", priority_new);
|
||||
|
||||
priority = priority_new;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDirectoryAccessor::GetPriorityForDirectory(Out<s32> out_priority) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
*out_priority = priority;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
IFileManager::IFileManager(Core::System& system_) : ServiceFramework{system_, "file_io"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IFileManager::OpenFile>, "OpenFile"},
|
||||
{1, D<&IFileManager::FileExists>, "FileExists"},
|
||||
{2, D<&IFileManager::DeleteFile>, "DeleteFile"},
|
||||
{3, D<&IFileManager::RenameFile>, "RenameFile"},
|
||||
{4, D<&IFileManager::GetIOType>, "GetIOType"},
|
||||
{5, D<&IFileManager::OpenDirectory>, "OpenDirectory"},
|
||||
{6, D<&IFileManager::DirectoryExists>, "DirectoryExists"},
|
||||
{7, D<&IFileManager::CreateDirectory>, "CreateDirectory"},
|
||||
{8, D<&IFileManager::DeleteDirectory>, "DeleteDirectory"},
|
||||
{9, D<&IFileManager::RenameDirectory>, "RenameDirectory"},
|
||||
{10, D<&IFileManager::CreateFile>, "CreateFile"},
|
||||
{11, D<&IFileManager::GetFileTimeStamp>, "GetFileTimeStamp"},
|
||||
{12, D<&IFileManager::GetCaseSensitivePath>, "GetCaseSensitivePath"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IFileManager::~IFileManager() = default;
|
||||
|
||||
Result IFileManager::OpenFile(OutInterface<IFileAccessor> out_file_accessor,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path, u32 open_mode) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, open_mode={}", open_mode);
|
||||
|
||||
*out_file_accessor = std::make_shared<IFileAccessor>(system);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::FileExists(Out<bool> out_exists, InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// No files exist on host
|
||||
*out_exists = false;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::DeleteFile(InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::RenameFile(InBuffer<BufferAttr_HipcMapAlias> src_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> dst_path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::GetIOType(Out<s32> out_entry_type, InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return 0 (does not exist)
|
||||
*out_entry_type = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::OpenDirectory(OutInterface<IDirectoryAccessor> out_directory_accessor,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path, u32 open_mode) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, open_mode={}", open_mode);
|
||||
|
||||
*out_directory_accessor = std::make_shared<IDirectoryAccessor>(system);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::DirectoryExists(Out<bool> out_exists, InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// No directories exist on host
|
||||
*out_exists = false;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::CreateDirectory(InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::DeleteDirectory(InBuffer<BufferAttr_HipcMapAlias> path, bool is_recursive) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, is_recursive={}", is_recursive);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::RenameDirectory(InBuffer<BufferAttr_HipcMapAlias> src_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> dst_path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::CreateFile(InBuffer<BufferAttr_HipcMapAlias> path, s64 size) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, size={}", size);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::GetFileTimeStamp(Out<u64> out_created_time, Out<u64> out_accessed_time,
|
||||
Out<u64> out_modified_time, InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return 0 timestamps
|
||||
*out_created_time = 0;
|
||||
*out_accessed_time = 0;
|
||||
*out_modified_time = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IFileManager::GetCaseSensitivePath(OutBuffer<BufferAttr_HipcMapAlias> out_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return the input path as-is
|
||||
size_t copy_size = std::min(out_path.size(), path.size());
|
||||
std::memcpy(out_path.data(), path.data(), copy_size);
|
||||
|
||||
// Null terminate if there's space
|
||||
if (copy_size < out_path.size()) {
|
||||
out_path[copy_size] = 0;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::TMA
|
||||
71
src/core/hle/service/tma/file_io.h
Normal file
71
src/core/hle/service/tma/file_io.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
class IFileAccessor final : public ServiceFramework<IFileAccessor> {
|
||||
public:
|
||||
explicit IFileAccessor(Core::System& system_);
|
||||
~IFileAccessor() override;
|
||||
|
||||
private:
|
||||
Result ReadFile(u32 read_option, Out<s64> out_bytes_read, s64 offset,
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer);
|
||||
Result WriteFile(u32 write_option, s64 offset, InBuffer<BufferAttr_HipcMapAlias> buffer);
|
||||
Result GetFileSize(Out<s64> out_file_size);
|
||||
Result SetFileSize(s64 file_size);
|
||||
Result FlushFile();
|
||||
Result SetPriorityForFile(s32 priority);
|
||||
Result GetPriorityForFile(Out<s32> out_priority);
|
||||
|
||||
s64 file_size{};
|
||||
s32 priority{};
|
||||
};
|
||||
|
||||
class IDirectoryAccessor final : public ServiceFramework<IDirectoryAccessor> {
|
||||
public:
|
||||
explicit IDirectoryAccessor(Core::System& system_);
|
||||
~IDirectoryAccessor() override;
|
||||
|
||||
private:
|
||||
Result GetEntryCount(Out<s64> out_entry_count);
|
||||
Result ReadDirectory(Out<s64> out_entries_read, OutBuffer<BufferAttr_HipcMapAlias> out_entry_buffer);
|
||||
Result SetPriorityForDirectory(s32 priority);
|
||||
Result GetPriorityForDirectory(Out<s32> out_priority);
|
||||
|
||||
s32 priority{};
|
||||
};
|
||||
|
||||
class IFileManager final : public ServiceFramework<IFileManager> {
|
||||
public:
|
||||
explicit IFileManager(Core::System& system_);
|
||||
~IFileManager() override;
|
||||
|
||||
private:
|
||||
Result OpenFile(OutInterface<IFileAccessor> out_file_accessor,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path, u32 open_mode);
|
||||
Result FileExists(Out<bool> out_exists, InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result DeleteFile(InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result RenameFile(InBuffer<BufferAttr_HipcMapAlias> src_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> dst_path);
|
||||
Result GetIOType(Out<s32> out_entry_type, InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result OpenDirectory(OutInterface<IDirectoryAccessor> out_directory_accessor,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path, u32 open_mode);
|
||||
Result DirectoryExists(Out<bool> out_exists, InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result CreateDirectory(InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result DeleteDirectory(InBuffer<BufferAttr_HipcMapAlias> path, bool is_recursive);
|
||||
Result RenameDirectory(InBuffer<BufferAttr_HipcMapAlias> src_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> dst_path);
|
||||
Result CreateFile(InBuffer<BufferAttr_HipcMapAlias> path, s64 size);
|
||||
Result GetFileTimeStamp(Out<u64> out_created_time, Out<u64> out_accessed_time,
|
||||
Out<u64> out_modified_time, InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
Result GetCaseSensitivePath(OutBuffer<BufferAttr_HipcMapAlias> out_path,
|
||||
InBuffer<BufferAttr_HipcMapAlias> path);
|
||||
};
|
||||
|
||||
} // namespace Service::TMA
|
||||
206
src/core/hle/service/tma/htc.cpp
Normal file
206
src/core/hle/service/tma/htc.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/tma/htc.h"
|
||||
|
||||
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
|
||||
#undef CreateEvent
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
IHtcManager::IHtcManager(Core::System& system_)
|
||||
: ServiceFramework{system_, "htc"}, service_context{system_, "htc"} {
|
||||
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IHtcManager::GetEnvironmentVariable>, "GetEnvironmentVariable"},
|
||||
{1, D<&IHtcManager::GetEnvironmentVariableLength>, "GetEnvironmentVariableLength"},
|
||||
{2, D<&IHtcManager::BindHostConnectionEvent>, "BindHostConnectionEvent"},
|
||||
{3, D<&IHtcManager::BindHostDisconnectionEvent>, "BindHostDisconnectionEvent"},
|
||||
{4, D<&IHtcManager::BindHostConnectionEventForSystem>, "BindHostConnectionEventForSystem"},
|
||||
{5, D<&IHtcManager::BindHostDisconnectionEventForSystem>, "BindHostDisconnectionEventForSystem"},
|
||||
{6, D<&IHtcManager::GetBridgeIpAddress>, "GetBridgeIpAddress"},
|
||||
{7, D<&IHtcManager::GetBridgePort>, "GetBridgePort"},
|
||||
{8, D<&IHtcManager::SetCradleAttached>, "SetCradleAttached"},
|
||||
{9, D<&IHtcManager::GetBridgeSubnetMask>, "GetBridgeSubnetMask"},
|
||||
{10, D<&IHtcManager::GetBridgeMacAddress>, "GetBridgeMacAddress"},
|
||||
{11, D<&IHtcManager::GetWorkingDirectoryPath>, "GetWorkingDirectoryPath"},
|
||||
{12, D<&IHtcManager::GetWorkingDirectoryPathSize>, "GetWorkingDirectoryPathSize"},
|
||||
{13, D<&IHtcManager::RunOnHostStart>, "RunOnHostStart"},
|
||||
{14, D<&IHtcManager::RunOnHostResults>, "RunOnHostResults"},
|
||||
{21, D<&IHtcManager::BeginUpdateBridge>, "BeginUpdateBridge"},
|
||||
{22, D<&IHtcManager::ContinueUpdateBridge>, "ContinueUpdateBridge"},
|
||||
{23, D<&IHtcManager::EndUpdateBridge>, "EndUpdateBridge"},
|
||||
{24, D<&IHtcManager::GetBridgeType>, "GetBridgeType"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Create events for host connection management
|
||||
connection_event = service_context.CreateEvent("htc:connection");
|
||||
disconnection_event = service_context.CreateEvent("htc:disconnection");
|
||||
system_connection_event = service_context.CreateEvent("htc:system_connection");
|
||||
system_disconnection_event = service_context.CreateEvent("htc:system_disconnection");
|
||||
}
|
||||
|
||||
IHtcManager::~IHtcManager() {
|
||||
service_context.CloseEvent(connection_event);
|
||||
service_context.CloseEvent(disconnection_event);
|
||||
service_context.CloseEvent(system_connection_event);
|
||||
service_context.CloseEvent(system_disconnection_event);
|
||||
}
|
||||
|
||||
Result IHtcManager::GetEnvironmentVariable(OutBuffer<BufferAttr_HipcMapAlias> out_value,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Clear output buffer as no environment variables are set
|
||||
std::memset(out_value.data(), 0, out_value.size());
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetEnvironmentVariableLength(Out<u32> out_length,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return 0 length for all environment variables
|
||||
*out_length = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::BindHostConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_TMA, "called");
|
||||
|
||||
*out_event = &connection_event->GetReadableEvent();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::BindHostDisconnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_TMA, "called");
|
||||
|
||||
*out_event = &disconnection_event->GetReadableEvent();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::BindHostConnectionEventForSystem(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_TMA, "called");
|
||||
|
||||
*out_event = &system_connection_event->GetReadableEvent();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::BindHostDisconnectionEventForSystem(OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||
LOG_DEBUG(Service_TMA, "called");
|
||||
|
||||
*out_event = &system_disconnection_event->GetReadableEvent();
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetBridgeIpAddress(Out<u32> out_ip_address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return localhost IP address as default
|
||||
*out_ip_address = 0x7F000001; // 127.0.0.1
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetBridgePort(Out<u16> out_port) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return default debug port
|
||||
*out_port = 19999;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::SetCradleAttached(bool is_attached) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, is_attached={}", is_attached);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetBridgeSubnetMask(Out<u32> out_subnet_mask) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return default subnet mask
|
||||
*out_subnet_mask = 0xFF000000; // 255.0.0.0
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetBridgeMacAddress(OutBuffer<BufferAttr_HipcMapAlias> out_mac_address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Clear MAC address buffer
|
||||
std::memset(out_mac_address.data(), 0, std::min<size_t>(out_mac_address.size(), 6));
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetWorkingDirectoryPath(OutBuffer<BufferAttr_HipcMapAlias> out_path) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return empty path
|
||||
if (out_path.size() > 0) {
|
||||
out_path[0] = 0;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetWorkingDirectoryPathSize(Out<u32> out_size) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
*out_size = 1; // Just null terminator
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::RunOnHostStart() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::RunOnHostResults() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::BeginUpdateBridge() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::ContinueUpdateBridge() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::EndUpdateBridge() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcManager::GetBridgeType(Out<u32> out_bridge_type) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
*out_bridge_type = 0; // Default bridge type
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::TMA
|
||||
52
src/core/hle/service/tma/htc.h
Normal file
52
src/core/hle/service/tma/htc.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
class KReadableEvent;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
class IHtcManager final : public ServiceFramework<IHtcManager> {
|
||||
public:
|
||||
explicit IHtcManager(Core::System& system_);
|
||||
~IHtcManager() override;
|
||||
|
||||
private:
|
||||
Result GetEnvironmentVariable(OutBuffer<BufferAttr_HipcMapAlias> out_value,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name);
|
||||
Result GetEnvironmentVariableLength(Out<u32> out_length,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name);
|
||||
Result BindHostConnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result BindHostDisconnectionEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result BindHostConnectionEventForSystem(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result BindHostDisconnectionEventForSystem(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||
Result GetBridgeIpAddress(Out<u32> out_ip_address);
|
||||
Result GetBridgePort(Out<u16> out_port);
|
||||
Result SetCradleAttached(bool is_attached);
|
||||
Result GetBridgeSubnetMask(Out<u32> out_subnet_mask);
|
||||
Result GetBridgeMacAddress(OutBuffer<BufferAttr_HipcMapAlias> out_mac_address);
|
||||
Result GetWorkingDirectoryPath(OutBuffer<BufferAttr_HipcMapAlias> out_path);
|
||||
Result GetWorkingDirectoryPathSize(Out<u32> out_size);
|
||||
Result RunOnHostStart();
|
||||
Result RunOnHostResults();
|
||||
Result BeginUpdateBridge();
|
||||
Result ContinueUpdateBridge();
|
||||
Result EndUpdateBridge();
|
||||
Result GetBridgeType(Out<u32> out_bridge_type);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* connection_event{};
|
||||
Kernel::KEvent* disconnection_event{};
|
||||
Kernel::KEvent* system_connection_event{};
|
||||
Kernel::KEvent* system_disconnection_event{};
|
||||
};
|
||||
|
||||
} // namespace Service::TMA
|
||||
81
src/core/hle/service/tma/htc_tenv.cpp
Normal file
81
src/core/hle/service/tma/htc_tenv.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/tma/htc_tenv.h"
|
||||
|
||||
// This is defined by synchapi.h and conflicts with ServiceContext::CreateEvent
|
||||
#undef CreateEvent
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
IService::IService(Core::System& system_)
|
||||
: ServiceFramework{system_, "IService"}, service_context{system_, "htc:tenv:IService"} {
|
||||
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IService::GetVariable>, "GetVariable"},
|
||||
{1, D<&IService::GetVariableLength>, "GetVariableLength"},
|
||||
{2, D<&IService::WaitUntilVariableAvailable>, "WaitUntilVariableAvailable"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
|
||||
// Create event for variable availability notification
|
||||
variable_available_event = service_context.CreateEvent("htc:tenv:variable_available");
|
||||
}
|
||||
|
||||
IService::~IService() {
|
||||
service_context.CloseEvent(variable_available_event);
|
||||
}
|
||||
|
||||
Result IService::GetVariable(OutBuffer<BufferAttr_HipcMapAlias> out_value,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Clear output buffer as no variables are set
|
||||
std::memset(out_value.data(), 0, out_value.size());
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IService::GetVariableLength(Out<u32> out_length,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Return 0 length for all variables
|
||||
*out_length = 0;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IService::WaitUntilVariableAvailable(InBuffer<BufferAttr_HipcMapAlias> name) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
|
||||
// Variables are never available, so this would block indefinitely
|
||||
// For now, just return success
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
IServiceManager::IServiceManager(Core::System& system_) : ServiceFramework{system_, "htc:tenv"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IServiceManager::GetServiceInterface>, "GetServiceInterface"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IServiceManager::~IServiceManager() = default;
|
||||
|
||||
Result IServiceManager::GetServiceInterface(OutInterface<IService> out_service) {
|
||||
LOG_DEBUG(Service_TMA, "called");
|
||||
|
||||
*out_service = std::make_shared<IService>(system);
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::TMA
|
||||
42
src/core/hle/service/tma/htc_tenv.h
Normal file
42
src/core/hle/service/tma/htc_tenv.h
Normal file
@@ -0,0 +1,42 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Kernel {
|
||||
class KEvent;
|
||||
class KReadableEvent;
|
||||
} // namespace Kernel
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
class IService final : public ServiceFramework<IService> {
|
||||
public:
|
||||
explicit IService(Core::System& system_);
|
||||
~IService() override;
|
||||
|
||||
private:
|
||||
Result GetVariable(OutBuffer<BufferAttr_HipcMapAlias> out_value,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name);
|
||||
Result GetVariableLength(Out<u32> out_length,
|
||||
InBuffer<BufferAttr_HipcMapAlias> name);
|
||||
Result WaitUntilVariableAvailable(InBuffer<BufferAttr_HipcMapAlias> name);
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* variable_available_event{};
|
||||
};
|
||||
|
||||
class IServiceManager final : public ServiceFramework<IServiceManager> {
|
||||
public:
|
||||
explicit IServiceManager(Core::System& system_);
|
||||
~IServiceManager() override;
|
||||
|
||||
private:
|
||||
Result GetServiceInterface(OutInterface<IService> out_service);
|
||||
};
|
||||
|
||||
} // namespace Service::TMA
|
||||
200
src/core/hle/service/tma/htcs.cpp
Normal file
200
src/core/hle/service/tma/htcs.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/tma/htcs.h"
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
ISocket::ISocket(Core::System& system_) : ServiceFramework{system_, "ISocket"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&ISocket::Close>, "Close"},
|
||||
{1, D<&ISocket::Connect>, "Connect"},
|
||||
{2, D<&ISocket::Bind>, "Bind"},
|
||||
{3, D<&ISocket::Listen>, "Listen"},
|
||||
{4, D<&ISocket::Accept>, "Accept"},
|
||||
{5, D<&ISocket::Recv>, "Recv"},
|
||||
{6, D<&ISocket::Send>, "Send"},
|
||||
{7, D<&ISocket::Shutdown>, "Shutdown"},
|
||||
{8, D<&ISocket::Fcntl>, "Fcntl"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
ISocket::~ISocket() = default;
|
||||
|
||||
Result ISocket::Close() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Connect(InBuffer<BufferAttr_HipcMapAlias> address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Bind(InBuffer<BufferAttr_HipcMapAlias> address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Listen(s32 backlog) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, backlog={}", backlog);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Accept(OutInterface<ISocket> out_socket) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
*out_socket = std::make_shared<ISocket>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Recv(Out<s32> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, s32 flags) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, flags={}", flags);
|
||||
*out_size = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Send(Out<s32> out_size, InBuffer<BufferAttr_HipcMapAlias> buffer, s32 flags) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, flags={}", flags);
|
||||
*out_size = static_cast<s32>(buffer.size());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Shutdown(s32 how) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, how={}", how);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISocket::Fcntl(Out<s32> out_result, s32 cmd, s32 arg) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, cmd={}, arg={}", cmd, arg);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
IHtcsManager::IHtcsManager(Core::System& system_) : ServiceFramework{system_, "htcs"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, D<&IHtcsManager::Socket>, "Socket"},
|
||||
{1, D<&IHtcsManager::Close>, "Close"},
|
||||
{2, D<&IHtcsManager::Connect>, "Connect"},
|
||||
{3, D<&IHtcsManager::Bind>, "Bind"},
|
||||
{4, D<&IHtcsManager::Listen>, "Listen"},
|
||||
{5, D<&IHtcsManager::Accept>, "Accept"},
|
||||
{6, D<&IHtcsManager::Recv>, "Recv"},
|
||||
{7, D<&IHtcsManager::Send>, "Send"},
|
||||
{8, D<&IHtcsManager::Shutdown>, "Shutdown"},
|
||||
{9, D<&IHtcsManager::Fcntl>, "Fcntl"},
|
||||
{10, D<&IHtcsManager::GetPeerNameAny>, "GetPeerNameAny"},
|
||||
{11, D<&IHtcsManager::GetDefaultHostName>, "GetDefaultHostName"},
|
||||
{12, D<&IHtcsManager::CreateSocketOld>, "CreateSocketOld"},
|
||||
{13, D<&IHtcsManager::CreateSocket>, "CreateSocket"},
|
||||
{100, D<&IHtcsManager::RegisterProcessId>, "RegisterProcessId"},
|
||||
{101, D<&IHtcsManager::MonitorManager>, "MonitorManager"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IHtcsManager::~IHtcsManager() = default;
|
||||
|
||||
Result IHtcsManager::Socket(Out<s32> out_socket, s32 domain, s32 type, s32 protocol) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, domain={}, type={}, protocol={}", domain, type, protocol);
|
||||
*out_socket = 1; // Return dummy socket descriptor
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Close(s32 socket) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}", socket);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Connect(Out<s32> out_result, s32 socket, InBuffer<BufferAttr_HipcMapAlias> address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}", socket);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Bind(Out<s32> out_result, s32 socket, InBuffer<BufferAttr_HipcMapAlias> address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}", socket);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Listen(Out<s32> out_result, s32 socket, s32 backlog) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}, backlog={}", socket, backlog);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Accept(Out<s32> out_socket, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}", socket);
|
||||
*out_socket = 2; // Return dummy accepted socket
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Recv(Out<s32> out_size, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, s32 flags) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}, flags={}", socket, flags);
|
||||
*out_size = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Send(Out<s32> out_size, s32 socket, InBuffer<BufferAttr_HipcMapAlias> buffer, s32 flags) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}, flags={}", socket, flags);
|
||||
*out_size = static_cast<s32>(buffer.size());
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Shutdown(Out<s32> out_result, s32 socket, s32 how) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}, how={}", socket, how);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::Fcntl(Out<s32> out_result, s32 socket, s32 cmd, s32 arg) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}, cmd={}, arg={}", socket, cmd, arg);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::GetPeerNameAny(Out<s32> out_result, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_address) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, socket={}", socket);
|
||||
*out_result = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::GetDefaultHostName(OutBuffer<BufferAttr_HipcMapAlias> out_hostname) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
if (out_hostname.size() > 0) {
|
||||
out_hostname[0] = 0; // Empty hostname
|
||||
}
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::CreateSocketOld(OutInterface<ISocket> out_socket, s32 domain, s32 type, s32 protocol) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, domain={}, type={}, protocol={}", domain, type, protocol);
|
||||
*out_socket = std::make_shared<ISocket>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::CreateSocket(OutInterface<ISocket> out_socket, s32 domain, s32 type, s32 protocol) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, domain={}, type={}, protocol={}", domain, type, protocol);
|
||||
*out_socket = std::make_shared<ISocket>(system);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::RegisterProcessId(ClientProcessId process_id) {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called, process_id={}", process_id.pid);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IHtcsManager::MonitorManager() {
|
||||
LOG_WARNING(Service_TMA, "(STUBBED) called");
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // namespace Service::TMA
|
||||
52
src/core/hle/service/tma/htcs.h
Normal file
52
src/core/hle/service/tma/htcs.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
class ISocket final : public ServiceFramework<ISocket> {
|
||||
public:
|
||||
explicit ISocket(Core::System& system_);
|
||||
~ISocket() override;
|
||||
|
||||
private:
|
||||
Result Close();
|
||||
Result Connect(InBuffer<BufferAttr_HipcMapAlias> address);
|
||||
Result Bind(InBuffer<BufferAttr_HipcMapAlias> address);
|
||||
Result Listen(s32 backlog);
|
||||
Result Accept(OutInterface<ISocket> out_socket);
|
||||
Result Recv(Out<s32> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, s32 flags);
|
||||
Result Send(Out<s32> out_size, InBuffer<BufferAttr_HipcMapAlias> buffer, s32 flags);
|
||||
Result Shutdown(s32 how);
|
||||
Result Fcntl(Out<s32> out_result, s32 cmd, s32 arg);
|
||||
};
|
||||
|
||||
class IHtcsManager final : public ServiceFramework<IHtcsManager> {
|
||||
public:
|
||||
explicit IHtcsManager(Core::System& system_);
|
||||
~IHtcsManager() override;
|
||||
|
||||
private:
|
||||
Result Socket(Out<s32> out_socket, s32 domain, s32 type, s32 protocol);
|
||||
Result Close(s32 socket);
|
||||
Result Connect(Out<s32> out_result, s32 socket, InBuffer<BufferAttr_HipcMapAlias> address);
|
||||
Result Bind(Out<s32> out_result, s32 socket, InBuffer<BufferAttr_HipcMapAlias> address);
|
||||
Result Listen(Out<s32> out_result, s32 socket, s32 backlog);
|
||||
Result Accept(Out<s32> out_socket, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_address);
|
||||
Result Recv(Out<s32> out_size, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_buffer, s32 flags);
|
||||
Result Send(Out<s32> out_size, s32 socket, InBuffer<BufferAttr_HipcMapAlias> buffer, s32 flags);
|
||||
Result Shutdown(Out<s32> out_result, s32 socket, s32 how);
|
||||
Result Fcntl(Out<s32> out_result, s32 socket, s32 cmd, s32 arg);
|
||||
Result GetPeerNameAny(Out<s32> out_result, s32 socket, OutBuffer<BufferAttr_HipcMapAlias> out_address);
|
||||
Result GetDefaultHostName(OutBuffer<BufferAttr_HipcMapAlias> out_hostname);
|
||||
Result CreateSocketOld(OutInterface<ISocket> out_socket, s32 domain, s32 type, s32 protocol);
|
||||
Result CreateSocket(OutInterface<ISocket> out_socket, s32 domain, s32 type, s32 protocol);
|
||||
Result RegisterProcessId(ClientProcessId process_id);
|
||||
Result MonitorManager();
|
||||
};
|
||||
|
||||
} // namespace Service::TMA
|
||||
32
src/core/hle/service/tma/tma.cpp
Normal file
32
src/core/hle/service/tma/tma.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "core/hle/service/server_manager.h"
|
||||
#include "core/hle/service/tma/file_io.h"
|
||||
#include "core/hle/service/tma/htc.h"
|
||||
#include "core/hle/service/tma/htc_tenv.h"
|
||||
#include "core/hle/service/tma/htcs.h"
|
||||
#include "core/hle/service/tma/tma.h"
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
void LoopProcess(Core::System& system) {
|
||||
auto server_manager = std::make_unique<ServerManager>(system);
|
||||
|
||||
// Register HTC (Host Target Connection) service
|
||||
server_manager->RegisterNamedService("htc", std::make_shared<IHtcManager>(system));
|
||||
|
||||
// Register HTCS (Host Target Connection Sockets) service
|
||||
server_manager->RegisterNamedService("htcs", std::make_shared<IHtcsManager>(system));
|
||||
|
||||
// Register HTC:TENV (Target Environment) service
|
||||
server_manager->RegisterNamedService("htc:tenv", std::make_shared<IServiceManager>(system));
|
||||
|
||||
// Register file_io (Host File I/O) service
|
||||
// Note: This service is not present on retail units
|
||||
server_manager->RegisterNamedService("file_io", std::make_shared<IFileManager>(system));
|
||||
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
}
|
||||
|
||||
} // namespace Service::TMA
|
||||
19
src/core/hle/service/tma/tma.h
Normal file
19
src/core/hle/service/tma/tma.h
Normal file
@@ -0,0 +1,19 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace Core {
|
||||
class System;
|
||||
}
|
||||
|
||||
namespace Service::SM {
|
||||
class ServiceManager;
|
||||
}
|
||||
|
||||
namespace Service::TMA {
|
||||
|
||||
/// Registers all TMA services with the specified service manager.
|
||||
void LoopProcess(Core::System& system);
|
||||
|
||||
} // namespace Service::TMA
|
||||
Reference in New Issue
Block a user