diff --git a/nx/include/switch.h b/nx/include/switch.h index c4322d7b..81f14dcf 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -92,6 +92,7 @@ extern "C" { #include "switch/services/ncm.h" #include "switch/services/psc.h" #include "switch/services/caps.h" +#include "switch/services/capsa.h" #include "switch/services/capsu.h" #include "switch/services/capssc.h" #include "switch/services/capssu.h" diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index bfffa09c..09bb0bb1 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -78,7 +78,7 @@ typedef struct { typedef struct { u64 program_id; ///< ProgramId. CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime - u8 unk_x10; ///< Unknown. + u8 location; ///< AlbumLocation u8 unk_x11; ///< Unknown. u8 pad[6]; ///< Padding? } CapsAlbumEntryId; @@ -99,10 +99,10 @@ typedef struct { } v0; ///< Pre-7.0.0 struct { - u8 unk_x0[0x8]; ///< Unknown. - u8 unk_x8[0x8]; ///< Unknown. - CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime - u8 unk_x18[0x8]; ///< Unknown. + u64 size; ///< size of the entry + u64 program_id; ///< ProgramId + CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime + u8 unk_x18[0x8]; ///< Unknown. } v1; ///< [7.0.0+] }; } CapsApplicationAlbumEntry; diff --git a/nx/include/switch/services/capsa.h b/nx/include/switch/services/capsa.h new file mode 100644 index 00000000..209c518b --- /dev/null +++ b/nx/include/switch/services/capsa.h @@ -0,0 +1,34 @@ +/** + * @file capsu.h + * @brief Album Accessor (caps:a) service IPC wrapper. + * @author Behemoth + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" +#include "../services/caps.h" + +typedef enum { + AlbumObjectLocation_BuiltInUser = 0, + AlbumObjectLocation_SdCard = 1, +} AlbumObjectLocation; + +/// Initialize caps:a. +Result capsaInitialize(void); + +/// Exit caps:a. +void capsaExit(void); + +/// Gets the Service for caps:u. +Service* capsuGetServiceSession(void); + +Result capsaGetAlbumFileCount(AlbumObjectLocation location, u64* count); +Result capsaGetAlbumFileList(AlbumObjectLocation location, u64* count, CapsApplicationAlbumEntry* buffer, u64 size); +Result capsaLoadAlbumFile(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size); +Result capsaDeleteAlbumFile(CapsAlbumEntryId entry_id); +Result capsaStorageCopyAlbumFile(u8 unk[0x20]); +Result capsaIsAlbumMounted(AlbumObjectLocation location, bool* is_mounted); +Result capsaGetAlbumUsage(AlbumObjectLocation location, u8 unk_out[0x30]); +Result capsaGetAlbumFileSize(CapsAlbumEntryId entry_id, u64* size); +Result capsLoadAlbumFileThumbnail(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size); diff --git a/nx/source/services/capsa.c b/nx/source/services/capsa.c new file mode 100644 index 00000000..cb012e4e --- /dev/null +++ b/nx/source/services/capsa.c @@ -0,0 +1,68 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/applet.h" +#include "services/capsa.h" + +static Service g_capsaSrv; + +NX_GENERATE_SERVICE_GUARD(capsa); + +Result _capsaInitialize(void) { + return smGetService(&g_capsaSrv, "caps:a"); +} + +void _capsaCleanup(void) { + serviceClose(&g_capsaSrv); +} + +Service* capsuGetServiceSession(void) { + return &g_capsaSrv; +} + +Result capsaGetAlbumFileCount(AlbumObjectLocation location, u64* count) { + return serviceDispatchInOut(&g_capsaSrv, 0, location, *count); +} + +Result capsaGetAlbumFileList(AlbumObjectLocation location, u64* count, CapsApplicationAlbumEntry* buffer, u64 buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 1, location, *count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, buffer_size } }, + ); +} + +Result capsaLoadAlbumFile(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 2, entry_id, *unk, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { jpeg_buffer, jpeg_buffer_size } }, + ); +} + +Result capsaDeleteAlbumFile(CapsAlbumEntryId entry_id) { + return serviceDispatchIn(&g_capsaSrv, 3, entry_id); +} + +Result capsaStorageCopyAlbumFile(u8 unk[0x20]) { + return serviceDispatchIn(&g_capsaSrv, 4, *unk); +} + +Result capsaIsAlbumMounted(AlbumObjectLocation location, bool* is_mounted) { + return serviceDispatchInOut(&g_capsaSrv, 5, location, *is_mounted); +} + +Result capsaGetAlbumUsage(AlbumObjectLocation location, u8 unk_out[0x30]) { + return serviceDispatchInOut(&g_capsaSrv, 6, location, *unk_out); +} + +Result capsaGetAlbumFileSize(CapsAlbumEntryId entry_id, u64* size) { + return serviceDispatchInOut(&g_capsaSrv, 7, entry_id, *size); +} + +Result capsLoadAlbumFileThumbnail(CapsAlbumEntryId entry_id, u8 unk[8], void* jpeg_buffer, u64 jpeg_buffer_size) { + return serviceDispatchInOut(&g_capsaSrv, 8, entry_id, *unk, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { jpeg_buffer, jpeg_buffer_size } }, + ); +}