#define NX_SERVICE_ASSUME_NON_DOMAIN #include #include #include "service_guard.h" #include "runtime/hosversion.h" #include "services/applet.h" #include "services/capsc.h" static Service g_capscSrv; static Service g_capscControl; static Result _capscSetShimLibraryVersion(u64 version); NX_GENERATE_SERVICE_GUARD(capsc); Result _capscInitialize(void) { Result rc=0; rc = smGetService(&g_capscSrv, "caps:c"); if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) rc = _capscSetShimLibraryVersion(capsGetShimLibraryVersion()); return rc; } void _capscCleanup(void) { serviceClose(&g_capscControl); serviceClose(&g_capscSrv); } Service* capscGetServiceSession(void) { return &g_capscSrv; } static Result _capscSetShimLibraryVersion(u64 version) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u64 version; u64 AppletResourceUserId; } in = { version, appletGetAppletResourceUserId() }; return serviceDispatchIn(&g_capscSrv, 33, in); } static Result _capscCmdInU8NoOut(Service *srv, u32 cmd_id, u64 inval) { return serviceDispatchIn(srv, cmd_id, inval); } Result capscNotifyAlbumStorageIsAvailable(CapsAlbumStorage storage) { return _capscCmdInU8NoOut(&g_capscSrv, 2001, storage); } Result capscNotifyAlbumStorageIsUnAvailable(CapsAlbumStorage storage) { return _capscCmdInU8NoOut(&g_capscSrv, 2002, storage); } Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u64 appletResourceUserId; CapsApplicationId applicationId; } in = { appletResourceUserId, *application_id }; return serviceDispatchIn(&g_capscSrv, 2011, in); } Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, const CapsApplicationId *application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u64 appletResourceUserId; CapsApplicationId applicationId; } in = { appletResourceUserId, *application_id }; return serviceDispatchIn(&g_capscSrv, 2012, in); } Result capscGetApplicationIdFromAruid(CapsApplicationId *application_id, u64 aruid) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (hosversionAtLeast(19,0,0)) return serviceDispatchInOut(&g_capscSrv, 2013, aruid, *application_id); u64 old_application_id=0; Result rc = serviceDispatchInOut(&g_capscSrv, 2013, aruid, old_application_id); if (R_SUCCEEDED(rc)) *application_id = (CapsApplicationId){ old_application_id, 0, 0 }; return rc; } Result capscCheckApplicationIdRegistered(u64 application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchIn(&g_capscSrv, 2014, application_id); } Result capscGenerateCurrentAlbumFileId(const CapsApplicationId *application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { u8 type; CapsApplicationId applicationId; } in = { contents, *application_id }; return serviceDispatchInOut(&g_capscSrv, 2101, in, *file_id); } Result capscGenerateApplicationAlbumEntry(CapsApplicationAlbumEntry *appEntry, const CapsAlbumEntry *entry, u64 application_id) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { CapsAlbumEntry entry; u64 applicationId; } in = { *entry, application_id }; return serviceDispatchInOut(&g_capscSrv, 2102, in, *appEntry); } Result capscSaveAlbumScreenShotFile(const CapsAlbumFileId *file_id, const void* buffer, u64 buffer_size) { if (hosversionBefore(2,0,0) || hosversionAtLeast(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return serviceDispatchIn(&g_capscSrv, 2201, *file_id, .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { buffer, buffer_size }, }, ); } Result capscSaveAlbumScreenShotFileEx(const CapsAlbumFileId *file_id, u64 version, u64 makernote_offset, u64 makernote_size, const void* buffer, u64 buffer_size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); const struct { CapsAlbumFileId file_id; u64 version; u64 mn_offset; u64 mn_size; } in = { *file_id, version, makernote_offset, makernote_size }; return serviceDispatchIn(&g_capscSrv, 2202, in, .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { buffer, buffer_size }, }, ); } static Result _capscSetOverlayThumbnailData(const CapsAlbumFileId *file_id, const void* image, u64 image_size, u32 cmd_id) { return serviceDispatchIn(&g_capscSrv, cmd_id, *file_id, .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { image, image_size }, }, ); } Result capscSetOverlayScreenShotThumbnailData(const CapsAlbumFileId *file_id, const void* image, u64 image_size) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _capscSetOverlayThumbnailData(file_id, image, image_size, 2301); } Result capscSetOverlayMovieThumbnailData(const CapsAlbumFileId *file_id, const void* image, u64 image_size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); return _capscSetOverlayThumbnailData(file_id, image, image_size, 2302); } static Result _capscOpenControlSession(Service *srv_out) { u64 AppletResourceUserId = appletGetAppletResourceUserId(); return serviceDispatchIn(&g_capscSrv, 60001, AppletResourceUserId, .in_send_pid = true, .out_num_objects = 1, .out_objects = srv_out, ); } static Result _capscOpenAlbumMovieStream(const CapsAlbumFileId *file_id, u64 *stream, u32 cmd_id) { return serviceDispatchInOut(&g_capscControl, cmd_id, *file_id, *stream); } static Result _capscControlReadDataFromAlbumMovieStream(u64 stream, u64 offset, void* buffer, size_t size, u64 *actual_size, u32 cmd_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); const struct { u64 stream; u64 offset; } in = { stream, offset }; return serviceDispatchInOut(&g_capscControl, cmd_id, in, *actual_size, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, .buffers = { { buffer, size } }, ); } static Result _capscControlCmdInU64NoOut(u64 inval, u32 cmd_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchIn(&g_capscControl, cmd_id, inval); } Result capscOpenAlbumMovieReadStream(u64 *stream, const CapsAlbumFileId *file_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc=0; if (!serviceIsActive(&g_capscControl)) rc = _capscOpenControlSession(&g_capscControl); if (R_SUCCEEDED(rc)) rc = _capscOpenAlbumMovieStream(file_id, stream, 2001); return rc; } Result capscCloseAlbumMovieStream(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2002); } Result capscGetAlbumMovieStreamSize(u64 stream, u64 *size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchInOut(&g_capscControl, 2003, stream, *size); } Result capscReadMovieDataFromAlbumMovieReadStream(u64 stream, u64 offset, void* buffer, size_t size, u64 *actual_size) { return _capscControlReadDataFromAlbumMovieStream(stream, offset, buffer, size, actual_size, 2004); } Result capscGetAlbumMovieReadStreamBrokenReason(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2005); } Result capscGetAlbumMovieReadStreamImageDataSize(u64 stream, u64 *size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchInOut(&g_capscControl, 2006, stream, *size); } Result capscReadImageDataFromAlbumMovieReadStream(u64 stream, u64 offset, void* buffer, size_t size, u64 *actual_size) { return _capscControlReadDataFromAlbumMovieStream(stream, offset, buffer, size, actual_size, 2007); } Result capscReadFileAttributeFromAlbumMovieReadStream(u64 stream, CapsScreenShotAttribute *attribute) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchInOut(&g_capscControl, 2008, stream, *attribute); } Result capscOpenAlbumMovieWriteStream(u64 *stream, const CapsAlbumFileId *file_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc=0; if (!serviceIsActive(&g_capscControl)) rc = _capscOpenControlSession(&g_capscControl); if (R_SUCCEEDED(rc)) rc = _capscOpenAlbumMovieStream(file_id, stream, 2401); return rc; } Result capscFinishAlbumMovieWriteStream(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2402); } Result capscCommitAlbumMovieWriteStream(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2403); } Result capscDiscardAlbumMovieWriteStream(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2404); } Result capscDiscardAlbumMovieWriteStreamNoDelete(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2405); } Result capscCommitAlbumMovieWriteStreamEx(u64 stream, CapsAlbumEntry *entry) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchInOut(&g_capscControl, 2406, stream, *entry); } Result capscStartAlbumMovieWriteStreamDataSection(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2411); } Result capscEndAlbumMovieWriteStreamDataSection(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2412); } Result capscStartAlbumMovieWriteStreamMetaSection(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2413); } Result capscEndAlbumMovieWriteStreamMetaSection(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2414); } Result capscReadDataFromAlbumMovieWriteStream(u64 stream, u64 offset, void* buffer, u64 size, u64 *actual_size) { return _capscControlReadDataFromAlbumMovieStream(stream, offset, buffer, size, actual_size ,2421); } static Result _capscWriteToAlbumMovieWriteStream(u64 stream, u64 offset, const void* buffer, u64 size, u32 cmd_id) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); const struct { u64 stream; u64 offset; } in = { stream, offset }; return serviceDispatchIn(&g_capscControl, cmd_id, in, .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, .buffers = { { buffer, size } }, ); } Result capscWriteDataToAlbumMovieWriteStream(u64 stream, u64 offset, const void* buffer, u64 size) { return _capscWriteToAlbumMovieWriteStream(stream, offset, buffer, size, 2422); } Result capscWriteMetaToAlbumMovieWriteStream(u64 stream, u64 offset, const void* buffer, u64 size) { return _capscWriteToAlbumMovieWriteStream(stream, offset, buffer, size, 2424); } Result capscGetAlbumMovieWriteStreamBrokenReason(u64 stream) { return _capscControlCmdInU64NoOut(stream, 2431); } Result capscGetAlbumMovieWriteStreamDataSize(u64 stream, u64 *size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); return serviceDispatchInOut(&g_capscControl, 2433, stream, *size); } Result capscSetAlbumMovieWriteStreamDataSize(u64 stream, u64 size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (!serviceIsActive(&g_capscControl)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); const struct { u64 stream; u64 size; } in = { stream, size }; return serviceDispatchIn(&g_capscControl, 2434, in); }