Add deactivation report fields to GameCardErrorReportInfo

This commit is contained in:
Alex Barney 2023-11-02 00:09:56 -07:00
parent 253c0cb011
commit a65b1b8b31
5 changed files with 54 additions and 23 deletions

View file

@ -85,7 +85,8 @@ public struct GameCardErrorInfo
public struct GameCardErrorReportInfo public struct GameCardErrorReportInfo
{ {
public ushort GameCardCrcErrorNum; public ushort GameCardCrcErrorNum;
public ushort Reserved2; public byte LastDeactivateReason;
public byte Reserved3;
public ushort AsicCrcErrorNum; public ushort AsicCrcErrorNum;
public ushort Reserved6; public ushort Reserved6;
public ushort RefreshNum; public ushort RefreshNum;
@ -106,7 +107,8 @@ public struct GameCardErrorReportInfo
public uint AwakenCount; public uint AwakenCount;
public uint ReadCountFromInsert; public uint ReadCountFromInsert;
public uint ReadCountFromAwaken; public uint ReadCountFromAwaken;
public Array8<byte> Reserved38; public uint LastDeactivateReasonResult;
public Array4<byte> Reserved3C;
} }
public struct GameCardUpdatePartitionInfo public struct GameCardUpdatePartitionInfo

View file

@ -23,7 +23,6 @@ internal class CardDeviceDetectionEventManager : IDisposable
{ {
public CardDeviceDetectionEventManager EventManager; public CardDeviceDetectionEventManager EventManager;
public SdkMutex Mutex; public SdkMutex Mutex;
public Sdmmc.Port Port;
} }
public CardDeviceDetectionEventManager() public CardDeviceDetectionEventManager()

View file

