mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Implement most of sdmmcsrv
This commit is contained in:
parent
99d497ca7c
commit
4ffc834427
15 changed files with 1539 additions and 143 deletions
|
@ -189,7 +189,8 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
|||
{
|
||||
// Missing: Register device address space
|
||||
|
||||
_mmcDeviceManager.Reset(new MmcManager());
|
||||
using SharedRef<MmcManager> mmcManager = MmcManager.CreateShared(_sdmmc);
|
||||
_mmcDeviceManager.SetByMove(ref mmcManager.Ref);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +200,8 @@ public class EmulatedStorageDeviceManagerFactory : IStorageDeviceManagerFactory
|
|||
|
||||
if (!_sdCardDeviceManager.HasValue)
|
||||
{
|
||||
_sdCardDeviceManager.Reset(new SdCardManager(_sdmmc));
|
||||
using SharedRef<SdCardManager> manager = SdCardManager.CreateShared(_sdmmc);
|
||||
_sdCardDeviceManager.SetByMove(ref manager.Ref);
|
||||
|
||||
// Todo: BuiltInStorageFileSystemCreator::SetSdCardPortReady
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace LibHac.FsSrv.Storage.Sf;
|
|||
// StorageServiceObjectAdapter is a template that is used with either IStorage or IStorageDevice
|
||||
public interface IStorageDevice : IStorage
|
||||
{
|
||||
Result GetHandle(out GameCardHandle handle);
|
||||
Result GetHandle(out uint handle);
|
||||
Result IsHandleValid(out bool isValid);
|
||||
Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator);
|
||||
|
||||
|
|
|
@ -36,6 +36,11 @@ public class SdkMutex : ILockable
|
|||
{
|
||||
return _mutex.IsLockedByCurrentThread();
|
||||
}
|
||||
|
||||
public ref SdkMutexType GetBase()
|
||||
{
|
||||
return ref _mutex;
|
||||
}
|
||||
}
|
||||
|
||||
public struct SdkMutexType : ILockable
|
||||
|
|
|
@ -26,7 +26,7 @@ public static class UniqueLock
|
|||
}
|
||||
|
||||
#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type
|
||||
public static unsafe ref UniqueLockRef<T> Ref<T>(this in UniqueLockRef<T> value) where T : struct, ILockable
|
||||
public static unsafe ref UniqueLockRef<T> Ref<T>(this scoped in UniqueLockRef<T> value) where T : struct, ILockable
|
||||
{
|
||||
fixed (UniqueLockRef<T>* p = &value)
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ public ref struct UniqueLockRef<TMutex> where TMutex : struct, ILockable
|
|||
other = default;
|
||||
}
|
||||
|
||||
public void Set(ref UniqueLockRef<TMutex> other)
|
||||
public void Set(scoped ref UniqueLockRef<TMutex> other)
|
||||
{
|
||||
if (_ownsLock)
|
||||
_mutex.Value.Unlock();
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using LibHac.Sdmmc;
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Sdmmc;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
public static class Common
|
||||
internal static class Common
|
||||
{
|
||||
public static Result CheckConnection(out SpeedMode outSpeedMode, out BusWidth outBusWidth, Port port)
|
||||
{
|
||||
|
@ -12,6 +14,12 @@ public static class Common
|
|||
return Result.Success;
|
||||
}
|
||||
|
||||
public static Result GetAndClearSdmmcStorageErrorInfo(out StorageErrorInfo outStorageErrorInfo, out long outLogSize,
|
||||
Span<byte> logBuffer, SdmmcApi sdmmc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static uint BytesToSectors(long byteCount)
|
||||
{
|
||||
return (uint)((ulong)byteCount / SdmmcApi.SectorSize);
|
||||
|
|
|
@ -1,54 +1,191 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Sdmmc.SdmmcApi;
|
||||
using static LibHac.SdmmcSrv.SdmmcResultConverter;
|
||||
using MmcPartition = LibHac.Sdmmc.MmcPartition;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
internal class MmcDeviceOperator : IStorageDeviceOperator
|
||||
{
|
||||
private SharedRef<MmcPartitionStorageDevice> _baseDevice;
|
||||
private SharedRef<MmcPartitionStorageDevice> _storageDevice;
|
||||
|
||||
public MmcDeviceOperator(ref SharedRef<MmcPartitionStorageDevice> baseDevice)
|
||||
// LibHac additions
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
public MmcDeviceOperator(ref SharedRef<MmcPartitionStorageDevice> storageDevice, SdmmcApi sdmmc)
|
||||
{
|
||||
_baseDevice = SharedRef<MmcPartitionStorageDevice>.CreateMove(ref baseDevice);
|
||||
_storageDevice = SharedRef<MmcPartitionStorageDevice>.CreateMove(ref storageDevice);
|
||||
_sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_baseDevice.Destroy();
|
||||
_storageDevice.Destroy();
|
||||
}
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var operation = (MmcOperationIdValue)operationId;
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
Result res = _storageDevice.Get.Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case MmcOperationIdValue.Erase:
|
||||
{
|
||||
Port port = _storageDevice.Get.GetPort();
|
||||
MmcPartition partition = _storageDevice.Get.GetPartition();
|
||||
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(port, partition));
|
||||
|
||||
try
|
||||
{
|
||||
res = GetFsResult(port, _sdmmc.EraseMmc(port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(port, MmcPartition.UserData));
|
||||
}
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
bytesWritten = 0;
|
||||
var operation = (MmcOperationIdValue)operationId;
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
Result res = _storageDevice.Get.Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Port port = _storageDevice.Get.GetPort();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case MmcOperationIdValue.GetSpeedMode:
|
||||
{
|
||||
if (buffer.Size < sizeof(SpeedMode))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceSpeedMode(out buffer.As<SpeedMode>(), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(SpeedMode);
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcOperationIdValue.GetCid:
|
||||
{
|
||||
if (buffer.Size < DeviceCidSize)
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceCid(buffer.Buffer.Slice(0, DeviceCidSize), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = DeviceCidSize;
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcOperationIdValue.GetPartitionSize:
|
||||
{
|
||||
if (buffer.Size < sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, GetPartitionCapacity(out uint numSectors, port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
buffer.As<long>() = numSectors * SectorSize;
|
||||
bytesWritten = sizeof(long);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcOperationIdValue.GetExtendedCsd:
|
||||
{
|
||||
if (buffer.Size < MmcExtendedCsdSize)
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
using var pooledBuffer = new PooledBuffer(MmcExtendedCsdSize, MmcExtendedCsdSize);
|
||||
if (pooledBuffer.GetSize() < MmcExtendedCsdSize)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceB.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetMmcExtendedCsd(pooledBuffer.GetBuffer(), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
pooledBuffer.GetBuffer().Slice(0, MmcExtendedCsdSize).CopyTo(buffer.Buffer);
|
||||
bytesWritten = MmcExtendedCsdSize;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWrittenBuffer1, out bytesWrittenBuffer2);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
private Result GetPartitionCapacity(out uint outNumSectors, Port port)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outNumSectors);
|
||||
|
||||
switch (_storageDevice.Get.GetPartition())
|
||||
{
|
||||
case MmcPartition.UserData:
|
||||
{
|
||||
Result res = _sdmmc.GetDeviceMemoryCapacity(out outNumSectors, port);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcPartition.BootPartition1:
|
||||
case MmcPartition.BootPartition2:
|
||||
{
|
||||
Result res = _sdmmc.GetMmcBootPartitionCapacity(out outNumSectors, port);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,141 +1,399 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
using LibHac.Sf;
|
||||
using IStorage = LibHac.FsSrv.Sf.IStorage;
|
||||
using MmcPartition = LibHac.Fs.MmcPartition;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
public class MmcManager : IStorageDeviceManager, IStorageDeviceOperator, ISdmmcDeviceManager
|
||||
internal class MmcManager : IStorageDeviceManager, IStorageDeviceOperator, ISdmmcDeviceManager
|
||||
{
|
||||
private Port _port;
|
||||
private const SdmmcHandle MmcHandle = 1;
|
||||
|
||||
private readonly Port _port;
|
||||
private bool _isInitialized;
|
||||
private bool _isActivated;
|
||||
private SdkMutexType _mutex;
|
||||
private SdkMutex _mutex;
|
||||
private readonly SdmmcStorage _sdmmcStorage;
|
||||
private PatrolReader _patrolReader;
|
||||
|
||||
public MmcManager()
|
||||
// LibHac additions
|
||||
private WeakRef<MmcManager> _selfReference;
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
private MmcManager(SdmmcApi sdmmc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_port = Port.Mmc0;
|
||||
_mutex = new SdkMutex();
|
||||
|
||||
_sdmmcStorage = new SdmmcStorage(_port, sdmmc);
|
||||
_patrolReader = new PatrolReader(_mutex, sdmmc);
|
||||
|
||||
_isInitialized = false;
|
||||
_isActivated = false;
|
||||
|
||||
// Missing: Setting the device address space
|
||||
|
||||
_sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public static SharedRef<MmcManager> CreateShared(SdmmcApi sdmmc)
|
||||
{
|
||||
var manager = new MmcManager(sdmmc);
|
||||
|
||||
using var sharedManager = new SharedRef<MmcManager>(manager);
|
||||
manager._selfReference.Set(in sharedManager);
|
||||
|
||||
return SharedRef<MmcManager>.CreateMove(ref sharedManager.Ref);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_patrolReader?.Dispose();
|
||||
_patrolReader = null;
|
||||
|
||||
_selfReference.Destroy();
|
||||
}
|
||||
|
||||
public void InitializeMmc()
|
||||
private Result ActivateMmc()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeMmc();
|
||||
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isActivated)
|
||||
return Result.Success;
|
||||
|
||||
Result res = SdmmcResultConverter.GetFsResult(_port, _sdmmc.Activate(_port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
_patrolReader.Start();
|
||||
_isActivated = true;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private void FinalizeMmc()
|
||||
{
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isInitialized)
|
||||
_sdmmc.Finalize(_port);
|
||||
}
|
||||
|
||||
private void InitializeMmc()
|
||||
{
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isInitialized)
|
||||
return;
|
||||
|
||||
_sdmmc.Initialize(_port);
|
||||
|
||||
// Missing: Register the device buffer
|
||||
// Missing: Allocate work buffer
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
isInserted = true;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out isValid);
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
isValid = Lock(ref scopedLock.Ref(), handle).IsSuccess();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.UnsupportedOperation.Log();
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result res = ActivateMmc();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using SharedRef<MmcManager> deviceOperator = SharedRef<MmcManager>.Create(in _selfReference);
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||
|
||||
Result res = OpenDeviceImpl(ref storageDevice.Ref, attribute);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||
|
||||
Result res = OpenDeviceImpl(ref storageDevice.Ref, attribute);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outStorage.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result OpenStorageDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
private Result OpenDeviceImpl(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result res = ActivateMmc();
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||
|
||||
switch ((MmcPartition)attribute)
|
||||
{
|
||||
case MmcPartition.UserData:
|
||||
{
|
||||
OpenDeviceUserDataPartition(ref storageDevice.Ref);
|
||||
break;
|
||||
}
|
||||
case MmcPartition.BootPartition1:
|
||||
{
|
||||
OpenDeviceBootPartition(MmcPartition.BootPartition1, ref storageDevice.Ref);
|
||||
break;
|
||||
}
|
||||
case MmcPartition.BootPartition2:
|
||||
{
|
||||
OpenDeviceBootPartition(MmcPartition.BootPartition2, ref storageDevice.Ref);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
|
||||
if (!storageDevice.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private void OpenDeviceUserDataPartition(ref SharedRef<IStorageDevice> outStorageDevice)
|
||||
{
|
||||
using SharedRef<ISdmmcDeviceManager> manager = SharedRef<ISdmmcDeviceManager>.Create(in _selfReference);
|
||||
|
||||
using SharedRef<MmcUserDataPartitionStorageDevice> storageDevice =
|
||||
MmcUserDataPartitionStorageDevice.CreateShared(ref manager.Ref, MmcHandle, _sdmmc);
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
}
|
||||
|
||||
private void OpenDeviceBootPartition(MmcPartition partition, ref SharedRef<IStorageDevice> outStorageDevice)
|
||||
{
|
||||
using SharedRef<ISdmmcDeviceManager> manager = SharedRef<ISdmmcDeviceManager>.Create(in _selfReference);
|
||||
|
||||
using SharedRef<MmcBootPartitionStorageDevice> storageDevice =
|
||||
MmcBootPartitionStorageDevice.CreateShared(partition, ref manager.Ref, MmcHandle, _sdmmc);
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
}
|
||||
|
||||
public Result PutToSleep()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (_isInitialized)
|
||||
_patrolReader.Sleep();
|
||||
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isInitialized)
|
||||
_sdmmc.PutMmcToSleep(_port);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Awaken()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isInitialized)
|
||||
{
|
||||
_sdmmc.AwakenMmc(_port);
|
||||
_patrolReader.Resume();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Shutdown()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (_isInitialized)
|
||||
_patrolReader.Stop();
|
||||
|
||||
FinalizeMmc();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.UnsupportedOperation.Log();
|
||||
}
|
||||
|
||||
public Result Lock(ref UniqueLockRef<SdkMutexType> outLock, SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>(ref _mutex.GetBase());
|
||||
|
||||
if (handle != MmcHandle)
|
||||
return ResultFs.PortMmcStorageDeviceInvalidated.Log();
|
||||
|
||||
outLock.Set(ref scopedLock.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Fs.IStorage GetStorage()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _sdmmcStorage;
|
||||
}
|
||||
|
||||
public Port GetPort()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _port;
|
||||
}
|
||||
|
||||
public void NotifyCloseStorageDevice(SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void NotifyCloseStorageDevice(SdmmcHandle handle) { }
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var operation = (MmcManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case MmcManagerOperationIdValue.SuspendControl:
|
||||
case MmcManagerOperationIdValue.ResumeControl:
|
||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||
|
||||
case MmcManagerOperationIdValue.SuspendPatrol:
|
||||
{
|
||||
_patrolReader.Sleep();
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcManagerOperationIdValue.ResumePatrol:
|
||||
{
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
_patrolReader.Resume();
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
bytesWritten = 0;
|
||||
var operation = (MmcManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case MmcManagerOperationIdValue.GetPatrolCount:
|
||||
{
|
||||
if (buffer.Size < sizeof(uint))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
Result res = _patrolReader.GetPatrolCount(out buffer.As<uint>());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(uint);
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
bytesWrittenBuffer1 = 0;
|
||||
bytesWrittenBuffer2 = 0;
|
||||
var operation = (MmcManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case MmcManagerOperationIdValue.GetAndClearErrorInfo:
|
||||
{
|
||||
if (buffer1.Size < Unsafe.SizeOf<StorageErrorInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
Result res = Common.GetAndClearSdmmcStorageErrorInfo(out buffer1.As<StorageErrorInfo>(),
|
||||
out bytesWrittenBuffer2, buffer2.Buffer, _sdmmc);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWrittenBuffer1 = Unsafe.SizeOf<StorageErrorInfo>();
|
||||
return Result.Success;
|
||||
}
|
||||
case MmcManagerOperationIdValue.GetAndClearPatrolReadAllocateBufferCount:
|
||||
{
|
||||
if (buffer1.Size < sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
if (buffer2.Size < sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
_patrolReader.GetAndClearAllocateCount(out buffer1.As<ulong>(), out buffer2.As<ulong>());
|
||||
|
||||
bytesWrittenBuffer1 = sizeof(long);
|
||||
bytesWrittenBuffer2 = sizeof(long);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
}
|
|
@ -10,20 +10,30 @@ using MmcPartition = LibHac.Sdmmc.MmcPartition;
|
|||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
internal class MmcPartitionStorageDevice : IDisposable
|
||||
internal abstract class MmcPartitionStorageDevice : IDisposable
|
||||
{
|
||||
private SharedRef<ISdmmcDeviceManager> _manager;
|
||||
private SdmmcHandle _handle;
|
||||
private MmcPartition _partition;
|
||||
private readonly SdmmcHandle _handle;
|
||||
private readonly MmcPartition _partition;
|
||||
|
||||
public MmcPartitionStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle, MmcPartition partition)
|
||||
// LibHac addition
|
||||
protected WeakRef<MmcPartitionStorageDevice> SelfReference;
|
||||
protected readonly SdmmcApi Sdmmc;
|
||||
|
||||
protected MmcPartitionStorageDevice(MmcPartition partition, ref SharedRef<ISdmmcDeviceManager> manager,
|
||||
SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
{
|
||||
_partition = partition;
|
||||
_manager = SharedRef<ISdmmcDeviceManager>.CreateMove(ref manager);
|
||||
_handle = handle;
|
||||
_partition = partition;
|
||||
Sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
public void Dispose()
|
||||
{
|
||||
_manager.Destroy();
|
||||
SelfReference.Destroy();
|
||||
}
|
||||
|
||||
public Result GetHandle(out SdmmcHandle handle)
|
||||
{
|
||||
|
@ -41,7 +51,18 @@ internal class MmcPartitionStorageDevice : IDisposable
|
|||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using SharedRef<MmcPartitionStorageDevice> storageDevice =
|
||||
SharedRef<MmcPartitionStorageDevice>.Create(in SelfReference);
|
||||
|
||||
using var deviceOperator =
|
||||
new SharedRef<MmcDeviceOperator>(new MmcDeviceOperator(ref storageDevice.Ref, Sdmmc));
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Lock(ref UniqueLockRef<SdkMutexType> outLock)
|
||||
|
@ -63,12 +84,13 @@ internal class MmcPartitionStorageDevice : IDisposable
|
|||
// 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
|
||||
internal abstract class MmcPartitionStorageDeviceInterfaceAdapter : MmcPartitionStorageDevice, IStorageDevice
|
||||
{
|
||||
private IStorage _baseStorage;
|
||||
private readonly IStorage _baseStorage;
|
||||
|
||||
public MmcPartitionStorageDeviceInterfaceAdapter(IStorage baseStorage, ref SharedRef<ISdmmcDeviceManager> manager,
|
||||
SdmmcHandle handle, MmcPartition partition) : base(ref manager, handle, partition)
|
||||
protected MmcPartitionStorageDeviceInterfaceAdapter(IStorage baseStorage, MmcPartition partition,
|
||||
ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
: base(partition, ref manager, handle, sdmmc)
|
||||
{
|
||||
_baseStorage = baseStorage;
|
||||
}
|
||||
|
@ -109,10 +131,22 @@ internal class MmcPartitionStorageDeviceInterfaceAdapter : MmcPartitionStorageDe
|
|||
|
||||
internal class MmcUserDataPartitionStorageDevice : MmcPartitionStorageDeviceInterfaceAdapter
|
||||
{
|
||||
public MmcUserDataPartitionStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle)
|
||||
: base(manager.Get.GetStorage(), ref manager, handle, MmcPartition.UserData)
|
||||
private MmcUserDataPartitionStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle,
|
||||
SdmmcApi sdmmc)
|
||||
: base(manager.Get.GetStorage(), MmcPartition.UserData, ref manager, handle, sdmmc)
|
||||
{ }
|
||||
|
||||
public static SharedRef<MmcUserDataPartitionStorageDevice> CreateShared(ref SharedRef<ISdmmcDeviceManager> manager,
|
||||
SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
{
|
||||
var storageDevice = new MmcUserDataPartitionStorageDevice(ref manager, handle, sdmmc);
|
||||
|
||||
using var sharedStorageDevice = new SharedRef<MmcUserDataPartitionStorageDevice>(storageDevice);
|
||||
storageDevice.SelfReference.Set(in sharedStorageDevice);
|
||||
|
||||
return SharedRef<MmcUserDataPartitionStorageDevice>.CreateMove(ref sharedStorageDevice.Ref);
|
||||
}
|
||||
|
||||
public override Result Read(long offset, OutBuffer destination, long size)
|
||||
{
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
@ -157,12 +191,20 @@ internal class MmcUserDataPartitionStorageDevice : MmcPartitionStorageDeviceInte
|
|||
|
||||
internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfaceAdapter
|
||||
{
|
||||
private SdmmcApi _sdmmc;
|
||||
private MmcBootPartitionStorageDevice(Fs.MmcPartition partition, ref SharedRef<ISdmmcDeviceManager> manager,
|
||||
SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
: base(manager.Get.GetStorage(), GetPartition(partition), ref manager, handle, sdmmc)
|
||||
{ }
|
||||
|
||||
public MmcBootPartitionStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, Fs.MmcPartition partition,
|
||||
SdmmcHandle handle, SdmmcApi sdmmc) : base(manager.Get.GetStorage(), ref manager, handle, GetPartition(partition))
|
||||
public static SharedRef<MmcBootPartitionStorageDevice> CreateShared(Fs.MmcPartition partition,
|
||||
ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
{
|
||||
_sdmmc = sdmmc;
|
||||
var storageDevice = new MmcBootPartitionStorageDevice(partition, ref manager, handle, sdmmc);
|
||||
|
||||
using var sharedStorageDevice = new SharedRef<MmcBootPartitionStorageDevice>(storageDevice);
|
||||
storageDevice.SelfReference.Set(in sharedStorageDevice);
|
||||
|
||||
return SharedRef<MmcBootPartitionStorageDevice>.CreateMove(ref sharedStorageDevice.Ref);
|
||||
}
|
||||
|
||||
private static MmcPartition GetPartition(Fs.MmcPartition partition)
|
||||
|
@ -188,7 +230,7 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
Result res = Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), GetPartition()));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(GetPort(), GetPartition()));
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -199,7 +241,7 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
}
|
||||
finally
|
||||
{
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -210,7 +252,7 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
Result res = Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), GetPartition()));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(GetPort(), GetPartition()));
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -221,7 +263,7 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
}
|
||||
finally
|
||||
{
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -236,11 +278,11 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
|
||||
Port port = GetPort();
|
||||
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(port, GetPartition()));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(port, GetPartition()));
|
||||
|
||||
try
|
||||
{
|
||||
res = SdmmcResultConverter.GetFsResult(port, _sdmmc.GetMmcBootPartitionCapacity(out uint numSectors, port));
|
||||
res = SdmmcResultConverter.GetFsResult(port, Sdmmc.GetMmcBootPartitionCapacity(out uint numSectors, port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
size = numSectors * SdmmcApi.SectorSize;
|
||||
|
@ -249,7 +291,7 @@ internal class MmcBootPartitionStorageDevice : MmcPartitionStorageDeviceInterfac
|
|||
}
|
||||
finally
|
||||
{
|
||||
Abort.DoAbortUnlessSuccess(_sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
Abort.DoAbortUnlessSuccess(Sdmmc.SelectMmcPartition(GetPort(), MmcPartition.UserData));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
using System;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
internal class PatrolReader
|
||||
{
|
||||
public PatrolReader(SdkMutex mutex)
|
||||
public PatrolReader(SdkMutex mutex, SdmmcApi sdmmc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ internal class PatrolReader
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void GetAndClearAllocateCount(out long outSuccessCount, out long outFailureCount)
|
||||
public void GetAndClearAllocateCount(out ulong outSuccessCount, out ulong outFailureCount)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace LibHac.SdmmcSrv;
|
|||
internal class SdCardDetectionEventManager : CardDeviceDetectionEventManager
|
||||
{
|
||||
// LibHac addition
|
||||
private SdmmcApi _sdmmc;
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
public SdCardDetectionEventManager(Port port, SdmmcApi sdmmc)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
using LibHac.Sf;
|
||||
using static LibHac.Sdmmc.SdmmcApi;
|
||||
using static LibHac.SdmmcSrv.SdmmcResultConverter;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
|
@ -9,9 +13,13 @@ internal class SdCardDeviceOperator : IStorageDeviceOperator
|
|||
{
|
||||
private SharedRef<SdCardStorageDevice> _storageDevice;
|
||||
|
||||
public SdCardDeviceOperator(ref SharedRef<SdCardStorageDevice> storageDevice)
|
||||
// LibHac additions
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
public SdCardDeviceOperator(ref SharedRef<SdCardStorageDevice> storageDevice, SdmmcApi sdmmc)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_storageDevice = SharedRef<SdCardStorageDevice>.CreateMove(ref storageDevice);
|
||||
_sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -21,34 +29,123 @@ internal class SdCardDeviceOperator : IStorageDeviceOperator
|
|||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
bytesWritten = 0;
|
||||
var operation = (SdCardOperationIdValue)operationId;
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
Result res = _storageDevice.Get.Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
Port port = _storageDevice.Get.GetPort();
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case SdCardOperationIdValue.GetSpeedMode:
|
||||
{
|
||||
if (buffer.Size < sizeof(SpeedMode))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceSpeedMode(out buffer.As<SpeedMode>(), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(SpeedMode);
|
||||
return Result.Success;
|
||||
}
|
||||
case SdCardOperationIdValue.GetCid:
|
||||
{
|
||||
if (buffer.Size < DeviceCidSize)
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceCid(buffer.Buffer.Slice(0, DeviceCidSize), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = DeviceCidSize;
|
||||
return Result.Success;
|
||||
}
|
||||
case SdCardOperationIdValue.GetUserAreaNumSectors:
|
||||
{
|
||||
if (buffer.Size < sizeof(uint))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceMemoryCapacity(out buffer.As<uint>(), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(uint);
|
||||
return Result.Success;
|
||||
}
|
||||
case SdCardOperationIdValue.GetUserAreaSize:
|
||||
{
|
||||
if (buffer.Size < sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetDeviceMemoryCapacity(out uint numSectors, port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
buffer.As<long>() = numSectors * SectorSize;
|
||||
bytesWritten = sizeof(long);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
case SdCardOperationIdValue.GetProtectedAreaNumSectors:
|
||||
{
|
||||
if (buffer.Size < sizeof(uint))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetSdCardProtectedAreaCapacity(out buffer.As<uint>(), port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWritten = sizeof(uint);
|
||||
return Result.Success;
|
||||
}
|
||||
case SdCardOperationIdValue.GetProtectedAreaSize:
|
||||
{
|
||||
if (buffer.Size < sizeof(long))
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
res = GetFsResult(port, _sdmmc.GetSdCardProtectedAreaCapacity(out uint numSectors, port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
buffer.As<long>() = numSectors * SectorSize;
|
||||
bytesWritten = sizeof(long);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWrittenBuffer1, out bytesWrittenBuffer2);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
}
|
|
@ -1,28 +1,56 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Sf;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
using LibHac.Sf;
|
||||
using LibHac.Util;
|
||||
using IStorage = LibHac.Fs.IStorage;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
||||
public class SdCardManager : IStorageDeviceManager, IStorageDeviceOperator, ISdmmcDeviceManager
|
||||
{
|
||||
private Port _port;
|
||||
private const SdmmcHandle InvalidHandle = 0;
|
||||
private const int OpenCountFinalized = -1;
|
||||
|
||||
private readonly Port _port;
|
||||
private bool _isInitialized;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks how many storage devices are open. A value of -1 indicates that the SD card device
|
||||
/// has been shut down and won't be opened again.
|
||||
/// </summary>
|
||||
private int _openCount;
|
||||
private SdkMutexType _mutex;
|
||||
private SdmmcStorage _sdStorage;
|
||||
private readonly SdmmcStorage _sdStorage;
|
||||
private SdmmcHandle _handle;
|
||||
private Optional<SdCardDetectionEventManager> _detectionEventManager;
|
||||
|
||||
public SdCardManager(SdmmcApi sdmmc)
|
||||
// LibHac additions
|
||||
private WeakRef<SdCardManager> _selfReference;
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
private SdCardManager(SdmmcApi sdmmc)
|
||||
{
|
||||
_port = Port.SdCard0;
|
||||
_mutex = new SdkMutexType();
|
||||
_sdStorage = new SdmmcStorage(_port, sdmmc);
|
||||
_sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public static SharedRef<SdCardManager> CreateShared(SdmmcApi sdmmc)
|
||||
{
|
||||
var manager = new SdCardManager(sdmmc);
|
||||
|
||||
using var sharedManager = new SharedRef<SdCardManager>(manager);
|
||||
manager._selfReference.Set(in sharedManager);
|
||||
|
||||
return SharedRef<SdCardManager>.CreateMove(ref sharedManager.Ref);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
@ -30,120 +58,354 @@ public class SdCardManager : IStorageDeviceManager, IStorageDeviceOperator, ISdm
|
|||
if (_detectionEventManager.HasValue)
|
||||
{
|
||||
_detectionEventManager.Value.Dispose();
|
||||
_detectionEventManager = default;
|
||||
_detectionEventManager.Clear();
|
||||
}
|
||||
|
||||
_selfReference.Destroy();
|
||||
}
|
||||
|
||||
private void DeactivateIfCardRemoved()
|
||||
{
|
||||
if (_openCount > 0 && _sdmmc.IsSdCardRemoved(_port))
|
||||
{
|
||||
_sdmmc.Deactivate(_port);
|
||||
_handle++;
|
||||
_openCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeSd()
|
||||
private bool IsShutDown()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _openCount < 0;
|
||||
}
|
||||
|
||||
private void InitializeSd()
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (_isInitialized)
|
||||
return;
|
||||
|
||||
// Missing: Work buffer management
|
||||
|
||||
if (_detectionEventManager.HasValue)
|
||||
{
|
||||
_detectionEventManager.Value.Dispose();
|
||||
_detectionEventManager.Clear();
|
||||
}
|
||||
|
||||
_detectionEventManager.Set(new SdCardDetectionEventManager(_port, _sdmmc));
|
||||
|
||||
_isInitialized = true;
|
||||
}
|
||||
|
||||
public Result IsInserted(out bool isInserted)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeSd();
|
||||
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
DeactivateIfCardRemoved();
|
||||
|
||||
isInserted = _sdmmc.IsSdCardInserted(_port);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid, SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
isValid = Lock(ref scopedLock.Ref(), handle).IsSuccess();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenDetectionEvent(ref SharedRef<IEventNotifier> outDetectionEvent)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeSd();
|
||||
|
||||
Result res = _detectionEventManager.Value.CreateDetectionEvent(ref outDetectionEvent);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeSd();
|
||||
|
||||
using SharedRef<SdCardManager> deviceOperator = SharedRef<SdCardManager>.Create(in _selfReference);
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
|
||||
}
|
||||
|
||||
public Result OpenDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||
|
||||
Result res = OpenDeviceImpl(ref storageDevice.Ref);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenStorage(ref SharedRef<IStorage> outStorage, ulong attribute)
|
||||
public Result OpenStorage(ref SharedRef<IStorageSf> outStorage, ulong attribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var storageDevice = new SharedRef<IStorageDevice>();
|
||||
|
||||
Result res = OpenDeviceImpl(ref storageDevice.Ref);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
outStorage.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result OpenStorageDevice(ref SharedRef<IStorageDevice> outStorageDevice, ulong attribute)
|
||||
private Result OpenDeviceImpl(ref SharedRef<IStorageDevice> outStorageDevice)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeSd();
|
||||
|
||||
Result res = EnsureActivated(out SdmmcHandle handle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using SharedRef<ISdmmcDeviceManager> manager = SharedRef<ISdmmcDeviceManager>.Create(in _selfReference);
|
||||
|
||||
using SharedRef<SdCardStorageDevice>
|
||||
storageDevice = SdCardStorageDevice.CreateShared(ref manager.Ref, handle, _sdmmc);
|
||||
|
||||
if (!storageDevice.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outStorageDevice.SetByMove(ref storageDevice.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private Result EnsureActivated(out SdmmcHandle outHandle)
|
||||
{
|
||||
UnsafeHelpers.SkipParamInit(out outHandle);
|
||||
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
DeactivateIfCardRemoved();
|
||||
|
||||
if (IsShutDown())
|
||||
{
|
||||
outHandle = InvalidHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
// Activate the device if we're the first to open it.
|
||||
if (_openCount == 0)
|
||||
{
|
||||
Result res = SdmmcResultConverter.GetFsResult(_port, _sdmmc.Activate(_port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
// Increment the handle if this is the first time the device has been activated.
|
||||
if (_handle == 0)
|
||||
{
|
||||
_handle++;
|
||||
}
|
||||
|
||||
if (_openCount++ >= 0)
|
||||
{
|
||||
outHandle = _handle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
outHandle = InvalidHandle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
// The device has already been activated. Just increment the open count.
|
||||
_openCount++;
|
||||
outHandle = _handle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result PutToSleep()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
if (_isInitialized)
|
||||
_sdmmc.PutSdCardToSleep(_port);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Awaken()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
if (_isInitialized)
|
||||
_sdmmc.AwakenSdCard(_port);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Shutdown()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
if (_isInitialized)
|
||||
{
|
||||
_sdmmc.Deactivate(_port);
|
||||
_handle++;
|
||||
_openCount = OpenCountFinalized;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Invalidate()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
if (_openCount > 0)
|
||||
{
|
||||
_sdmmc.Deactivate(_port);
|
||||
_handle++;
|
||||
_openCount = 0;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Lock(ref UniqueLockRef<SdkMutexType> outLock, SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
InitializeSd();
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>(ref _mutex);
|
||||
|
||||
DeactivateIfCardRemoved();
|
||||
|
||||
if (handle == InvalidHandle || _handle != handle)
|
||||
return ResultFs.PortSdCardStorageDeviceInvalidated.Log();
|
||||
|
||||
outLock.Set(ref scopedLock.Ref());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Fs.IStorage GetStorage()
|
||||
public IStorage GetStorage()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _sdStorage;
|
||||
}
|
||||
|
||||
public Port GetPort()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _port;
|
||||
}
|
||||
|
||||
public void NotifyCloseStorageDevice(uint handle)
|
||||
public void NotifyCloseStorageDevice(SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
if (_handle != handle)
|
||||
return;
|
||||
|
||||
if (_openCount > 0)
|
||||
{
|
||||
_openCount--;
|
||||
|
||||
if (_openCount == 0)
|
||||
{
|
||||
_sdmmc.Deactivate(_port);
|
||||
_handle++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Result Operate(int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var operation = (SdCardManagerOperationIdValue)operationId;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case SdCardManagerOperationIdValue.SuspendControl:
|
||||
case SdCardManagerOperationIdValue.ResumeControl:
|
||||
return ResultFs.StorageDeviceInvalidOperation.Log();
|
||||
|
||||
case SdCardManagerOperationIdValue.SimulateDetectionEventSignaled:
|
||||
_detectionEventManager.Value.SignalAll();
|
||||
return Result.Success;
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateIn(InBuffer buffer, long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateOut(out long bytesWritten, OutBuffer buffer, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateOut2(out long bytesWrittenBuffer1, OutBuffer buffer1, out long bytesWrittenBuffer2,
|
||||
OutBuffer buffer2, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var operation = (SdCardManagerOperationIdValue)operationId;
|
||||
bytesWrittenBuffer1 = 0;
|
||||
bytesWrittenBuffer2 = 0;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case SdCardManagerOperationIdValue.GetAndClearErrorInfo:
|
||||
{
|
||||
if (buffer1.Size < Unsafe.SizeOf<StorageErrorInfo>())
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
|
||||
Result res = GetAndClearSdCardErrorInfo(out buffer1.As<StorageErrorInfo>(), out bytesWrittenBuffer2,
|
||||
buffer2.Buffer);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
bytesWrittenBuffer1 = Unsafe.SizeOf<StorageErrorInfo>();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
default:
|
||||
return ResultFs.InvalidArgument.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result OperateInOut(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer, long offset, long size,
|
||||
int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
public Result OperateIn2Out(out long bytesWritten, OutBuffer outBuffer, InBuffer inBuffer1, InBuffer inBuffer2,
|
||||
long offset, long size, int operationId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out bytesWritten);
|
||||
|
||||
return ResultFs.NotImplemented.Log();
|
||||
}
|
||||
|
||||
private Result GetAndClearSdCardErrorInfo(out StorageErrorInfo outStorageErrorInfo, out long outLogSize,
|
||||
Span<byte> logBuffer)
|
||||
{
|
||||
using ScopedLock<SdkMutexType> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
Result res = Common.GetAndClearSdmmcStorageErrorInfo(out outStorageErrorInfo, out outLogSize, logBuffer, _sdmmc);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using System;
|
||||
using LibHac.Common;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSrv.Storage.Sf;
|
||||
using LibHac.Os;
|
||||
using LibHac.Sdmmc;
|
||||
|
@ -10,52 +10,112 @@ namespace LibHac.SdmmcSrv;
|
|||
internal class SdCardStorageDevice : SdmmcStorageInterfaceAdapter, IStorageDevice
|
||||
{
|
||||
private SharedRef<ISdmmcDeviceManager> _manager;
|
||||
private SdmmcHandle _handle;
|
||||
private readonly SdmmcHandle _handle;
|
||||
|
||||
public SdCardStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle)
|
||||
// LibHac additions
|
||||
private WeakRef<SdCardStorageDevice> _selfReference;
|
||||
private readonly SdmmcApi _sdmmc;
|
||||
|
||||
private SdCardStorageDevice(ref SharedRef<ISdmmcDeviceManager> manager, SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
: base(manager.Get.GetStorage())
|
||||
{
|
||||
_manager = SharedRef<ISdmmcDeviceManager>.CreateMove(ref manager);
|
||||
_handle = handle;
|
||||
_sdmmc = sdmmc;
|
||||
}
|
||||
|
||||
public static SharedRef<SdCardStorageDevice> CreateShared(ref SharedRef<ISdmmcDeviceManager> manager,
|
||||
SdmmcHandle handle, SdmmcApi sdmmc)
|
||||
{
|
||||
var device = new SdCardStorageDevice(ref manager, handle, sdmmc);
|
||||
|
||||
using var sharedDevice = new SharedRef<SdCardStorageDevice>(device);
|
||||
device._selfReference.Set(in sharedDevice);
|
||||
|
||||
return SharedRef<SdCardStorageDevice>.CreateMove(ref sharedDevice.Ref);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_manager.Get.NotifyCloseStorageDevice(_handle);
|
||||
_manager.Destroy();
|
||||
|
||||
_selfReference.Destroy();
|
||||
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public Port GetPort()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _manager.Get.GetPort();
|
||||
}
|
||||
|
||||
public Result GetHandle(out uint handle)
|
||||
public Result GetHandle(out SdmmcHandle handle)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
handle = _handle;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result IsHandleValid(out bool isValid)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
isValid = Lock(ref scopedLock.Ref()).IsSuccess();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result OpenOperator(ref SharedRef<IStorageDeviceOperator> outDeviceOperator)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using SharedRef<SdCardStorageDevice> storageDevice = SharedRef<SdCardStorageDevice>.Create(in _selfReference);
|
||||
|
||||
using var deviceOperator =
|
||||
new SharedRef<SdCardDeviceOperator>(new SdCardDeviceOperator(ref storageDevice.Ref, _sdmmc));
|
||||
|
||||
if (!deviceOperator.HasValue)
|
||||
return ResultFs.AllocationMemoryFailedInSdmmcStorageServiceA.Log();
|
||||
|
||||
outDeviceOperator.SetByMove(ref deviceOperator.Ref);
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Lock(ref UniqueLockRef<SdkMutexType> outLock)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result res = _manager.Get.Lock(ref outLock, _handle);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override Result Read(long offset, OutBuffer destination, long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
Result res = Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return base.Read(offset, destination, size).Ret();
|
||||
}
|
||||
|
||||
public override Result Write(long offset, InBuffer source, long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
Result res = Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return base.Write(offset, source, size).Ret();
|
||||
}
|
||||
|
||||
public override Result GetSize(out long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
using var scopedLock = new UniqueLockRef<SdkMutexType>();
|
||||
|
||||
Result res = Lock(ref scopedLock.Ref());
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
return base.GetSize(out size).Ret();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Sdmmc;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
@ -22,11 +22,445 @@ public static class SdmmcResultConverter
|
|||
|
||||
private static Result GetFsResultFromMmcResult(Result result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (ResultSdmmc.NoDevice.Includes(result))
|
||||
return ResultFs.PortMmcNoDevice.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotActivated.Includes(result))
|
||||
return ResultFs.PortMmcNotActivated.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceRemoved.Includes(result))
|
||||
return ResultFs.PortMmcDeviceRemoved.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotAwakened.Includes(result))
|
||||
return ResultFs.PortMmcNotAwakened.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.ResponseIndexError.Includes(result))
|
||||
return ResultFs.PortMmcResponseIndexError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseEndBitError.Includes(result))
|
||||
return ResultFs.PortMmcResponseEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseCrcError.Includes(result))
|
||||
return ResultFs.PortMmcResponseCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseTimeoutError.Includes(result))
|
||||
return ResultFs.PortMmcResponseTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataEndBitError.Includes(result))
|
||||
return ResultFs.PortMmcDataEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataCrcError.Includes(result))
|
||||
return ResultFs.PortMmcDataCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataTimeoutError.Includes(result))
|
||||
return ResultFs.PortMmcDataTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseIndexError.Includes(result))
|
||||
return ResultFs.PortMmcAutoCommandResponseIndexError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseEndBitError.Includes(result))
|
||||
return ResultFs.PortMmcAutoCommandResponseEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseCrcError.Includes(result))
|
||||
return ResultFs.PortMmcAutoCommandResponseCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseTimeoutError.Includes(result))
|
||||
return ResultFs.PortMmcAutoCommandResponseTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandCompleteSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcCommandCompleteSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.TransferCompleteSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcTransferCompleteSwTimeout.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.DeviceStatusAddressOutOfRange.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusAddressOutOfRange.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusAddressMisaligned.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusAddressMisalign.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusBlockLenError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusBlockLenError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseSeqError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusEraseSeqError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseParam.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusEraseParam.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusWpViolation.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusWpViolation.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusLockUnlockFailed.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusLockUnlockFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusComCrcError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusComCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusIllegalCommand.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusIllegalCommand.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusDeviceEccFailed.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusDeviceEccFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusCcError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusCcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusCidCsdOverwrite.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusCidCsdOverwrite.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusWpEraseSkip.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusWpEraseSkip.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseReset.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusEraseReset.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusSwitchError.Includes(result))
|
||||
return ResultFs.PortMmcDeviceStatusSwitchError.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.UnexpectedDeviceState.Includes(result))
|
||||
return ResultFs.PortMmcUnexpectedDeviceState.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedDeviceCsdValue.Includes(result))
|
||||
return ResultFs.PortMmcUnexpectedDeviceCsdValue.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AbortTransactionSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcAbortTransactionSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandInhibitCmdSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcCommandInhibitCmdSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandInhibitDatSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcCommandInhibitDatSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.BusySoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcBusySwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.IssueTuningCommandSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcIssueTuningCommandSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.TuningFailed.Includes(result))
|
||||
return ResultFs.PortMmcTuningFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcInitializationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcMmcInitializationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcNotSupportExtendedCsd.Includes(result))
|
||||
return ResultFs.PortMmcMmcNotSupportExtendedCsd.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedMmcExtendedCsdValue.Includes(result))
|
||||
return ResultFs.PortMmcUnexpectedMmcExtendedCsdValue.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcEraseSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcMmcEraseSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardValidationError.Includes(result))
|
||||
return ResultFs.PortMmcSdCardValidationError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardInitializationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcSdCardInitializationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardGetValidRcaSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcSdCardGetValidRcaSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedSdCardAcmdDisabled.Includes(result))
|
||||
return ResultFs.PortMmcUnexpectedSdCardAcmdDisabled.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportSwitchFunctionStatus.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNotSupportSwitchFunctionStatus.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedSdCardSwitchFunctionStatus.Includes(result))
|
||||
return ResultFs.PortMmcUnexpectedSdCardSwitchFunctionStatus.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportAccessMode.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNotSupportAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNot4BitBusWidthAtUhsIMode.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNot4BitBusWidthAtUhsIMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportSdr104AndSdr50.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNotSupportSdr104AndSdr50.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardCannotSwitchAccessMode.Includes(result))
|
||||
return ResultFs.PortMmcSdCardCannotSwitchedAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardFailedSwitchAccessMode.Includes(result))
|
||||
return ResultFs.PortMmcSdCardFailedSwitchedAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardUnacceptableCurrentConsumption.Includes(result))
|
||||
return ResultFs.PortMmcSdCardUnacceptableCurrentConsumption.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotReadyToVoltageSwitch.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNotReadyToVoltageSwitch.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotCompleteVoltageSwitch.Includes(result))
|
||||
return ResultFs.PortMmcSdCardNotCompleteVoltageSwitch.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.InternalClockStableSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcInternalClockStableSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardUnknownAutoCmdError.Includes(result))
|
||||
return ResultFs.PortMmcSdHostStandardUnknownAutoCmdError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardUnknownError.Includes(result))
|
||||
return ResultFs.PortMmcSdHostStandardUnknownError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdmmcDllCalibrationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcSdmmcDllCalibrationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdmmcDllApplicationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcSdmmcDllApplicationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardFailSwitchTo18V.Includes(result))
|
||||
return ResultFs.PortMmcSdHostStandardFailSwitchTo18V.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.NoWaitedInterrupt.Includes(result))
|
||||
return ResultFs.PortMmcNoWaitedInterrupt.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.WaitInterruptSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortMmcWaitInterruptSwTimeout.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.AbortCommandIssued.Includes(result))
|
||||
return ResultFs.PortMmcAbortCommandIssued.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.NotSupported.Includes(result))
|
||||
return ResultFs.PortMmcNotSupported.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotImplemented.Includes(result))
|
||||
return ResultFs.PortMmcNotImplemented.LogConverted(result);
|
||||
|
||||
return ResultFs.PortMmcUnexpected.LogConverted(result);
|
||||
}
|
||||
|
||||
private static Result GetFsResultFromSdCardResult(Result result)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (ResultSdmmc.NoDevice.Includes(result))
|
||||
return ResultFs.PortSdCardNoDevice.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotActivated.Includes(result))
|
||||
return ResultFs.PortSdCardNotActivated.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceRemoved.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceRemoved.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotAwakened.Includes(result))
|
||||
return ResultFs.PortSdCardNotAwakened.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.ResponseIndexError.Includes(result))
|
||||
return ResultFs.PortSdCardResponseIndexError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseEndBitError.Includes(result))
|
||||
return ResultFs.PortSdCardResponseEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseCrcError.Includes(result))
|
||||
return ResultFs.PortSdCardResponseCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.ResponseTimeoutError.Includes(result))
|
||||
return ResultFs.PortSdCardResponseTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataEndBitError.Includes(result))
|
||||
return ResultFs.PortSdCardDataEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataCrcError.Includes(result))
|
||||
return ResultFs.PortSdCardDataCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DataTimeoutError.Includes(result))
|
||||
return ResultFs.PortSdCardDataTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseIndexError.Includes(result))
|
||||
return ResultFs.PortSdCardAutoCommandResponseIndexError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseEndBitError.Includes(result))
|
||||
return ResultFs.PortSdCardAutoCommandResponseEndBitError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseCrcError.Includes(result))
|
||||
return ResultFs.PortSdCardAutoCommandResponseCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AutoCommandResponseTimeoutError.Includes(result))
|
||||
return ResultFs.PortSdCardAutoCommandResponseTimeoutError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandCompleteSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardCommandCompleteSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.TransferCompleteSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardTransferCompleteSwTimeout.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.DeviceStatusAddressOutOfRange.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusAddressOutOfRange.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusAddressMisaligned.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusAddressMisalign.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusBlockLenError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusBlockLenError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseSeqError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusEraseSeqError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseParam.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusEraseParam.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusWpViolation.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusWpViolation.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusLockUnlockFailed.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusLockUnlockFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusComCrcError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusComCrcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusIllegalCommand.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusIllegalCommand.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusDeviceEccFailed.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusDeviceEccFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusCcError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusCcError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusCidCsdOverwrite.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusCidCsdOverwrite.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusWpEraseSkip.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusWpEraseSkip.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusEraseReset.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusEraseReset.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.DeviceStatusSwitchError.Includes(result))
|
||||
return ResultFs.PortSdCardDeviceStatusSwitchError.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.UnexpectedDeviceState.Includes(result))
|
||||
return ResultFs.PortSdCardUnexpectedDeviceState.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedDeviceCsdValue.Includes(result))
|
||||
return ResultFs.PortSdCardUnexpectedDeviceCsdValue.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.AbortTransactionSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardAbortTransactionSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandInhibitCmdSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardCommandInhibitCmdSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.CommandInhibitDatSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardCommandInhibitDatSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.BusySoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardBusySwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.IssueTuningCommandSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardIssueTuningCommandSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.TuningFailed.Includes(result))
|
||||
return ResultFs.PortSdCardTuningFailed.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcInitializationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardMmcInitializationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcNotSupportExtendedCsd.Includes(result))
|
||||
return ResultFs.PortSdCardMmcNotSupportExtendedCsd.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedMmcExtendedCsdValue.Includes(result))
|
||||
return ResultFs.PortSdCardUnexpectedMmcExtendedCsdValue.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.MmcEraseSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardMmcEraseSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardValidationError.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardValidationError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardInitializationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardInitializationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardGetValidRcaSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardGetValidRcaSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedSdCardAcmdDisabled.Includes(result))
|
||||
return ResultFs.PortSdCardUnexpectedSdCardAcmdDisabled.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportSwitchFunctionStatus.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNotSupportSwitchFunctionStatus.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.UnexpectedSdCardSwitchFunctionStatus.Includes(result))
|
||||
return ResultFs.PortSdCardUnexpectedSdCardSwitchFunctionStatus.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportAccessMode.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNotSupportAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNot4BitBusWidthAtUhsIMode.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNot4BitBusWidthAtUhsIMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotSupportSdr104AndSdr50.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNotSupportSdr104AndSdr50.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardCannotSwitchAccessMode.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardCannotSwitchedAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardFailedSwitchAccessMode.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardFailedSwitchedAccessMode.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardUnacceptableCurrentConsumption.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardUnacceptableCurrentConsumption.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotReadyToVoltageSwitch.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNotReadyToVoltageSwitch.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdCardNotCompleteVoltageSwitch.Includes(result))
|
||||
return ResultFs.PortSdCardSdCardNotCompleteVoltageSwitch.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.InternalClockStableSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardInternalClockStableSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardUnknownAutoCmdError.Includes(result))
|
||||
return ResultFs.PortSdCardSdHostStandardUnknownAutoCmdError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardUnknownError.Includes(result))
|
||||
return ResultFs.PortSdCardSdHostStandardUnknownError.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdmmcDllCalibrationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardSdmmcDllCalibrationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdmmcDllApplicationSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardSdmmcDllApplicationSwTimeout.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.SdHostStandardFailSwitchTo18V.Includes(result))
|
||||
return ResultFs.PortSdCardSdHostStandardFailSwitchTo18V.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.NoWaitedInterrupt.Includes(result))
|
||||
return ResultFs.PortSdCardNoWaitedInterrupt.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.WaitInterruptSoftwareTimeout.Includes(result))
|
||||
return ResultFs.PortSdCardWaitInterruptSwTimeout.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.AbortCommandIssued.Includes(result))
|
||||
return ResultFs.PortSdCardAbortCommandIssued.LogConverted(result);
|
||||
|
||||
|
||||
if (ResultSdmmc.NotSupported.Includes(result))
|
||||
return ResultFs.PortSdCardNotSupported.LogConverted(result);
|
||||
|
||||
if (ResultSdmmc.NotImplemented.Includes(result))
|
||||
return ResultFs.PortSdCardNotImplemented.LogConverted(result);
|
||||
|
||||
return ResultFs.PortSdCardUnexpected.LogConverted(result);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,15 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.FsSystem;
|
||||
using LibHac.Sdmmc;
|
||||
using LibHac.Sf;
|
||||
using LibHac.Util;
|
||||
using static LibHac.Sdmmc.SdmmcApi;
|
||||
using static LibHac.SdmmcSrv.Common;
|
||||
using static LibHac.SdmmcSrv.SdmmcResultConverter;
|
||||
using IStorageSf = LibHac.FsSrv.Sf.IStorage;
|
||||
|
||||
namespace LibHac.SdmmcSrv;
|
||||
|
@ -22,33 +29,116 @@ internal class SdmmcStorage : IStorage
|
|||
|
||||
public override Result Read(long offset, Span<byte> destination)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresAligned(offset, SectorSize);
|
||||
Assert.SdkRequiresAligned(destination.Length, SectorSize);
|
||||
|
||||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
// Missing: Allocate a device buffer if the destination buffer is not one
|
||||
|
||||
return _sdmmc.Read(destination, _port, BytesToSectors(offset), BytesToSectors(destination.Length)).Ret();
|
||||
}
|
||||
|
||||
public override Result Write(long offset, ReadOnlySpan<byte> source)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
const int alignment = 0x4000;
|
||||
Result res;
|
||||
|
||||
Assert.SdkRequiresAligned(offset, SectorSize);
|
||||
Assert.SdkRequiresAligned(source.Length, SectorSize);
|
||||
|
||||
if (source.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
// Missing: Allocate a device buffer if the source buffer is not one
|
||||
|
||||
// Check if we have any unaligned data at the head of the source buffer.
|
||||
long alignedUpOffset = Alignment.AlignUp(offset, alignment);
|
||||
int unalignedHeadSize = (int)(alignedUpOffset - offset);
|
||||
int remainingSize = source.Length;
|
||||
|
||||
// The start offset must be aligned to 0x4000 bytes. The end offset does not need to be aligned to 0x4000 bytes.
|
||||
if (alignedUpOffset != offset)
|
||||
{
|
||||
// Get the number of bytes that come before the unaligned data.
|
||||
int paddingSize = alignment - unalignedHeadSize;
|
||||
|
||||
// If the end offset is inside the first 0x4000-byte block, don't write past the end offset.
|
||||
// Otherwise write the entire aligned block.
|
||||
int writeSize = Math.Min(alignment, paddingSize + source.Length);
|
||||
|
||||
using var pooledBuffer = new PooledBuffer(writeSize, alignment);
|
||||
|
||||
// Get the number of bytes from source to be written to the aligned buffer, and copy that data to the buffer.
|
||||
int unalignedSize = writeSize - paddingSize;
|
||||
source.Slice(0, unalignedSize).CopyTo(pooledBuffer.GetBuffer().Slice(paddingSize));
|
||||
|
||||
// Read the current data into the aligned buffer.
|
||||
res = GetFsResult(_port,
|
||||
_sdmmc.Read(pooledBuffer.GetBuffer().Slice(0, paddingSize), _port,
|
||||
BytesToSectors(alignedUpOffset - alignment), BytesToSectors(paddingSize)));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
// Write the aligned buffer.
|
||||
res = GetFsResult(_port,
|
||||
_sdmmc.Write(_port, BytesToSectors(alignedUpOffset - alignment), BytesToSectors(writeSize),
|
||||
pooledBuffer.GetBuffer().Slice(0, writeSize)));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
remainingSize -= unalignedSize;
|
||||
}
|
||||
|
||||
// We've written any unaligned data. Write the remaining aligned data.
|
||||
if (remainingSize > 0)
|
||||
{
|
||||
res = GetFsResult(_port,
|
||||
_sdmmc.Write(_port, BytesToSectors(alignedUpOffset), BytesToSectors(remainingSize),
|
||||
source.Slice(unalignedHeadSize, remainingSize)));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override Result Flush()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override Result SetSize(long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return ResultFs.UnsupportedSetSizeForSdmmcStorage.Log();
|
||||
}
|
||||
|
||||
public override Result GetSize(out long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out size);
|
||||
|
||||
Result res = GetFsResult(_port, _sdmmc.GetDeviceMemoryCapacity(out uint numSectors, _port));
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
size = numSectors * SectorSize;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override Result OperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
switch (operationId)
|
||||
{
|
||||
case OperationId.InvalidateCache:
|
||||
return Result.Success;
|
||||
case OperationId.QueryRange:
|
||||
if (outBuffer.Length != Unsafe.SizeOf<QueryRangeInfo>())
|
||||
return ResultFs.InvalidSize.Log();
|
||||
|
||||
SpanHelpers.AsStruct<QueryRangeInfo>(outBuffer).Clear();
|
||||
|
||||
return Result.Success;
|
||||
default:
|
||||
return ResultFs.UnsupportedOperateRangeForSdmmcStorage.Log();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue