add caps:c (#375)

This commit is contained in:
HookedBehemoth 2020-02-19 23:32:01 +01:00 committed by GitHub
parent 86a5aa4466
commit d8a50a46cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 763 additions and 30 deletions

View File

@ -93,6 +93,7 @@ extern "C" {
#include "switch/services/psc.h"
#include "switch/services/caps.h"
#include "switch/services/capsa.h"
#include "switch/services/capsc.h"
#include "switch/services/capsdc.h"
#include "switch/services/capsu.h"
#include "switch/services/capssc.h"

View File

@ -88,9 +88,8 @@ typedef struct {
CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime
u8 storage; ///< \ref CapsAlbumStorage
u8 content; ///< \ref CapsAlbumFileContents
u32 pad_x12; ///< Set to 0 by official software
u16 pad_x16; ///< Set to 0 by official software
} PACKED CapsAlbumFileId;
u8 pad_x12[0x6]; ///< padding
} CapsAlbumFileId;
/// AlbumEntry
typedef struct {
@ -104,14 +103,17 @@ typedef struct {
u8 data[0x20]; ///< Data.
struct {
u8 unk_x0[0x20]; ///< Unknown.
u8 unk_x0[0x20]; ///< aes256 with random key over \ref AlbumEntry.
} v0; ///< Pre-7.0.0
struct {
u64 size; ///< size of the entry
u64 application_id; ///< ApplicationId
u64 hash; ///< aes256 with hardcoded key over \ref AlbumEntry.
CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime
u8 unk_x18[0x8]; ///< Unknown.
u8 storage; ///< \ref CapsAlbumStorage
u8 content; ///< \ref CapsAlbumFileContents
u8 pad_x1a[0x5]; ///< padding
u8 unk_x1f; ///< Set to 1 by official software
} v1; ///< [7.0.0+]
};
} CapsApplicationAlbumEntry;
@ -162,12 +164,6 @@ typedef struct {
CapsAlbumContentsUsage usages[16]; ///< \ref CapsAlbumContentsUsage
} CapsAlbumUsage16;
/// OverlayThumbnailData
typedef struct {
CapsAlbumFileId file_id; ///< \ref CapsAlbumFileId
u64 size; ///< Size.
} CapsOverlayThumbnailData;
/// UserIdList
typedef struct {
AccountUid uids[ACC_USER_LIST_SIZE]; ///< \ref AccountUid
@ -201,7 +197,7 @@ typedef enum {
/// AlbumCache
typedef struct {
u64 count; ///< Count
u8 unk_x8[8]; ///< Unknown
u64 unk_x8; ///< Unknown
} CapsAlbumCache;
/// Gets the ShimLibraryVersion.

View File

@ -116,6 +116,15 @@ Result capsaLoadAlbumScreenShotImage(u64 *width, u64 *height, const CapsAlbumFil
*/
Result capsaLoadAlbumScreenShotThumbnailImage(u64 *width, u64 *height, const CapsAlbumFileId *file_id, void* image, u64 image_size, void* workbuf, u64 workbuf_size);
/**
* @brief Load an \ref CapsAlbumEntry from a \ref CapsApplicationAlbumEntry and an ApplicationId.
* @note Only available on [2.0.0+].
* @param[out] entry \ref CapsAlbumEntry
* @param[in] application_entry \ref CapsApplicationAlbumEntry
* @param[in] application_id ApplicationId
*/
Result capsaGetAlbumEntryFromApplicationAlbumEntry(CapsAlbumEntry *entry, const CapsApplicationAlbumEntry *application_entry, u64 application_id);
/**
* @brief Load the ScreenShotImage for the specified AlbumFile.
* @note Only available on [3.0.0+].
@ -178,9 +187,10 @@ Result capsaGetAlbumMountResult(CapsAlbumStorage storage);
* @brief Returns the AlbumUsage for a specified \ref CapsAlbumStorage.
* @note Only available on [4.0.0+].
* @param[in] storage \ref CapsAlbumStorage
* @param[in] flags \ref CapsAlbumFileContentsFlag
* @param[out] out \ref CapsAlbumUsage16
*/
Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out);
Result capsaGetAlbumUsage16(CapsAlbumStorage storage, u8 flags, CapsAlbumUsage16 *out);
/**
* @brief Returns the start and end of the Applet Id range.
@ -213,20 +223,22 @@ Result capsaGetAlbumFileListEx0(CapsAlbumStorage storage, u8 flags, u64 *out, Ca
/**
* @brief Returns the image from the last shown ScreenShot Overlay.
* @param[out] data \ref CapsOverlayThumbnailData
* @param[out] file_id \ref CapsAlbumFileId
* @param[out] out_size Size of the thumbnail image. Always 0x5100.
* @param[out] image RGBA8 image output buffer.
* @param[in] image_size Image buffer size, should be at least large enough for RGBA8 96×54.
*/
Result capsaGetLastOverlayScreenShotThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size);
Result capsaGetLastOverlayScreenShotThumbnail(CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size);
/**
* @brief Returns the image from the last shown Movie Overlay.
* @note Only available on [4.0.0+].
* @param[out] data \ref CapsOverlayThumbnailData
* @param[out] file_id \ref CapsAlbumFileId
* @param[out] out_size Size of the thumbnail image. Always 0x5100.
* @param[out] image RGBA8 image output buffer.
* @param[in] image_size Image buffer size, should be at least large enough for RGBA8 96×54.
*/
Result capsaGetLastOverlayMovieThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size);
Result capsaGetLastOverlayMovieThumbnail(CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size);
/**
* @brief Gets the currently set autosaving storage.
@ -305,6 +317,7 @@ Result capsaRefreshAlbumCache(CapsAlbumStorage storage);
/**
* @brief Gets the AlbumCache of the specified AlbumStorage.
* @note Stubbed on [4.0.0+].
* @note use \ref capsaGetAlbumCacheEx instead.
* @param[in] storage \ref CapsAlbumStorage
* @param[out] cache \ref CapsAlbumCache
@ -313,13 +326,20 @@ Result capsaGetAlbumCache(CapsAlbumStorage storage, CapsAlbumCache *cache);
/**
* @brief Gets the AlbumCache for the specified type of the specified AlbumStorage.
* @note Stubbed on [4.0.0+].
* @param[in] storage \ref CapsAlbumStorage
* @param[in] contents \ref CapsAlbumFileContents
* @param[out] cache \ref CapsAlbumCache
*/
Result capsaGetAlbumCacheEx(CapsAlbumStorage storage, CapsAlbumFileContents contents, CapsAlbumCache *cache);
/**
* @brief Load an \ref CapsAlbumEntry from a \ref CapsApplicationAlbumEntry and an AppletResourceUserId.
* @note Only available on [2.0.0+].
* @param[out] entry \ref CapsAlbumEntry
* @param[in] application_entry \ref CapsApplicationAlbumEntry
*/
Result capsaGetAlbumEntryFromApplicationAlbumEntryAruid(CapsAlbumEntry *entry, const CapsApplicationAlbumEntry *application_entry);
/**
* @brief Opens an AlbumMovieStream.
* @note This opens IAlbumAccessorSession if not previously opened, it's closed during \ref capsaExit.

View File

@ -0,0 +1,333 @@
/**
* @file capsc.h
* @brief Album Control (caps:c) service IPC wrapper.
* @author Behemoth
* @copyright libnx Authors
*/
#pragma once
#include "../types.h"
#include "../sf/service.h"
#include "../services/caps.h"
/// Initialize caps:c
Result capscInitialize(void);
/// Exit caps:c.
void capscExit(void);
/// Gets the Service for caps:c.
Service* capscGetServiceSession(void);
/**
* @brief Notify the service that a storage is now available.
* @note This will result in capsrv mounting the image directory on that storage medium.
* @param[in] storage \ref CapsAlbumStorage
*/
Result capscNotifyAlbumStorageIsAvailable(CapsAlbumStorage storage);
/**
* @brief Notify the service that a storage is now unavailable.
* @note This will result in capsrv unmounting the image directory on that storage medium.
* @param[in] storage \ref CapsAlbumStorage
*/
Result capscNotifyAlbumStorageIsUnAvailable(CapsAlbumStorage storage);
/**
* @brief Register an applet for later usage.
* @note Called at application launch by the system.
* @note Will generate a random AES-256 key for this application for use on Shim-Version 0.
* @note Only available on [2.0.0+].
* @param[in] appletResourceUserId AppletResourceUserId.
* @param[in] application_id ApplicationId.
*/
Result capscRegisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id);
/**
* @brief Unregister an applet.
* @note Called at application exit by the system.
* @note Only available on [2.0.0+].
* @param[in] appletResourceUserId AppletResourceUserId.
* @param[in] application_id ApplicationId.
*/
Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id);
/**
* @brief Get an ApplicationId that corresponds to an AppletResourceUserId.
* @note Returns value set by \ref capscRegisterAppletResourceUserId.
* @note Only available on [2.0.0+].
* @param[out] application_id ApplicationId.
* @param[in] appletResourceUserId AppletResourceUserId.
*/
Result capscGetApplicationIdFromAruid(u64 *application_id, u64 aruid);
/**
* @brief Checks whether an ApplicationId is registered.
* @note Only available on [2.0.0+].
* @param[in] application_id ApplicationId.
*/
Result capscCheckApplicationIdRegistered(u64 application_id);
/**
* @brief Generate an AlbumFileId based on parameters and current time.
* @param[in] application_id ApplicationId.
* @note Only available on [2.0.0+].
* @param[in] contents \ref CapsAlbumFileContents
* @param[out] file_id \ref CapsAlbumFileId
*/
Result capscGenerateCurrentAlbumFileId(u64 application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id);
/**
* @brief Generate an ApplicationAlbumEntry based on parameters.
* @note Output will be different between Shim Version 0 and 1.
* @note Only available on [2.0.0+].
* @param[out] appEntry \ref CapsApplicationAlbumEntry
* @param[in] entry \ref CapsAlbumEntry
* @param[in] application_id ApplicationId.
*/
Result capscGenerateApplicationAlbumEntry(CapsApplicationAlbumEntry *appEntry, const CapsAlbumEntry *entry, u64 application_id);
/**
* @brief Save a jpeg image.
* @note Only available on [2.0.0-3.0.2].
* @param[in] file_id \ref CapsAlbumFileId
* @param[in] buffer JPEG image buffer.
* @param[in] buffer_size Size of the JPEG image.
*/
Result capscSaveAlbumScreenShotFile(const CapsAlbumFileId *file_id, const void* buffer, u64 buffer_size);
/**
* @brief Save a jpeg image.
* @note Only available on [4.0.0+].
* @note Version 3 as of [9.1.0].
* @param[in] file_id \ref CapsAlbumFileId
* @param[in] version Revision number.
* @param[in] makernote_offset Offset to makernote in JPEG buffer.
* @param[in] makernote_size Size of the makernote in JPEG buffer.
* @param[in] buffer JPEG image buffer.
* @param[in] buffer_size Size of the JPEG image.
*/
Result capscSaveAlbumScreenShotFileEx(const CapsAlbumFileId *file_id, u64 version, u64 makernote_offset, u64 makernote_size, const void* buffer, u64 buffer_size);
/**
* @brief Sets thumbnail data for the last taken screenshot.
* @note 96×54 Image will get saved.
* @param[in] file_id \ref CapsAlbumFileId
* @param[in] image RGBA8 image buffer.
* @param[in] image_size size of the RGBA8 image buffer.
*/
Result capscSetOverlayScreenShotThumbnailData(const CapsAlbumFileId *file_id, const void* image, u64 image_size);
/**
* @brief Sets thumbnail data for the last recorded movie.
* @note Only availabe on [4.0.0+].
* @note 96×54 Image will get saved.
* @param[in] file_id \ref CapsAlbumFileId
* @param[in] image RGBA8 image buffer.
* @param[in] image_size size of the RGBA8 image buffer.
*/
Result capscSetOverlayMovieThumbnailData(const CapsAlbumFileId *file_id, const void* image, u64 image_size);
/**
* @brief Opens an AlbumMovieReadStream.
* @note This opens IAlbumControlSession if not previously opened, it's closed during \ref capscExit.
* @note Up to 4 streams can be open at the same time. Multiple streams can be open at the same time for the same \ref CapsAlbumFileId.
* @note Only available on [4.0.0+].
* @param[out] stream Stream handle.
* @param[in] entry \ref CapsAlbumFileId
*/
Result capscOpenAlbumMovieReadStream(u64 *stream, const CapsAlbumFileId *file_id);
/**
* @brief Closes an AlbumMovieReadStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscCloseAlbumMovieStream(u64 stream);
/**
* @brief Gets the data size of an AlbumMovieReadStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] size Size of the actual MP4, without the JPEG at the end.
*/
Result capscGetAlbumMovieStreamSize(u64 stream, u64 *size);
/**
* @brief Reads data from an AlbumMovieReadStream.
* @note offset(+size) must not be negative. offset and size must be aligned to 0x40000-bytes.
* @note When offset(+size) goes beyond the size from \ref capscGetAlbumMovieStreamSize, the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[in] offset Offset.
* @param[out] Output data buffer.
* @param[in] size Data buffer size.
* @param[out] actual_size Actual read size.
*/
Result capscReadMovieDataFromAlbumMovieReadStream(u64 stream, u64 offset, void* buffer, size_t size, u64 *actual_size);
/**
* @brief Gets the BrokenReason for an AlbumMovieReadStream.
* @note Official sw doesn't use this.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscGetAlbumMovieReadStreamBrokenReason(u64 stream);
/**
* @brief Gets the data size of an Image taken from an AlbumMovieReadStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] size Expected size of an Image.
*/
Result capscGetAlbumMovieReadStreamImageDataSize(u64 stream, u64 *size);
/**
* @brief Reads data of an Image taken from an AlbumMovieReadStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[in] offset Offset.
* @param[out] buffer Output data buffer.
* @param[in] size Data buffer size.
* @param[out] actual_size Actual read size.
*/
Result capscReadImageDataFromAlbumMovieReadStream(u64 stream, u64 offset, void* buffer, size_t size, u64 *actual_size);
/**
* @brief Gets the file attribute of an AlbumMovieReadStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] attr \ref CapsScreenShotAttribute
*/
Result capscReadFileAttributeFromAlbumMovieReadStream(u64 stream, CapsScreenShotAttribute *attribute);
/**
* @brief Opens an AlbumMovieWriteStream.
* @note This opens IAlbumControlSession if not previously opened, it's closed during \ref capsaExit.
* @note Up to 2 streams can be open at the same time.
* @note Only available on [4.0.0+].
* @param[out] stream Stream handle.
* @param[in] entry \ref CapsAlbumFileId
*/
Result capscOpenAlbumMovieWriteStream(u64 *stream, const CapsAlbumFileId *file_id);
/**
* @brief Finish write to AlbumMovieWriteStream.
* @note Copies file from save to destination storage and deletes the temporary file.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscFinishAlbumMovieWriteStream(u64 stream);
/**
* @brief Closes a finished AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscCommitAlbumMovieWriteStream(u64 stream);
/**
* @brief Closes an AlbumMovieWriteStream in any state.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscDiscardAlbumMovieWriteStream(u64 stream);
/**
* @brief Closes an AlbumMovieWriteStream in any state without deleting the temporary file.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscDiscardAlbumMovieWriteStreamNoDelete(u64 stream);
/**
* @brief Closes a finished AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] entry \ref CapsAlbumEntry
*/
Result capscCommitAlbumMovieWriteStreamEx(u64 stream, CapsAlbumEntry *entry);
/**
* @brief Start AlbumMovieWriteStream data section.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscStartAlbumMovieWriteStreamDataSection(u64 stream);
/**
* @brief End AlbumMovieWriteStream data section.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscEndAlbumMovieWriteStreamDataSection(u64 stream);
/**
* @brief Start AlbumMovieWriteStream meta section.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscStartAlbumMovieWriteStreamMetaSection(u64 stream);
/**
* @brief End AlbumMovieWriteStream meta section.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscEndAlbumMovieWriteStreamMetaSection(u64 stream);
/**
* @brief Reads data from an AlbumMovieWriteStream.
* @note offset(+size) must not be negative. offset and size must be aligned to 0x40000-bytes.
* @note When offset(+size) goes beyond the size from \ref capscGetAlbumMovieStreamSize, the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[in] offset Offset.
* @param[out] buffer Output data buffer.
* @param[in] size Data buffer size.
* @param[out] actual_size Actual read size.
*/
Result capscReadDataFromAlbumMovieWriteStream(u64 stream, u64 offset, void* buffer, u64 size, u64 *actual_size);
/**
* @brief Write data to an AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[in] offset Offset.
* @param[in] buffer Input data buffer.
* @param[in] size Data buffer size.
*/
Result capscWriteDataToAlbumMovieWriteStream(u64 stream, u64 offset, const void* buffer, u64 size);
/**
* @brief Write meta data to an AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[in] offset Offset.
* @param[in] buffer Input data buffer.
* @param[in] size Data buffer size.
*/
Result capscWriteMetaToAlbumMovieWriteStream(u64 stream, u64 offset, const void* buffer, u64 size);
/**
* @brief Gets the BrokenReason for an AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
*/
Result capscGetAlbumMovieWriteStreamBrokenReason(u64 stream);
/**
* @brief Gets the data size of an AlbumMovieWriteStream.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] size Size of the data section.
*/
Result capscGetAlbumMovieWriteStreamDataSize(u64 stream, u64 *size);
/**
* @brief Sets the data size of an AlbumMovieWriteStream.
* @note Must not be bigger than 2GiB.
* @note Only available on [4.0.0+].
* @param[in] stream Stream handle.
* @param[out] size Size of the data section.
*/
Result capscSetAlbumMovieWriteStreamDataSize(u64 stream, u64 size);

View File

@ -112,6 +112,16 @@ Result capsaLoadAlbumScreenShotThumbnailImage(u64 *width, u64 *height, const Cap
return _capsaLoadAlbumScreenshot(width, height, file_id, image, image_size, workbuf, workbuf_size, 10);
}
Result capsaGetAlbumEntryFromApplicationAlbumEntry(CapsAlbumEntry *entry, const CapsApplicationAlbumEntry *application_entry, u64 application_id) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
CapsApplicationAlbumEntry application_entry;
u64 application_id;
} in = { *application_entry, application_id };
return serviceDispatchInOut(&g_capsaSrv, 11, in, *entry);
}
static Result _capsaLoadAlbumScreenshotEx(u64 *width, u64 *height, const CapsAlbumFileId *file_id, const CapsScreenShotDecodeOption *opts, void* image, u64 image_size, void* workbuf, u64 workbuf_size, u32 cmd_id) {
if (hosversionBefore(3,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
@ -183,11 +193,19 @@ Result capsaGetAlbumMountResult(CapsAlbumStorage storage) {
return _capsaCmdInU8NoOut(&g_capsaSrv, storage, 16);
}
Result capsaGetAlbumUsage16(CapsAlbumStorage storage, CapsAlbumUsage16 *out) {
Result capsaGetAlbumUsage16(CapsAlbumStorage storage, u8 flags, CapsAlbumUsage16 *out) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
u8 inval = storage;
return serviceDispatchInOut(&g_capsaSrv, 17, inval, *out);
struct {
u8 storage;
u8 pad_x1[7];
u8 flags;
u8 pad_x9[7];
} in = { storage, {0}, flags, {0} };
return serviceDispatchIn(&g_capsaSrv, 17, in,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_FixedSize, },
.buffers = { { out, sizeof(CapsAlbumUsage16) } },
);
}
Result capsaGetMinMaxAppletId(bool *success, u64* min, u64* max) {
@ -228,7 +246,7 @@ Result capsaGetAlbumFileListEx0(CapsAlbumStorage storage, u8 flags, u64 *out, Ca
struct {
u8 storage;
u8 pad_x1[7];
u8 contents;
u8 flags;
u8 pad_x9[7];
} in = { storage, {0}, flags, {0} };
return serviceDispatchInOut(&g_capsaSrv, 101, in, *out,
@ -237,21 +255,30 @@ Result capsaGetAlbumFileListEx0(CapsAlbumStorage storage, u8 flags, u64 *out, Ca
);
}
Result _capsaGetLastOverlayThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size, u32 cmd_id) {
return serviceDispatchOut(&g_capsaSrv, cmd_id, *data,
Result _capsaGetLastOverlayThumbnail(CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size, u32 cmd_id) {
struct {
CapsAlbumFileId file_id;
u64 size;
} out;
Result rc = serviceDispatchOut(&g_capsaSrv, cmd_id, out,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, },
.buffers = { { image, image_size }, },
);
if (R_SUCCEEDED(rc)) {
if (file_id) *file_id = out.file_id;
if (out_size) *out_size = out.size;
}
return rc;
}
Result capsaGetLastOverlayScreenShotThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size) {
return _capsaGetLastOverlayThumbnail(data, image, image_size, 301);
Result capsaGetLastOverlayScreenShotThumbnail(CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size) {
return _capsaGetLastOverlayThumbnail(file_id, out_size, image, image_size, 301);
}
Result capsaGetLastOverlayMovieThumbnail(CapsOverlayThumbnailData *data, void* image, u64 image_size) {
Result capsaGetLastOverlayMovieThumbnail(CapsAlbumFileId *file_id, u64 *out_size, void* image, u64 image_size) {
if (hosversionBefore(4,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return _capsaGetLastOverlayThumbnail(data, image, image_size, 302);
return _capsaGetLastOverlayThumbnail(file_id, out_size, image, image_size, 302);
}
Result capsaGetAutoSavingStorage(CapsAlbumStorage *storage) {
@ -309,7 +336,8 @@ Result capsaRefreshAlbumCache(CapsAlbumStorage storage) {
}
Result capsaGetAlbumCache(CapsAlbumStorage storage, CapsAlbumCache *cache) {
return serviceDispatchInOut(&g_capsaSrv, 8012, storage, *cache);
u8 inval = storage;
return serviceDispatchInOut(&g_capsaSrv, 8012, inval, *cache);
}
Result capsaGetAlbumCacheEx(CapsAlbumStorage storage, CapsAlbumFileContents contents, CapsAlbumCache *cache) {
@ -322,6 +350,16 @@ Result capsaGetAlbumCacheEx(CapsAlbumStorage storage, CapsAlbumFileContents cont
return serviceDispatchInOut(&g_capsaSrv, 8013, in, *cache);
}
Result capsaGetAlbumEntryFromApplicationAlbumEntryAruid(CapsAlbumEntry *entry, const CapsApplicationAlbumEntry *application_entry) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
CapsApplicationAlbumEntry application_entry;
u64 aruid;
} in = { *application_entry, appletGetAppletResourceUserId() };
return serviceDispatchInOut(&g_capsaSrv, 8021, in, *entry, .in_send_pid = true);
}
static Result _capsaOpenAccessorSession(Service *srv_out) {
u64 AppletResourceUserId = appletGetAppletResourceUserId();

345
nx/source/services/capsc.c Normal file
View File

@ -0,0 +1,345 @@
#define NX_SERVICE_ASSUME_NON_DOMAIN
#include <string.h>
#include <time.h>
#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, u64 application_id) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 appletResourceUserId;
u64 applicationId;
} in = { appletResourceUserId, application_id };
return serviceDispatchIn(&g_capscSrv, 2011, in);
}
Result capscUnregisterAppletResourceUserId(u64 appletResourceUserId, u64 application_id) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u64 appletResourceUserId;
u64 applicationId;
} in = { appletResourceUserId, application_id };
return serviceDispatchIn(&g_capscSrv, 2012, in);
}
Result capscGetApplicationIdFromAruid(u64 *application_id, u64 aruid) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
return serviceDispatchInOut(&g_capscSrv, 2013, aruid, *application_id);
}
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(u64 application_id, CapsAlbumFileContents contents, CapsAlbumFileId *file_id) {
if (hosversionBefore(2,0,0))
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
const struct {
u8 type;
u64 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);
}