@ -40,12 +40,28 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
Write = 3 Write = 3
} }
private enum DeactivateReason : byte
{
Reason0 = 0,
Reason1 = 1,
Reason2 = 2,
Reason3 = 3,
Reason4 = 4,
Reason5 = 5,
Reason6 = 6,
Reason7 = 7,
Reason8 = 8,
Reason9 = 9,
}
private ReaderWriterLock _rwLock; private ReaderWriterLock _rwLock;
private bool _isInitialized; private bool _isInitialized;
private bool _isFinalized; private bool _isFinalized;
private CardState _state; private CardState _state;
private DeactivateReason _lastDeactivateReason;
private GameCardHandle _currentHandle; private GameCardHandle _currentHandle;
private GameCardDetectionEventManager _detectionEventManager; private GameCardDetectionEventManager _detectionEventManager;
private Result _lastDeactivateReasonResult;
// LibHac additions // LibHac additions
private WeakRef<GameCardManager> _selfReference; private WeakRef<GameCardManager> _selfReference;
@ -81,18 +97,19 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
_selfReference.Destroy(); _selfReference.Destroy();
} }
private void DeactivateAndChangeState() private void DeactivateAndChangeState(DeactivateReason reason)
{ {
_gc.Deactivate(); _gc.Deactivate();
_currentHandle++; _currentHandle++;
_state = CardState.Initial; _state = CardState.Initial;
_lastDeactivateReason = reason;
} }
private void CheckGameCardAndDeactivate() private void CheckGameCardAndDeactivate(DeactivateReason reason)
{ {
if (_state != CardState.Initial && !_gc.IsCardActivationValid()) if (_state != CardState.Initial && !_gc.IsCardActivationValid())
{ {
DeactivateAndChangeState(); DeactivateAndChangeState(reason);
} }
} }
@ -162,7 +179,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
UnsafeHelpers.SkipParamInit(out outNewHandle); UnsafeHelpers.SkipParamInit(out outNewHandle);
if (_state == CardState.Normal) if (_state == CardState.Normal)
CheckGameCardAndDeactivate(); CheckGameCardAndDeactivate(DeactivateReason.Reason6);
switch (_state) switch (_state)
{ {
@ -183,7 +200,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
case CardState.Secure: case CardState.Secure:
{ {
// Secure -> Initial -> Normal // Secure -> Initial -> Normal
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason7);
Result res = ActivateGameCard(); Result res = ActivateGameCard();
if (res.IsFailure()) return res.Miss(); if (res.IsFailure()) return res.Miss();
@ -194,7 +211,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
case CardState.Write: case CardState.Write:
{ {
// Write -> Initial -> Normal // Write -> Initial -> Normal
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason9);
_gc.Writer.ChangeMode(AsicMode.Read); _gc.Writer.ChangeMode(AsicMode.Read);
Result res = ActivateGameCard(); Result res = ActivateGameCard();
@ -217,7 +234,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
UnsafeHelpers.SkipParamInit(out outNewHandle); UnsafeHelpers.SkipParamInit(out outNewHandle);
if (_state == CardState.Secure) if (_state == CardState.Secure)
CheckGameCardAndDeactivate(); CheckGameCardAndDeactivate(DeactivateReason.Reason8);
switch (_state) switch (_state)
{ {
@ -251,7 +268,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
case CardState.Write: case CardState.Write:
{ {
// Write -> Initial -> Normal -> Secure // Write -> Initial -> Normal -> Secure
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason9);
_gc.Writer.ChangeMode(AsicMode.Read); _gc.Writer.ChangeMode(AsicMode.Read);
Result res = ActivateGameCard(); Result res = ActivateGameCard();
@ -293,7 +310,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
case CardState.Secure: case CardState.Secure:
{ {
// Normal/Secure -> Initial -> Write // Normal/Secure -> Initial -> Write
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason9);
_gc.Writer.ChangeMode(AsicMode.Write); _gc.Writer.ChangeMode(AsicMode.Write);
Result res = ActivateGameCardForWriter(); Result res = ActivateGameCardForWriter();
@ -623,12 +640,17 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
public Result Invalidate() public Result Invalidate()
{ {
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock); InvalidateImpl(DeactivateReason.Reason1);
DeactivateAndChangeState();
return Result.Success; return Result.Success;
} }
private void InvalidateImpl(DeactivateReason reason)
{
using var writeLock = new UniqueLock<ReaderWriterLock>(_rwLock);
DeactivateAndChangeState(reason);
}
public Result Operate(int operationId) public Result Operate(int operationId)
{ {
var operation = (GameCardManagerOperationIdValue)operationId; var operation = (GameCardManagerOperationIdValue)operationId;
@ -879,6 +901,9 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
Result res = _gc.GetErrorInfo(out outErrorInfo); Result res = _gc.GetErrorInfo(out outErrorInfo);
if (res.IsFailure()) return res.Miss(); if (res.IsFailure()) return res.Miss();
outErrorInfo.LastDeactivateReasonResult = _lastDeactivateReasonResult.Value;
outErrorInfo.LastDeactivateReason = (byte)_lastDeactivateReason;
return Result.Success; return Result.Success;
} }
@ -1033,7 +1058,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
} }
} }
Invalidate().IgnoreResult(); InvalidateImpl(DeactivateReason.Reason2);
return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log(); return ResultFs.GameCardFsCheckHandleInAcquireReadLock.Log();
} }
@ -1051,7 +1076,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
if (_state != CardState.Initial && !_gc.IsCardActivationValid()) if (_state != CardState.Initial && !_gc.IsCardActivationValid())
{ {
readLock.Unlock(); readLock.Unlock();
Invalidate().IgnoreResult(); InvalidateImpl(DeactivateReason.Reason3);
} }
else if (_currentHandle == inOutHandle) else if (_currentHandle == inOutHandle)
{ {
@ -1115,7 +1140,8 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
if (result.IsFailure()) if (result.IsFailure())
{ {
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason4);
_lastDeactivateReasonResult = result;
} }
return result; return result;
@ -1127,7 +1153,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
if (_state == CardState.Normal || _state == CardState.Secure) if (_state == CardState.Normal || _state == CardState.Secure)
{ {
CheckGameCardAndDeactivate(); CheckGameCardAndDeactivate(DeactivateReason.Reason5);
} }
switch (_state) switch (_state)
@ -1144,7 +1170,7 @@ public class GameCardManager : IStorageDeviceManager, IStorageDeviceOperator, IG
break; break;
case CardState.Write: case CardState.Write:
{ {
DeactivateAndChangeState(); DeactivateAndChangeState(DeactivateReason.Reason9);
_gc.Writer.ChangeMode(AsicMode.Read); _gc.Writer.ChangeMode(AsicMode.Read);
Result res = ActivateGameCard(); Result res = ActivateGameCard();

View file

@ -9,12 +9,14 @@ namespace LibHac.SdmmcSrv;
/// <remarks>Based on nnSdk 16.2.0 (FS 16.0.0)</remarks> /// <remarks>Based on nnSdk 16.2.0 (FS 16.0.0)</remarks>
internal class SdCardDetectionEventManager : CardDeviceDetectionEventManager internal class SdCardDetectionEventManager : CardDeviceDetectionEventManager
{ {
public Port Port;
// LibHac addition // LibHac addition
private readonly SdmmcApi _sdmmc; private readonly SdmmcApi _sdmmc;
public SdCardDetectionEventManager(Port port, SdmmcApi sdmmc) public SdCardDetectionEventManager(Port port, SdmmcApi sdmmc)
{ {
CallbackArgs.Port = port; Port = port;
_sdmmc = sdmmc; _sdmmc = sdmmc;
_sdmmc.RegisterSdCardDetectionEventCallback(port, DetectionEventCallback, CallbackArgs); _sdmmc.RegisterSdCardDetectionEventCallback(port, DetectionEventCallback, CallbackArgs);
@ -22,7 +24,7 @@ internal class SdCardDetectionEventManager : CardDeviceDetectionEventManager
public override void Dispose() public override void Dispose()
{ {
_sdmmc.UnregisterSdCardDetectionEventCallback(CallbackArgs.Port); _sdmmc.UnregisterSdCardDetectionEventCallback(Port);
base.Dispose(); base.Dispose();
} }

View file

@ -520,7 +520,8 @@ public class TypeLayoutTests
Assert.Equal(0x40, Unsafe.SizeOf<GameCardErrorReportInfo>()); Assert.Equal(0x40, Unsafe.SizeOf<GameCardErrorReportInfo>());
Assert.Equal(0x00, GetOffset(in s, in s.GameCardCrcErrorNum)); Assert.Equal(0x00, GetOffset(in s, in s.GameCardCrcErrorNum));
Assert.Equal(0x02, GetOffset(in s, in s.Reserved2)); Assert.Equal(0x02, GetOffset(in s, in s.LastDeactivateReason));
Assert.Equal(0x03, GetOffset(in s, in s.Reserved3));
Assert.Equal(0x04, GetOffset(in s, in s.AsicCrcErrorNum)); Assert.Equal(0x04, GetOffset(in s, in s.AsicCrcErrorNum));
Assert.Equal(0x06, GetOffset(in s, in s.Reserved6)); Assert.Equal(0x06, GetOffset(in s, in s.Reserved6));
Assert.Equal(0x08, GetOffset(in s, in s.RefreshNum)); Assert.Equal(0x08, GetOffset(in s, in s.RefreshNum));
@ -541,7 +542,8 @@ public class TypeLayoutTests
Assert.Equal(0x2C, GetOffset(in s, in s.AwakenCount)); Assert.Equal(0x2C, GetOffset(in s, in s.AwakenCount));
Assert.Equal(0x30, GetOffset(in s, in s.ReadCountFromInsert)); Assert.Equal(0x30, GetOffset(in s, in s.ReadCountFromInsert));
Assert.Equal(0x34, GetOffset(in s, in s.ReadCountFromAwaken)); Assert.Equal(0x34, GetOffset(in s, in s.ReadCountFromAwaken));
Assert.Equal(0x38, GetOffset(in s, in s.Reserved38)); Assert.Equal(0x38, GetOffset(in s, in s.LastDeactivateReasonResult));
Assert.Equal(0x3C, GetOffset(in s, in s.Reserved3C));
} }
[Fact] [Fact]