diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2023-01-04 19:15:45 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-04 23:15:45 +0100 |
| commit | 08831eecf77cedd3c4192ebab5a9c485fb15d51e (patch) | |
| tree | 6d95b921a18e9cfa477579fcecb9d041e03d682e /Ryujinx.Horizon/Sdk/Sm | |
| parent | c6a139a6e7e3ffe1591bc14dafafed60b9bef0dc (diff) | |
IPC refactor part 3+4: New server HIPC message processor (#4188)
* IPC refactor part 3 + 4: New server HIPC message processor with source generator based serialization
* Make types match on calls to AlignUp/AlignDown
* Formatting
* Address some PR feedback
* Move BitfieldExtensions to Ryujinx.Common.Utilities and consolidate implementations
* Rename Reader/Writer to SpanReader/SpanWriter and move to Ryujinx.Common.Memory
* Implement EventType
* Address more PR feedback
* Log request processing errors since they are not normal
* Rename waitable to multiwait and add missing lock
* PR feedback
* Ac_K PR feedback
Diffstat (limited to 'Ryujinx.Horizon/Sdk/Sm')
| -rw-r--r-- | Ryujinx.Horizon/Sdk/Sm/ServiceName.cs | 98 | ||||
| -rw-r--r-- | Ryujinx.Horizon/Sdk/Sm/SmApi.cs | 107 |
2 files changed, 205 insertions, 0 deletions
diff --git a/Ryujinx.Horizon/Sdk/Sm/ServiceName.cs b/Ryujinx.Horizon/Sdk/Sm/ServiceName.cs new file mode 100644 index 00000000..dbb30078 --- /dev/null +++ b/Ryujinx.Horizon/Sdk/Sm/ServiceName.cs @@ -0,0 +1,98 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Horizon.Sdk.Sm +{ + [StructLayout(LayoutKind.Sequential, Pack = 1)] + struct ServiceName + { + public static ServiceName Invalid { get; } = new ServiceName(0); + + public bool IsInvalid => Packed == 0; + + public int Length => sizeof(ulong); + + public ulong Packed { get; } + + public byte this[int index] + { + get + { + if ((uint)index >= sizeof(ulong)) + { + throw new IndexOutOfRangeException(); + } + + return (byte)(Packed >> (index * 8)); + } + } + + private ServiceName(ulong packed) + { + Packed = packed; + } + + public static ServiceName Encode(string name) + { + ulong packed = 0; + + for (int index = 0; index < sizeof(ulong); index++) + { + if (index < name.Length) + { + packed |= (ulong)(byte)name[index] << (index * 8); + } + else + { + break; + } + } + + return new ServiceName(packed); + } + + public override bool Equals(object obj) + { + return obj is ServiceName serviceName && serviceName.Equals(this); + } + + public bool Equals(ServiceName other) + { + return other.Packed == Packed; + } + + public override int GetHashCode() + { + return Packed.GetHashCode(); + } + + public static bool operator ==(ServiceName lhs, ServiceName rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(ServiceName lhs, ServiceName rhs) + { + return !lhs.Equals(rhs); + } + + public override string ToString() + { + string name = string.Empty; + + for (int index = 0; index < sizeof(ulong); index++) + { + byte character = (byte)(Packed >> (index * 8)); + + if (character == 0) + { + break; + } + + name += (char)character; + } + + return name; + } + } +} diff --git a/Ryujinx.Horizon/Sdk/Sm/SmApi.cs b/Ryujinx.Horizon/Sdk/Sm/SmApi.cs new file mode 100644 index 00000000..e4b0eea1 --- /dev/null +++ b/Ryujinx.Horizon/Sdk/Sm/SmApi.cs @@ -0,0 +1,107 @@ +using Ryujinx.Common.Memory; +using Ryujinx.Horizon.Common; +using Ryujinx.Horizon.Sdk.Sf.Cmif; +using System; + +namespace Ryujinx.Horizon.Sdk.Sm +{ + class SmApi + { + private int _portHandle; + + public Result Initialize() + { + Result result = HorizonStatic.Syscall.ConnectToNamedPort(out int portHandle, "sm:"); + + while (result == KernelResult.NotFound) + { + HorizonStatic.Syscall.SleepThread(50000000L); + result = HorizonStatic.Syscall.ConnectToNamedPort(out portHandle, "sm:"); + } + + if (result.IsFailure) + { + return result; + } + + _portHandle = portHandle; + + return RegisterClient(); + } + + private Result RegisterClient() + { + Span<byte> data = stackalloc byte[8]; + + SpanWriter writer = new SpanWriter(data); + + writer.Write(0UL); + + return ServiceUtil.SendRequest(out _, _portHandle, 0, sendPid: true, data); + } + + public Result GetServiceHandle(out int handle, ServiceName name) + { + Span<byte> data = stackalloc byte[8]; + + SpanWriter writer = new SpanWriter(data); + + writer.Write(name); + + Result result = ServiceUtil.SendRequest(out CmifResponse response, _portHandle, 1, sendPid: false, data); + + if (result.IsFailure) + { + handle = 0; + return result; + } + + handle = response.MoveHandles[0]; + return Result.Success; + } + + public Result RegisterService(out int handle, ServiceName name, int maxSessions, bool isLight) + { + Span<byte> data = stackalloc byte[16]; + + SpanWriter writer = new SpanWriter(data); + + writer.Write(name); + writer.Write(isLight ? 1 : 0); + writer.Write(maxSessions); + + Result result = ServiceUtil.SendRequest(out CmifResponse response, _portHandle, 2, sendPid: false, data); + + if (result.IsFailure) + { + handle = 0; + return result; + } + + handle = response.MoveHandles[0]; + return Result.Success; + } + + public Result UnregisterService(ServiceName name) + { + Span<byte> data = stackalloc byte[8]; + + SpanWriter writer = new SpanWriter(data); + + writer.Write(name); + + return ServiceUtil.SendRequest(out _, _portHandle, 3, sendPid: false, data); + } + + public Result DetachClient() + { + Span<byte> data = stackalloc byte[8]; + + SpanWriter writer = new SpanWriter(data); + + writer.Write(0UL); + + return ServiceUtil.SendRequest(out _, _portHandle, 4, sendPid: true, data); + } + } +} |
