aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Horizon/Sdk/Sm
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-01-04 19:15:45 -0300
committerGitHub <noreply@github.com>2023-01-04 23:15:45 +0100
commit08831eecf77cedd3c4192ebab5a9c485fb15d51e (patch)
tree6d95b921a18e9cfa477579fcecb9d041e03d682e /Ryujinx.Horizon/Sdk/Sm
parentc6a139a6e7e3ffe1591bc14dafafed60b9bef0dc (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.cs98
-rw-r--r--Ryujinx.Horizon/Sdk/Sm/SmApi.cs107
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);
+ }
+ }
+}