diff options
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Ldn')
8 files changed, 220 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/IMonitorServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/IMonitorServiceCreator.cs new file mode 100644 index 00000000..09dfa78f --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/IMonitorServiceCreator.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.HLE.HOS.Services.Ldn +{ + [Service("ldn:m")] + class IMonitorServiceCreator : IpcService + { + public IMonitorServiceCreator(ServiceCtx context) { } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs new file mode 100644 index 00000000..b4dac449 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/ISystemServiceCreator.cs @@ -0,0 +1,8 @@ +namespace Ryujinx.HLE.HOS.Services.Ldn +{ + [Service("ldn:s")] + class ISystemServiceCreator : IpcService + { + public ISystemServiceCreator(ServiceCtx context) { } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs new file mode 100644 index 00000000..4f3094ae --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/IUserServiceCreator.cs @@ -0,0 +1,19 @@ +using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator; + +namespace Ryujinx.HLE.HOS.Services.Ldn +{ + [Service("ldn:u")] + class IUserServiceCreator : IpcService + { + public IUserServiceCreator(ServiceCtx context) { } + + [CommandCmif(0)] + // CreateUserLocalCommunicationService() -> object<nn::ldn::detail::IUserLocalCommunicationService> + public ResultCode CreateUserLocalCommunicationService(ServiceCtx context) + { + MakeObject(context, new IUserLocalCommunicationService(context)); + + return ResultCode.Success; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs new file mode 100644 index 00000000..9c9ee3be --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/Lp2p/IServiceCreator.cs @@ -0,0 +1,9 @@ +namespace Ryujinx.HLE.HOS.Services.Ldn.Lp2p +{ + [Service("lp2p:app")] // 9.0.0+ + [Service("lp2p:sys")] // 9.0.0+ + class IServiceCreator : IpcService + { + public IServiceCreator(ServiceCtx context) { } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs new file mode 100644 index 00000000..274b6132 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/NetworkInterface.cs @@ -0,0 +1,59 @@ +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Kernel.Threading; +using Ryujinx.HLE.HOS.Services.Ldn.Types; +using System.Net; + +namespace Ryujinx.HLE.HOS.Services.Ldn +{ + internal class NetworkInterface + { + public ResultCode NifmState { get; set; } + public KEvent StateChangeEvent { get; private set; } + + private NetworkState _state; + + public NetworkInterface(Horizon system) + { + // TODO(Ac_K): Determine where the internal state is set. + NifmState = ResultCode.Success; + StateChangeEvent = new KEvent(system.KernelContext); + + _state = NetworkState.None; + } + + public ResultCode Initialize(int unknown, int version, IPAddress ipv4Address, IPAddress subnetMaskAddress) + { + // TODO(Ac_K): Call nn::nifm::InitializeSystem(). + // If the call failed, it returns the result code. + // If the call succeed, it signal and clear an event then start a new thread named nn.ldn.NetworkInterfaceMonitor. + + Logger.Stub?.PrintStub(LogClass.ServiceLdn, new { version }); + + // NOTE: Since we don't support ldn for now, we can return this following result code to make it disabled. + return ResultCode.DeviceDisabled; + } + + public ResultCode GetState(out NetworkState state) + { + // Return ResultCode.InvalidArgument if _state is null, doesn't occur in our case. + + state = _state; + + return ResultCode.Success; + } + + public ResultCode Finalize() + { + // TODO(Ac_K): Finalize nifm service then kill the thread named nn.ldn.NetworkInterfaceMonitor. + + _state = NetworkState.None; + + StateChangeEvent.WritableEvent.Signal(); + StateChangeEvent.WritableEvent.Clear(); + + Logger.Stub?.PrintStub(LogClass.ServiceLdn); + + return ResultCode.Success; + } + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/ResultCode.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/ResultCode.cs new file mode 100644 index 00000000..87674f7c --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/ResultCode.cs @@ -0,0 +1,16 @@ +namespace Ryujinx.HLE.HOS.Services.Ldn +{ + enum ResultCode + { + ModuleId = 203, + ErrorCodeShift = 9, + + Success = 0, + + DeviceDisabled = (22 << ErrorCodeShift) | ModuleId, + InvalidState = (32 << ErrorCodeShift) | ModuleId, + Unknown1 = (48 << ErrorCodeShift) | ModuleId, + InvalidArgument = (96 << ErrorCodeShift) | ModuleId, + InvalidObject = (97 << ErrorCodeShift) | ModuleId, + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/Types/NetworkState.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/Types/NetworkState.cs new file mode 100644 index 00000000..6ac20483 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/Types/NetworkState.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.HLE.HOS.Services.Ldn.Types +{ + enum NetworkState + { + None, + Initialized, + AccessPoint, + AccessPointCreated, + Station, + StationConnected, + Error + } +}
\ No newline at end of file diff --git a/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs new file mode 100644 index 00000000..f425ddf7 --- /dev/null +++ b/src/Ryujinx.HLE/HOS/Services/Ldn/UserServiceCreator/IUserLocalCommunicationService.cs @@ -0,0 +1,88 @@ +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.HOS.Services.Ldn.Types; +using Ryujinx.Horizon.Common; +using System; +using System.Net; + +namespace Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator +{ + class IUserLocalCommunicationService : IpcService + { + // TODO(Ac_K): Determine what the hardcoded unknown value is. + private const int UnknownValue = 90; + + private NetworkInterface _networkInterface; + + private int _stateChangeEventHandle = 0; + + public IUserLocalCommunicationService(ServiceCtx context) + { + _networkInterface = new NetworkInterface(context.Device.System); + } + + [CommandCmif(0)] + // GetState() -> s32 state + public ResultCode GetState(ServiceCtx context) + { + if (_networkInterface.NifmState != ResultCode.Success) + { + context.ResponseData.Write((int)NetworkState.Error); + + return ResultCode.Success; + } + + ResultCode result = _networkInterface.GetState(out NetworkState state); + + if (result == ResultCode.Success) + { + context.ResponseData.Write((int)state); + } + + return result; + } + + [CommandCmif(100)] + // AttachStateChangeEvent() -> handle<copy> + public ResultCode AttachStateChangeEvent(ServiceCtx context) + { + if (_stateChangeEventHandle == 0) + { + if (context.Process.HandleTable.GenerateHandle(_networkInterface.StateChangeEvent.ReadableEvent, out _stateChangeEventHandle) != Result.Success) + { + throw new InvalidOperationException("Out of handles!"); + } + } + + context.Response.HandleDesc = IpcHandleDesc.MakeCopy(_stateChangeEventHandle); + + // Return ResultCode.InvalidArgument if handle is null, doesn't occur in our case since we already throw an Exception. + + return ResultCode.Success; + } + + [CommandCmif(400)] + // InitializeOld(u64, pid) + public ResultCode InitializeOld(ServiceCtx context) + { + return _networkInterface.Initialize(UnknownValue, 0, null, null); + } + + [CommandCmif(401)] + // Finalize() + public ResultCode Finalize(ServiceCtx context) + { + return _networkInterface.Finalize(); + } + + [CommandCmif(402)] // 7.0.0+ + // Initialize(u64 ip_addresses, u64, pid) + public ResultCode Initialize(ServiceCtx context) + { + // TODO(Ac_K): Determine what addresses are. + IPAddress unknownAddress1 = new IPAddress(context.RequestData.ReadUInt32()); + IPAddress unknownAddress2 = new IPAddress(context.RequestData.ReadUInt32()); + + return _networkInterface.Initialize(UnknownValue, version: 1, unknownAddress1, unknownAddress2); + } + } +}
\ No newline at end of file |
