From 6b2ee7a54daba8e17de0659a3ae79fe301a19abf Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Wed, 29 Jun 2022 13:32:11 -0700 Subject: [PATCH] Skeleton most of sdmmcsrv --- src/LibHac/FsSrv/DefaultFsServerObjects.cs | 4 +- .../EmulatedStorageDeviceManagerFactory.cs | 8 +- src/LibHac/SdmmcSrv/Common.cs | 5 + src/LibHac/SdmmcSrv/ISdmmcDeviceManager.cs | 13 +- src/LibHac/SdmmcSrv/MmcDeviceOperator.cs | 54 ++++ src/LibHac/SdmmcSrv/MmcManager.cs | 76 +++++- .../SdmmcSrv/MmcPartitionStorageDevice.cs | 255 ++++++++++++++++++ src/LibHac/SdmmcSrv/PatrolReader.cs | 72 +++++ .../SdmmcSrv/SdCardDetectionEventManager.cs | 25 ++ .../SdmmcSrv/SdCardDeviceDetectionEvent.cs | 19 -- src/LibHac/SdmmcSrv/SdCardDeviceOperator.cs | 54 ++++ src/LibHac/SdmmcSrv/SdCardManager.cs | 88 +++++- src/LibHac/SdmmcSrv/SdCardStorageDevice.cs | 61 +++++ src/LibHac/SdmmcSrv/SdmmcResultConverter.cs | 32 +++ src/LibHac/SdmmcSrv/SdmmcStorage.cs | 98 +++++++ 15 files changed, 831 insertions(+), 33 deletions(-) create mode 100644 src/LibHac/SdmmcSrv/MmcDeviceOperator.cs create mode 100644 src/LibHac/SdmmcSrv/MmcPartitionStorageDevice.cs create mode 100644 src/LibHac/SdmmcSrv/PatrolReader.cs create mode 100644 src/LibHac/SdmmcSrv/SdCardDetectionEventManager.cs delete mode 100644 src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs create mode 100644 src/LibHac/SdmmcSrv/SdCardDeviceOperator.cs create mode 100644 src/LibHac/SdmmcSrv/SdCardStorageDevice.cs create mode 100644 src/LibHac/SdmmcSrv/SdmmcResultConverter.cs create mode 100644 src/LibHac/SdmmcSrv/SdmmcStorage.cs diff --git a/src/LibHac/FsSrv/DefaultFsServerObjects.cs b/src/LibHac/FsSrv/DefaultFsServerObjects.cs index 0426a42c..f759fea4 100644 --- a/src/LibHac/FsSrv/DefaultFsServerObjects.cs +++ b/src/LibHac/FsSrv/DefaultFsServerObjects.cs @@ -4,6 +4,7 @@ using LibHac.FsSrv.FsCreator; using LibHac.FsSrv.Storage; using LibHac.FsSystem; using LibHac.Gc; +using LibHac.Sdmmc; using IFileSystem = LibHac.Fs.Fsa.IFileSystem; namespace LibHac.FsSrv; @@ -24,6 +25,7 @@ public class DefaultFsServerObjects var sdCard = new EmulatedSdCard(); var gameCardNew = new GameCardDummy(); + var sdmmcNew = new SdmmcApi(); var gcStorageCreator = new EmulatedGameCardStorageCreator(gameCard); @@ -43,7 +45,7 @@ public class DefaultFsServerObjects creators.BuiltInStorageFileSystemCreator = new EmulatedBisFileSystemCreator(ref sharedRootFileSystem.Ref); creators.SdCardFileSystemCreator = new EmulatedSdCardFileSystemCreator(sdCard, ref sharedRootFileSystemCopy.Ref); - var storageDeviceManagerFactory = new EmulatedStorageDeviceManagerFactory(fsServer, gameCardNew, hasGameCard: true); + var storageDeviceManagerFactory = new EmulatedStorageDeviceManagerFactory(fsServer, sdmmcNew, gameCardNew, hasGameCard: true); return new DefaultFsServerObjects { diff --git a/src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs b/src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs index 5408019d..72d0a8bf 100644 --- a/src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs +++ b/src/LibHac/FsSrv/Storage/EmulatedStorageDeviceManagerFactory.cs @@ -4,6 +4,7 @@ using LibHac.FsSrv.Storage.Sf; using LibHac.Gc; using LibHac.GcSrv; using LibHac.Os; +using LibHac.Sdmmc; using LibHac.SdmmcSrv; using LibHac.Sf; @@ -23,11 +24,14 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory private readonly bool _hasGameCard; private readonly FileSystemServer _fsServer; + private readonly SdmmcApi _sdmmc; private readonly GameCardDummy _gc; - public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, GameCardDummy gc, bool hasGameCard) + public EmulatedStorageDeviceManagerFactory(FileSystemServer fsServer, SdmmcApi sdmmc, GameCardDummy gc, + bool hasGameCard) { _fsServer = fsServer; + _sdmmc = sdmmc; _gc = gc; _hasGameCard = hasGameCard; @@ -195,7 +199,7 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory if (!_sdCardDeviceManager.HasValue) { - _sdCardDeviceManager.Reset(new SdCardManager()); + _sdCardDeviceManager.Reset(new SdCardManager(_sdmmc)); // Todo: BuiltInStorageFileSystemCreator::SetSdCardPortReady } diff --git a/src/LibHac/SdmmcSrv/Common.cs b/src/LibHac/SdmmcSrv/Common.cs index 2569400e..b69cd7a6 100644 --- a/src/LibHac/SdmmcSrv/Common.cs +++ b/src/LibHac/SdmmcSrv/Common.cs @@ -11,4 +11,9 @@ public static class Common return Result.Success; } + + public static uint BytesToSectors(long byteCount) + { + return (uint)((ulong)byteCount / SdmmcApi.SectorSize); + } } \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/ISdmmcDeviceManager.cs b/src/LibHac/SdmmcSrv/ISdmmcDeviceManager.cs index 8753954a..e080f219 100644 --- a/src/LibHac/SdmmcSrv/ISdmmcDeviceManager.cs +++ b/src/LibHac/SdmmcSrv/ISdmmcDeviceManager.cs @@ -1,11 +1,14 @@ -using LibHac.Fs; +using System; +using LibHac.Fs; +using LibHac.Os; +using LibHac.Sdmmc; namespace LibHac.SdmmcSrv; -internal interface ISdmmcDeviceManager +internal interface ISdmmcDeviceManager : IDisposable { - Result Lock(out object locker, uint handle); + Result Lock(ref UniqueLockRef outLock, SdmmcHandle handle); IStorage GetStorage(); - SdmmcPort GetPortId(); - Result NotifyCloseStorageDevice(uint handle); + Port GetPort(); + void NotifyCloseStorageDevice(SdmmcHandle handle); } \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/MmcDeviceOperator.cs b/src/LibHac/SdmmcSrv/MmcDeviceOperator.cs new file mode 100644 index 00000000..96dbe9cb --- /dev/null +++ b/src/LibHac/SdmmcSrv/MmcDeviceOperator.cs @@ -0,0 +1,54 @@ +using System; +using LibHac.Common; +using LibHac.FsSrv.Storage.Sf; +using LibHac.Sf; + +namespace LibHac.SdmmcSrv; + +internal class MmcDeviceOperator : IStorageDeviceOperator +{ + private SharedRef _baseDevice; + + public MmcDeviceOperator(ref SharedRef baseDevice) + { + _baseDevice = SharedRef.CreateMove(ref baseDevice); + } + + public void Dispose() + { + _baseDevice.Destroy(); + } + + public Result Operate(int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn(InBuffer buffer, long offset, long size, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2, + OutBuffer buffer2, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size, + int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2, + long offset, long size, int operationId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/MmcManager.cs b/src/LibHac/SdmmcSrv/MmcManager.cs index 9e2eb601..4a90abd4 100644 --- a/src/LibHac/SdmmcSrv/MmcManager.cs +++ b/src/LibHac/SdmmcSrv/MmcManager.cs @@ -2,11 +2,20 @@ using LibHac.Common; using LibHac.FsSrv.Sf; using LibHac.FsSrv.Storage.Sf; +using LibHac.Os; +using LibHac.Sdmmc; +using LibHac.Sf; +using IStorage = LibHac.FsSrv.Sf.IStorage; namespace LibHac.SdmmcSrv; -public class MmcManager : IStorageDeviceManager +public class MmcManager : IStorageDeviceManager, IStorageDeviceOperator, ISdmmcDeviceManager { + private Port _port; + private bool _isInitialized; + private bool _isActivated; + private SdkMutexType _mutex; + public MmcManager() { throw new NotImplementedException(); @@ -17,12 +26,17 @@ public class MmcManager : IStorageDeviceManager throw new NotImplementedException(); } + public void InitializeMmc() + { + throw new NotImplementedException(); + } + public Result IsInserted(out bool isInserted) { throw new NotImplementedException(); } - public Result IsHandleValid(out bool isValid, uint handle) + public Result IsHandleValid(out bool isValid, SdmmcHandle handle) { throw new NotImplementedException(); } @@ -47,6 +61,11 @@ public class MmcManager : IStorageDeviceManager throw new NotImplementedException(); } + private Result OpenStorageDevice(ref SharedRef outStorageDevice, ulong attribute) + { + throw new NotImplementedException(); + } + public Result PutToSleep() { throw new NotImplementedException(); @@ -66,4 +85,57 @@ public class MmcManager : IStorageDeviceManager { throw new NotImplementedException(); } + + public Result Lock(ref UniqueLockRef outLock, SdmmcHandle handle) + { + throw new NotImplementedException(); + } + + public Fs.IStorage GetStorage() + { + throw new NotImplementedException(); + } + + public Port GetPort() + { + throw new NotImplementedException(); + } + + public void NotifyCloseStorageDevice(SdmmcHandle handle) + { + throw new NotImplementedException(); + } + + public Result Operate(int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn(InBuffer buffer, long offset, long size, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2, + OutBuffer buffer2, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size, + int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2, + long offset, long size, int operationId) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/MmcPartitionStorageDevice.cs b/src/LibHac/SdmmcSrv/MmcPartitionStorageDevice.cs new file mode 100644 index 00000000..018878bc --- /dev/null +++ b/src/LibHac/SdmmcSrv/MmcPartitionStorageDevice.cs @@ -0,0 +1,255 @@ +using System; +using LibHac.Common; +using LibHac.Diag; +using LibHac.Fs; +using LibHac.FsSrv.Storage.Sf; +using LibHac.Os; +using LibHac.Sdmmc; +using LibHac.Sf; +using MmcPartition = LibHac.Sdmmc.MmcPartition; + +namespace LibHac.SdmmcSrv; + +internal class MmcPartitionStorageDevice : IDisposable +{ + private SharedRef _manager; + private SdmmcHandle _handle; + private MmcPartition _partition; + + public MmcPartitionStorageDevice(ref SharedRef manager, SdmmcHandle handle, MmcPartition partition) + { + _manager = SharedRef.CreateMove(ref manager); + _handle = handle; + _partition = partition; + } + + public void Dispose() { } + + public Result GetHandle(out SdmmcHandle handle) + { + handle = _handle; + return Result.Success; + } + + public Result IsHandleValid(out bool isValid) + { + using var scopedLock = new UniqueLockRef(); + isValid = _manager.Get.Lock(ref scopedLock.Ref(), _handle).IsSuccess(); + + return Result.Success; + } + + public Result OpenOperator(ref SharedRef outDeviceOperator) + { + throw new NotImplementedException(); + } + + public Result Lock(ref UniqueLockRef outLock) + { + return _manager.Get.Lock(ref outLock.Ref(), _handle).Ret(); + } + + public Port GetPort() + { + return _manager.Get.GetPort(); + } + + public MmcPartition GetPartition() + { + return _partition; + } +} + +// The Mmc*PartitionStorageDevice classes inherit both from SdmmcStorageInterfaceAdapter and MmcPartitionStorageDevice +// Because C# doesn't have multiple inheritance, we make a copy of the SdmmcStorageInterfaceAdapter class that inherits +// from MmcPartitionStorageDevice. This class must mirror any changes made to SdmmcStorageInterfaceAdapter. +internal class MmcPartitionStorageDeviceInterfaceAdapter : MmcPartitionStorageDevice, IStorageDevice +{ + private IStorage _baseStorage; + + public MmcPartitionStorageDeviceInterfaceAdapter(IStorage baseStorage, ref SharedRef manager, + SdmmcHandle handle, MmcPartition partition) : base(ref manager, handle, partition) + { + _baseStorage = baseStorage; + } + + public virtual Result Read(long offset, OutBuffer destination, long size) + { + return _baseStorage.Read(offset, destination.Buffer.Slice(0, (int)size)).Ret(); + } + + public virtual Result Write(long offset, InBuffer source, long size) + { + return _baseStorage.Write(offset, source.Buffer.Slice(0, (int)size)).Ret(); + } + + public virtual Result Flush() + { + return _baseStorage.Flush().Ret(); + } + + public virtual Result SetSize(long size) + { + return _baseStorage.SetSize(size).Ret(); + } + + public virtual Result GetSize(out long size) + { + return _baseStorage.GetSize(out size).Ret(); + } + + public virtual Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, long size) + { + UnsafeHelpers.SkipParamInit(out rangeInfo); + + return _baseStorage.OperateRange(SpanHelpers.AsByteSpan(ref rangeInfo), (OperationId)operationId, offset, + size, ReadOnlySpan.Empty).Ret(); + } +} + +internal class MmcUserDataPartitionStorageDevice : MmcPartitionStorageDeviceInterfaceAdapter +{ + public MmcUserDataPartitionStorageDevice(ref SharedRef manager, SdmmcHandle handle) + : base(manager.Get.GetStorage(), ref manager, handle, MmcPartition.UserData) + { } + + public override Result Read(long offset, OutBuffer destination, long size) + { + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + base.Read(offset, destination, size); + if (res.IsFailure()) return res.Miss(); + + return Result.Success; + } + + public override Result Write(long offset, InBuffer source, long size) + { + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + res = base.Write(offset, source, size); + if (res.IsFailure()) return res.Miss(); + + return Result.Success; + } + + public override Result GetSize(out long size) + { + UnsafeHelpers.SkipParamInit(out size); + + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + res = base.GetSize(out size); + if (res.IsFailure()) return res.Miss(); + + return Result.Success; + } +} + +internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfaceAdapter +{ + private SdmmcApi _sdmmc; + + public MmcBootPartitionStorageDevice(ref SharedRef manager, Fs.MmcPartition partition, + SdmmcHandle handle, SdmmcApi sdmmc) : base(manager.Get.GetStorage(), ref manager, handle, GetPartition(partition)) + { + _sdmmc = sdmmc; + } + + private static MmcPartition GetPartition(Fs.MmcPartition partition) + { + switch (partition) + { + case Fs.MmcPartition.UserData: + return MmcPartition.UserData; + case Fs.MmcPartition.BootPartition1: + return MmcPartition.BootPartition1; + case Fs.MmcPartition.BootPartition2: + return MmcPartition.BootPartition2; + default: + Abort.UnexpectedDefault(); + return default; + } + } + + public override Result Read(long offset, OutBuffer destination, long size) + { + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), GetPartition())); + + try + { + base.Read(offset, destination, size); + if (res.IsFailure()) return res.Miss(); + + return Result.Success; + } + finally + { + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData)); + } + } + + public override Result Write(long offset, InBuffer source, long size) + { + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), GetPartition())); + + try + { + base.Write(offset, source, size); + if (res.IsFailure()) return res.Miss(); + + return Result.Success; + } + finally + { + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData)); + } + } + + public override Result GetSize(out long size) + { + UnsafeHelpers.SkipParamInit(out size); + + using var scopedLock = new UniqueLockRef(); + + Result res = Lock(ref scopedLock.Ref()); + if (res.IsFailure()) return res.Miss(); + + Port port = GetPort(); + + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(port, GetPartition())); + + try + { + res = SdmmcResultConverter.GetFsResult(port, _sdmmc.GetMmcBootPartitionCapacity(out uint numSectors, port)); + if (res.IsFailure()) return res.Miss(); + + size = numSectors * SdmmcApi.SectorSize; + + return Result.Success; + } + finally + { + Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData)); + } + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/PatrolReader.cs b/src/LibHac/SdmmcSrv/PatrolReader.cs new file mode 100644 index 00000000..546cfd57 --- /dev/null +++ b/src/LibHac/SdmmcSrv/PatrolReader.cs @@ -0,0 +1,72 @@ +using System; +using LibHac.Os; + +namespace LibHac.SdmmcSrv; + +internal class PatrolReader +{ + public PatrolReader(SdkMutex mutex) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + throw new NotImplementedException(); + } + + public static void PatrolReaderThreadEntry(object args) + { + throw new NotImplementedException(); + } + + public void FinalizeObject() + { + throw new NotImplementedException(); + } + + public Result GetPatrolCount(out uint outCount) + { + throw new NotImplementedException(); + } + + public void GetAndClearAllocateCount(out long outSuccessCount, out long outFailureCount) + { + throw new NotImplementedException(); + } + + public bool LoadState() + { + throw new NotImplementedException(); + } + + public bool SaveState() + { + throw new NotImplementedException(); + } + + public void Start() + { + throw new NotImplementedException(); + } + + public void Stop() + { + throw new NotImplementedException(); + } + + public void Sleep() + { + throw new NotImplementedException(); + } + + public void Resume() + { + throw new NotImplementedException(); + } + + public void PatrolReaderThread() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdCardDetectionEventManager.cs b/src/LibHac/SdmmcSrv/SdCardDetectionEventManager.cs new file mode 100644 index 00000000..85645ba8 --- /dev/null +++ b/src/LibHac/SdmmcSrv/SdCardDetectionEventManager.cs @@ -0,0 +1,25 @@ +using LibHac.FsSystem; +using LibHac.Sdmmc; + +namespace LibHac.SdmmcSrv; + +internal class SdCardDetectionEventManager : CardDeviceDetectionEventManager +{ + // LibHac addition + private SdmmcApi _sdmmc; + + public SdCardDetectionEventManager(Port port, SdmmcApi sdmmc) + { + CallbackArgs.Port = port; + _sdmmc = sdmmc; + + _sdmmc.RegisterSdCardDetectionEventCallback(port, DetectionEventCallback, CallbackArgs); + } + + public override void Dispose() + { + _sdmmc.UnregisterSdCardDetectionEventCallback(CallbackArgs.Port); + + base.Dispose(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs b/src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs deleted file mode 100644 index 46c02f50..00000000 --- a/src/LibHac/SdmmcSrv/SdCardDeviceDetectionEvent.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using LibHac.FsSystem; - -namespace LibHac.SdmmcSrv; - -internal class SdCardDeviceDetectionEventManager : CardDeviceDetectionEventManager -{ - public SdCardDeviceDetectionEventManager(Sdmmc.Port port) - { - CallbackArgs.Port = port; - - throw new NotImplementedException(); - } - - public override void Dispose() - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdCardDeviceOperator.cs b/src/LibHac/SdmmcSrv/SdCardDeviceOperator.cs new file mode 100644 index 00000000..14495ac3 --- /dev/null +++ b/src/LibHac/SdmmcSrv/SdCardDeviceOperator.cs @@ -0,0 +1,54 @@ +using System; +using LibHac.Common; +using LibHac.FsSrv.Storage.Sf; +using LibHac.Sf; + +namespace LibHac.SdmmcSrv; + +internal class SdCardDeviceOperator : IStorageDeviceOperator +{ + private SharedRef _storageDevice; + + public SdCardDeviceOperator(ref SharedRef storageDevice) + { + throw new NotImplementedException(); + } + + public void Dispose() + { + _storageDevice.Destroy(); + } + + public Result Operate(int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn(InBuffer buffer, long offset, long size, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2, + OutBuffer buffer2, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size, + int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2, + long offset, long size, int operationId) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdCardManager.cs b/src/LibHac/SdmmcSrv/SdCardManager.cs index cf8f0496..45630576 100644 --- a/src/LibHac/SdmmcSrv/SdCardManager.cs +++ b/src/LibHac/SdmmcSrv/SdCardManager.cs @@ -2,17 +2,39 @@ using LibHac.Common; using LibHac.FsSrv.Sf; using LibHac.FsSrv.Storage.Sf; +using LibHac.Os; +using LibHac.Sdmmc; +using LibHac.Sf; +using LibHac.Util; namespace LibHac.SdmmcSrv; -public class SdCardManager : IStorageDeviceManager +public class SdCardManager : IStorageDeviceManager, IStorageDeviceOperator, ISdmmcDeviceManager { - public SdCardManager() - { + private Port _port; + private bool _isInitialized; + private SdkMutexType _mutex; + private SdmmcStorage _sdStorage; + private SdmmcHandle _handle; + private Optional _detectionEventManager; + public SdCardManager(SdmmcApi sdmmc) + { + _port = Port.SdCard0; + _mutex = new SdkMutexType(); + _sdStorage = new SdmmcStorage(_port, sdmmc); } public void Dispose() + { + if (_detectionEventManager.HasValue) + { + _detectionEventManager.Value.Dispose(); + _detectionEventManager = default; + } + } + + public void InitializeSd() { throw new NotImplementedException(); } @@ -22,7 +44,7 @@ public class SdCardManager : IStorageDeviceManager throw new NotImplementedException(); } - public Result IsHandleValid(out bool isValid, uint handle) + public Result IsHandleValid(out bool isValid, SdmmcHandle handle) { throw new NotImplementedException(); } @@ -47,6 +69,11 @@ public class SdCardManager : IStorageDeviceManager throw new NotImplementedException(); } + private Result OpenStorageDevice(ref SharedRef outStorageDevice, ulong attribute) + { + throw new NotImplementedException(); + } + public Result PutToSleep() { throw new NotImplementedException(); @@ -66,4 +93,57 @@ public class SdCardManager : IStorageDeviceManager { throw new NotImplementedException(); } + + public Result Lock(ref UniqueLockRef outLock, SdmmcHandle handle) + { + throw new NotImplementedException(); + } + + public Fs.IStorage GetStorage() + { + throw new NotImplementedException(); + } + + public Port GetPort() + { + throw new NotImplementedException(); + } + + public void NotifyCloseStorageDevice(uint handle) + { + throw new NotImplementedException(); + } + + public Result Operate(int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn(InBuffer buffer, long offset, long size, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2, + OutBuffer buffer2, int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size, + int operationId) + { + throw new NotImplementedException(); + } + + public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2, + long offset, long size, int operationId) + { + throw new NotImplementedException(); + } } \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdCardStorageDevice.cs b/src/LibHac/SdmmcSrv/SdCardStorageDevice.cs new file mode 100644 index 00000000..440dd02c --- /dev/null +++ b/src/LibHac/SdmmcSrv/SdCardStorageDevice.cs @@ -0,0 +1,61 @@ +using System; +using LibHac.Common; +using LibHac.FsSrv.Storage.Sf; +using LibHac.Os; +using LibHac.Sdmmc; +using LibHac.Sf; + +namespace LibHac.SdmmcSrv; + +internal class SdCardStorageDevice : SdmmcStorageInterfaceAdapter, IStorageDevice +{ + private SharedRef _manager; + private SdmmcHandle _handle; + + public SdCardStorageDevice(ref SharedRef manager, SdmmcHandle handle) + : base(manager.Get.GetStorage()) + { + _manager = SharedRef.CreateMove(ref manager); + _handle = handle; + } + + public Port GetPort() + { + throw new NotImplementedException(); + } + + public Result GetHandle(out uint handle) + { + throw new NotImplementedException(); + } + + public Result IsHandleValid(out bool isValid) + { + throw new NotImplementedException(); + } + + public Result OpenOperator(ref SharedRef outDeviceOperator) + { + throw new NotImplementedException(); + } + + public Result Lock(ref UniqueLockRef outLock) + { + throw new NotImplementedException(); + } + + public override Result Read(long offset, OutBuffer destination, long size) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, InBuffer source, long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdmmcResultConverter.cs b/src/LibHac/SdmmcSrv/SdmmcResultConverter.cs new file mode 100644 index 00000000..9050fb2b --- /dev/null +++ b/src/LibHac/SdmmcSrv/SdmmcResultConverter.cs @@ -0,0 +1,32 @@ +using System; +using LibHac.Sdmmc; + +namespace LibHac.SdmmcSrv; + +public static class SdmmcResultConverter +{ + public static Result GetFsResult(Port port, Result result) + { + if (result.IsSuccess()) + return Result.Success; + + if (port == Port.Mmc0) + { + return GetFsResultFromMmcResult(result).Ret(); + } + else + { + return GetFsResultFromSdCardResult(result).Ret(); + } + } + + private static Result GetFsResultFromMmcResult(Result result) + { + throw new NotImplementedException(); + } + + private static Result GetFsResultFromSdCardResult(Result result) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/LibHac/SdmmcSrv/SdmmcStorage.cs b/src/LibHac/SdmmcSrv/SdmmcStorage.cs new file mode 100644 index 00000000..bb22a746 --- /dev/null +++ b/src/LibHac/SdmmcSrv/SdmmcStorage.cs @@ -0,0 +1,98 @@ +using System; +using LibHac.Common; +using LibHac.Fs; +using LibHac.Sdmmc; +using LibHac.Sf; +using IStorageSf = LibHac.FsSrv.Sf.IStorage; + +namespace LibHac.SdmmcSrv; + +internal class SdmmcStorage : IStorage +{ + private Port _port; + + // LibHac additions + private SdmmcApi _sdmmc; + + public SdmmcStorage(Port port, SdmmcApi sdmmc) + { + _port = port; + _sdmmc = sdmmc; + } + + public override Result Read(long offset, Span destination) + { + throw new NotImplementedException(); + } + + public override Result Write(long offset, ReadOnlySpan source) + { + throw new NotImplementedException(); + } + + public override Result Flush() + { + throw new NotImplementedException(); + } + + public override Result SetSize(long size) + { + throw new NotImplementedException(); + } + + public override Result GetSize(out long size) + { + throw new NotImplementedException(); + } + + public override Result OperateRange(Span outBuffer, OperationId operationId, long offset, long size, + ReadOnlySpan inBuffer) + { + throw new NotImplementedException(); + } +} + +internal class SdmmcStorageInterfaceAdapter : IStorageSf +{ + private IStorage _baseStorage; + + public SdmmcStorageInterfaceAdapter(IStorage baseStorage) + { + _baseStorage = baseStorage; + } + + public virtual void Dispose() { } + + public virtual Result Read(long offset, OutBuffer destination, long size) + { + return _baseStorage.Read(offset, destination.Buffer.Slice(0, (int)size)).Ret(); + } + + public virtual Result Write(long offset, InBuffer source, long size) + { + return _baseStorage.Write(offset, source.Buffer.Slice(0, (int)size)).Ret(); + } + + public virtual Result Flush() + { + return _baseStorage.Flush().Ret(); + } + + public virtual Result SetSize(long size) + { + return _baseStorage.SetSize(size).Ret(); + } + + public virtual Result GetSize(out long size) + { + return _baseStorage.GetSize(out size).Ret(); + } + + public virtual Result OperateRange(out QueryRangeInfo rangeInfo, int operationId, long offset, long size) + { + UnsafeHelpers.SkipParamInit(out rangeInfo); + + return _baseStorage.OperateRange(SpanHelpers.AsByteSpan(ref rangeInfo), (OperationId)operationId, offset, + size, ReadOnlySpan.Empty).Ret(); + } +} \ No newline at end of file