diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index 4f276c014..0bbeaaa2c 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -246,7 +246,7 @@ typedef enum { FsSaveDataMetaType_ExtensionContext = 2, } FsSaveDataMetaType; -typedef enum { +typedef enum FsGameCardAttribute : u8 { FsGameCardAttribute_AutoBootFlag = BIT(0), ///< Causes the cartridge to automatically start on bootup FsGameCardAttribute_HistoryEraseFlag = BIT(1), ///< Causes NS to throw an error on attempt to load the cartridge FsGameCardAttribute_RepairToolFlag = BIT(2), ///< [4.0.0+] Indicates that this gamecard is a repair tool. @@ -261,6 +261,57 @@ typedef enum { FsGameCardPartition_Logo = 3, ///< [4.0.0+] } FsGameCardPartition; +typedef enum { + FsMmcPartition_UserData = 0, + FsMmcPartition_BootPartition1 = 1, + FsMmcPartition_BootPartition2 = 2, +} FsMmcPartition; + +typedef enum { + FsGameCardClockRate_ClockRate25MHz = 25, + FsGameCardClockRate_ClockRate50MHz = 50, +} FsGameCardClockRate; + +typedef enum { + FsGameCardSize_Size1GB = 1, + FsGameCardSize_Size2GB = 2, + FsGameCardSize_Size4GB = 4, + FsGameCardSize_Size8GB = 8, + FsGameCardSize_Size16GB = 16, + FsGameCardSize_Size32GB = 32, +} FsGameCardSize; + +typedef enum { + FsSpeedEmulationMode_None = 0, + FsSpeedEmulationMode_Faster = 1, + FsSpeedEmulationMode_Slower = 2, + FsSpeedEmulationMode_Random = 3, +} FsSpeedEmulationMode; + +typedef enum { + FsSimulatingDeviceType_Mmc = 0, + FsSimulatingDeviceType_SdCard = 1, + FsSimulatingDeviceType_GameCard = 2, +} FsSimulatingDeviceType; + +typedef enum { + FsSimulatingDeviceDetectionMode_NoSimulation = 0, + FsSimulatingDeviceDetectionMode_DeviceAttached = 1, + FsSimulatingDeviceDetectionMode_DeviceRemoved = 2, +} FsSimulatingDeviceDetectionMode; + +typedef enum { + FsSimulatingDeviceAccessFailureEventType_None = 0, + FsSimulatingDeviceAccessFailureEventType_AccessTimeoutFailure = 1, + FsSimulatingDeviceAccessFailureEventType_AccessFailure = 2, + FsSimulatingDeviceAccessFailureEventType_DataCorruption = 3, +} FsSimulatingDeviceAccessFailureEventType; + +typedef enum { + FsSimulatingDeviceTargetOperation_Read = 1, + FsSimulatingDeviceTargetOperation_Write = 2, +} FsSimulatingDeviceTargetOperation; + typedef struct { u32 value; } FsGameCardHandle; @@ -271,6 +322,27 @@ typedef struct { u64 id; } FsGameCardUpdatePartitionInfo; +typedef struct { + u8 data[0xC]; +} FsHostControllerStatus; + +typedef struct { + u8 data[0x8]; +} FsSdmmcConnectionStatus; + +typedef enum { + FsSdCardActivationMode_Normal = 0, ///< Normal activation mode. + FsSdCardActivationMode_Override = 1, ///< Override activation mode. +} FsSdCardActivationMode; + +typedef struct { + u32 device_type; ///< \ref FsSimulatingDeviceType + u32 detection_mode; ///< \ref FsSimulatingDeviceDetectionMode + u32 access_failure_event; ///< \ref FsSimulatingDeviceAccessFailureEventType + u32 target_operation; ///< \ref FsSimulatingDeviceTargetOperation + u32 access_failure_result; +} FsDeviceSimulationEvent; + typedef struct { u32 aes_ctr_key_type; ///< Contains bitflags describing how data is AES encrypted. u32 speed_emulation_type; ///< Contains bitflags describing how data is emulated. @@ -386,6 +458,18 @@ typedef struct { u32 num_read_write_error_corrections; } FsStorageErrorInfo; +/// FsGameCardErrorInfo +typedef struct { + u16 game_card_crc_error_num; + u16 reserved1; + u16 asic_crc_error_num; + u16 reserved2; + u16 refresh_num; + u16 reserved3; + u16 retry_limit_out_num; + u16 timeout_retry_num; +} FsGameCardErrorInfo; + /// FatFatError typedef struct { s32 error; @@ -676,18 +760,56 @@ Result fsDeviceOperatorGetSdCardCid(FsDeviceOperator* d, void* dst, size_t dst_s Result fsDeviceOperatorGetSdCardUserAreaSize(FsDeviceOperator* d, s64* out); Result fsDeviceOperatorGetSdCardProtectedAreaSize(FsDeviceOperator* d, s64* out); Result fsDeviceOperatorGetAndClearSdCardErrorInfo(FsDeviceOperator* d, FsStorageErrorInfo* out, s64 *out_log_size, void *dst, size_t dst_size, s64 size); +Result fsDeviceOperatorGetSdCardHostControllerStatus(FsDeviceOperator* d, FsHostControllerStatus* out); ///< [17.0.0+] +Result fsDeviceOperatorSetSdCardActivationMode(FsDeviceOperator* d, FsSdCardActivationMode mode); ///< [20.0.0+] +Result fsDeviceOperatorTryGetSdCardInfo(FsDeviceOperator* d, void* out, size_t out_size, s64 size); ///< [20.0.0+] Result fsDeviceOperatorGetMmcCid(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); Result fsDeviceOperatorGetMmcSpeedMode(FsDeviceOperator* d, s64* out); +Result fsDeviceOperatorEraseMmc(FsDeviceOperator* d, FsMmcPartition partition); +Result fsDeviceOperatorGetMmcPartitionSize(FsDeviceOperator* d, FsMmcPartition partition, s64* out); Result fsDeviceOperatorGetMmcPatrolCount(FsDeviceOperator* d, u32* out); Result fsDeviceOperatorGetAndClearMmcErrorInfo(FsDeviceOperator* d, FsStorageErrorInfo* out, s64 *out_log_size, void *dst, size_t dst_size, s64 size); Result fsDeviceOperatorGetMmcExtendedCsd(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); +Result fsDeviceOperatorSuspendMmcPatrol(FsDeviceOperator* d); ///< [4.0.0+] +Result fsDeviceOperatorResumeMmcPatrol(FsDeviceOperator* d); ///< [4.0.0+] +Result fsDeviceOperatorEraseMmcWithRange(FsDeviceOperator* d, FsMmcPartition partition, s64 offset, s64 size); ///< [17.0.0+] +Result fsDeviceOperatorMarkBeforeEraseMmcPartitionUserData(FsDeviceOperator* d); ///< [20.0.0+] +Result fsDeviceOperatorCheckAfterEraseMmcPartitionUserData(FsDeviceOperator* d); ///< [20.0.0+] Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out); +Result fsDeviceOperatorEraseGameCard(FsDeviceOperator* d, FsGameCardSize size, u64 normal_area_size); Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, FsGameCardHandle* out); Result fsDeviceOperatorGetGameCardUpdatePartitionInfo(FsDeviceOperator* d, const FsGameCardHandle* handle, FsGameCardUpdatePartitionInfo* out); -Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out); +Result fsDeviceOperatorFinalizeGameCardDriver(FsDeviceOperator* d); +Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, FsGameCardAttribute *out); Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64* out_size, s64 size); +Result fsDeviceOperatorGetGameCardAsicInfo(FsDeviceOperator* d, const void* fw, size_t fw_size, s64 fw_buffer_size, void* rma, size_t rma_size, s64 rma_info_size); Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); +Result fsDeviceOperatorWriteToGameCardDirectly(FsDeviceOperator* d, void* dst, size_t dst_size, s64 offset, s64 size); +Result fsDeviceOperatorSetVerifyWriteEnableFlag(FsDeviceOperator* d, bool flag); +Result fsDeviceOperatorGetGameCardImageHash(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size); +Result fsDeviceOperatorGetGameCardDeviceIdForProdCard(FsDeviceOperator* d, const void* card_header, size_t card_header_size, s64 card_header_buffer_size, void* dst, size_t dst_size, s64 size); ///< [2.0.0+] +Result fsDeviceOperatorEraseAndWriteParamDirectly(FsDeviceOperator* d, const void* buf, size_t buf_size, s64 size); ///< [2.0.0+] +Result fsDeviceOperatorReadParamDirectly(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); ///< [2.0.0+] +Result fsDeviceOperatorForceEraseGameCard(FsDeviceOperator* d); ///< [2.0.0+] +Result fsDeviceOperatorGetGameCardErrorInfo(FsDeviceOperator* d, FsGameCardErrorInfo* out); ///< [2.0.0+] Result fsDeviceOperatorGetGameCardErrorReportInfo(FsDeviceOperator* d, FsGameCardErrorReportInfo* out); Result fsDeviceOperatorGetGameCardDeviceId(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); Result fsDeviceOperatorChallengeCardExistence(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, void* seed, size_t seed_size, void* value, size_t value_size); +Result fsDeviceOperatorGetGameCardCompatibilityType(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out); ///< [9.0.0+] +Result fsDeviceOperatorGetGameCardAsicCertificate(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size); ///< [17.0.0+] +Result fsDeviceOperatorGetGameCardCardHeader(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size); ///< [18.0.0+] +Result fsDeviceOperatorSetGameCardSessionCreationDelay(FsDeviceOperator* d, bool flag0, bool flag1, u32 delay); ///< [19.0.0+] +Result fsDeviceOperatorGetGameCardApplicationIdList(FsDeviceOperator* d, const FsGameCardHandle* handle, u64* buf, size_t buf_size, s64 size, u16* out_count); ///< [19.0.0+] +Result fsDeviceOperatorRegisterGameCardConfigurationData(FsDeviceOperator* d, const void* buf, size_t buf_size, s64 size); ///< [20.0.0+] +Result fsDeviceOperatorGetGameCardDetailedErrorReportInfo(FsDeviceOperator* d, void* out, size_t out_size, s64 size); ///< [20.0.0+] +Result fsDeviceOperatorSetSpeedEmulationMode(FsDeviceOperator* d, FsSpeedEmulationMode mode); +Result fsDeviceOperatorGetSpeedEmulationMode(FsDeviceOperator* d, FsSpeedEmulationMode* out); +Result fsDeviceOperatorSetApplicationStorageSpeed(FsDeviceOperator* d, s32 speed); ///< [18.0.0+] +Result fsDeviceOperatorSetGameCardClockRateForSpeedEmulation(FsDeviceOperator* d, s32 clock_rate); ///< [20.0.0+] +Result fsDeviceOperatorClearGameCardClockRateForSpeedEmulation(FsDeviceOperator* d); ///< [20.0.0+] +Result fsDeviceOperatorSuspendSdmmcControl(FsDeviceOperator* d); ///< [5.0.0+] +Result fsDeviceOperatorResumeSdmmcControl(FsDeviceOperator* d); ///< [5.0.0+] +Result fsDeviceOperatorGetSdmmcConnectionStatus(FsDeviceOperator* d, u32 input, FsSdmmcConnectionStatus* out); ///< [6.0.0+] +Result fsDeviceOperatorSetDeviceSimulationEvent(FsDeviceOperator* d, const FsDeviceSimulationEvent* event); ///< [6.0.0+] +Result fsDeviceOperatorClearDeviceSimulationEvent(FsDeviceOperator* d, FsSimulatingDeviceType device_type); ///< [6.0.0+] void fsDeviceOperatorClose(FsDeviceOperator* d); diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index 227396824..0bb0fe93d 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -1169,6 +1169,13 @@ static Result _fsCmdGetAndClearStorageErrorInfo(Service *srv, FsStorageErrorInfo return rc; } +static Result _fsCmdInSizeInBuffer(Service* srv, const void* src, size_t src_size, s64 size, u32 cmd_id) { + return _fsObjectDispatchIn(srv, cmd_id, size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { src, src_size } }, + ); +} + Result fsDeviceOperatorIsSdCardInserted(FsDeviceOperator* d, bool* out) { return _fsCmdNoInOutBool(&d->s, out, 0); } @@ -1201,6 +1208,28 @@ Result fsDeviceOperatorGetAndClearSdCardErrorInfo(FsDeviceOperator* d, FsStorage return _fsCmdGetAndClearStorageErrorInfo(&d->s, out, out_log_size, dst, dst_size, size, 5); } +Result fsDeviceOperatorGetSdCardHostControllerStatus(FsDeviceOperator* d, FsHostControllerStatus* out) { + if (hosversionBefore(17,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchOut(&d->s, 6, *out); +} + +Result fsDeviceOperatorSetSdCardActivationMode(FsDeviceOperator* d, FsSdCardActivationMode mode) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 tmp = mode; + return _fsObjectDispatchIn(&d->s, 7, tmp); +} + +Result fsDeviceOperatorTryGetSdCardInfo(FsDeviceOperator* d, void* out, size_t out_size, s64 size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 8, size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, out_size } }, + ); +} + Result fsDeviceOperatorGetMmcCid(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size) { return _fsCmdInSizeOutBuffer(&d->s, dst, dst_size, size, 100); } @@ -1209,6 +1238,16 @@ Result fsDeviceOperatorGetMmcSpeedMode(FsDeviceOperator* d, s64* out) { return _fsCmdNoInOutS64(&d->s, out, 101); } +Result fsDeviceOperatorEraseMmc(FsDeviceOperator* d, FsMmcPartition partition) { + u32 tmp = partition; + return _fsObjectDispatchIn(&d->s, 110, tmp); +} + +Result fsDeviceOperatorGetMmcPartitionSize(FsDeviceOperator* d, FsMmcPartition partition, s64* out) { + u32 tmp = partition; + return _fsObjectDispatchInOut(&d->s, 111, tmp, *out); +} + Result fsDeviceOperatorGetMmcPatrolCount(FsDeviceOperator* d, u32* out) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -1227,10 +1266,58 @@ Result fsDeviceOperatorGetMmcExtendedCsd(FsDeviceOperator* d, void* dst, size_t return _fsCmdInSizeOutBuffer(&d->s, dst, dst_size, size, 114); } +Result fsDeviceOperatorSuspendMmcPatrol(FsDeviceOperator* d) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 115); +} + +Result fsDeviceOperatorResumeMmcPatrol(FsDeviceOperator* d) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 116); +} + +Result fsDeviceOperatorEraseMmcWithRange(FsDeviceOperator* d, FsMmcPartition partition, s64 offset, s64 size) { + if (hosversionBefore(17,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u32 partition; + u32 pad; + s64 offset; + s64 size; + } in = { partition, 0, offset, size }; + + return _fsObjectDispatchIn(&d->s, 117, in); +} + +Result fsDeviceOperatorMarkBeforeEraseMmcPartitionUserData(FsDeviceOperator* d) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 118); +} + +Result fsDeviceOperatorCheckAfterEraseMmcPartitionUserData(FsDeviceOperator* d) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 119); +} + Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out) { return _fsCmdNoInOutBool(&d->s, out, 200); } +Result fsDeviceOperatorEraseGameCard(FsDeviceOperator* d, FsGameCardSize size, u64 normal_area_size) { + const struct { + u32 size; + u32 pad; + u64 normal_area_size; + } in = { size, 0, normal_area_size }; + + return _fsObjectDispatchIn(&d->s, 201, in); +} + Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, FsGameCardHandle* out) { return _fsObjectDispatchOut(&d->s, 202, *out); } @@ -1239,17 +1326,21 @@ Result fsDeviceOperatorGetGameCardUpdatePartitionInfo(FsDeviceOperator* d, const return _fsObjectDispatchInOut(&d->s, 203, *handle, *out); } -Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out) { +Result fsDeviceOperatorFinalizeGameCardDriver(FsDeviceOperator* d) { + return _fsCmdNoIO(&d->s, 204); +} + +Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, FsGameCardAttribute *out) { return _fsObjectDispatchInOut(&d->s, 205, *handle, *out); } Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64* out_size, s64 size) { const struct { - FsGameCardHandle handle; s64 buffer_size; - } in = { *handle, size }; + FsGameCardHandle handle; + u32 pad; + } in = { size, *handle, 0 }; - // Assume old gamecard certificate size on pre-19.0.0 s64 os = 0x200; Result rc; @@ -1269,10 +1360,103 @@ Result fsDeviceOperatorGetGameCardDeviceCertificate(FsDeviceOperator* d, const F return rc; } +Result fsDeviceOperatorGetGameCardAsicInfo(FsDeviceOperator* d, const void* fw, size_t fw_size, s64 fw_buffer_size, void* rma, size_t rma_size, s64 rma_info_size) { + const struct { + s64 fw_buffer_size; + s64 rma_info_size; + } in = { fw_buffer_size, rma_info_size }; + + return _fsObjectDispatchIn(&d->s, 207, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { fw, fw_size }, + { rma, rma_size }, + }, + ); +} + Result fsDeviceOperatorGetGameCardIdSet(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size) { return _fsCmdInSizeOutBuffer(&d->s, dst, dst_size, size, 208); } +Result fsDeviceOperatorWriteToGameCardDirectly(FsDeviceOperator* d, void* dst, size_t dst_size, s64 offset, s64 size) { + const struct { + s64 offset; + s64 buffer_size; + } in = { offset, size }; + + return _fsObjectDispatchIn(&d->s, 209, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { dst, dst_size } }, + ); +} + +Result fsDeviceOperatorSetVerifyWriteEnableFlag(FsDeviceOperator* d, bool flag) { + u8 tmp = flag; + return _fsObjectDispatchIn(&d->s, 210, tmp); +} + +Result fsDeviceOperatorGetGameCardImageHash(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size) { + const struct { + s64 buffer_size; + FsGameCardHandle handle; + u32 pad; + } in = { size, *handle, 0 }; + + return _fsObjectDispatchIn(&d->s, 211, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { dst, dst_size } }, + ); +} + +Result fsDeviceOperatorGetGameCardDeviceIdForProdCard(FsDeviceOperator* d, const void* card_header, size_t card_header_size, s64 card_header_buffer_size, void* dst, size_t dst_size, s64 size) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + s64 card_header_buffer_size; + s64 buffer_size; + } in = { card_header_buffer_size, size }; + + return _fsObjectDispatchIn(&d->s, 212, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { card_header, card_header_size }, + { dst, dst_size }, + }, + ); +} + +Result fsDeviceOperatorEraseAndWriteParamDirectly(FsDeviceOperator* d, const void* buf, size_t buf_size, s64 size) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdInSizeInBuffer(&d->s, buf, buf_size, size, 213); +} + +Result fsDeviceOperatorReadParamDirectly(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdInSizeOutBuffer(&d->s, dst, dst_size, size, 214); +} + +Result fsDeviceOperatorForceEraseGameCard(FsDeviceOperator* d) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 215); +} + +Result fsDeviceOperatorGetGameCardErrorInfo(FsDeviceOperator* d, FsGameCardErrorInfo* out) { + if (hosversionBefore(2,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchOut(&d->s, 216, *out); +} + Result fsDeviceOperatorGetGameCardErrorReportInfo(FsDeviceOperator* d, FsGameCardErrorReportInfo* out) { if (hosversionBefore(2,1,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); @@ -1303,6 +1487,143 @@ Result fsDeviceOperatorChallengeCardExistence(FsDeviceOperator* d, const FsGameC ); } +Result fsDeviceOperatorGetGameCardCompatibilityType(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out) { + if (hosversionBefore(9,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchInOut(&d->s, 220, *handle, *out); +} + +Result fsDeviceOperatorGetGameCardAsicCertificate(FsDeviceOperator* d, void* dst, size_t dst_size, s64 size) { + if (hosversionBefore(17,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdInSizeOutBuffer(&d->s, dst, dst_size, size, 221); +} + +Result fsDeviceOperatorGetGameCardCardHeader(FsDeviceOperator* d, const FsGameCardHandle* handle, void* dst, size_t dst_size, s64 size) { + if (hosversionBefore(18,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + s64 buffer_size; + FsGameCardHandle handle; + u32 pad; + } in = { size, *handle, 0 }; + + return _fsObjectDispatchIn(&d->s, 222, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { dst, dst_size } }, + ); +} + +Result fsDeviceOperatorSetGameCardSessionCreationDelay(FsDeviceOperator* d, bool flag0, bool flag1, u32 delay) { + if (hosversionBefore(19,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + u8 flag0; + u8 flag1; + u8 pad[2]; + u32 delay; + } in = { flag0, flag1, {0}, delay }; + + return _fsObjectDispatchIn(&d->s, 223, in); +} + +Result fsDeviceOperatorGetGameCardApplicationIdList(FsDeviceOperator* d, const FsGameCardHandle* handle, u64* buf, size_t buf_size, s64 size, u16* out_count) { + if (hosversionBefore(19,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + const struct { + s64 buffer_size; + FsGameCardHandle handle; + u32 pad; + } in = { size, *handle, 0 }; + + return _fsObjectDispatchInOut(&d->s, 224, in, *out_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, buf_size } }, + ); +} + +Result fsDeviceOperatorRegisterGameCardConfigurationData(FsDeviceOperator* d, const void* buf, size_t buf_size, s64 size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 225, size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buf, buf_size } }, + ); +} + +Result fsDeviceOperatorGetGameCardDetailedErrorReportInfo(FsDeviceOperator* d, void* out, size_t out_size, s64 size) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 226, size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, out_size } }, + ); +} + +Result fsDeviceOperatorSetSpeedEmulationMode(FsDeviceOperator* d, FsSpeedEmulationMode mode) { + u32 tmp = mode; + return _fsObjectDispatchIn(&d->s, 300, tmp); +} + +Result fsDeviceOperatorGetSpeedEmulationMode(FsDeviceOperator* d, FsSpeedEmulationMode* out) { + u32 tmp=0; + Result rc = _fsObjectDispatchOut(&d->s, 301, tmp); + if (R_SUCCEEDED(rc) && out) *out = tmp; + return rc; +} + +Result fsDeviceOperatorSetApplicationStorageSpeed(FsDeviceOperator* d, s32 speed) { + if (hosversionBefore(18,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 302, speed); +} + +Result fsDeviceOperatorSetGameCardClockRateForSpeedEmulation(FsDeviceOperator* d, s32 clock_rate) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 303, clock_rate); +} + +Result fsDeviceOperatorClearGameCardClockRateForSpeedEmulation(FsDeviceOperator* d) { + if (hosversionBefore(20,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 304); +} + +Result fsDeviceOperatorSuspendSdmmcControl(FsDeviceOperator* d) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 400); +} + +Result fsDeviceOperatorResumeSdmmcControl(FsDeviceOperator* d) { + if (hosversionBefore(5,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsCmdNoIO(&d->s, 401); +} + +Result fsDeviceOperatorGetSdmmcConnectionStatus(FsDeviceOperator* d, u32 input, FsSdmmcConnectionStatus* out) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchInOut(&d->s, 402, input, *out); +} + +Result fsDeviceOperatorSetDeviceSimulationEvent(FsDeviceOperator* d, const FsDeviceSimulationEvent* event) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _fsObjectDispatchIn(&d->s, 500, *event); +} + +Result fsDeviceOperatorClearDeviceSimulationEvent(FsDeviceOperator* d, FsSimulatingDeviceType device_type) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u32 tmp = device_type; + return _fsObjectDispatchIn(&d->s, 501, tmp); +} + void fsDeviceOperatorClose(FsDeviceOperator* d) { _fsObjectClose(&d->s); }