diff --git a/Changelog.md b/Changelog.md index f427f601..fbd6fa89 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,100 @@ # Changelog +## Version 2.5.0 + +#### system +* Corrected type of id0 in svcGetInfo. + +#### filesystem +* Added fsExtendSaveDataFileSystem, fsOpenCustomStorageFileSystem, fsSetGlobalAccessLogMode, fsGetGlobalAccessLogMode. +* Added FsCustomStorageId enum. +* Fixed by-name RomFS mount lookups to actually compare the entire name. + +#### graphics +* Added binder session argument to nwindowCreate (nwindowCreateFromLayer not affected). +* Binder code now supports domain objects. +* Fixed bug in nvAddressSpaceCreate. + +#### input +* **Explicitly announce support for System/SystemExt layouts, which in turn fixes input on 9.0.0+. It is of utmost importance that all homebrew be recompiled as soon as possible in order to work properly on 9.0.0+.** +* **Fixed Hdls to work on 9.0.0+.** + * Several Hdls structs were redefined in 9.0.0+ and libnx was updated to reflect the new struct definitions (this is a breaking change). The old structs are still available but they now have a `V7` suffix, and libnx transparently handles conversion to/from the new 9.x structs at runtime on older system versions; so the new structs are *always* used regardless of system version. List of structs affected: + * HiddbgHdlsDeviceInfo(V7) + * HiddbgHdlsState(V7) + * HiddbgHdlsStateListEntry(V7) + * HiddbgHdlsStateList(V7) + * Added hiddbgGetUniquePadDeviceTypeSetInternal. +* Added hidGetNpadInterfaceType. +* Added HidNpadInterfaceType, HidDeviceTypeBits, HidDeviceType enums. +* Prevent AbstractedPad/VirtualPad commands from being used on 9.0.0+ since they were removed. +* Corrected several commands by internally calling hidControllerIDToOfficial. + +#### applet +* Added AppletAttribute, AppletProcessLaunchReason, AppletInfo, AppletApplicationLaunchProperty, AppletApplicationLaunchRequestInfo, AppletResourceUsageInfo structs. +* Added AppletApplicationExitReason, AppletSystemButtonType, AppletProgramSpecifyKind enums. +* Renamed AppletNotificationMessage to AppletMessage. +* Renamed AppletLaunchParameterKind_Application to AppletLaunchParameterKind_UserChannel. +* Added appletGetServiceSession_* funcs. +* Added appletGetAppletInfo. +* Changed appletRequestToShutdown/appletRequestToReboot and appletStartShutdownSequenceForOverlay/appletStartRebootSequenceForOverlay on success to enter an infinite sleep loop. + * This is also used with `_appletExitProcess` when the exit commands were successful, which is used during `__nx_applet_exit_mode` handling. +* Use OpenLibraryAppletProxy command on 3.0.0+ when running appletInitialize for AppletType_LibraryApplet. +* Added libappletArgsPop and libappletSetJumpFlag. + +* **ILibraryAppletSelfAccessor**: + * Added appletPopInData, appletPushOutData, appletPopInteractiveInData, appletPushInteractiveOutData, appletGetPopInDataEvent, appletGetPopInteractiveInDataEvent. + * Added appletCanUseApplicationCore, appletGetMainAppletApplicationControlProperty, appletGetMainAppletStorageId, appletGetDesirableKeyboardLayout. + * Added appletPopExtraStorage, appletGetPopExtraStorageEvent, appletUnpopInData, appletUnpopExtraStorage. + * Added appletGetIndirectLayerProducerHandle, appletGetMainAppletApplicationDesiredLanguage, appletGetCurrentApplicationId. + * Added appletCreateGameMovieTrimmer, appletReserveResourceForMovieOperation, appletUnreserveResourceForMovieOperation. + * Added appletGetMainAppletAvailableUsers. +* **IProcessWindingController**: + * Added appletPushContext, appletPopContext. +* **IDebugFunctions**: + * Added appletOpenMainApplication, appletPerformSystemButtonPressing, appletInvalidateTransitionLayer, appletRequestLaunchApplicationWithUserAndArgumentForDebug, appletGetAppletResourceUsageInfo. +* **ILibraryAppletAccessor**: + * Added appletHolderTerminate, appletHolderRequestExitOrTerminate. +* **IProcessWindingController**: + * Added appletHolderJump. +* **IOverlayFunctions**: + * Added appletBeginToObserveHidInputForDevelop. +* **IHomeMenuFunctions**: + * Added appletPopRequestLaunchApplicationForDebug, appletLaunchDevMenu. +* **IApplicationCreator**: + * Added support for AppletApplication. + * Added appletCreateApplication, appletPopLaunchRequestedApplication, appletCreateSystemApplication, appletPopFloatingApplicationForDevelopment. +* **ILibraryAppletCreator**: + * Added appletTerminateAllLibraryApplets, appletAreAnyLibraryAppletsLeft. +* **IApplicationFunctions**: + * Added appletGetLaunchStorageInfoForDebug, appletRequestFlushGamePlayingMovieForDebug, appletExitAndRequestToShowThanksMessage. + * Added appletExecuteProgram, appletJumpToSubApplicationProgramForDevelopment, appletRestartProgram, and appletGetPreviousProgramIndex. + * Added appletCreateMovieMaker and appletPrepareForJit. + +#### libapplets +* Added support for launching the Album applet via albumLa. + +#### other services +* **Added GRC service support** (video recording, streaming and trimming). +* Changes to caps (capture service) wrappers: + * Added support for the caps:u service. + * Added CapsAlbumFileDateTime, CapsAlbumEntryId, CapsApplicationData, CapsUserIdList, CapsScreenShotAttributeForApplication, CapsScreenShotDecodeOption, CapsApplicationAlbumFileEntry, CapsLoadAlbumScreenShotImageOutputForApplication structs. + * Added AlbumReportOption, CapsContentType enums. + * Added capsGetShimLibraryVersion (not an actual IPC wrapper). + * Added capsGetDefaultStartDateTime, capsGetDefaultEndDateTime, capsConvertApplicationAlbumFileEntryToApplicationAlbumEntry, capsConvertApplicationAlbumEntryToApplicationAlbumFileEntry helper functions. + * Added capssuSaveScreenShotWithUserData, capssuSaveScreenShotWithUserIds, capssuSaveScreenShotEx1, capssuSaveScreenShotEx2. + * Improved definition of capssuSaveScreenShot and capssuSaveScreenShotEx0. + * Improved definition of CapsScreenShotAttribute, CapsApplicationAlbumEntry structs. + * Changed caps:su wrapper to call SetShimLibraryVersion on 7.0.0+. + * Renamed capsscCaptureScreenshot with capsscCaptureRawImageWithTimeout. +* Fixed lr RedirectApplication commands on 9.0.0+. + * Renamed lrLrResolveLegalInformationPath to lrLrResolveApplicationLegalInformationPath. + * Renamed lrLrRedirectLegalInformationPath to lrLrRedirectApplicationLegalInformationPath. +* Added missing fields to NacpStruct and other miscellaneous corrections. +* Fixed definition of setsysGetServiceSession. + +#### miscellaneous +* Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience. + ## Version 2.4.0 #### system diff --git a/nx/Makefile b/nx/Makefile index 6a427ed2..d236e525 100644 --- a/nx/Makefile +++ b/nx/Makefile @@ -9,7 +9,7 @@ endif include $(DEVKITPRO)/devkitA64/base_rules export LIBNX_MAJOR := 2 -export LIBNX_MINOR := 4 +export LIBNX_MINOR := 5 export LIBNX_PATCH := 0 @@ -39,7 +39,7 @@ CFLAGS := -g -Wall -Werror \ $(ARCH) \ $(BUILD_CFLAGS) -CFLAGS += $(INCLUDE) -DSWITCH +CFLAGS += $(INCLUDE) -D__SWITCH__ -DLIBNX_NO_DEPRECATION CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 diff --git a/nx/include/switch.h b/nx/include/switch.h index 72b039e4..88197f50 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -36,9 +36,13 @@ extern "C" { #include "switch/kernel/detect.h" #include "switch/kernel/random.h" #include "switch/kernel/jit.h" -#include "switch/kernel/ipc.h" +#include "switch/kernel/ipc.h" // Deprecated #include "switch/kernel/barrier.h" +#include "switch/sf/hipc.h" +#include "switch/sf/cmif.h" +#include "switch/sf/service.h" + #include "switch/services/sm.h" #include "switch/services/smm.h" #include "switch/services/fs.h" @@ -47,6 +51,7 @@ extern "C" { #include "switch/services/acc.h" #include "switch/services/apm.h" #include "switch/services/applet.h" +#include "switch/services/async.h" #include "switch/services/audin.h" #include "switch/services/audout.h" #include "switch/services/audren.h" @@ -78,6 +83,7 @@ extern "C" { #include "switch/services/ns.h" #include "switch/services/ldr.h" #include "switch/services/ro.h" +#include "switch/services/ts.h" #include "switch/services/pm.h" #include "switch/services/set.h" #include "switch/services/lr.h" @@ -85,6 +91,7 @@ extern "C" { #include "switch/services/ncm.h" #include "switch/services/psc.h" #include "switch/services/caps.h" +#include "switch/services/capsu.h" #include "switch/services/capssc.h" #include "switch/services/capssu.h" #include "switch/services/nfc.h" @@ -92,6 +99,7 @@ extern "C" { #include "switch/services/pctl.h" #include "switch/services/pdm.h" #include "switch/services/grc.h" +#include "switch/services/friends.h" #include "switch/display/binder.h" #include "switch/display/parcel.h" @@ -111,6 +119,8 @@ extern "C" { #include "switch/audio/driver.h" #include "switch/applets/libapplet.h" +#include "switch/applets/album_la.h" +#include "switch/applets/friends_la.h" #include "switch/applets/pctlauth.h" #include "switch/applets/psel.h" #include "switch/applets/error.h" diff --git a/nx/include/switch/applets/album_la.h b/nx/include/switch/applets/album_la.h new file mode 100644 index 00000000..89204b46 --- /dev/null +++ b/nx/include/switch/applets/album_la.h @@ -0,0 +1,31 @@ +/** + * @file album_la.h + * @brief Wrapper for using the Album LibraryApplet. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" + +/// Arg type values pushed for the applet input storage, stored as an u8. +typedef enum { + AlbumLaArg_ShowAlbumFiles = 0, ///< ShowAlbumFiles. Only displays AlbumFiles associated with the title which launched the Album applet, with the filter button disabled. + AlbumLaArg_ShowAllAlbumFiles = 1, ///< ShowAllAlbumFiles. Displays all AlbumFiles, with filtering allowed. + AlbumLaArg_ShowAllAlbumFilesForHomeMenu = 2, ///< ShowAllAlbumFilesForHomeMenu. Similar to ::AlbumLaArg_ShowAllAlbumFiles. +} AlbumLaArg; + +/** + * @brief Launches the applet with ::AlbumLaArg_ShowAlbumFiles and playStartupSound=false. + */ +Result albumLaShowAlbumFiles(void); + +/** + * @brief Launches the applet with ::AlbumLaArg_ShowAllAlbumFiles and playStartupSound=false. + */ +Result albumLaShowAllAlbumFiles(void); + +/** + * @brief Launches the applet with ::AlbumLaArg_ShowAllAlbumFilesForHomeMenu and playStartupSound=true. + */ +Result albumLaShowAllAlbumFilesForHomeMenu(void); + diff --git a/nx/include/switch/applets/friends_la.h b/nx/include/switch/applets/friends_la.h new file mode 100644 index 00000000..2b0f0d3d --- /dev/null +++ b/nx/include/switch/applets/friends_la.h @@ -0,0 +1,94 @@ +/** + * @file friends_la.h + * @brief Wrapper for using the MyPage (friends) LibraryApplet. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../services/acc.h" +#include "../services/friends.h" + +/// Arg type values used with \ref FriendsLaArg. +typedef enum { + FriendsLaArgType_ShowFriendList = 0, ///< ShowFriendList. Launches the applet with the "Friend List" menu initially selected. + FriendsLaArgType_ShowUserDetailInfo = 1, ///< ShowUserDetailInfo + FriendsLaArgType_StartSendingFriendRequest = 2, ///< StartSendingFriendRequest + FriendsLaArgType_ShowMethodsOfSendingFriendRequest = 3, ///< ShowMethodsOfSendingFriendRequest. Launches the applet with the "Add Friend" menu initially selected. + FriendsLaArgType_StartFacedFriendRequest = 4, ///< StartFacedFriendRequest. Launches the applet where the "Search for Local Users" menu is initially shown. Returning from this menu will exit the applet. + FriendsLaArgType_ShowReceivedFriendRequestList = 5, ///< ShowReceivedFriendRequestList. Launches the applet where the "Received Friend Requests" menu is initially shown. Returning from this menu will exit the applet. + FriendsLaArgType_ShowBlockedUserList = 6, ///< ShowBlockedUserList. Launches the applet where the "Blocked-User List" menu is initially shown. Returning from this menu will exit the applet. + FriendsLaArgType_ShowMyProfile = 7, ///< ShowMyProfile. Launches the applet with the "Profile" menu initially selected. ShowMyProfileForHomeMenu is identical to this except for playStartupSound=true. +} FriendsLaArgType; + +/// Arg struct pushed for the applet input storage. +/// The fields following the userID are only set for ::FriendsLaArgType_ShowUserDetailInfo/::FriendsLaArgType_StartSendingFriendRequest, for everything else these are cleared. +typedef struct { + u32 type; ///< \ref FriendsLaArgType + u32 pad; ///< Padding. + AccountUid userID; ///< \ref AccountUid + u64 networkServiceAccountId; ///< NetworkServiceAccountId for the other account. + FriendsInAppScreenName first_inAppScreenName; ///< First InAppScreenName. + FriendsInAppScreenName second_inAppScreenName; ///< Second InAppScreenName. +} FriendsLaArg; + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowFriendList, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowFriendList(AccountUid *userID); + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowUserDetailInfo, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + * @param[in] networkServiceAccountId NetworkServiceAccountId for the user to show UserDetailInfo for. + * @param[in] first_inAppScreenName First \ref FriendsInAppScreenName. + * @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName. + */ +Result friendsLaShowUserDetailInfo(AccountUid *userID, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName); + +/** + * @brief Launches the applet with ::FriendsLaArgType_StartSendingFriendRequest, the specified input, and playStartupSound=false. On success, this will load the output Result from the output storage. + * @param[in] userID \ref AccountUid + * @param[in] networkServiceAccountId NetworkServiceAccountId to send the friend request to. + * @param[in] first_inAppScreenName First \ref FriendsInAppScreenName. + * @param[in] second_inAppScreenName Second \ref FriendsInAppScreenName. + */ +Result friendsLaStartSendingFriendRequest(AccountUid *userID, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName); + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowMethodsOfSendingFriendRequest, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowMethodsOfSendingFriendRequest(AccountUid *userID); + +/** + * @brief Launches the applet with ::FriendsLaArgType_StartFacedFriendRequest, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaStartFacedFriendRequest(AccountUid *userID); + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowReceivedFriendRequestList, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowReceivedFriendRequestList(AccountUid *userID); + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowBlockedUserList, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowBlockedUserList(AccountUid *userID); + +/** + * @brief Launches the applet with ::FriendsLaArgType_ShowMyProfile, the specified input, and playStartupSound=false. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowMyProfile(AccountUid *userID); + +/** + * @brief Same as \ref friendsLaShowMyProfile except with playStartupSound=true. + * @param[in] userID \ref AccountUid + */ +Result friendsLaShowMyProfileForHomeMenu(AccountUid *userID); + diff --git a/nx/include/switch/applets/swkbd.h b/nx/include/switch/applets/swkbd.h index d139f185..cc8e77bf 100644 --- a/nx/include/switch/applets/swkbd.h +++ b/nx/include/switch/applets/swkbd.h @@ -197,12 +197,13 @@ typedef struct { s32 unk_x20; s32 unk_x24; u8 returnButtonFlag; ///< Controls whether the Return button is enabled, for newlines input. 0 = disabled, non-zero = enabled. - u16 unk_x29; + u8 unk_x29; + u8 unk_x2a; u8 unk_x2b; u32 flags; ///< Bitmask 0x4: unknown. u8 unk_x30; u8 unk_x31[0x17]; -} PACKED SwkbdAppearArg; +} SwkbdAppearArg; typedef struct { u32 unk_x0; @@ -226,7 +227,8 @@ typedef struct { u8 disableTouch; ///< Flags bitmask 0x200. u8 disableUSBKeyboard; ///< Flags bitmask 0x800. u8 unk_x468[5]; - u16 unk_x46d; + u8 unk_x46d; + u8 unk_x46e; u8 unk_x46f; float keytopScaleX; ///< Flags bitmask 0x200. float keytopScaleY; ///< Flags bitmask 0x200. @@ -241,7 +243,7 @@ typedef struct { u8 triggerFlag; ///< [6.0.0+] Enables using the trigger field when set. u8 trigger; ///< [6.0.0+] Trigger u8 pad_x49f; -} PACKED SwkbdInlineCalcArg; +} SwkbdInlineCalcArg; /// Struct data for SwkbdInline Interactive reply storage ChangedString*, at the end following the string. typedef struct { diff --git a/nx/include/switch/applets/web.h b/nx/include/switch/applets/web.h index 69bf81b8..954e4b79 100644 --- a/nx/include/switch/applets/web.h +++ b/nx/include/switch/applets/web.h @@ -8,6 +8,7 @@ #include "../types.h" #include "../services/applet.h" #include "../services/caps.h" +#include "../services/acc.h" /// This indicates the type of web-applet. typedef enum { @@ -126,7 +127,7 @@ typedef enum { WebArgType_NewsFlag = 0xB, ///< [1.0.0+] u8 bool WebArgType_UnknownC = 0xC, ///< [1.0.0+] u8 WebArgType_UnknownD = 0xD, ///< [1.0.0+] u8 - WebArgType_UserID = 0xE, ///< [1.0.0+] u128 userID, controls which user-specific savedata to mount. + WebArgType_Uid = 0xE, ///< [1.0.0+] \ref AccountUid, controls which user-specific savedata to mount. WebArgType_AlbumEntry0 = 0xF, ///< [1.0.0+] Share-applet caps AlbumEntry, entry 0. WebArgType_ScreenShot = 0x10, ///< [1.0.0+] u8 bool WebArgType_EcClientCert = 0x11, ///< [1.0.0+] u8 bool @@ -344,9 +345,9 @@ Result webConfigSetWhitelist(WebCommonConfig* config, const char* whitelist); * @note Only available with config created by \ref webPageCreate, \ref webLobbyCreate, or with Share-applet. * @note Used automatically by \ref webShareCreate and \ref webLobbyCreate with userID=0. * @param config WebCommonConfig object. - * @param userID Account userID + * @param uid \ref AccountUid */ -Result webConfigSetUserID(WebCommonConfig* config, u128 userID); +Result webConfigSetUid(WebCommonConfig* config, AccountUid *uid); /** * @brief Sets the Share CapsAlbumEntry. diff --git a/nx/include/switch/audio/audio.h b/nx/include/switch/audio/audio.h index 13a65825..059f3adf 100644 --- a/nx/include/switch/audio/audio.h +++ b/nx/include/switch/audio/audio.h @@ -8,6 +8,7 @@ #include "../types.h" +/// PcmFormat typedef enum { PcmFormat_Invalid = 0, PcmFormat_Int8 = 1, @@ -18,6 +19,7 @@ typedef enum { PcmFormat_Adpcm = 6, } PcmFormat; +/// AudioDeviceName typedef struct { char name[0x100]; } AudioDeviceName; diff --git a/nx/include/switch/display/binder.h b/nx/include/switch/display/binder.h index aa8cefc7..d61abe3c 100644 --- a/nx/include/switch/display/binder.h +++ b/nx/include/switch/display/binder.h @@ -10,7 +10,7 @@ typedef struct { bool initialized : 1; bool has_transact_auto : 1; s32 id; - size_t ipc_buffer_size; + size_t dummy; Service* relay; } Binder; diff --git a/nx/include/switch/kernel/ipc.h b/nx/include/switch/kernel/ipc.h index fff802f7..114936fa 100644 --- a/nx/include/switch/kernel/ipc.h +++ b/nx/include/switch/kernel/ipc.h @@ -9,6 +9,9 @@ #include "../arm/tls.h" #include "../kernel/svc.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// IPC input header magic #define SFCI_MAGIC 0x49434653 /// IPC output header magic @@ -29,13 +32,13 @@ typedef enum { BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory. BufferType_Invalid=2, BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping. -} BufferType; +} BufferType DEPRECATED; typedef enum { BufferDirection_Send=0, BufferDirection_Recv=1, BufferDirection_Exch=2, -} BufferDirection; +} BufferDirection DEPRECATED; typedef enum { IpcCommandType_Invalid = 0, @@ -46,13 +49,13 @@ typedef enum { IpcCommandType_Control = 5, IpcCommandType_RequestWithContext = 6, IpcCommandType_ControlWithContext = 7, -} IpcCommandType; +} IpcCommandType DEPRECATED; typedef enum { DomainMessageType_Invalid = 0, DomainMessageType_SendMessage = 1, DomainMessageType_Close = 2, -} DomainMessageType; +} DomainMessageType DEPRECATED; /// IPC domain message header. typedef struct { @@ -61,13 +64,13 @@ typedef struct { u16 Length; u32 ThisObjectId; u32 Pad[2]; -} DomainMessageHeader; +} DomainMessageHeader DEPRECATED; /// IPC domain response header. typedef struct { u32 NumObjectIds; u32 Pad[3]; -} DomainResponseHeader; +} DomainResponseHeader DEPRECATED; typedef struct { @@ -91,12 +94,13 @@ typedef struct { size_t NumObjectIds; u32 ObjectIds[IPC_MAX_OBJECTS]; -} IpcCommand; +} IpcCommand DEPRECATED; /** * @brief Initializes an IPC command structure. * @param cmd IPC command structure. */ +DEPRECATED static inline void ipcInitialize(IpcCommand* cmd) { *cmd = (IpcCommand){}; } @@ -106,19 +110,19 @@ typedef struct { u32 Size; ///< Size of the buffer. u32 Addr; ///< Lower 32-bits of the address of the buffer u32 Packed; ///< Packed data (including higher bits of the address) -} IpcBufferDescriptor; +} IpcBufferDescriptor DEPRECATED; /// IPC static send-buffer descriptor. typedef struct { u32 Packed; ///< Packed data (including higher bits of the address) u32 Addr; ///< Lower 32-bits of the address -} IpcStaticSendDescriptor; +} IpcStaticSendDescriptor DEPRECATED; /// IPC static receive-buffer descriptor. typedef struct { u32 Addr; ///< Lower 32-bits of the address of the buffer u32 Packed; ///< Packed data (including higher bits of the address) -} IpcStaticRecvDescriptor; +} IpcStaticRecvDescriptor DEPRECATED; /** * @brief Adds a buffer to an IPC command structure. @@ -127,6 +131,7 @@ typedef struct { * @param size Size of the buffer. * @param type Buffer type. */ +DEPRECATED static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type) { size_t off = cmd->NumSend; cmd->Buffers[off] = buffer; @@ -142,6 +147,7 @@ static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t * @param size Size of the buffer. * @param type Buffer type. */ +DEPRECATED static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) { size_t off = cmd->NumSend + cmd->NumRecv; cmd->Buffers[off] = buffer; @@ -157,6 +163,7 @@ static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, * @param size Size of the buffer. * @param type Buffer type. */ +DEPRECATED static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) { size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch; cmd->Buffers[off] = buffer; @@ -172,6 +179,7 @@ static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, * @param size Size of the buffer. * @param index Index of buffer. */ +DEPRECATED static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) { size_t off = cmd->NumStaticIn; cmd->Statics[off] = buffer; @@ -187,6 +195,7 @@ static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t * @param size Size of the buffer. * @param index Index of buffer. */ +DEPRECATED static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) { size_t off = cmd->NumStaticIn + cmd->NumStaticOut; cmd->Statics[off] = buffer; @@ -203,6 +212,7 @@ static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, * @param size Size of the buffer. * @param index Index of buffer. */ +DEPRECATED static inline void ipcAddSendSmart(IpcCommand* cmd, size_t pointer_buffer_size, const void* buffer, size_t size, u8 index) { if (pointer_buffer_size != 0 && size <= pointer_buffer_size) { ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal); @@ -221,6 +231,7 @@ static inline void ipcAddSendSmart(IpcCommand* cmd, size_t pointer_buffer_size, * @param size Size of the buffer. * @param index Index of buffer. */ +DEPRECATED static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t pointer_buffer_size, void* buffer, size_t size, u8 index) { if (pointer_buffer_size != 0 && size <= pointer_buffer_size) { ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal); @@ -235,6 +246,7 @@ static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t pointer_buffer_size, * @brief Tags an IPC command structure to send the PID. * @param cmd IPC command structure. */ +DEPRECATED static inline void ipcSendPid(IpcCommand* cmd) { cmd->SendPid = true; } @@ -245,6 +257,7 @@ static inline void ipcSendPid(IpcCommand* cmd) { * @param h Handle to send. * @remark The receiving process gets a copy of the handle. */ +DEPRECATED static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) { cmd->Handles[cmd->NumHandlesCopy++] = h; } @@ -255,6 +268,7 @@ static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) { * @param h Handle to send. * @remark The sending process loses ownership of the handle, which is transferred to the receiving process. */ +DEPRECATED static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) { cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h; } @@ -265,6 +279,7 @@ static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) { * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request * @return Pointer to the raw embedded data structure in the request, ready to be filled out. */ +DEPRECATED static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) { u32* buf = (u32*)armGetTls(); size_t i; @@ -350,6 +365,7 @@ static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) { * @param session IPC session handle. * @return Result code. */ +DEPRECATED static inline Result ipcDispatch(Handle session) { return svcSendSyncRequest(session); } @@ -361,8 +377,8 @@ static inline Result ipcDispatch(Handle session) { /// IPC parsed command (response) structure. typedef struct { - IpcCommandType CommandType; ///< Type of the command - + IpcCommandType CommandType; ///< Type of the command + bool HasPid; ///< true if the 'Pid' field is filled out. u64 Pid; ///< PID included in the response (only if HasPid is true) @@ -376,7 +392,7 @@ typedef struct { u32 InThisObjectId; ///< Object ID to call the command on (for domain messages). size_t InNumObjectIds; ///< Number of object IDs (for domain messages). u32 InObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages). - + bool IsDomainResponse; ///< true if the the message is a Domain response. size_t OutNumObjectIds; ///< Number of object IDs (for domain responses). u32 OutObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain responses). @@ -391,25 +407,26 @@ typedef struct { void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics. size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics. u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics. - + size_t NumStaticsOut; ///< Number of output statics available in the response. void* Raw; ///< Pointer to the raw embedded data structure in the response. void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding. size_t RawSize; ///< Size of the raw embedded data. -} IpcParsedCommand; +} IpcParsedCommand DEPRECATED; /** * @brief Parse an IPC command response into an IPC parsed command structure. * @param r IPC parsed command structure to fill in. * @return Result code. */ +DEPRECATED static inline Result ipcParse(IpcParsedCommand* r) { u32* buf = (u32*)armGetTls(); u32 ctrl0 = *buf++; u32 ctrl1 = *buf++; size_t i; - + r->IsDomainRequest = false; r->IsDomainResponse = false; @@ -417,7 +434,7 @@ static inline Result ipcParse(IpcParsedCommand* r) { r->HasPid = false; r->RawSize = (ctrl1 & 0x1ff) * 4; r->NumHandles = 0; - + r->NumStaticsOut = (ctrl1 >> 10) & 15; if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors @@ -505,6 +522,7 @@ static inline Result ipcParse(IpcParsedCommand* r) { * @param size Output variable in which to store the size. * @return Result code. */ +DEPRECATED static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) { u32* buf = (u32*)armGetTls(); @@ -544,6 +562,7 @@ static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) { * @param session IPC session handle. * @return Result code. */ +DEPRECATED static inline Result ipcCloseSession(Handle session) { u32* buf = (u32*)armGetTls(); buf[0] = IpcCommandType_Close; @@ -558,6 +577,7 @@ static inline Result ipcCloseSession(Handle session) { * @param new_session_out Output cloned IPC session handle. * @return Result code. */ +DEPRECATED static inline Result ipcCloneSession(Handle session, u32 unk, Handle* new_session_out) { u32* buf = (u32*)armGetTls(); @@ -603,6 +623,7 @@ static inline Result ipcCloneSession(Handle session, u32 unk, Handle* new_sessio * @param object_id_out Output variable in which to store the object ID. * @return Result code. */ +DEPRECATED static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) { u32* buf = (u32*)armGetTls(); @@ -640,6 +661,7 @@ static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_ou * @param cmd IPC domain command structure. * @param object_id Object ID to send. */ +DEPRECATED static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) { cmd->ObjectIds[cmd->NumObjectIds++] = object_id; } @@ -651,6 +673,7 @@ static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) { * @param object_id Domain object ID. * @return Pointer to the raw embedded data structure in the request, ready to be filled out. */ +DEPRECATED static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) { void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader) + cmd->NumObjectIds*sizeof(u32)); DomainMessageHeader* hdr = (DomainMessageHeader*) raw; @@ -672,6 +695,7 @@ static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw * @param r IPC parsed command structure to fill in. * @return Result code. */ +DEPRECATED static inline Result ipcParseDomainRequest(IpcParsedCommand* r) { Result rc = ipcParse(r); DomainMessageHeader *hdr; @@ -710,6 +734,7 @@ static inline Result ipcParseDomainRequest(IpcParsedCommand* r) { * @param sizeof_raw Size in bytes of the raw data structure. * @return Result code. */ +DEPRECATED static inline Result ipcParseDomainResponse(IpcParsedCommand* r, size_t sizeof_raw) { Result rc = ipcParse(r); DomainResponseHeader *hdr; @@ -722,7 +747,7 @@ static inline Result ipcParseDomainResponse(IpcParsedCommand* r, size_t sizeof_r object_ids = (u32*)(((uintptr_t) r->Raw) + sizeof_raw);//Official sw doesn't align this. r->IsDomainResponse = true; - + r->OutNumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds; if ((uintptr_t)object_ids + sizeof(u32) * r->OutNumObjectIds - (uintptr_t)armGetTls() >= 0x100) { return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds); @@ -739,6 +764,7 @@ static inline Result ipcParseDomainResponse(IpcParsedCommand* r, size_t sizeof_r * @param object_id ID of the object to close. * @return Result code. */ +DEPRECATED static inline Result ipcCloseObjectById(Handle session, u32 object_id) { IpcCommand c; DomainMessageHeader* hdr; @@ -756,3 +782,5 @@ static inline Result ipcCloseObjectById(Handle session, u32 object_id) { } ///@} + +#pragma GCC diagnostic pop diff --git a/nx/include/switch/result.h b/nx/include/switch/result.h index e55f25c5..c0d47a07 100644 --- a/nx/include/switch/result.h +++ b/nx/include/switch/result.h @@ -123,6 +123,7 @@ enum { LibnxError_NvinfoFailedToInitialize, LibnxError_NvbufFailedToInitialize, LibnxError_LibAppletBadExit, + LibnxError_InvalidCmifOutHeader, }; /// libnx binder error codes diff --git a/nx/include/switch/runtime/devices/fs_dev.h b/nx/include/switch/runtime/devices/fs_dev.h index 50e84866..910e7d63 100644 --- a/nx/include/switch/runtime/devices/fs_dev.h +++ b/nx/include/switch/runtime/devices/fs_dev.h @@ -49,7 +49,7 @@ int fsdevTranslatePath(const char *path, FsFileSystem** device, char *outpath); Result fsdevSetArchiveBit(const char *path); /// This calls fsFsCreateFile on the filesystem specified by the input path (as used in stdio). -Result fsdevCreateFile(const char* path, size_t size, int flags); +Result fsdevCreateFile(const char* path, size_t size, u32 flags); /// Recursively deletes the directory specified by the input path (as used in stdio). Result fsdevDeleteDirectoryRecursively(const char *path); diff --git a/nx/include/switch/runtime/env.h b/nx/include/switch/runtime/env.h index 6f207ef6..2576739e 100644 --- a/nx/include/switch/runtime/env.h +++ b/nx/include/switch/runtime/env.h @@ -6,6 +6,7 @@ */ #pragma once #include "../types.h" +#include "../services/acc.h" /// Structure representing an entry in the homebrew environment configuration. typedef struct { @@ -114,4 +115,4 @@ bool envHasRandomSeed(void); void envGetRandomSeed(u64 out[2]); /// Returns a pointer to the user id storage area (if present). -u128* envGetUserIdStorage(void); +AccountUid* envGetUserIdStorage(void); diff --git a/nx/include/switch/services/acc.h b/nx/include/switch/services/acc.h index 560b5b7f..a24d62d7 100644 --- a/nx/include/switch/services/acc.h +++ b/nx/include/switch/services/acc.h @@ -6,37 +6,60 @@ */ #pragma once #include "../types.h" -#include "sm.h" +#include "../sf/service.h" #define ACC_USER_LIST_SIZE 8 +typedef enum { + AccountServiceType_NotInitialized = 0, ///< Same as ::AccountServiceType_Application during \ref accountInitialize. + AccountServiceType_Application = 1, ///< Initializes acc:u0. + AccountServiceType_System = 2, ///< Initializes acc:u1. + AccountServiceType_Administrator = 3, ///< Initializes acc:su. +} AccountServiceType; + /// Profile typedef struct { - Service s; + Service s; ///< IProfile } AccountProfile; -typedef struct -{ - u32 unk_x0; +/// Account UserId. +typedef struct { + u64 uid[2]; ///< UserId. All-zero is invalid / Uid not set. See also \ref accountUidIsValid. +} AccountUid; + +/// UserData +typedef struct { + u32 unk_x0; ///< Unknown. u32 iconID; ///< Icon ID. 0 = Mii, the rest are character icon IDs. u8 iconBackgroundColorID; ///< Profile icon background color ID - u8 unk_x9[0x7]; + u8 unk_x9[0x7]; ///< Unknown. u8 miiID[0x10]; ///< Some ID related to the Mii? All zeros when a character icon is used. u8 unk_x20[0x60]; ///< Usually zeros? -} PACKED AccountUserData; +} AccountUserData; -typedef struct -{ - u128 userID; +/// ProfileBase +typedef struct { + AccountUid userID; ///< \ref AccountUid u64 lastEditTimestamp; ///< POSIX UTC timestamp, for the last account edit. - char username[0x20]; ///< UTF-8 Username. -} PACKED AccountProfileBase; + char nickname[0x20]; ///< UTF-8 Nickname. +} AccountProfileBase; +/** + * @brief Sets the \ref AccountServiceType for initialization. Call this function before \ref accountInitialize, if needed. + * @note By default ::AccountServiceType_NotInitialized will be used. + */ +void accountSetServiceType(AccountServiceType serviceType); + +/// Initialize account. Result accountInitialize(void); + +/// Exit account. void accountExit(void); + +/// Gets the Service object for the actual account service session. Service* accountGetServiceSession(void); -/// Get the total number of user profiles +/// Get the total number of user profiles. Result accountGetUserCount(s32* user_count); /** @@ -45,26 +68,35 @@ Result accountGetUserCount(s32* user_count); * @param max_userIDs Maximum number of user IDs to return. * @param actual_total The actual total number of user IDs found. */ -Result accountListAllUsers(u128* userIDs, size_t max_userIDs, size_t *actual_total); +Result accountListAllUsers(AccountUid* userIDs, s32 max_userIDs, s32 *actual_total); -/// Get the userID for the last opened user. The output userID is only valid when the output account_selected==1. -Result accountGetLastOpenedUser(u128 *userID, bool *account_selected); +/// Get the userID for the last opened user. +Result accountGetLastOpenedUser(AccountUid *userID); /// Get an AccountProfile for the specified userID. -Result accountGetProfile(AccountProfile* out, u128 userID); +Result accountGetProfile(AccountProfile* out, const AccountUid *userID); + +/// Close the AccountProfile. +void accountProfileClose(AccountProfile* profile); /// Get \ref AccountUserData and \ref AccountProfileBase for the specified profile, userdata is optional (can be NULL). Result accountProfileGet(AccountProfile* profile, AccountUserData* userdata, AccountProfileBase* profilebase); /// Get the icon image size. -Result accountProfileGetImageSize(AccountProfile* profile, size_t* image_size); +Result accountProfileGetImageSize(AccountProfile* profile, u32* image_size); /// Load the JPEG profile icon, valid for both Miis and character icons. The output image_size is the same as the one from \ref accountProfileGetImageSize. -Result accountProfileLoadImage(AccountProfile* profile, void* buf, size_t len, size_t* image_size); - -void accountProfileClose(AccountProfile* profile); +Result accountProfileLoadImage(AccountProfile* profile, void* buf, size_t len, u32* image_size); /// Gets the userID which was selected by the profile-selector applet (if any), prior to launching the currently running Application title. /// This gets the cached PreselectedUser loaded during accountInitialize, when PreselectedUser is available. -Result accountGetPreselectedUser(u128 *userID); +Result accountGetPreselectedUser(AccountUid *userID); + +/** + * @brief Checks whether the specified \ref AccountUid is valid/set (non-zero). + * @param[in] Uid \ref AccountUid + */ +NX_CONSTEXPR bool accountUidIsValid(const AccountUid *Uid) { + return Uid->uid[0]!=0 || Uid->uid[1]!=0; +} diff --git a/nx/include/switch/services/apm.h b/nx/include/switch/services/apm.h index 6e5e44b3..3f3fcbd3 100644 --- a/nx/include/switch/services/apm.h +++ b/nx/include/switch/services/apm.h @@ -1,12 +1,18 @@ /** * @file apm.h - * @brief Performance management (apm) service IPC wrapper. This is used internally by applet with __nx_applet_PerformanceConfiguration, however if you prefer non-init/exit can be used manually. + * @brief Performance management (apm) service IPC wrapper. This is used internally by applet with __nx_applet_PerformanceConfiguration, however if you prefer non-init/exit can be used manually. See also: https://switchbrew.org/wiki/PTM_services#apm:am * @author yellows8 * @copyright libnx Authors */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" + +/// PerformanceMode +typedef enum { + ApmPerformanceMode_Handheld = 0, ///< Handheld + ApmPerformanceMode_Docked = 1, ///< Docked +} ApmPerformanceMode; /// CpuBoostMode. With \ref appletSetCpuBoostMode, only values 0/1 are available. This allows using higher clock rates. typedef enum { @@ -15,9 +21,28 @@ typedef enum { ApmCpuBoostMode_Type2 = 2, ///< Use performance configurations 0x9222000B and 0x9222000C. } ApmCpuBoostMode; +/// Initialize apm. Used automatically by \ref appletInitialize. Result apmInitialize(void); + +/// Exit apm. Used automatically by \ref appletExit. void apmExit(void); + +/// Gets the Service object for the actual apm service session. Service* apmGetServiceSession(void); -Result apmSetPerformanceConfiguration(u32 PerformanceMode, u32 PerformanceConfiguration); -Result apmGetPerformanceConfiguration(u32 PerformanceMode, u32 *PerformanceConfiguration); +/// Gets the Service object for ISession. +Service* apmGetServiceSession_Session(void); + +/** + * @brief Sets the PerformanceConfiguration for the specified PerformanceMode. + * @param[in] PerformanceMode \ref ApmPerformanceMode + * @param[in] PerformanceConfiguration PerformanceConfiguration + */ +Result apmSetPerformanceConfiguration(ApmPerformanceMode PerformanceMode, u32 PerformanceConfiguration); + +/** + * @brief Gets the PerformanceConfiguration for the specified PerformanceMode. + * @param[in] PerformanceMode \ref ApmPerformanceMode + * @param[out] PerformanceConfiguration PerformanceConfiguration + */ +Result apmGetPerformanceConfiguration(ApmPerformanceMode PerformanceMode, u32 *PerformanceConfiguration); diff --git a/nx/include/switch/services/applet.h b/nx/include/switch/services/applet.h index f961c498..9c081344 100644 --- a/nx/include/switch/services/applet.h +++ b/nx/include/switch/services/applet.h @@ -7,12 +7,13 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../services/apm.h" #include "../services/pdm.h" #include "../services/caps.h" #include "../services/pm.h" #include "../services/fs.h" +#include "../services/acc.h" #include "../kernel/tmem.h" #include "../kernel/event.h" #include "../nacp.h" @@ -740,13 +741,6 @@ Result appletGetCurrentIlluminanceEx(bool *bOverLimit, float *fLux); */ Result appletSetWirelessPriorityMode(AppletWirelessPriorityMode mode); -/** - * @brief Sets whether ::AppletMessage_AlbumImageTaken is enabled. - * @note Only available with [7.0.0+]. - * @param[in] flag Whether to enable the notification. - */ -Result appletSetAlbumImageTakenNotificationEnabled(bool flag); - /** * @brief Gets the total time in nanoseconds that the current process was actively running (not suspended), relative to when \ref appletInitialize was last used. * @note Only available with [6.0.0+]. @@ -754,6 +748,13 @@ Result appletSetAlbumImageTakenNotificationEnabled(bool flag); */ Result appletGetProgramTotalActiveTime(u64 *activeTime); +/** + * @brief Sets whether ::AppletMessage_AlbumImageTaken is enabled. + * @note Only available with [7.0.0+]. + * @param[in] flag Whether to enable the notification. + */ +Result appletSetAlbumImageTakenNotificationEnabled(bool flag); + /** * @brief Sets the Application AlbumUserData. * @note Only available with [8.0.0+]. @@ -1423,13 +1424,13 @@ Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats, /** * @brief Same as \ref appletQueryApplicationPlayStatistics except this gets playstats specific to the input userID. * @note Only available with AppletType_*Application on [6.0.0+]. - * @param userID userID - * @param stats Output \ref PdmApplicationPlayStatistics array. - * @param titleIDs Input titleIDs array. - * @param count Total entries in the input/output arrays. - * @param total_out Total output entries. + * @param[in] uid \ref AccountUid + * @param[out] stats Output \ref PdmApplicationPlayStatistics array. + * @param[in] titleIDs Input titleIDs array. + * @param[in] count Total entries in the input/output arrays. + * @param[out] total_out Total output entries. */ -Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out); +Result appletQueryApplicationPlayStatisticsByUid(AccountUid *uid, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out); /** * @brief Launches Application title {current_titleID}+programIndex. This will enter an infinite-sleep-loop on success. @@ -1476,6 +1477,14 @@ Result appletGetPreviousProgramIndex(s32 *programIndex); */ Result appletGetGpuErrorDetectedSystemEvent(Event *out_event); +/** + * @brief CreateMovieMaker. Do not use this directly, use \ref grcCreateMovieMaker instead. + * @note Only available with AppletType_*Application on [5.0.0+]. + * @param[out] srv_out Output Service for applet IMovieMaker. + * @param[in] tmem TransferMemory + */ +Result appletCreateMovieMaker(Service* srv_out, TransferMemory *tmem); + /** * @brief Launches the jit-sysmodule when it was not previously launched by this cmd. Returns 0 when it was previously launched. * @note Only available with AppletType_*Application on [5.0.0+]. @@ -1532,12 +1541,12 @@ Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a); /** * @brief PopRequestLaunchApplicationForDebug * @note Only available with AppletType_SystemApplet on [6.0.0+]. - * @param[out] userIDs Output array of userIDs. + * @param[out] userIDs Output array of \ref AccountUid. * @param[in] count Size of the userID array in entries, must be at least the size stored in state. * @param[out] titleID Output Application titleID. * @param[out] total_out Total output userID entries. */ -Result appletPopRequestLaunchApplicationForDebug(u128 *userIDs, s32 count, u64 *titleID, s32 *total_out); +Result appletPopRequestLaunchApplicationForDebug(AccountUid *userIDs, s32 count, u64 *titleID, s32 *total_out); /** * @brief Launches DevMenu and the dev Overlay-applet. This will enter an infinite-sleep-loop on success. @@ -1774,11 +1783,11 @@ Result appletApplicationGetApplicationLaunchRequestInfo(AppletApplication *a, Ap * @brief SetUsers for the Application. * @note Only available on [6.0.0+]. * @param a \ref AppletApplication - * @param[in] userIDs Input array of userIDs. + * @param[in] userIDs Input array of \ref AccountUid. * @param[in] count Size of the userID array in entries, must be <=ACC_USER_LIST_SIZE. * @param[in] flag When this flag is true, this just clears the users_available state flag to 0 and returns. */ -Result appletApplicationSetUsers(AppletApplication *a, const u128 *userIDs, s32 count, bool flag); +Result appletApplicationSetUsers(AppletApplication *a, const AccountUid *userIDs, s32 count, bool flag); /** * @brief CheckRightsEnvironmentAvailable. @@ -1801,11 +1810,11 @@ Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 * * @note Only available on [6.0.0+]. * @note qlaunch only uses 1 userID with this. * @param a \ref AppletApplication - * @param[out] userIDs Output array of userIDs. + * @param[out] userIDs Output array of \ref AccountUid. * @param[in] count Size of the userID array in entries, must be at least the size stored in state. * @param[out] total_out Total output entries. */ -Result appletApplicationGetDesirableUids(AppletApplication *a, u128 *userIDs, s32 count, s32 *total_out); +Result appletApplicationGetDesirableUids(AppletApplication *a, AccountUid *userIDs, s32 count, s32 *total_out); /** * @brief ReportApplicationExitTimeout. @@ -2029,12 +2038,12 @@ Result appletUnreserveResourceForMovieOperation(void); /** * @brief Gets an array of userIDs for the MainApplet AvailableUsers. * @note Only available with AppletType_LibraryApplet on [6.0.0+]. - * @param[out] userIDs Output array of userIDs. + * @param[out] userIDs Output array of \ref AccountUid. * @param[in] count Size of the userID array in entries, must be at least ACC_USER_LIST_SIZE. * @param[out] flag When true, this indicates that no users are available. * @param[out] total_out Total output entries. This is -1 when flag is true. */ -Result appletGetMainAppletAvailableUsers(u128 *userIDs, s32 count, bool *flag, s32 *total_out); +Result appletGetMainAppletAvailableUsers(AccountUid *userIDs, s32 count, bool *flag, s32 *total_out); ///@} @@ -2129,7 +2138,7 @@ Result appletBeginToObserveHidInputForDevelop(void); * @param[in] offset Offset within the ThemeStorage. * @param[out] transfer_size Actual read size. */ -Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, size_t *transfer_size); +Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, u64 *transfer_size); /** * @brief Writes the ThemeStorage for the current applet. @@ -2201,13 +2210,13 @@ Result appletInvalidateTransitionLayer(void); * @brief Requests to launch the specified Application, with the specified users. * @note Only available on [6.0.0+]. * @param[in] titleID Application titleID. - * @param[in] userIDs Input array of userIDs. + * @param[in] userIDs Input array of \ref AccountUid. * @param[in] total_userIDs Total input userIDs, must be <=ACC_USER_LIST_SIZE. * @param[in] flag Whether to use the specified buffer to create a storage which will be pushed for ::AppletLaunchParameterKind_UserChannel. * @param[in] buffer Buffer containing the above storage data. * @param[in] size Size of the storage buffer. */ -Result appletRequestLaunchApplicationWithUserAndArgumentForDebug(u64 titleID, u128 *userIDs, size_t total_userIDs, bool flag, const void* buffer, size_t size); +Result appletRequestLaunchApplicationWithUserAndArgumentForDebug(u64 titleID, AccountUid *userIDs, size_t total_userIDs, bool flag, const void* buffer, size_t size); /** * @brief Gets the \ref AppletResourceUsageInfo. @@ -2262,8 +2271,8 @@ void appletHook(AppletHookCookie* cookie, AppletHookFn callback, void* param); void appletUnhook(AppletHookCookie* cookie); /// These return state which is updated by appletMainLoop() when notifications are received. -u8 appletGetOperationMode(void); -u32 appletGetPerformanceMode(void); +AppletOperationMode appletGetOperationMode(void); +ApmPerformanceMode appletGetPerformanceMode(void); AppletFocusState appletGetFocusState(void); Result appletSetFocusHandlingMode(AppletFocusHandlingMode mode); diff --git a/nx/include/switch/services/async.h b/nx/include/switch/services/async.h new file mode 100644 index 00000000..98f68488 --- /dev/null +++ b/nx/include/switch/services/async.h @@ -0,0 +1,113 @@ +/** + * @file async.h + * @brief NS/NIM IAsync* IPC wrapper. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" +#include "../applets/error.h" +#include "../kernel/event.h" + +/// AsyncValue +typedef struct { + Service s; ///< IAsyncValue + Event event; ///< Event with autoclear=false. +} AsyncValue; + +/// AsyncResult +typedef struct { + Service s; ///< IAsyncResult + Event event; ///< Event with autoclear=false. +} AsyncResult; + +///@name IAsyncValue +///@{ + +/** + * @brief Close a \ref AsyncValue. + * @note When the object is initialized, this uses \ref asyncValueCancel then \ref asyncValueWait with timeout=U64_MAX. + * @param a \ref AsyncValue + */ +void asyncValueClose(AsyncValue *a); + +/** + * @brief Waits for the async operation to finish using the specified timeout. + * @param a \ref AsyncValue + * @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout. + */ +Result asyncValueWait(AsyncValue *a, u64 timeout); + +/** + * @brief Gets the value size. + * @param a \ref AsyncValue + * @param[out] size Output size. + */ +Result asyncValueGetSize(AsyncValue *a, u64 *size); + +/** + * @brief Gets the value. + * @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=U64_MAX. + * @param a \ref AsyncValue + * @param[out] buffer Output buffer. + * @param[in] size Output buffer size. + */ +Result asyncValueGet(AsyncValue *a, void* buffer, size_t size); + +/** + * @brief Cancels the async operation. + * @note Used automatically by \ref asyncValueClose. + * @param a \ref AsyncValue + */ +Result asyncValueCancel(AsyncValue *a); + +/** + * @brief Gets the \ref ErrorContext. + * @param a \ref AsyncValue + * @param[out] context \ref ErrorContext + */ +Result asyncValueGetErrorContext(AsyncValue *a, ErrorContext *context); + +///@} + +///@name IAsyncResult +///@{ + +/** + * @brief Close a \ref AsyncResult. + * @note When the object is initialized, this uses \ref asyncResultCancel then \ref asyncResultWait with timeout=U64_MAX. + * @param a \ref AsyncResult + */ +void asyncResultClose(AsyncResult *a); + +/** + * @brief Waits for the async operation to finish using the specified timeout. + * @param a \ref AsyncResult + * @param[in] timeout Timeout in nanoseconds. U64_MAX for no timeout. + */ +Result asyncResultWait(AsyncResult *a, u64 timeout); + +/** + * @brief Gets the Result. + * @note Prior to using the cmd, this uses \ref asyncResultWait with timeout=U64_MAX. + * @param a \ref AsyncResult + */ +Result asyncResultGet(AsyncResult *a); + +/** + * @brief Cancels the async operation. + * @note Used automatically by \ref asyncResultClose. + * @param a \ref AsyncResult + */ +Result asyncResultCancel(AsyncResult *a); + +/** + * @brief Gets the \ref ErrorContext. + * @param a \ref AsyncResult + * @param[out] context \ref ErrorContext + */ +Result asyncResultGetErrorContext(AsyncResult *a, ErrorContext *context); + +///@} + diff --git a/nx/include/switch/services/audren.h b/nx/include/switch/services/audren.h index 8a2d3215..67738728 100644 --- a/nx/include/switch/services/audren.h +++ b/nx/include/switch/services/audren.h @@ -9,12 +9,6 @@ #include "../audio/audio.h" #include "../services/sm.h" -#if __cplusplus >= 201402L -#define AUDREN_CONSTEXPR constexpr -#else -#define AUDREN_CONSTEXPR static inline -#endif - #define AUDREN_TIMER_FREQ_HZ 200.0f #define AUDREN_TIMER_PERIOD_MS 5.0f #define AUDREN_SAMPLES_PER_FRAME_32KHZ 160 @@ -287,12 +281,12 @@ static inline u32 audrenGetRevision(void) return g_audrenRevision; } -AUDREN_CONSTEXPR int audrenGetMemPoolCount(const AudioRendererConfig* config) +NX_CONSTEXPR int audrenGetMemPoolCount(const AudioRendererConfig* config) { return config->num_effects + 4 * config->num_voices; } -AUDREN_CONSTEXPR size_t audrenGetInputParamSize(const AudioRendererConfig* config) +NX_CONSTEXPR size_t audrenGetInputParamSize(const AudioRendererConfig* config) { size_t size = 0; size += sizeof(AudioRendererUpdateDataHeader); @@ -307,7 +301,7 @@ AUDREN_CONSTEXPR size_t audrenGetInputParamSize(const AudioRendererConfig* confi return size; } -AUDREN_CONSTEXPR size_t audrenGetOutputParamSize(const AudioRendererConfig* config) +NX_CONSTEXPR size_t audrenGetOutputParamSize(const AudioRendererConfig* config) { size_t size = 0; size += sizeof(AudioRendererUpdateDataHeader); diff --git a/nx/include/switch/services/caps.h b/nx/include/switch/services/caps.h index 22b934e7..07b36e47 100644 --- a/nx/include/switch/services/caps.h +++ b/nx/include/switch/services/caps.h @@ -7,21 +7,72 @@ #pragma once #include "../types.h" #include "../services/sm.h" +#include "../services/acc.h" +/// ImageOrientation +typedef enum { + AlbumImageOrientation_Unknown0 = 0, ///< Unknown. Default. + AlbumImageOrientation_Unknown1 = 1, ///< Unknown. + AlbumImageOrientation_Unknown2 = 2, ///< Unknown. + AlbumImageOrientation_Unknown3 = 3, ///< Unknown. +} AlbumImageOrientation; + +/// AlbumReportOption +typedef enum { + AlbumReportOption_Disable = 0, ///< Don't display the screenshot-taken Overlay-applet notification. + AlbumReportOption_Enable = 1, ///< Display the screenshot-taken Overlay notification. +} AlbumReportOption; + +/// ContentType +typedef enum { + CapsContentType_Screenshot = 0, ///< Album screenshots. + CapsContentType_Movie = 1, ///< Album videos. + CapsContentType_ExtraMovie = 3, ///< Videos recorded by the current Application host title via \ref grcCreateMovieMaker. +} CapsContentType; + +/// ScreenShotAttribute typedef struct { - u32 unk_x0; - u8 unk_x4[0x3c]; + u32 unk_x0; ///< Always set to 0 by official sw. + u32 orientation; ///< \ref AlbumImageOrientation + u32 unk_x8; ///< Always set to 0 by official sw. + u32 unk_xc; ///< Always set to 1 by official sw. + u8 unk_x10[0x30]; ///< Always set to 0 by official sw. } CapsScreenShotAttribute; -/// AlbumFileDateTime. This corresponds to each field in the Album entry filename, prior to the "-". +/// ScreenShotAttributeForApplication. Only unk_x0 is used by official sw. +typedef struct { + u32 unk_x0; ///< Unknown. + u8 unk_x4; ///< Unknown. + u8 unk_x5; ///< Unknown. + u8 unk_x6; ///< Unknown. + u8 pad; ///< Padding. + u32 unk_x8; ///< Unknown. + u32 unk_xc; ///< Unknown. + u32 unk_x10; ///< Unknown. + u32 unk_x14; ///< Unknown. + u32 unk_x18; ///< Unknown. + u32 unk_x1c; ///< Unknown. + u16 unk_x20; ///< Unknown. + u16 unk_x22; ///< Unknown. + u16 unk_x24; ///< Unknown. + u16 unk_x26; ///< Unknown. + u8 reserved[0x18]; ///< Always zero. +} CapsScreenShotAttributeForApplication; + +/// ScreenShotDecodeOption +typedef struct { + u8 unk_x0[0x20]; ///< Unknown. Set to all-zero by official sw. +} CapsScreenShotDecodeOption; + +/// AlbumFileDateTime. This corresponds to each field in the Album entry filename, prior to the "-": "YYYYMMDDHHMMSSII". typedef struct { u16 year; ///< Year. u8 month; ///< Month. - u8 day; ///< Day. + u8 day; ///< Day of the month. u8 hour; ///< Hour. u8 minute; ///< Minute. u8 second; ///< Second. - u8 unk_x7; ///< Unknown. + u8 id; ///< Unique ID for when there's multiple Album files with the same timestamp. } CapsAlbumFileDateTime; /// AlbumEntryId @@ -35,20 +86,79 @@ typedef struct { /// AlbumEntry typedef struct { - u8 unk_x0[0x8]; - CapsAlbumEntryId id; + u8 unk_x0[0x8]; ///< Unknown. + CapsAlbumEntryId id; ///< \ref CapsAlbumEntryId } CapsAlbumEntry; /// ApplicationAlbumEntry typedef struct { - u8 unk_x0[0x20]; + union { + u8 data[0x20]; ///< Data. + + struct { + u8 unk_x0[0x20]; ///< Unknown. + } 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. + } v1; ///< [7.0.0+] + }; } CapsApplicationAlbumEntry; -/// ImageOrientation -typedef enum { - AlbumImageOrientation_Unknown0 = 0, ///< Unknown. - AlbumImageOrientation_Unknown1 = 1, ///< Unknown. - AlbumImageOrientation_Unknown2 = 2, ///< Unknown. - AlbumImageOrientation_Unknown3 = 3, ///< Unknown. -} AlbumImageOrientation; +/// ApplicationAlbumFileEntry +typedef struct { + CapsApplicationAlbumEntry entry; ///< \ref CapsApplicationAlbumEntry + CapsAlbumFileDateTime datetime; ///< \ref CapsAlbumFileDateTime + u64 unk_x28; ///< Unknown. +} CapsApplicationAlbumFileEntry; + +/// ApplicationData +typedef struct { + u8 userdata[0x400]; ///< UserData. + u32 size; ///< UserData size. +} CapsApplicationData; + +/// UserIdList +typedef struct { + AccountUid userIDs[ACC_USER_LIST_SIZE]; ///< \ref AccountUid + u8 count; ///< Total userIDs. + u8 pad[7]; ///< Padding. +} CapsUserIdList; + +/// LoadAlbumScreenShotImageOutputForApplication +typedef struct { + s64 width; ///< Width. Official sw copies this to a s32 output field. + s64 height; ///< Height. Official sw copies this to a s32 output field. + CapsScreenShotAttributeForApplication attr; ///< \ref CapsScreenShotAttributeForApplication + CapsApplicationData appdata; ///< \ref CapsApplicationData + u8 reserved[0xac]; ///< Unused. +} CapsLoadAlbumScreenShotImageOutputForApplication; + +/// Gets the ShimLibraryVersion. +u64 capsGetShimLibraryVersion(void); + +/// Gets the default start_datetime. +static inline CapsAlbumFileDateTime capsGetDefaultStartDateTime(void) { + return (CapsAlbumFileDateTime){.year = 1970, .month = 1, .day = 1}; +} + +/// Gets the default end_datetime. +static inline CapsAlbumFileDateTime capsGetDefaultEndDateTime(void) { + return (CapsAlbumFileDateTime){.year = 3000, .month = 1, .day = 1}; +} + +/// Convert a \ref CapsApplicationAlbumFileEntry to \ref CapsApplicationAlbumEntry. +static inline void capsConvertApplicationAlbumFileEntryToApplicationAlbumEntry(CapsApplicationAlbumEntry *out, CapsApplicationAlbumFileEntry *in) { + *out = in->entry; +} + +/// Convert a \ref CapsApplicationAlbumEntry to \ref CapsApplicationAlbumFileEntry. Should only be used on [7.0.0+]. +static inline void capsConvertApplicationAlbumEntryToApplicationAlbumFileEntry(CapsApplicationAlbumFileEntry *out, CapsApplicationAlbumEntry *in) { + out->entry = *in; + out->datetime = in->v1.datetime; + out->unk_x28 = 0; +} diff --git a/nx/include/switch/services/capssc.h b/nx/include/switch/services/capssc.h index 06250829..38fb9c6e 100644 --- a/nx/include/switch/services/capssc.h +++ b/nx/include/switch/services/capssc.h @@ -6,12 +6,16 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../services/caps.h" /// Initialize caps:sc. Only available on [2.0.0+]. Result capsscInitialize(void); + +/// Exit caps:sc. void capsscExit(void); + +/// Gets the Service for caps:sc. Service* capsscGetServiceSession(void); /** @@ -27,5 +31,5 @@ Service* capsscGetServiceSession(void); * @param buffer_index Starting image buffer index. Must be < buffer_count. * @param timeout Timeout in nanoseconds. A default value of 100000000 can be used. */ -Result capsscCaptureScreenshot(void* buf, size_t size, u32 inval, u64 width, u64 height, s64 buffer_count, s64 buffer_index, u64 timeout); +Result capsscCaptureRawImageWithTimeout(void* buf, size_t size, u32 inval, u64 width, u64 height, s64 buffer_count, s64 buffer_index, u64 timeout); diff --git a/nx/include/switch/services/capssu.h b/nx/include/switch/services/capssu.h index b4e910c8..59a33612 100644 --- a/nx/include/switch/services/capssu.h +++ b/nx/include/switch/services/capssu.h @@ -6,17 +6,89 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" +#include "../services/acc.h" #include "../services/caps.h" /// Initialize caps:su. Only available on [4.0.0+]. Result capssuInitialize(void); + +/// Exit caps:su. void capssuExit(void); + +/// Gets the Service for caps:su. Service* capssuGetServiceSession(void); -/// Same as \ref capssuSaveScreenShotEx0, except this uses an all-zero CapsScreenShotAttribute where the first u32 is set to attr_val. attr_val can be zero. -Result capssuSaveScreenShot(const void* buffer, size_t size, u32 unk, u32 attr_val, CapsApplicationAlbumEntry *out); +/** + * @brief This is a wrapper for \ref capssuSaveScreenShotEx0. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @param[in] buffer RGBA8 1280x720 image buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShot(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, CapsApplicationAlbumEntry *out); -/// Saves an Album screenshot using the specified gfx data in buffer (1280x720 RGBA8), size must be at least 0x384000. unk can be zero. -Result capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out); +/** + * @brief Similar to \ref capssuSaveScreenShot, except this is a wrapper for \ref capssuSaveScreenShotEx1. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @note Only available on [8.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[in] userdata Input UserData buffer. If NULL, the \ref CapsApplicationData will be empty. + * @param[in] userdata_size Input UserData size, must be within bounds for CapsApplicationData::userdata. If 0, the \ref CapsApplicationData will be empty. + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotWithUserData(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const void* userdata, size_t userdata_size, CapsApplicationAlbumEntry *out); + +/** + * @brief Similar to \ref capssuSaveScreenShot, except this is a wrapper for \ref capssuSaveScreenShotEx2. + * @note This uses an all-zero \ref CapsScreenShotAttribute with orientation = input orientation, and unk_xc = 1. + * @note Only available on [6.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer. + * @param[in] reportoption \ref AlbumReportOption + * @param[in] orientation \ref AlbumImageOrientation + * @param[in] userIDs Input array of \ref AccountUid. If NULL, the \ref CapsUserIdList will be empty. + * @param[in] userID_count Size of the userID array in entries, must be within bounds for CapsUserIdList::userIDs. If 0, the \ref CapsUserIdList will be empty. + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotWithUserIds(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const AccountUid* userIDs, size_t userID_count, CapsApplicationAlbumEntry *out); + +/** + * @brief Saves an Album screenshot using the specified gfx data in the buffer, with the specified \ref CapsScreenShotAttribute. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out); + +/** + * @brief Same as \ref capssuSaveScreenShotEx0, except this allows specifying the \ref CapsApplicationData. + * @note Only available on [8.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @param[in] appdata \ref CapsApplicationData + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx1(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationData *appdata, CapsApplicationAlbumEntry *out); + +/** + * @brief Same as \ref capssuSaveScreenShotEx0, except this allows specifying the \ref CapsUserIdList. + * @note Only available on [6.0.0+]. + * @param[in] buffer RGBA8 1280x720 image data buffer. + * @param[in] size Size of the buffer, must be at least 0x384000. + * @param[in] attr \ref CapsScreenShotAttribute + * @param[in] reportoption \ref AlbumReportOption + * @param[in] list \ref CapsUserIdList + * @param[out] out \ref CapsApplicationAlbumEntry. Optional, can be NULL. + */ +Result capssuSaveScreenShotEx2(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsUserIdList *list, CapsApplicationAlbumEntry *out); diff --git a/nx/include/switch/services/capsu.h b/nx/include/switch/services/capsu.h new file mode 100644 index 00000000..5c2f7a81 --- /dev/null +++ b/nx/include/switch/services/capsu.h @@ -0,0 +1,173 @@ +/** + * @file capsu.h + * @brief Application Album (caps:u) service IPC wrapper. + * This is only usable with AlbumFiles associated with the current Application host title. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" +#include "../services/caps.h" +#include "../services/acc.h" + +/// Initialize caps:u. Only available on [5.0.0+]. +Result capsuInitialize(void); + +/// Exit caps:u. +void capsuExit(void); + +/// Gets the Service for caps:u. +Service* capsuGetServiceSession(void); + +/// Gets the Service for IAlbumAccessorApplicationSession, only initialized after \ref capsuOpenAlbumMovieStream was used (unaffected by using \ref capsuCloseAlbumMovieStream). +Service* capsuGetServiceSession_Accessor(void); + +/** + * @brief Gets a listing of \ref CapsApplicationAlbumFileEntry. + * @note On [6.0.0+] this uses GetAlbumFileList1AafeAruidDeprecated, otherwise this uses GetAlbumFileList0AafeAruidDeprecated. + * @note This is an old version of \ref capsuGetAlbumFileList3. + * @param[out] entries Output array of \ref CapsApplicationAlbumFileEntry. + * @param[in] count Max size of the output array in entries. + * @param[in] type \ref CapsContentType + * @param[in] start_datetime Start \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] end_datetime End \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[out] total_entries Total output entries. + */ +Result capsuGetAlbumFileListDeprecated1(CapsApplicationAlbumFileEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, s32 *total_entries); + +/** + * @brief Gets a listing of \ref CapsApplicationAlbumFileEntry, where the AlbumFile has an UserId which matches the input one. See also \ref capssuSaveScreenShotWithUserIds. + * @note Only available on [6.0.0+]. + * @note This is an old version of \ref capsuGetAlbumFileList4. + * @param[out] entries Output array of \ref CapsApplicationAlbumFileEntry. + * @param[in] count Max size of the output array in entries. + * @param[in] type \ref CapsContentType + * @param[in] start_datetime Start \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] end_datetime End \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] userID \ref AccountUid + * @param[out] total_entries Total output entries. + */ +Result capsuGetAlbumFileListDeprecated2(CapsApplicationAlbumFileEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, AccountUid *userID, s32 *total_entries); + +/** + * @brief Gets a listing of \ref CapsApplicationAlbumEntry. + * @note Only available on [7.0.0+], on prior sysvers use \ref capsuGetAlbumFileListDeprecated1 instead. + * @param[out] entries Output array of \ref CapsApplicationAlbumEntry. + * @param[in] count Max size of the output array in entries. + * @param[in] type \ref CapsContentType + * @param[in] start_datetime Start \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] end_datetime End \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[out] total_entries Total output entries. + */ +Result capsuGetAlbumFileList3(CapsApplicationAlbumEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, s32 *total_entries); + +/** + * @brief Gets a listing of \ref CapsApplicationAlbumEntry, where the AlbumFile has an UserId which matches the input one. See also \ref capssuSaveScreenShotWithUserIds. + * @note Only available on [7.0.0+], on prior sysvers use \ref capsuGetAlbumFileListDeprecated2 instead. + * @param[out] entries Output array of \ref CapsApplicationAlbumEntry. + * @param[in] count Max size of the output array in entries. + * @param[in] type \ref CapsContentType + * @param[in] start_datetime Start \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] end_datetime End \ref CapsAlbumFileDateTime, when NULL the default is used. + * @param[in] userID \ref AccountUid + * @param[out] total_entries Total output entries. + */ +Result capsuGetAlbumFileList4(CapsApplicationAlbumEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, AccountUid *userID, s32 *total_entries); + +/** + * @brief Deletes the specified AlbumFile. + * @param[in] type \ref CapsContentType, must match ::CapsContentType_ExtraMovie. + * @param[in] entry \ref CapsApplicationAlbumFileEntry + */ +Result capsuDeleteAlbumFile(CapsContentType type, const CapsApplicationAlbumFileEntry *entry); + +/** + * @brief Gets the filesize for the entire specified AlbumFile. + * @param[in] entry \ref CapsApplicationAlbumFileEntry + * @param[out] size Output filesize. + */ +Result capsuGetAlbumFileSize(const CapsApplicationAlbumFileEntry *entry, u64 *size); + +/** + * @brief Load the ScreenShotImage for the specified AlbumFile. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[out] attr \ref CapsScreenShotAttributeForApplication + * @param[out] userdata Output buffer containing the UserData. Optional, can be NULL. This buffer is cleared to 0 using userdata_maxsize, prior to doing the memcpy. + * @param[in] userdata_maxsize Max size of the userdata buffer. Optional, can be 0. + * @param[out] userdata_size Userdata size field, clamped to max size sizeof(CapsApplicationData::userdata) when needed. + * @param[out] image RGBA8 image output buffer. + * @param[out] image_size Image buffer size, should be at least large enough for RGBA8 1280x720. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[out] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + * @param[in] entry \ref CapsApplicationAlbumFileEntry + * @param[in] option \ref CapsScreenShotDecodeOption + */ +Result capsuLoadAlbumScreenShotImage(s32 *width, s32 *height, CapsScreenShotAttributeForApplication *attr, void* userdata, size_t userdata_maxsize, u32 *userdata_size, void* image, size_t image_size, void* workbuf, size_t workbuf_size, const CapsApplicationAlbumFileEntry *entry, const CapsScreenShotDecodeOption *option); + +/** + * @brief Load the ScreenShotThumbnailImage for the specified AlbumFile. + * @param[out] width Output image width. Optional, can be NULL. + * @param[out] height Output image height. Optional, can be NULL. + * @param[out] attr \ref CapsScreenShotAttributeForApplication + * @param[out] userdata Output buffer containing the UserData. Optional, can be NULL. This buffer is cleared to 0 using userdata_maxsize, prior to doing the memcpy. + * @param[in] userdata_maxsize Max size of the userdata buffer. Optional, can be 0. + * @param[out] userdata_size Userdata size field, clamped to max size sizeof(CapsApplicationData::userdata) when needed. + * @param[out] image RGBA8 image output buffer. + * @param[out] image_size Image buffer size, should be at least large enough for RGBA8 320x180. + * @param[out] workbuf Work buffer, cleared to 0 by the cmd before it returns. + * @param[out] workbuf_size Work buffer size, must be at least the size of the JPEG within the AlbumFile. + * @param[in] entry \ref CapsApplicationAlbumFileEntry + * @param[in] option \ref CapsScreenShotDecodeOption + */ +Result capsuLoadAlbumScreenShotThumbnailImage(s32 *width, s32 *height, CapsScreenShotAttributeForApplication *attr, void* userdata, size_t userdata_maxsize, u32 *userdata_size, void* image, size_t image_size, void* workbuf, size_t workbuf_size, const CapsApplicationAlbumFileEntry *entry, const CapsScreenShotDecodeOption *option); + +/** + * @brief PrecheckToCreateContents. Official sw only uses this with ::CapsContentType_ExtraMovie. + * @param[in] type \ref CapsContentType + * @param[in] unk Unknown. + */ +Result capsuPrecheckToCreateContents(CapsContentType type, u64 unk); + +/** + * @brief Opens an AlbumMovieStream. + * @note This opens IAlbumAccessorApplicationSession if not previously opened, it's closed during \ref capsuExit. + * @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 CapsApplicationAlbumFileEntry. + * @param[out] stream Stream handle. + * @param[in] entry \ref CapsApplicationAlbumFileEntry + */ +Result capsuOpenAlbumMovieStream(u64 *stream, const CapsApplicationAlbumFileEntry *entry); + +/** + * @brief Closes an AlbumMovieStream. + * @param[in] stream Stream handle. + */ +Result capsuCloseAlbumMovieStream(u64 stream); + +/** + * @brief Gets the data size of an AlbumMovieStream. + * @param[in] stream Stream handle. + * @param[out] size Size of the actual MP4, without the JPEG at the end. + */ +Result capsuGetAlbumMovieStreamSize(u64 stream, u64 *size); + +/** + * @brief Reads data from an AlbumMovieStream. + * @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 capsuGetAlbumMovieStreamSize, the regions of the buffer which goes beyond that are cleared to 0, and actual_size is still set to the input size. + * @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 capsuReadAlbumMovieStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size); + +/** + * @brief Gets the BrokenReason for an AlbumMovieStream. + * @note Official sw doesn't use this. + * @param[in] stream Stream handle. + */ +Result capsuGetAlbumMovieStreamBrokenReason(u64 stream); + diff --git a/nx/include/switch/services/csrng.h b/nx/include/switch/services/csrng.h index af45e7a8..b938c81b 100644 --- a/nx/include/switch/services/csrng.h +++ b/nx/include/switch/services/csrng.h @@ -6,7 +6,7 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" Result csrngInitialize(void); void csrngExit(void); diff --git a/nx/include/switch/services/friends.h b/nx/include/switch/services/friends.h new file mode 100644 index 00000000..0c0c7d81 --- /dev/null +++ b/nx/include/switch/services/friends.h @@ -0,0 +1,16 @@ +/** + * @file friend.h + * @brief Friends (friend:*) service IPC wrapper. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../services/sm.h" + +/// InAppScreenName +typedef struct { + char name[0x40]; ///< UTF-8 string, NUL-terminated. + u64 languageCode; ///< LanguageCode, see set.h. +} FriendsInAppScreenName; + diff --git a/nx/include/switch/services/fs.h b/nx/include/switch/services/fs.h index 3d706054..a7487d5a 100644 --- a/nx/include/switch/services/fs.h +++ b/nx/include/switch/services/fs.h @@ -8,7 +8,9 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../kernel/event.h" +#include "../services/acc.h" +#include "../sf/service.h" // We use wrapped handles for type safety. @@ -17,9 +19,6 @@ /// For use with FsSave. #define FS_SAVEDATA_CURRENT_TITLEID 0 -/// For use with \ref FsSave and \ref FsSaveDataInfo. -#define FS_SAVEDATA_USERID_COMMONSAVE 0 - typedef struct { u8 c[0x10]; } FsRightsId; @@ -57,7 +56,7 @@ typedef struct { char name[FS_MAX_PATH]; ///< Entry name. u8 pad[3]; - s8 type; ///< See FsEntryType. + s8 type; ///< See FsDirEntryType. u8 pad2[3]; ///< ? u64 fileSize; ///< File size. } FsDirectoryEntry; @@ -66,7 +65,7 @@ typedef struct typedef struct { u64 titleID; ///< titleID of the savedata to access when accessing other titles' savedata via SaveData, otherwise FS_SAVEDATA_CURRENT_TITLEID. - union { u128 userID; } PACKED; ///< userID of the user-specific savedata to access, otherwise FS_SAVEDATA_USERID_COMMONSAVE. See account.h. + AccountUid userID; ///< \ref AccountUid for the user-specific savedata to access, otherwise 0 for common savedata. u64 saveID; ///< saveID, 0 for SaveData. u8 saveDataType; ///< See \ref FsSaveDataType. u8 rank; ///< Save data 'rank' or 'precedence'. 0 if this save data is considered the primary save data. 1 if it's considered the secondary save data. @@ -108,7 +107,7 @@ typedef struct u8 saveDataSpaceId; ///< See \ref FsSaveDataSpaceId. u8 saveDataType; ///< See \ref FsSaveDataType. u8 pad[6]; ///< Padding. - u128 userID; ///< See userID for \ref FsSave. + AccountUid userID; ///< FsSave::userID u64 saveID; ///< See saveID for \ref FsSave. u64 titleID; ///< titleID for FsSaveDataType_SaveData. u64 size; ///< Raw saveimage size. @@ -126,57 +125,62 @@ typedef struct u8 padding[7]; } FsTimeStampRaw; +/// Returned by fsFsGetEntryType. typedef enum { - ENTRYTYPE_DIR = 0, - ENTRYTYPE_FILE = 1, -} FsEntryType; + FsDirEntryType_Dir = 0, ///< Entry is a directory. + FsDirEntryType_File = 1, ///< Entry is a file. +} FsDirEntryType; +/// For use with fsFsOpenFile. typedef enum { - FS_OPEN_READ = BIT(0), ///< Open for reading. - FS_OPEN_WRITE = BIT(1), ///< Open for writing. - FS_OPEN_APPEND = BIT(2), ///< Append file. -} FsFileFlags; + FsOpenMode_Read = BIT(0), ///< Open for reading. + FsOpenMode_Write = BIT(1), ///< Open for writing. + FsOpenMode_Append = BIT(2), ///< Append file. +} FsOpenMode; +/// For use with fsFsCreateFile. typedef enum { - FS_CREATE_BIG_FILE = BIT(0), ///< Creates a ConcatenationFile (dir with archive bit) instead of file. -} FsFileCreateFlags; + FsCreateOption_BigFile = BIT(0), ///< Creates a ConcatenationFile (dir with archive bit) instead of file. +} FsCreateOption; /// For use with fsFsOpenDirectory. typedef enum { - FS_DIROPEN_DIRECTORY = BIT(0), ///< Enable reading directory entries. - FS_DIROPEN_FILE = BIT(1), ///< Enable reading file entries. - FS_DIROPEN_NO_FILE_SIZE = BIT(31), ///< Causes result entries to not contain filesize information (always 0). -} FsDirectoryFlags; + FsDirOpenMode_ReadDirs = BIT(0), ///< Enable reading directory entries. + FsDirOpenMode_ReadFiles = BIT(1), ///< Enable reading file entries. + FsDirOpenMode_NoFileSize = BIT(31), ///< Causes result entries to not contain filesize information (always 0). +} FsDirOpenMode; +/// For use with fsFileRead. typedef enum { - FS_READOPTION_NONE = 0, ///< No Option. + FsReadOption_None = 0, ///< No option. } FsReadOption; +/// For use with fsFileWrite. typedef enum { - FS_WRITEOPTION_NONE = 0, ///< No option. - FS_WRITEOPTION_FLUSH = BIT(0), ///< Forces a flush after write. + FsWriteOption_None = 0, ///< No option. + FsWriteOption_Flush = BIT(0), ///< Forces a flush after write. } FsWriteOption; -typedef enum -{ - FsStorageId_None = 0, - FsStorageId_Host = 1, - FsStorageId_GameCard = 2, - FsStorageId_NandSystem = 3, - FsStorageId_NandUser = 4, - FsStorageId_SdCard = 5, +/// StorageId +typedef enum { + FsStorageId_None = 0, ///< None + FsStorageId_Host = 1, ///< Host + FsStorageId_GameCard = 2, ///< GameCard + FsStorageId_NandSystem = 3, ///< NandSystem + FsStorageId_NandUser = 4, ///< NandUser + FsStorageId_SdCard = 5, ///< SdCard } FsStorageId; typedef enum { - FS_CONTENTSTORAGEID_NandSystem = 0, - FS_CONTENTSTORAGEID_NandUser = 1, - FS_CONTENTSTORAGEID_SdCard = 2, + FsContentStorageId_NandSystem = 0, + FsContentStorageId_NandUser = 1, + FsContentStorageId_SdCard = 2, } FsContentStorageId; typedef enum @@ -213,9 +217,9 @@ typedef enum { } FsSaveDataFlags; typedef enum { - FsGameCardAttribute_AutoBoot = (1 << 0), ///< Causes the cartridge to automatically start on bootup - FsGameCardAttribute_ForceError = (1 << 1), ///< Causes NS to throw an error on attempt to load the cartridge - FsGameCardAttribute_Repair = (1 << 2), ///< Indicates that this gamecard is a repair tool. + FsGameCardAttribute_AutoBoot = BIT(0), ///< Causes the cartridge to automatically start on bootup + FsGameCardAttribute_ForceError = BIT(1), ///< Causes NS to throw an error on attempt to load the cartridge + FsGameCardAttribute_Repair = BIT(2), ///< Indicates that this gamecard is a repair tool. } FsGameCardAttribute; typedef enum { @@ -262,11 +266,20 @@ typedef enum { FsBisStorageId_SystemProperPartition = 33, } FsBisStorageId; +typedef enum { + FsPriority_Normal = 0, + FsPriority_Realtime = 1, + FsPriority_Low = 2, + FsPriority_Background = 3, +} FsPriority; + Result fsInitialize(void); void fsExit(void); Service* fsGetServiceSession(void); +void fsSetPriority(FsPriority prio); + Result fsOpenBisStorage(FsStorage* out, FsBisStorageId partitionId); Result fsOpenBisFileSystem(FsFileSystem* out, FsBisStorageId partitionId, const char* string); @@ -283,9 +296,9 @@ Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, /// Do not call this directly, see fs_dev.h. Result fsMountSdcard(FsFileSystem* out); -Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save); -Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save); -Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 saveDataSpaceId); +Result fsMountSaveData(FsFileSystem* out, u8 inval, const FsSave *save); +Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, const FsSave *save); +Result fsOpenSaveDataIterator(FsSaveDataIterator* out, FsSaveDataSpaceId saveDataSpaceId); Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id); Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id); /// [7.0.0+] Result fsOpenDataStorageByCurrentProcess(FsStorage* out); @@ -306,14 +319,14 @@ Result fsGetGlobalAccessLogMode(u32* out_mode); // todo: Rest of commands here // Wrapper(s) for fsCreateSaveDataFileSystemBySystemSaveDataId. -Result fsCreate_SystemSaveDataWithOwner(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, u128 userID, u64 ownerId, u64 size, u64 journalSize, u32 flags); +Result fsCreate_SystemSaveDataWithOwner(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, AccountUid *userID, u64 ownerId, u64 size, u64 journalSize, u32 flags); Result fsCreate_SystemSaveData(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, u64 size, u64 journalSize, u32 flags); /// FsFileSystem can be mounted with fs_dev for use with stdio, see fs_dev.h. /// Wrapper(s) for fsMountSaveData. /// See FsSave for titleID and userID. -Result fsMount_SaveData(FsFileSystem* out, u64 titleID, u128 userID); +Result fsMount_SaveData(FsFileSystem* out, u64 titleID, AccountUid *userID); /// Wrapper for fsMountSystemSaveData. /// WARNING: You can brick when writing to SystemSaveData, if the data is corrupted etc. @@ -340,16 +353,16 @@ Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType f Result fsOpenFileSystemWithPatch(FsFileSystem* out, u64 titleId, FsFileSystemType fsType); /// [2.0.0+], like OpenFileSystemWithId but without content path. // IFileSystem -Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags); +Result fsFsCreateFile(FsFileSystem* fs, const char* path, u64 size, u32 option); Result fsFsDeleteFile(FsFileSystem* fs, const char* path); Result fsFsCreateDirectory(FsFileSystem* fs, const char* path); Result fsFsDeleteDirectory(FsFileSystem* fs, const char* path); Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path); Result fsFsRenameFile(FsFileSystem* fs, const char* cur_path, const char* new_path); Result fsFsRenameDirectory(FsFileSystem* fs, const char* cur_path, const char* new_path); -Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsEntryType* out); -Result fsFsOpenFile(FsFileSystem* fs, const char* path, int flags, FsFile* out); -Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, int flags, FsDir* out); +Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsDirEntryType* out); +Result fsFsOpenFile(FsFileSystem* fs, const char* path, u32 mode, FsFile* out); +Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, u32 mode, FsDir* out); Result fsFsCommit(FsFileSystem* fs); Result fsFsGetFreeSpace(FsFileSystem* fs, const char* path, u64* out); Result fsFsGetTotalSpace(FsFileSystem* fs, const char* path, u64* out); @@ -363,36 +376,36 @@ void fsFsClose(FsFileSystem* fs); Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path); // IFile -Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, u32 option, size_t* out); -Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, u32 option); +Result fsFileRead(FsFile* f, u64 off, void* buf, u64 read_size, u32 option, u64* bytes_read); +Result fsFileWrite(FsFile* f, u64 off, const void* buf, u64 write_size, u32 option); Result fsFileFlush(FsFile* f); Result fsFileSetSize(FsFile* f, u64 sz); Result fsFileGetSize(FsFile* f, u64* out); -Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out); /// [4.0.0+] +Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, u64 len, FsRangeInfo* out); /// [4.0.0+] void fsFileClose(FsFile* f); // IDirectory -Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf); +Result fsDirRead(FsDir* d, u64 inval, u64* total_entries, size_t max_entries, FsDirectoryEntry *buf); Result fsDirGetEntryCount(FsDir* d, u64* count); void fsDirClose(FsDir* d); // IStorage -Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len); -Result fsStorageWrite(FsStorage* s, u64 off, const void* buf, size_t len); +Result fsStorageRead(FsStorage* s, u64 off, void* buf, u64 read_size); +Result fsStorageWrite(FsStorage* s, u64 off, const void* buf, u64 write_size); Result fsStorageFlush(FsStorage* s); Result fsStorageSetSize(FsStorage* s, u64 sz); Result fsStorageGetSize(FsStorage* s, u64* out); -Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out); /// [4.0.0+] +Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, u64 len, FsRangeInfo* out); /// [4.0.0+] void fsStorageClose(FsStorage* s); // ISaveDataInfoReader /// Read FsSaveDataInfo data into the buf array. -Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, size_t* total_entries); +Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, u64* total_entries); void fsSaveDataIteratorClose(FsSaveDataIterator *s); // IEventNotifier -Result fsEventNotifierGetEventHandle(FsEventNotifier* e, Handle* out); +Result fsEventNotifierGetEventHandle(FsEventNotifier* e, Event* out, bool autoclear); void fsEventNotifierClose(FsEventNotifier* e); // IDeviceOperator diff --git a/nx/include/switch/services/fsldr.h b/nx/include/switch/services/fsldr.h index bd471517..3e4a8224 100644 --- a/nx/include/switch/services/fsldr.h +++ b/nx/include/switch/services/fsldr.h @@ -6,7 +6,7 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../services/fs.h" Result fsldrInitialize(void); @@ -15,4 +15,4 @@ Service* fsldrGetServiceSession(void); Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out); Result fsldrIsArchivedProgram(u64 pid, bool *out); -Result fsldrSetCurrentProcess(void); \ No newline at end of file +Result fsldrSetCurrentProcess(void); diff --git a/nx/include/switch/services/grc.h b/nx/include/switch/services/grc.h index e09c2a3d..74cc86fa 100644 --- a/nx/include/switch/services/grc.h +++ b/nx/include/switch/services/grc.h @@ -10,18 +10,7 @@ #include "../services/caps.h" #include "../kernel/event.h" #include "../kernel/tmem.h" - -/// GameMovieTrimmer -typedef struct { - Service s; ///< IGameMovieTrimmer - TransferMemory tmem; ///< TransferMemory -} GrcGameMovieTrimmer; - -/// GameMovieId -typedef struct { - CapsAlbumEntryId album_id; ///< \ref CapsAlbumEntryId - u8 reserved[0x28]; ///< Unused, always zero. -} GrcGameMovieId; +#include "../display/native_window.h" /// Stream type values for \ref grcdRead. typedef enum { @@ -29,7 +18,58 @@ typedef enum { GrcStream_Audio = 1, ///< Audio stream with PcmFormat_Int16, 2 channels, and samplerate = 48000Hz. Official sw uses buffer size 0x1000. } GrcStream; -// Trimming +/// GameMovieTrimmer +typedef struct { + Service s; ///< IGameMovieTrimmer + TransferMemory tmem; ///< TransferMemory +} GrcGameMovieTrimmer; + +/// IMovieMaker +typedef struct { + Service a; ///< applet IMovieMaker + Service s; ///< grc IMovieMaker + Service video_proxy; ///< IHOSBinderDriver VideoProxy + Event recording_event; ///< Output Event from GetOffscreenLayerRecordingFinishReadyEvent with autoclear=false. + Event audio_event; ///< Output Event from GetOffscreenLayerAudioEncodeReadyEvent with autoclear=false. + TransferMemory tmem; ///< TransferMemory + NWindow win; ///< \ref NWindow + u64 layer_handle; ///< LayerHandle + bool layer_open; ///< Whether OpenOffscreenLayer was used successfully, indicating that CloseOffscreenLayer should be used during \ref grcMovieMakerClose. + bool started_flag; ///< Whether \ref grcMovieMakerStart was used successfully. This is also used by \ref grcMovieMakerAbort. +} GrcMovieMaker; + +/// GameMovieId +typedef struct { + CapsAlbumEntryId album_id; ///< \ref CapsAlbumEntryId + u8 reserved[0x28]; ///< Unused, always zero. +} GrcGameMovieId; + +/// OffscreenRecordingParameter +typedef struct { + u8 unk_x0[0x10]; ///< Unknown. Default value is 0. + u32 unk_x10; ///< Unknown. Must match value 0x103, which is the default value. + + s32 video_bitrate; ///< VideoBitRate, 0 is invalid. Default value is 8000000. + s32 video_width; ///< VideoWidth, must match 1280 or 1920. Default value is 1280. + s32 video_height; ///< VideoHeight, must match 720 or 1080. Default value is 720. + s32 video_framerate; ///< VideoFrameRate, must match 30 or 60. Default value is 30. + s32 video_keyFrameInterval; ///< VideoKeyFrameInterval, 0 is invalid. Default value is 30. + + s32 audio_bitrate; ///< AudioBitRate. Default value is 128000 ([5.0.0-5.1.0] 1536000). + s32 audio_samplerate; ///< AudioSampleRate, 0 is invalid. Default value is 48000. + s32 audio_channel_count; ///< AudioChannelCount. Must match 2, which is the default value. + s32 audio_sample_format; ///< \ref PcmFormat AudioSampleFormat. Must match PcmFormat_Int16, which is the default value. + + s32 video_imageOrientation; ///< \ref AlbumImageOrientation VideoImageOrientation. Default value is ::AlbumImageOrientation_Unknown0. + + u8 unk_x3c[0x44]; ///< Unknown. Default value is 0. +} GrcOffscreenRecordingParameter; + +/// Default size for \ref grcCreateMovieMaker, this is the size used by official sw. +#define GRC_MOVIEMAKER_WORKMEMORY_SIZE_DEFAULT 0x6000000 + +///@name Trimming +///@{ /** * @brief Creates a \ref GrcGameMovieTrimmer using \ref appletCreateGameMovieTrimmer, uses the cmds from it to trim the specified video, then closes it. @@ -44,7 +84,90 @@ typedef enum { */ Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_movieid, size_t tmem_size, const void* thumbnail, s32 start, s32 end); -// grc:d +///@} + +///@name IMovieMaker +///@{ + +/** + * @brief Creates a \ref GrcOffscreenRecordingParameter with the default values, see \ref GrcOffscreenRecordingParameter for the default values. + * @param[out] param \ref GrcOffscreenRecordingParameter + */ +void grcCreateOffscreenRecordingParameter(GrcOffscreenRecordingParameter *param); + +/** + * @brief Creates a \ref GrcMovieMaker using \ref appletCreateMovieMaker, and does the required initialization. + * @note See \ref appletCreateMovieMaker for the requirements for using this. + * @param[out] m \ref GrcMovieMaker + * @param[in] size TransferMemory WorkMemory size. See \ref GRC_MOVIEMAKER_WORKMEMORY_SIZE_DEFAULT. + */ +Result grcCreateMovieMaker(GrcMovieMaker *m, size_t size); + +/** + * @brief Closes a \ref GrcMovieMaker. + * @note This also uses \ref grcMovieMakerAbort. + * @param m \ref GrcMovieMaker + */ +void grcMovieMakerClose(GrcMovieMaker *m); + +/** + * @brief Gets the \ref NWindow for the specified MovieMaker. + * @param m \ref GrcMovieMaker + */ +static inline NWindow* grcMovieMakerGetNWindow(GrcMovieMaker *m) { + return &m->win; +} + +/** + * @brief Starts recording with the specified MovieMaker and \ref GrcOffscreenRecordingParameter. + * @param m \ref GrcMovieMaker + * @param[in] param \ref GrcOffscreenRecordingParameter + */ +Result grcMovieMakerStart(GrcMovieMaker *m, const GrcOffscreenRecordingParameter *param); + +/** + * @brief Aborts recording with the specified MovieMaker. + * @note This is used automatically by \ref grcMovieMakerClose. + * @note This will throw an error if \ref grcMovieMakerStart was not used previously, with the flag used for this being cleared afterwards on success. + * @param m \ref GrcMovieMaker + */ +Result grcMovieMakerAbort(GrcMovieMaker *m); + +/** + * @brief Finishes recording with the specified MovieMaker. + * @note This automatically uses \ref grcMovieMakerAbort on error. + * @note The recorded video will not be accessible via the Album-applet since it's stored separately from other Album data. + * @param m \ref GrcMovieMaker + * @param width Width for the thumbnail, must be 1280. + * @param height Height for the thumbnail, must be 720. + * @param[in] userdata UserData input buffer for the JPEG thumbnail. Optional, can be NULL. + * @param[in] userdata_size Size of the UserData input buffer. Optional, can be 0. Must be <=0x400. + * @param[in] thumbnail RGBA8 image buffer containing the thumbnail. Optional, can be NULL. + * @param[in] thumbnail_size Size of the thumbnail buffer. Optional, can be 0. + * @param[out] entry Output \ref CapsApplicationAlbumEntry for the recorded video. Optional, can be NULL. Only available on [7.0.0+], if this is not NULL on pre-7.0.0 an error is thrown. + */ +Result grcMovieMakerFinish(GrcMovieMaker *m, s32 width, s32 height, const void* userdata, size_t userdata_size, const void* thumbnail, size_t thumbnail_size, CapsApplicationAlbumEntry *entry); + +/** + * @brief Gets the recording error with the specified MovieMaker. + * @param m \ref GrcMovieMaker + */ +Result grcMovieMakerGetError(GrcMovieMaker *m); + +/** + * @brief Encodes audio sample data with the specified MovieMaker. + * @note This waits on the event and uses the cmd repeatedly until the entire input buffer is handled. + * @note If you don't use this the recorded video will be missing audio. + * @param m \ref GrcMovieMaker + * @param[in] buffer Audio buffer. + * @param[in] size Size of the buffer. + */ +Result grcMovieMakerEncodeAudioSample(GrcMovieMaker *m, const void* buffer, size_t size); + +///@} + +///@name grc:d +///@{ /// Initialize grc:d. Result grcdInitialize(void); @@ -70,3 +193,5 @@ Result grcdBegin(void); */ Result grcdRead(GrcStream stream, void* buffer, size_t size, u32 *unk, u32 *data_size, u64 *timestamp); +///@} + diff --git a/nx/include/switch/services/hid.h b/nx/include/switch/services/hid.h index 06f80809..eea00652 100644 --- a/nx/include/switch/services/hid.h +++ b/nx/include/switch/services/hid.h @@ -222,6 +222,9 @@ typedef enum TYPE_JOYCON_PAIR = BIT(2), TYPE_JOYCON_LEFT = BIT(3), TYPE_JOYCON_RIGHT = BIT(4), + + TYPE_SYSTEM_EXT = BIT(29), + TYPE_SYSTEM = BIT(30), } HidControllerType; typedef enum @@ -240,6 +243,7 @@ typedef enum COLORS_NONEXISTENT = BIT(1), } HidControllerColorDescription; +/// HidControllerKeys typedef enum { KEY_A = BIT(0), ///< A @@ -327,6 +331,52 @@ typedef enum HidJoyHoldType_Horizontal = 1, ///< Joy-Con held horizontally with HID state orientation adjustment, see \ref HidControllerLayoutType. } HidJoyHoldType; +/// DeviceType +typedef enum { + HidDeviceTypeBits_FullKey = BIT(0), ///< Pro Controller and Gc controller. + HidDeviceTypeBits_Unknown1 = BIT(1), ///< Unknown. + HidDeviceTypeBits_HandheldLeft = BIT(2), ///< Joy-Con/Famicom/NES left controller in handheld mode. + HidDeviceTypeBits_HandheldRight = BIT(3), ///< Joy-Con/Famicom/NES right controller in handheld mode. + HidDeviceTypeBits_JoyLeft = BIT(4), ///< Joy-Con left controller. + HidDeviceTypeBits_JoyRight = BIT(5), ///< Joy-Con right controller. + HidDeviceTypeBits_Palma = BIT(6), ///< Poké Ball Plus controller. + HidDeviceTypeBits_LarkLeftHVC = BIT(7), ///< Famicom left controller. + HidDeviceTypeBits_LarkRightHVC = BIT(8), ///< Famicom right controller (with microphone). + HidDeviceTypeBits_LarkLeftNES = BIT(9), ///< NES left controller. + HidDeviceTypeBits_LarkRightNES = BIT(10), ///< NES right controller. + HidDeviceTypeBits_SystemExt = BIT(15), ///< Generic external controller. + HidDeviceTypeBits_System = BIT(31), ///< Generic controller. +} HidDeviceTypeBits; + +/// Internal DeviceType for [9.0.0+]. Converted to/from the pre-9.0.0 version of this by the hiddbg funcs. +typedef enum { + HidDeviceType_JoyRight1 = 1, ///< ::HidDeviceTypeBits_JoyRight + HidDeviceType_JoyLeft2 = 2, ///< ::HidDeviceTypeBits_JoyLeft + HidDeviceType_FullKey3 = 3, ///< ::HidDeviceTypeBits_FullKey + HidDeviceType_JoyLeft4 = 4, ///< ::HidDeviceTypeBits_JoyLeft + HidDeviceType_JoyRight5 = 5, ///< ::HidDeviceTypeBits_JoyRight + HidDeviceType_FullKey6 = 6, ///< ::HidDeviceTypeBits_FullKey + HidDeviceType_LarkLeftHVC = 7, ///< ::HidDeviceTypeBits_LarkLeftHVC + HidDeviceType_LarkRightHVC = 8, ///< ::HidDeviceTypeBits_LarkRightHVC + HidDeviceType_LarkLeftNES = 9, ///< ::HidDeviceTypeBits_LarkLeftNES + HidDeviceType_LarkRightNES = 10, ///< ::HidDeviceTypeBits_LarkRightNES + HidDeviceType_Palma = 12, ///< [9.0.0+] ::HidDeviceTypeBits_Palma + HidDeviceType_FullKey13 = 13, ///< ::HidDeviceTypeBits_FullKey + HidDeviceType_FullKey15 = 15, ///< ::HidDeviceTypeBits_FullKey + HidDeviceType_System19 = 19, ///< ::HidDeviceTypeBits_System with HidControllerType |= TYPE_PROCONTROLLER. + HidDeviceType_System20 = 20, ///< ::HidDeviceTypeBits_System with HidControllerType |= TYPE_JOYCON_PAIR. + HidDeviceType_System21 = 21, ///< ::HidDeviceTypeBits_System with HidControllerType |= TYPE_JOYCON_PAIR. +} HidDeviceType; + +/// NpadInterfaceType +typedef enum +{ + NpadInterfaceType_Bluetooth = 1, ///< Bluetooth. + NpadInterfaceType_Rail = 2, ///< Rail. + NpadInterfaceType_USB = 3, ///< USB. + NpadInterfaceType_Unknown4 = 4, ///< Unknown. +} HidNpadInterfaceType; + typedef struct touchPosition { u32 id; @@ -666,7 +716,7 @@ HidControllerType hidGetControllerType(HidControllerID id); void hidGetControllerColors(HidControllerID id, HidControllerColors *colors); bool hidIsControllerConnected(HidControllerID id); -/// Gets the DeviceType for the specified controller. +/// Gets the \ref HidDeviceTypeBits for the specified controller. u32 hidGetControllerDeviceType(HidControllerID id); /// Gets the flags for the specified controller. @@ -789,3 +839,7 @@ Result hidGetSevenSixAxisSensorFusionStrength(float *strength); /// Resets the timestamp for the SevenSixAxisSensor. Only available on [6.0.0+]. Result hidResetSevenSixAxisSensorTimestamp(void); +/// Gets the \ref HidNpadInterfaceType for the specified controller. +/// Only available on [4.0.0+]. +Result hidGetNpadInterfaceType(HidControllerID id, u8 *out); + diff --git a/nx/include/switch/services/hiddbg.h b/nx/include/switch/services/hiddbg.h index c82b0779..0e074a66 100644 --- a/nx/include/switch/services/hiddbg.h +++ b/nx/include/switch/services/hiddbg.h @@ -8,16 +8,27 @@ #include "../services/hid.h" #include "../services/sm.h" -/// HdlsDeviceInfo +/// HdlsDeviceInfo, for [7.0.0-8.1.0]. typedef struct { - u32 type; ///< Only one bit can be set. BIT(N*4+0) = Pro-Controller, BIT(N*4+1) = Joy-Con Left, BIT(N*4+2) = Joy-Con Right, BIT(N*4+3) = invalid. Where N is 0-1. BIT(8-10) = Pro-Controller, BIT(11) = Famicom-Controller, BIT(12) = Famicom-Controller II with microphone, BIT(13) = NES-Controller(DeviceType=0x200), BIT(14) = NES-Controller(DeviceType=0x400), BIT(15-16) = invalid, BIT(17) = unknown(DeviceType=0x8000), BIT(18-20) = invalid, BIT(21-23) = unknown(DeviceType=0x80000000). - u32 singleColorBody; ///< RGBA Single Body Color - u32 singleColorButtons; ///< RGBA Single Buttons Color - u8 type2; ///< Additional type field used with the above type field (only applies to type bit0-bit2 and bit21), if the value doesn't match one of the following a default is used. Type Pro-Controller: value 0x3 indicates that the controller is connected via USB. Type BIT(21): value 0x3 = unknown. When value is 0x2, state is merged with an existing controller (when the type value is compatible with this). Otherwise, it's a dedicated controller. - u8 pad[0x3]; ///< Padding + u32 deviceTypeInternal; ///< Only one bit can be set. BIT(N*4+0) = Pro-Controller, BIT(N*4+1) = Joy-Con Left, BIT(N*4+2) = Joy-Con Right, BIT(N*4+3) = invalid. Where N is 0-1. BIT(8-10) = Pro-Controller, BIT(11) = Famicom-Controller, BIT(12) = Famicom-Controller II with microphone, BIT(13) = NES-Controller(DeviceType=0x200), BIT(14) = NES-Controller(DeviceType=0x400), BIT(15-16) = invalid, BIT(17) = unknown(DeviceType=0x8000), BIT(18-20) = invalid, BIT(21-23) = unknown(DeviceType=0x80000000). + u32 singleColorBody; ///< RGBA Single Body Color. + u32 singleColorButtons; ///< RGBA Single Buttons Color. + u8 npadInterfaceType; ///< \ref HidNpadInterfaceType. Additional type field used with the above type field (only applies to type bit0-bit2 and bit21), if the value doesn't match one of the following a default is used. Type Pro-Controller: value 0x3 indicates that the controller is connected via USB. Type BIT(21): value 0x3 = unknown. When value is 0x2, state is merged with an existing controller (when the type value is compatible with this). Otherwise, it's a dedicated controller. + u8 pad[0x3]; ///< Padding. +} HiddbgHdlsDeviceInfoV7; + +/// HdlsDeviceInfo, for [9.0.0+]. Converted to/from \ref HiddbgHdlsDeviceInfoV7 on prior sysvers. +typedef struct { + u8 deviceType; ///< \ref HidDeviceType + u8 npadInterfaceType; ///< \ref HidNpadInterfaceType. Additional type field used with the above type field (only applies to ::HidDeviceType_JoyRight1, ::HidDeviceType_JoyLeft2, ::HidDeviceType_FullKey3, and ::HidDeviceType_System19), if the value doesn't match one of the following a default is used. ::HidDeviceType_FullKey3: ::NpadInterfaceType_USB indicates that the controller is connected via USB. :::HidDeviceType_System19: ::NpadInterfaceType_USB = unknown. When value is ::NpadInterfaceType_Rail, state is merged with an existing controller (with ::HidDeviceType_JoyRight1 / ::HidDeviceType_JoyLeft2). Otherwise, it's a dedicated controller. + u8 pad[0x2]; ///< Padding. + u32 singleColorBody; ///< RGBA Single Body Color. + u32 singleColorButtons; ///< RGBA Single Buttons Color. + u32 colorLeftGrip; ///< [9.0.0+] RGBA Left Grip Color. + u32 colorRightGrip; ///< [9.0.0+] RGBA Right Grip Color. } HiddbgHdlsDeviceInfo; -/// HdlsState +/// HdlsState, for [7.0.0-8.1.0]. typedef struct { u8 powerConnected; ///< powerConnected for the main PowerInfo, see \ref HidFlags. u8 flags; ///< ORRed with powerConnected to set the value of the first byte for \ref HidFlags. For example, value 1 here will set isCharging for the main PowerInfo. @@ -27,6 +38,16 @@ typedef struct { JoystickPosition joysticks[JOYSTICK_NUM_STICKS]; ///< \ref JoystickPosition u8 unk_x20; ///< Unused for input. Set with output from \ref hiddbgDumpHdlsStates. Not set by \ref hiddbgGetAbstractedPadsState. u8 padding[0x3]; ///< Padding +} HiddbgHdlsStateV7; + +/// HdlsState, for [9.0.0+]. Converted to/from \ref HiddbgHdlsDeviceInfoV7 on prior sysvers. +typedef struct { + u32 batteryCharge; ///< batteryCharge for the main PowerInfo, see \ref HidPowerInfo. + u32 flags; ///< Used to set the main PowerInfo for \ref HidFlags. BIT(0) -> powerConnected, BIT(1) -> isCharging. + u64 buttons; ///< See \ref HidControllerKeys. [9.0.0+] Masked with 0xfffffffff00fffff. + JoystickPosition joysticks[JOYSTICK_NUM_STICKS]; ///< \ref JoystickPosition + u8 unk_x20; ///< Unused for input. Set with output from \ref hiddbgDumpHdlsStates. + u8 padding[0x3]; ///< Padding } HiddbgHdlsState; /// HdlsNpadAssignmentEntry @@ -46,14 +67,29 @@ typedef struct { HiddbgHdlsNpadAssignmentEntry entries[0x10]; ///< \ref HiddbgHdlsNpadAssignmentEntry } HiddbgHdlsNpadAssignment; -/// HdlsStateListEntry +/// HdlsStateListEntryV7, for [7.0.0-8.1.0]. +typedef struct { + u64 HdlsHandle; ///< HdlsHandle + HiddbgHdlsDeviceInfoV7 device; ///< \ref HiddbgHdlsDeviceInfoV7. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. + HiddbgHdlsStateV7 state; ///< \ref HiddbgHdlsState +} HiddbgHdlsStateListEntryV7; + +/// HdlsStateListV7, for [7.0.0-8.1.0]. This contains a list of all controllers, including non-virtual controllers. +typedef struct { + s32 total_entries; ///< Total entries for the below entries. + u32 pad; ///< Padding + HiddbgHdlsStateListEntryV7 entries[0x10]; ///< \ref HiddbgHdlsStateListEntryV7 +} HiddbgHdlsStateListV7; + +/// HdlsStateListEntry, for [9.0.0+]. Converted to/from \ref HiddbgHdlsStateListEntryV7 on prior sysvers. typedef struct { u64 HdlsHandle; ///< HdlsHandle HiddbgHdlsDeviceInfo device; ///< \ref HiddbgHdlsDeviceInfo. With \ref hiddbgApplyHdlsStateList this is only used when creating new devices. - HiddbgHdlsState state; ///< \ref HiddbgHdlsState + alignas(8) HiddbgHdlsState state; ///< \ref HiddbgHdlsState } HiddbgHdlsStateListEntry; -/// HdlsStateList. This contains a list of all controllers, including non-virtual controllers. +/// HdlsStateList, for [9.0.0+]. Converted to/from \ref HiddbgHdlsStateListV7 on prior sysvers. +/// This contains a list of all controllers, including non-virtual controllers. typedef struct { s32 total_entries; ///< Total entries for the below entries. u32 pad; ///< Padding @@ -62,16 +98,16 @@ typedef struct { /// AbstractedPadState typedef struct { - u32 type; ///< Type. Converted to HiddbgHdlsDeviceInfo::type internally by \ref hiddbgSetAutoPilotVirtualPadState. BIT(0) -> BIT(0), BIT(1) -> BIT(15), BIT(2-3) -> BIT(1-2), BIT(4-5) -> BIT(1-2), BIT(6) -> BIT(3). BIT(7-11) -> BIT(11-15), BIT(12-14) -> BIT(12-14), BIT(15) -> BIT(17), BIT(31) -> BIT(21). + u32 type; ///< Type. Converted to HiddbgHdlsDeviceInfoV7::type internally by \ref hiddbgSetAutoPilotVirtualPadState. BIT(0) -> BIT(0), BIT(1) -> BIT(15), BIT(2-3) -> BIT(1-2), BIT(4-5) -> BIT(1-2), BIT(6) -> BIT(3). BIT(7-11) -> BIT(11-15), BIT(12-14) -> BIT(12-14), BIT(15) -> BIT(17), BIT(31) -> BIT(21). u8 flags; ///< Flags. Only bit0 is used by \ref hiddbgSetAutoPilotVirtualPadState: when clear it will skip using the rest of the input and run \ref hiddbgUnsetAutoPilotVirtualPadState internally. u8 pad[0x3]; ///< Padding u32 singleColorBody; ///< RGBA Single Body Color u32 singleColorButtons; ///< RGBA Single Buttons Color - u8 type2; ///< See HiddbgHdlsDeviceInfo::type2. + u8 npadInterfaceType; ///< See HiddbgHdlsDeviceInfo::npadInterfaceType. u8 pad2[0x3]; ///< Padding - HiddbgHdlsState state; ///< State + HiddbgHdlsStateV7 state; ///< State u8 unused[0x60]; ///< Unused with \ref hiddbgSetAutoPilotVirtualPadState. Not set by \ref hiddbgGetAbstractedPadsState. } HiddbgAbstractedPadState; @@ -90,20 +126,30 @@ Result hiddbgUpdateDesignInfo(u32 colorBody, u32 colorButtons, u32 colorLeftGrip /// This doesn't seem to be usable? Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePadId); -/// Gets a list of AbstractedPadHandles, where AbstractedPadHandles is the output array with max entries = count. total_entries is total entries written to the output array. Only available with [5.0.0+]. +/// Gets the internal DeviceType for the specified controller. See hidsys.h for UniquePadId. +/// Only available with [6.0.0+]. +/// Pre-9.0.0 the output is an u32, with [9.0.0+] it's an u8. +Result hiddbgGetUniquePadDeviceTypeSetInternal(u64 UniquePadId, u32 *out); + +/// Gets a list of AbstractedPadHandles, where AbstractedPadHandles is the output array with max entries = count. total_entries is total entries written to the output array. +/// Only available with [5.0.0-8.1.0]. Result hiddbgGetAbstractedPadHandles(u64 *AbstractedPadHandles, s32 count, s32 *total_entries); -/// Gets the state for the specified AbstractedPadHandle. Only available with [5.0.0+]. +/// Gets the state for the specified AbstractedPadHandle. +/// Only available with [5.0.0-8.1.0]. Result hiddbgGetAbstractedPadState(u64 AbstractedPadHandle, HiddbgAbstractedPadState *state); -/// Similar to \ref hiddbgGetAbstractedPadHandles except this also returns the state for each pad in output array states. Only available with [5.0.0+]. +/// Similar to \ref hiddbgGetAbstractedPadHandles except this also returns the state for each pad in output array states. +/// Only available with [5.0.0-8.1.0]. Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedPadState *states, s32 count, s32 *total_entries); /// Sets AutoPilot state for the specified pad. /// AbstractedVirtualPadId can be any unique value as long as it's within bounds. For example, 0-7 is usable. +/// Only available with [5.0.0-8.1.0]. Result hiddbgSetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId, const HiddbgAbstractedPadState *state); /// Clears AutoPilot state for the specified pad set by \ref hiddbgSetAutoPilotVirtualPadState. +/// Only available with [5.0.0-8.1.0]. Result hiddbgUnsetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId); /// Clears AutoPilot state for all pads set by \ref hiddbgSetAutoPilotVirtualPadState. diff --git a/nx/include/switch/services/hidsys.h b/nx/include/switch/services/hidsys.h index c5942b75..b2730efd 100644 --- a/nx/include/switch/services/hidsys.h +++ b/nx/include/switch/services/hidsys.h @@ -43,6 +43,11 @@ Result hidsysEnableAppletToGetInput(bool enable); **/ Result hidsysAcquireHomeButtonEventHandle(Event* event_out); +/** +* @brief Returns an event that fires when the capture button is pressed. This event does not auto clear. +**/ +Result hidsysAcquireCaptureButtonEventHandle(Event* event_out); + Result hidsysActivateHomeButton(void); Result hidsysActivateSleepButton(void); Result hidsysActivateCaptureButton(void); diff --git a/nx/include/switch/services/lr.h b/nx/include/switch/services/lr.h index 6e7c19c8..dac7f60a 100644 --- a/nx/include/switch/services/lr.h +++ b/nx/include/switch/services/lr.h @@ -6,7 +6,7 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../services/fs.h" typedef struct { @@ -31,10 +31,10 @@ Result lrLrRedirectProgramPath(LrLocationResolver* lr, u64 tid, const char *path Result lrLrResolveApplicationControlPath(LrLocationResolver* lr, u64 tid, char *out); Result lrLrResolveApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, char *out); Result lrLrResolveDataPath(LrLocationResolver* lr, u64 tid, char *out); -Result lrLrRedirectApplicationControlPath(LrLocationResolver* lr, u64 tid, const char *path); -Result lrLrRedirectApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, const char *path); -Result lrLrResolveLegalInformationPath(LrLocationResolver* lr, u64 tid, char *out); -Result lrLrRedirectLegalInformationPath(LrLocationResolver* lr, u64 tid, const char *path); +Result lrLrRedirectApplicationControlPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path); +Result lrLrRedirectApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path); +Result lrLrResolveApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, char *out); +Result lrLrRedirectApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path); Result lrLrRefresh(LrLocationResolver* lr); // IRegisteredLocationResolver diff --git a/nx/include/switch/services/ncm.h b/nx/include/switch/services/ncm.h index 7f572d9b..cc926206 100644 --- a/nx/include/switch/services/ncm.h +++ b/nx/include/switch/services/ncm.h @@ -1,7 +1,7 @@ /** * @file ncm.h * @brief Content Manager (ncm) service IPC wrapper. - * @author zhuowei & Adubbz + * @author Adubbz & zhuowei * @copyright libnx Authors */ #pragma once @@ -9,102 +9,190 @@ #include "../services/fs.h" #include "../services/sm.h" -typedef enum { - NcmContentType_CNMT = 0, - NcmContentType_Program = 1, - NcmContentType_Data = 2, - NcmContentType_Icon = 3, - NcmContentType_Doc = 4, - NcmContentType_Info = 5, -} NcmContentType; - -typedef enum { - NcmContentMetaType_SystemProgram = 0x01, - NcmContentMetaType_SystemData = 0x02, - NcmContentMetaType_SystemUpdate = 0x03, - NcmContentMetaType_BootImagePackage = 0x04, - NcmContentMetaType_BootImagePackageSafe = 0x05, - NcmContentMetaType_Application = 0x80, - NcmContentMetaType_Patch = 0x81, - NcmContentMetaType_AddOnContent = 0x82, - NcmContentMetaType_Delta = 0x83, -} NcmContentMetaType; - -typedef enum { - NcmContentMetaAttribute_Exfat = (1 << 0), - NcmContentMetaAttribute_Rebootless = (1 << 1), -} NcmContentMetaAttribute; - +/// ContentStorage typedef struct { - Service s; + Service s; ///< IContentStorage } NcmContentStorage; +/// ContentMetaDatabase typedef struct { - Service s; + Service s; ///< IContentMetaDatabase } NcmContentMetaDatabase; +/// ContentType +typedef enum { + NcmContentType_Meta = 0, ///< Meta + NcmContentType_Program = 1, ///< Program + NcmContentType_Data = 2, ///< Data + NcmContentType_Control = 3, ///< Control + NcmContentType_HtmlDocument = 4, ///< HtmlDocument + NcmContentType_LegalInformation = 5, ///< LegalInformation + NcmContentType_DeltaFragment = 6, ///< DeltaFragment +} NcmContentType; + +/// ContentMetaType +typedef enum { + NcmContentMetaType_Unknown = 0x0, ///< Unknown + NcmContentMetaType_SystemProgram = 0x1, ///< SystemProgram + NcmContentMetaType_SystemData = 0x2, ///< SystemData + NcmContentMetaType_SystemUpdate = 0x3, ///< SystemUpdate + NcmContentMetaType_BootImagePackage = 0x4, ///< BootImagePackage + NcmContentMetaType_BootImagePackageSafe = 0x5, ///< BootImagePackageSafe + NcmContentMetaType_Application = 0x80, ///< Application + NcmContentMetaType_Patch = 0x81, ///< Patch + NcmContentMetaType_AddOnContent = 0x82, ///< AddOnContent + NcmContentMetaType_Delta = 0x83, ///< Delta +} NcmContentMetaType; + +/// ContentMetaAttribute +typedef enum { + NcmContentMetaAttribute_None = 0, ///< None + NcmContentMetaAttribute_IncludesExFatDriver = BIT(0), ///< IncludesExFatDriver + NcmContentMetaAttribute_Rebootless = BIT(1), ///< Rebootless +} NcmContentMetaAttribute; + +/// ContentInstallType +typedef enum { + NcmContentInstallType_Full = 0, ///< Full + NcmContentInstallType_FragmentOnly = 1, ///< FragmentOnly + NcmContentInstallType_Unknown = 7, ///< Unknown +} NcmContentInstallType; + +/// NcaId typedef struct { - u8 c[0x10]; + u8 c[0x10]; ///< Id } NcmNcaId; +/// ContentMetaKey typedef struct { - u64 titleId; - u32 version; - u8 type; - u8 flags; - u8 padding[2]; -} NcmMetaRecord; + u64 title_id; ///< Title id. + u32 version; ///< Title version. + u8 type; ///< \ref NcmContentMetaType + u8 install_type; ///< \ref NcmContentInstallType + u8 padding[2]; ///< Padding. +} NcmContentMetaKey; +/// ApplicationContentMetaKey typedef struct { - NcmNcaId ncaId; - u8 size[0x6]; - u8 type; - u8 padding; -} NcmContentRecord; - -typedef struct { - u16 numExtraBytes; ///< Size of optional struct that comes after this one. - u16 numContentRecords; ///< Number of NcmContentRecord entries after the extra bytes. - u16 numMetaRecords; ///< Number of NcmMetaRecord entries that come after the NcmContentRecords. - u16 padding; ///< Always zero. -} NcmContentMetaRecordsHeader; - -typedef struct { - NcmMetaRecord metaRecord; - u64 baseTitleId; + NcmContentMetaKey key; ///< \ref NcmContentMetaKey + u64 application_id; ///< Title id of an application. } NcmApplicationContentMetaKey; +/// ContentInfo +typedef struct { + NcmNcaId content_id; ///< \ref NcmNcaId + u8 size[0x6]; ///< Content size. + u8 content_type; ///< \ref NcmContentType. + u8 id_offset; ///< Offset of this content. Unused by most applications. +} NcmContentInfo; + +/// Used by system updates. They share the exact same struct as NcmContentMetaKey +typedef NcmContentMetaKey NcmContentMetaInfo; + +/// ContentMetaHeader +typedef struct { + u16 extended_header_size; ///< Size of optional struct that comes after this one. + u16 content_count; ///< Number of NcmContentInfos after the extra bytes. + u16 content_meta_count; ///< Number of NcmContentMetaInfos that come after the NcmContentInfos. + u8 attributes; ///< Usually None (0). + u8 storage_id; ///< Usually None (0). +} NcmContentMetaHeader; + +/// ApplicationMetaExtendedHeader +typedef struct { + u64 patch_id; ///< Title id of this application's patch. + u32 required_system_version; ///< Firmware version required by this application. + u32 required_application_version; ///< [9.0.0+] Owner application version required by this application. Previously padding. +} NcmApplicationMetaExtendedHeader; + +/// PatchMetaExtendedHeader +typedef struct { + u64 application_id; ///< Title id of this patch's corresponding application. + u32 required_system_version; ///< Firmware version required by this patch. + u32 extended_data_size; ///< Size of the extended data following the NcmContentInfos. + u8 reserved[0x8]; ///< Unused. +} NcmPatchMetaExtendedHeader; + +/// AddOnContentMetaExtendedHeader +typedef struct { + u64 application_id; ///< Title id of this add-on-content's corresponding application. + u32 required_application_version; ///< Version of the application required by this add-on-content. + u32 padding; ///< Padding. +} NcmAddOnContentMetaExtendedHeader; + +/// SystemUpdateMetaExtendedHeader +typedef struct { + u32 extended_data_size; ///< Size of the extended data after NcmContentInfos and NcmContentMetaInfos. +} NcmSystemUpdateMetaExtendedHeader; + Result ncmInitialize(void); void ncmExit(void); Service* ncmGetServiceSession(void); -Result ncmOpenContentStorage(FsStorageId storage, NcmContentStorage* out); -Result ncmOpenContentMetaDatabase(FsStorageId storage, NcmContentMetaDatabase* out); +Result ncmCreateContentStorage(FsStorageId storage_id); +Result ncmCreateContentMetaDatabase(FsStorageId storage_id); +Result ncmVerifyContentStorage(FsStorageId storage_id); +Result ncmVerifyContentMetaDatabase(FsStorageId storage_id); +Result ncmOpenContentStorage(NcmContentStorage* out_content_storage, FsStorageId storage_id); +Result ncmOpenContentMetaDatabase(NcmContentMetaDatabase* out_content_meta_database, FsStorageId storage_id); +Result ncmCloseContentStorageForcibly(FsStorageId storage_id); ///< [1.0.0] +Result ncmCloseContentMetaDatabaseForcibly(FsStorageId storage_id); ///< [1.0.0] +Result ncmCleanupContentMetaDatabase(FsStorageId storage_id); +Result ncmActivateContentStorage(FsStorageId storage_id); ///< [2.0.0+] +Result ncmInactivateContentStorage(FsStorageId storage_id); ///< [2.0.0+] +Result ncmActivateContentMetaDatabase(FsStorageId storage_id); ///< [2.0.0+] +Result ncmInactivateContentMetaDatabase(FsStorageId storage_id); ///< [2.0.0+] +Result ncmInvalidateRightsIdCache(void); ///< [9.0.0+] -Result ncmContentStorageGeneratePlaceHolderId(NcmContentStorage* cs, NcmNcaId* outputId); -Result ncmContentStorageCreatePlaceHolder(NcmContentStorage* cs, const NcmNcaId* registeredId, const NcmNcaId* placeholderId, u64 size); -Result ncmContentStorageDeletePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholderId); -Result ncmContentStorageWritePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholderId, u64 offset, const void* srcData, size_t srcDataSize); -Result ncmContentStorageRegister(NcmContentStorage* cs, const NcmNcaId* registeredId, const NcmNcaId* placeholderId); -Result ncmContentStorageDelete(NcmContentStorage* cs, const NcmNcaId* registeredId); -Result ncmContentStorageHas(NcmContentStorage* cs, const NcmNcaId* ncaId, bool* out); -Result ncmContentStorageGetPath(NcmContentStorage* cs, const NcmNcaId* ncaId, char* out, size_t outSize); -Result ncmContentStorageGetPlaceHolderPath(NcmContentStorage* cs, const NcmNcaId* ncaId, char* out, size_t outSize); +void ncmContentStorageClose(NcmContentStorage* cs); +Result ncmContentStorageGeneratePlaceHolderId(NcmContentStorage* cs, NcmNcaId* out_id); +Result ncmContentStorageCreatePlaceHolder(NcmContentStorage* cs, const NcmNcaId* content_id, const NcmNcaId* placeholder_id, u64 size); +Result ncmContentStorageDeletePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id); +Result ncmContentStorageHasPlaceHolder(NcmContentStorage* cs, bool* out, const NcmNcaId* placeholder_id); +Result ncmContentStorageWritePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id, u64 offset, const void* data, size_t data_size); +Result ncmContentStorageRegister(NcmContentStorage* cs, const NcmNcaId* content_id, const NcmNcaId* placeholder_id); +Result ncmContentStorageDelete(NcmContentStorage* cs, const NcmNcaId* content_id); +Result ncmContentStorageHas(NcmContentStorage* cs, bool* out, const NcmNcaId* content_id); +Result ncmContentStorageGetPath(NcmContentStorage* cs, char* out_path, size_t out_size, const NcmNcaId* content_id); +Result ncmContentStorageGetPlaceHolderPath(NcmContentStorage* cs, const char* out_path, size_t out_size, const NcmNcaId* placeholder_id); Result ncmContentStorageCleanupAllPlaceHolder(NcmContentStorage* cs); -Result ncmContentStorageGetSize(NcmContentStorage* cs, const NcmNcaId* ncaId, u64* out); +Result ncmContentStorageListPlaceHolder(NcmContentStorage* cs, NcmNcaId* out_ids, size_t out_ids_size, u32* out_count); +Result ncmContentStorageGetContentCount(NcmContentStorage* cs, u32* out_count); +Result ncmContentStorageListContentId(NcmContentStorage* cs, NcmNcaId* out_ids, size_t out_ids_size, u32* out_count, u32 start_offset); +Result ncmContentStorageGetSizeFromContentId(NcmContentStorage* cs, u64* out_size, const NcmNcaId* content_id); Result ncmContentStorageDisableForcibly(NcmContentStorage* cs); -Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, const NcmNcaId* ncaId, u64 offset, void* outBuf, size_t bufSize); -Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, FsRightsId* rightsIdOut, u32* keyGenerationOut); +Result ncmContentStorageRevertToPlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id, const NcmNcaId* old_content_id, const NcmNcaId* new_content_id); ///< [2.0.0+] +Result ncmContentStorageSetPlaceHolderSize(NcmContentStorage* cs, const NcmNcaId* placeholder_id, u64 size); ///< [2.0.0+] +Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, void* out_data, size_t out_data_size, const NcmNcaId* content_id, u64 offset); ///< [2.0.0+] +Result ncmContentStorageGetRightsIdFromPlaceHolderId(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* placeholder_id); ///< [2.0.0+] +Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* content_id); ///< [2.0.0+] +Result ncmContentStorageWriteContentForDebug(NcmContentStorage* cs, const NcmNcaId* content_id, u64 offset, const void* data, size_t data_size); ///< [2.0.0+] +Result ncmContentStorageGetFreeSpaceSize(NcmContentStorage* cs, u64* out_size); ///< [2.0.0+] +Result ncmContentStorageGetTotalSpaceSize(NcmContentStorage* cs, u64* out_size); ///< [2.0.0+] +Result ncmContentStorageFlushPlaceHolder(NcmContentStorage* cs); ///< [3.0.0+] +Result ncmContentStorageGetSizeFromPlaceHolderId(NcmContentStorage* cs, u64* out_size, const NcmNcaId* placeholder_id); ///< [4.0.0+] +Result ncmContentStorageRepairInvalidFileAttribute(NcmContentStorage* cs); ///< [4.0.0+] +Result ncmContentStorageGetRightsIdFromPlaceHolderIdWithCache(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* placeholder_id, const NcmNcaId* cache_content_id); ///< [8.0.0+] -Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 inDataSize, const NcmContentMetaRecordsHeader* srcRecordsData); -Result ncmContentMetaDatabaseGet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 outDataSize, NcmContentMetaRecordsHeader* outRecordsData, u64* sizeRead); -Result ncmContentMetaDatabaseRemove(NcmContentMetaDatabase* db, const NcmMetaRecord *record); -Result ncmContentMetaDatabaseGetContentIdByType(NcmContentMetaDatabase* db, NcmContentType contentType, const NcmMetaRecord* record, NcmNcaId* out); -Result ncmContentMetaDatabaseListContentInfo(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u32 index, NcmContentRecord* contentRecordsOut, size_t contentRecordsBufSize, u32* numEntriesRead); -Result ncmContentMetaDatabaseList(NcmContentMetaDatabase* db, u32 titleType, u64 titleIdExact, u64 titleIdLow, u64 titleIdHigh, NcmMetaRecord* metaRecordsOut, size_t metaRecordsBufSize, u32* numEntriesWritten, u32* numEntriesTotal); -Result ncmContentMetaDatabaseGetLatestContentMetaKey(NcmContentMetaDatabase* db, u64 titleId, NcmMetaRecord* out); -Result ncmContentMetaDatabaseListApplication(NcmContentMetaDatabase* db, u8 filter, NcmApplicationContentMetaKey* outBuf, size_t outBufSize, u32* numEntriesWritten, u32* numEntriesTotal); -Result ncmContentMetaDatabaseHas(NcmContentMetaDatabase* db, const NcmMetaRecord* record, bool* out); +void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db); +Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, const void* data, u64 data_size); +Result ncmContentMetaDatabaseGet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u64* out_size, void* out_data, u64 out_data_size); +Result ncmContentMetaDatabaseRemove(NcmContentMetaDatabase* db, const NcmContentMetaKey *key); +Result ncmContentMetaDatabaseGetContentIdByType(NcmContentMetaDatabase* db, NcmNcaId* out_content_id, const NcmContentMetaKey* key, NcmContentType type); +Result ncmContentMetaDatabaseListContentInfo(NcmContentMetaDatabase* db, u32* out_entries_written, NcmContentInfo* out_info, size_t out_info_size, const NcmContentMetaKey* key, u32 start_index); +Result ncmContentMetaDatabaseList(NcmContentMetaDatabase* db, u32* out_entries_total, u32* out_entries_written, NcmContentMetaKey* out_keys, size_t out_keys_size, NcmContentMetaType meta_type, u64 application_title_id, u64 title_id_min, u64 title_id_max, NcmContentInstallType install_type); +Result ncmContentMetaDatabaseGetLatestContentMetaKey(NcmContentMetaDatabase* db, NcmContentMetaKey* out_key, u64 title_id); +Result ncmContentMetaDatabaseListApplication(NcmContentMetaDatabase* db, u32* out_entries_total, u32* out_entries_written, NcmApplicationContentMetaKey* out_keys, size_t out_keys_size, NcmContentMetaType meta_type); +Result ncmContentMetaDatabaseHas(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* key); +Result ncmContentMetaDatabaseHasAll(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* keys, size_t keys_size); +Result ncmContentMetaDatabaseGetSize(NcmContentMetaDatabase* db, u64* out_size, const NcmContentMetaKey* key); +Result ncmContentMetaDatabaseGetRequiredSystemVersion(NcmContentMetaDatabase* db, u64* out_version, const NcmContentMetaKey* key); +Result ncmContentMetaDatabaseGetPatchId(NcmContentMetaDatabase* db, u64* out_patch_id, const NcmContentMetaKey* key); Result ncmContentMetaDatabaseDisableForcibly(NcmContentMetaDatabase* db); +Result ncmContentMetaDatabaseLookupOrphanContent(NcmContentMetaDatabase* db, bool* out_orphaned, size_t out_orphaned_size, const NcmNcaId* content_ids, size_t content_ids_size); Result ncmContentMetaDatabaseCommit(NcmContentMetaDatabase* db); -Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u8* out); +Result ncmContentMetaDatabaseHasContent(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* key, const NcmNcaId* content_id); +Result ncmContentMetaDatabaseListContentMetaInfo(NcmContentMetaDatabase* db, u32* out_entries_written, void* out_meta_info, size_t out_meta_info_size, const NcmContentMetaKey* key, u32 start_index); +Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u8* out); +Result ncmContentMetaDatabaseGetRequiredApplicationVersion(NcmContentMetaDatabase* db, u64* out_version, const NcmContentMetaKey* key); ///< [2.0.0+] +Result ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(NcmContentMetaDatabase* db, NcmNcaId* out_content_id, const NcmContentMetaKey* key, NcmContentType type, u8 id_offset); ///< [5.0.0+] diff --git a/nx/include/switch/services/nifm.h b/nx/include/switch/services/nifm.h index 6c994c69..1357c591 100644 --- a/nx/include/switch/services/nifm.h +++ b/nx/include/switch/services/nifm.h @@ -1,13 +1,13 @@ /** * @file nifm.h * @brief Network interface service IPC wrapper. - * @author shadowninja108, shibboleet, exelix + * @author shadowninja108, shibboleet, exelix, yellows8 * @copyright libnx Authors */ #pragma once -#include "../kernel/ipc.h" -#include "../services/sm.h" +#include "../types.h" +#include "../sf/service.h" typedef enum { NifmServiceType_NotInitialized = 0, ///< Initializes nifm:u. @@ -35,18 +35,27 @@ typedef enum { */ void nifmSetServiceType(NifmServiceType serviceType); +/// Initialize nifm. This is used automatically by \ref socketInitialize. Result nifmInitialize(void); + +/// Exit nifm. This is used automatically by \ref socketExit. void nifmExit(void); -Result nifmGetCurrentIpAddress(u32* out); +/// Gets the Service object for the actual nifm:* service session. +Service* nifmGetServiceSession_StaticService(void); -Result nifmIsWirelessCommunicationEnabled(bool* out); +/// Gets the Service object for IGeneralService. +Service* nifmGetServiceSession_GeneralService(void); + +Result nifmGetCurrentIpAddress(u32* out); /** * @note Works only if called from nifm:a or nifm:s. */ Result nifmSetWirelessCommunicationEnabled(bool enable); +Result nifmIsWirelessCommunicationEnabled(bool* out); + /** * @note Will fail with 0xd46ed if Internet is neither connecting or connected (airplane mode or no known network in reach). * @param wifiStrength Strength of the Wi-Fi signal in number of bars from 0 to 3. diff --git a/nx/include/switch/services/ns.h b/nx/include/switch/services/ns.h index 372f0299..f3733666 100644 --- a/nx/include/switch/services/ns.h +++ b/nx/include/switch/services/ns.h @@ -1,101 +1,527 @@ /** * @file ns.h - * @brief NS service IPC wrapper. + * @brief NS services IPC wrapper. * @author yellows8 * @copyright libnx Authors */ #pragma once #include "../types.h" #include "../nacp.h" +#include "../sf/service.h" #include "../services/fs.h" +#include "../services/ncm.h" +#include "../services/async.h" #include "../kernel/event.h" +#include "../kernel/tmem.h" -typedef struct { - NacpStruct nacp; - u8 icon[0x20000];//JPEG -} NsApplicationControlData; - -typedef struct -{ - u8 title_type; - u8 storageID; - u8 unk_x02; - u8 padding; - u32 title_version; - u64 titleID; -} NsApplicationContentMetaStatus; - -typedef struct -{ - u64 titleID; - u8 type; - u8 unk_x09; - u8 unk_x0A[6]; - u8 unk_x10; - u8 unk_x11[7]; -} NsApplicationRecord; - -typedef struct { - u64 titleID; - u32 version; - u8 storageID; - u8 index; - u8 is_application; -} NsLaunchProperties; - +/// ShellEvent typedef enum { - NsShellEvent_None = 0, - NsShellEvent_Exit = 1, - NsShellEvent_Start = 2, - NsShellEvent_Crash = 3, - NsShellEvent_Debug = 4, + NsShellEvent_None = 0, ///< None + NsShellEvent_Exit = 1, ///< Exit + NsShellEvent_Start = 2, ///< Start + NsShellEvent_Crash = 3, ///< Crash + NsShellEvent_Debug = 4, ///< Debug } NsShellEvent; +/// ApplicationControlSource +typedef enum { + NsApplicationControlSource_CacheOnly = 0, ///< Returns data from cache. + NsApplicationControlSource_Storage = 1, ///< Returns data from storage if not present in cache. + NsApplicationControlSource_StorageOnly = 2, ///< Returns data from storage without using cache. +} NsApplicationControlSource; + +/// BackgroundNetworkUpdateState +typedef enum { + NsBackgroundNetworkUpdateState_None = 0, ///< No sysupdate task exists. + NsBackgroundNetworkUpdateState_Downloading = 1, ///< Sysupdate download in progress. + NsBackgroundNetworkUpdateState_Ready = 2, ///< Sysupdate ready, pending install. +} NsBackgroundNetworkUpdateState; + +/// LatestSystemUpdate +typedef enum { + NsLatestSystemUpdate_Unknown0 = 0, ///< Unknown. + NsLatestSystemUpdate_Unknown1 = 1, ///< Unknown. + NsLatestSystemUpdate_Unknown2 = 2, ///< Unknown. +} NsLatestSystemUpdate; + +/// SystemUpdateControl typedef struct { - NsShellEvent event; - u64 process_id; + Service s; ///< ISystemUpdateControl + TransferMemory tmem; ///< TransferMemory for SetupCardUpdate/SetupCardUpdateViaSystemUpdater. +} NsSystemUpdateControl; + +/// ApplicationControlData +typedef struct { + NacpStruct nacp; ///< \ref NacpStruct + u8 icon[0x20000]; ///< JPEG +} NsApplicationControlData; + +/// NsApplicationContentMetaStatus +typedef struct { + u8 title_type; ///< \ref NcmContentMetaType + u8 storageID; ///< \ref FsStorageId + u8 unk_x02; ///< Unknown. + u8 padding; ///< Padding. + u32 title_version; ///< Title version. + u64 titleID; ///< titleID. +} NsApplicationContentMetaStatus; + +/// ApplicationRecord +typedef struct { + u64 titleID; ///< titleID. + u8 type; ///< Type. + u8 unk_x09; ///< Unknown. + u8 unk_x0A[6]; ///< Unknown. + u8 unk_x10; ///< Unknown. + u8 unk_x11[7]; ///< Unknown. +} NsApplicationRecord; + +/// LaunchProperties +typedef struct { + u64 titleID; ///< titleID. + u32 version; ///< Title version. + u8 storageID; ///< \ref FsStorageId + u8 index; ///< Index. + u8 is_application; ///< Whether this is an Application. +} NsLaunchProperties; + +/// ShellEventInfo +typedef struct { + NsShellEvent event; ///< \ref NsShellEvent + u64 process_id; ///< processID. } NsShellEventInfo; +/// SystemUpdateProgress. Commands which have this as output will return 0 with the output cleared, when no task is available. +typedef struct { + s64 current_size; ///< Current size. This value can be larger than total_size when the async operation is finishing. When total_size is <=0, this current_size field may contain a progress value for when the total_size is not yet determined. + s64 total_size; ///< Total size, this field is only valid when >0. +} NsSystemUpdateProgress; + +/// EulaDataPath +typedef struct { + char path[0x100]; ///< Path. +} NsEulaDataPath; + +/// SystemDeliveryInfo +typedef struct { + u32 protocol_version; ///< Must be <= to and match a system-setting. + u8 unk_x4[0x8]; ///< Unused by \ref nssuRequestSendSystemUpdate / \ref nssuControlRequestReceiveSystemUpdate, besides HMAC validation. + u32 systemupdate_meta_version; ///< SystemUpdate meta version. + u64 systemupdate_meta_titleid; ///< SystemUpdate meta titleID. + u8 unk_x18; ///< Copied into state by \ref nssuRequestSendSystemUpdate. + u8 unk_x19[0xc7]; ///< Unused by \ref nssuRequestSendSystemUpdate / \ref nssuControlRequestReceiveSystemUpdate, besides HMAC validation. + u8 hmac[0x20]; ///< HMAC-SHA256 over the previous 0xe0-bytes. +} NsSystemDeliveryInfo; + +/// Default size for \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater. This is the size used by qlaunch for SetupCardUpdate. +#define NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT 0x100000 + +///@name ns +///@{ + +/// Initialize ns services. Uses ns:am on pre-3.0.0, ns:am2 on [3.0.0+]. Result nsInitialize(void); + +/// Exit ns services. void nsExit(void); -Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t entry_offset, size_t* out_entrycount); -Result nsListApplicationContentMetaStatus(u64 titleID, u32 index, NsApplicationContentMetaStatus* buffer, size_t size, size_t* out_entrycount); -Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, size_t* actual_size); +/// Gets the Service object for the actual ns:* service session. Only initialized on [3.0.0+], on pre-3.0.0 see \ref nsGetServiceSession_ApplicationManagerInterface. +Service* nsGetServiceSession_GetterInterface(void); + +/// Gets the Service object for IApplicationManagerInterface. +Service* nsGetServiceSession_ApplicationManagerInterface(void); + +/** + * @brief Gets an listing of \ref NsApplicationRecord. + * @param[out] records Output array of \ref NsApplicationRecord. + * @param[in] count Size of the records array in entries. + * @param[in] entry_offset Starting entry offset. + * @param[out] out_entrycount Total output entries. + */ +Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount); + +/** + * @brief Gets an listing of \ref NsApplicationContentMetaStatus. + * @param[in] titleID titleID. + * @param[in] index Starting entry index. + * @param[out] list Output array of \ref NsApplicationContentMetaStatus. + * @param[in] count Size of the list array in entries. + * @param[out] out_entrycount Total output entries. + */ +Result nsListApplicationContentMetaStatus(u64 titleID, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount); + +/** + * @brief Gets the \ref NsApplicationControlData for the specified title. + * @param[in] flag Flag, official sw uses value 1. + * @param[in] titleID titleID. + * @param[out] buffer \ref NsApplicationControlData + * @param[in] size Size of the buffer. + * @param[out] actual_size Actual output size. + */ +Result nsGetApplicationControlData(NsApplicationControlSource source, u64 titleID, NsApplicationControlData* buffer, size_t size, u64* actual_size); /** * @brief Returns the total storage capacity (used + free) from content manager services. - * @param storage_id Specified FsStorageId. (Must be FsStorageId_SdCard) - * @param size Pointer to output the total storage size to. + * @param[in] storage_id Specified FsStorageId. (Must be FsStorageId_SdCard) + * @param[out] size Pointer to output the total storage size to. */ Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size); /** * @brief Returns the available storage capacity from content manager services. - * @param storage_id Specified FsStorageId. (Must be FsStorageId_SdCard) - * @param size Pointer to output the free storage size to. + * @param[in] storage_id Specified FsStorageId. (Must be FsStorageId_SdCard) + * @param[out] size Pointer to output the free storage size to. */ Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size); +///@} + +///@name ns:vm +///@{ + +/// Initialize ns:vm. On pre-3.0.0 this must be used with \ref nsInitialize. Result nsvmInitialize(void); + +/// Exit ns:vm. void nsvmExit(void); -Result nsvmNeedsUpdateVulnerability(bool *out); -Result nsvmGetSafeSystemVersion(u16 *out); +/// Gets the Service object for ns:vm. This is only initialized on [3.0.0+]. +Service* nsvmGetServiceSession(void); -/* ns:dev */ +Result nsvmNeedsUpdateVulnerability(bool *out); +Result nsvmGetSafeSystemVersion(NcmContentMetaKey *out); ///< [4.0.0+] + +///@} + +///@name ns:dev +///@{ + +/// Initialize ns:dev. Result nsdevInitialize(void); + +/// Initialize ns:dev. void nsdevExit(void); +/// Gets the Service object for ns:dev. +Service* nsdevGetServiceSession(void); + Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags); Result nsdevTerminateProcess(u64 pid); Result nsdevTerminateProgram(u64 tid); -Result nsdevGetShellEvent(Event* out); // Autoclear for nsdevShellEvent is always true. +Result nsdevGetShellEvent(Event* out_event); ///< Autoclear for nsdevShellEvent is always true. Result nsdevGetShellEventInfo(NsShellEventInfo* out); Result nsdevTerminateApplication(void); Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len); -Result nsdevLaunchApplication(u64* out_pid, u64 app_title_id, u32 flags); -Result nsdevLaunchApplicationWithStorageId(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id); -Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); -Result nsdevGetRunningApplicationProcessId(u64* out_pid); -Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active); +Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 app_title_id, u32 flags); +Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id); +Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out); ///< [6.0.0-8.1.0] +Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid); ///< [6.0.0+] +Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active); ///< [6.0.0+] + +///@} + +///@name ns:su +///@{ + +/// Initialize ns:su. +Result nssuInitialize(void); + +/// Exit ns:su. +void nssuExit(void); + +/// Gets the Service object for ns:su. +Service* nssuGetServiceSession(void); + +/** + * @brief Gets the \ref NsBackgroundNetworkUpdateState. + * @note Internally this uses nim commands ListSystemUpdateTask and GetSystemUpdateTaskInfo to determine the output state. + * @param[out] out \ref NsBackgroundNetworkUpdateState + */ +Result nssuGetBackgroundNetworkUpdateState(NsBackgroundNetworkUpdateState *out); + +/** + * @brief Opens a \ref NsSystemUpdateControl. + * @note Only 1 \ref NsSystemUpdateControl can be open at a time. + * @param[out] c \ref NsSystemUpdateControl + */ +Result nssuOpenSystemUpdateControl(NsSystemUpdateControl *c); + +/** + * @brief Uses nim ListSystemUpdateTask, then uses the task with DestroySystemUpdateTask if it exists. Then this runs ExFat handling, updates state, and sets the same state flag as \ref nssuRequestBackgroundNetworkUpdate. + * @note Only usable when a \ref NsSystemUpdateControl isn't open. + */ +Result nssuNotifyExFatDriverRequired(void); + +/** + * @brief ClearExFatDriverStatusForDebug + */ +Result nssuClearExFatDriverStatusForDebug(void); + +/** + * @brief RequestBackgroundNetworkUpdate + * @note Only usable when a \ref NsSystemUpdateControl isn't open. + */ +Result nssuRequestBackgroundNetworkUpdate(void); + +/** + * @brief This checks whether a sysupdate is needed with the input \ref NcmContentMetaKey using NCM commands, if not this will just return 0. Otherwise, this will then run code which is identical to \ref nssuRequestBackgroundNetworkUpdate. + * @note Only usable when a \ref NsSystemUpdateControl isn't open. + * @param[in] key \ref NcmContentMetaKey + */ +Result nssuNotifyBackgroundNetworkUpdate(const NcmContentMetaKey *key); + +/** + * @brief NotifyExFatDriverDownloadedForDebug + */ +Result nssuNotifyExFatDriverDownloadedForDebug(void); + +/** + * @brief Gets an Event which can be signaled by \ref nssuNotifySystemUpdateForContentDelivery. + * @note The Event must be closed by the user once finished with it. + * @param[out] out_event Output Event with autoclear=false. + */ +Result nssuGetSystemUpdateNotificationEventForContentDelivery(Event* out_event); + +/** + * @brief Signals the event returned by \ref nssuGetSystemUpdateNotificationEventForContentDelivery. + */ +Result nssuNotifySystemUpdateForContentDelivery(void); + +/** + * @brief This does shutdown preparation. + * @note This is used by am-sysmodule, so generally there's no need to use this. + * @note Only available on [3.0.0+]. + */ +Result nssuPrepareShutdown(void); + +/** + * @brief This uses nim ListSystemUpdateTask, then when a task is returned uses it with DestroySystemUpdateTask. + * @note Only available on [4.0.0+]. + */ +Result nssuDestroySystemUpdateTask(void); + +/** + * @brief RequestSendSystemUpdate + * @note Only available on [4.0.0+]. + * @param[out] a \ref AsyncResult + * @param[in] inval0 Unknown input value. + * @param[in] inval1 Unknown input value. qlaunch uses value 0xD904 (55556). + * @param[in] info \ref NsSystemDeliveryInfo + */ +Result nssuRequestSendSystemUpdate(AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info); + +/** + * @brief GetSendSystemUpdateProgress + * @note Only available on [4.0.0+]. + * @param[out] out \ref NsSystemUpdateProgress + */ +Result nssuGetSendSystemUpdateProgress(NsSystemUpdateProgress *out); + +///@} + +///@name ISystemUpdateControl +///@{ + +/** + * @brief Close a \ref NsSystemUpdateControl. + * @param c \ref NsSystemUpdateControl + */ +void nssuControlClose(NsSystemUpdateControl *c); + +/** + * @brief Gets whether a network sysupdate was downloaded, with install pending. + * @param c \ref NsSystemUpdateControl + * @param[out] out Output flag. + */ +Result nssuControlHasDownloaded(NsSystemUpdateControl *c, bool* out); + +/** + * @brief RequestCheckLatestUpdate + * @param c \ref NsSystemUpdateControl + * @param[out] a \ref AsyncValue. The data that can be read from this is u8 \ref NsLatestSystemUpdate. + */ +Result nssuControlRequestCheckLatestUpdate(NsSystemUpdateControl *c, AsyncValue *a); + +/** + * @brief RequestDownloadLatestUpdate + * @param c \ref NsSystemUpdateControl + * @param[out] a \ref AsyncResult + */ +Result nssuControlRequestDownloadLatestUpdate(NsSystemUpdateControl *c, AsyncResult *a); + +/** + * @brief GetDownloadProgress + * @param c \ref NsSystemUpdateControl + * @param[out] out \ref NsSystemUpdateProgress + */ +Result nssuControlGetDownloadProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out); + +/** + * @brief ApplyDownloadedUpdate + * @param c \ref NsSystemUpdateControl + */ +Result nssuControlApplyDownloadedUpdate(NsSystemUpdateControl *c); + +/** + * @brief RequestPrepareCardUpdate + * @param c \ref NsSystemUpdateControl + * @param[out] a \ref AsyncResult + */ +Result nssuControlRequestPrepareCardUpdate(NsSystemUpdateControl *c, AsyncResult *a); + +/** + * @brief GetPrepareCardUpdateProgress + * @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this. + * @param c \ref NsSystemUpdateControl + * @param[out] out \ref NsSystemUpdateProgress + */ +Result nssuControlGetPrepareCardUpdateProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out); + +/** + * @brief HasPreparedCardUpdate + * @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this. + * @param c \ref NsSystemUpdateControl + * @param[out] out Output flag. + */ +Result nssuControlHasPreparedCardUpdate(NsSystemUpdateControl *c, bool* out); + +/** + * @brief ApplyCardUpdate + * @note \ref nssuControlSetupCardUpdate / \ref nssuControlSetupCardUpdateViaSystemUpdater must have been used at some point prior to using this. + * @param c \ref NsSystemUpdateControl + */ +Result nssuControlApplyCardUpdate(NsSystemUpdateControl *c); + +/** + * @brief Gets the filesize for the specified DownloadedEulaData. + * @note This mounts the Eula title, then uses the file ":/". + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetDownloadedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize); + +/** + * @brief Gets the specified DownloadedEulaData. + * @note See the note for \ref nssuControlGetDownloadedEulaDataSize. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] buffer Output buffer. + * @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetDownloadedEulaDataSize. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetDownloadedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize); + +/** + * @brief SetupCardUpdate + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[in] buffer TransferMemory buffer, when NULL this is automatically allocated. + * @param[in] size TransferMemory buffer size, see \ref NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT. + */ +Result nssuControlSetupCardUpdate(NsSystemUpdateControl *c, void* buffer, size_t size); + +/** + * @brief Gets the filesize for the specified PreparedCardUpdateEulaData. + * @note See the note for \ref nssuControlGetDownloadedEulaDataSize. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetPreparedCardUpdateEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize); + +/** + * @brief Gets the specified PreparedCardUpdateEulaData. + * @note See the note for \ref nssuControlGetDownloadedEulaDataSize. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] buffer Output buffer. + * @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetPreparedCardUpdateEulaDataSize. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetPreparedCardUpdateEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize); + +/** + * @brief SetupCardUpdateViaSystemUpdater + * @note Same as \ref nssuControlSetupCardUpdate, except this doesn't run the code for fs cmds GetGameCardHandle/GetGameCardUpdatePartitionInfo, and uses fs OpenRegisteredUpdatePartition instead of OpenGameCardFileSystem. + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[in] buffer TransferMemory buffer, when NULL this is automatically allocated. + * @param[in] size TransferMemory buffer size, see \ref NSSU_CARDUPDATE_TMEM_SIZE_DEFAULT. + */ +Result nssuControlSetupCardUpdateViaSystemUpdater(NsSystemUpdateControl *c, void* buffer, size_t size); + +/** + * @brief HasReceived + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[out] out Output flag. + */ +Result nssuControlHasReceived(NsSystemUpdateControl *c, bool* out); + +/** + * @brief RequestReceiveSystemUpdate + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[out] a \ref AsyncResult + * @param[in] inval0 Unknown input value. + * @param[in] inval1 Unknown input value. qlaunch uses value 0xD904 (55556). + * @param[in] info \ref NsSystemDeliveryInfo + */ +Result nssuControlRequestReceiveSystemUpdate(NsSystemUpdateControl *c, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info); + +/** + * @brief GetReceiveProgress + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[out] out \ref NsSystemUpdateProgress + */ +Result nssuControlGetReceiveProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out); + +/** + * @brief ApplyReceivedUpdate + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + */ +Result nssuControlApplyReceivedUpdate(NsSystemUpdateControl *c); + +/** + * @brief Gets the filesize for the specified ReceivedEulaData. + * @note See the note for \ref nssuControlGetDownloadedEulaDataSize. + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetReceivedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize); + +/** + * @brief Gets the specified ReceivedEulaData. + * @note See the note for \ref nssuControlGetDownloadedEulaDataSize. + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[in] path EulaData path. + * @param[out] buffer Output buffer. + * @param[in] size Size of the output buffer, must be at least the output size from \ref nssuControlGetReceivedEulaDataSize. + * @param[out] filesize Output filesize. + */ +Result nssuControlGetReceivedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize); + +/** + * @brief Does setup for ReceiveSystemUpdate by using the same nim cmds as \ref nssuDestroySystemUpdateTask. + * @note Only available on [4.0.0+]. + * @param c \ref NsSystemUpdateControl + */ +Result nssuControlSetupToReceiveSystemUpdate(NsSystemUpdateControl *c); + +/** + * @brief RequestCheckLatestUpdateIncludesRebootlessUpdate + * @note Only available on [6.0.0+]. + * @param c \ref NsSystemUpdateControl + * @param[out] a \ref AsyncValue + */ +Result nssuControlRequestCheckLatestUpdateIncludesRebootlessUpdate(NsSystemUpdateControl *c, AsyncValue *a); + +///@} + diff --git a/nx/include/switch/services/nv.h b/nx/include/switch/services/nv.h index 353627cf..056cb4d0 100644 --- a/nx/include/switch/services/nv.h +++ b/nx/include/switch/services/nv.h @@ -6,6 +6,7 @@ */ #pragma once #include "../types.h" +#include "../sf/service.h" #include "../kernel/event.h" Result nvInitialize(void); diff --git a/nx/include/switch/services/pm.h b/nx/include/switch/services/pm.h index 3ab480ba..5175a994 100644 --- a/nx/include/switch/services/pm.h +++ b/nx/include/switch/services/pm.h @@ -9,7 +9,7 @@ #pragma once #include "../types.h" #include "../kernel/event.h" -#include "../services/sm.h" +#include "../sf/service.h" /// LaunchFlag typedef enum { @@ -79,10 +79,10 @@ Service* pmbmGetServiceSession(void); Result pmdmntGetDebugProcesses(u32* out_count, u64* out_pids, size_t max_pids); Result pmdmntStartProcess(u64 pid); Result pmdmntGetTitlePid(u64* pid_out, u64 title_id); -Result pmdmntEnableDebugForTitleId(Handle* handle_out, u64 title_id); +Result pmdmntEnableDebugForTitleId(Event* out, u64 title_id); Result pmdmntGetApplicationPid(u64* pid_out); -Result pmdmntEnableDebugForApplication(Handle* handle_out); -Result pmdmntDisableDebug(void); +Result pmdmntEnableDebugForApplication(Event* out); +Result pmdmntDisableDebug(u32 which); Result pminfoGetTitleId(u64* title_id_out, u64 pid); diff --git a/nx/include/switch/services/psm.h b/nx/include/switch/services/psm.h index 1113e25b..689dec66 100644 --- a/nx/include/switch/services/psm.h +++ b/nx/include/switch/services/psm.h @@ -6,7 +6,7 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../kernel/event.h" typedef enum { diff --git a/nx/include/switch/services/ro.h b/nx/include/switch/services/ro.h index 492ed929..7c7680e5 100644 --- a/nx/include/switch/services/ro.h +++ b/nx/include/switch/services/ro.h @@ -6,7 +6,7 @@ */ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" #include "../services/ldr.h" Result ldrRoInitialize(void); diff --git a/nx/include/switch/services/set.h b/nx/include/switch/services/set.h index 9e150519..e5162561 100644 --- a/nx/include/switch/services/set.h +++ b/nx/include/switch/services/set.h @@ -7,37 +7,39 @@ * @copyright libnx Authors */ #pragma once -#include "../result.h" +#include "../types.h" #include "../kernel/event.h" -#include "../services/sm.h" +#include "../sf/service.h" #define SET_MAX_NAME_SIZE 0x48 #define SET_MAX_NICKNAME_SIZE 0x80 typedef enum { - ColorSetId_Light=0, - ColorSetId_Dark=1 + ColorSetId_Light = 0, + ColorSetId_Dark = 1, } ColorSetId; /// IDs for Language. typedef enum { - SetLanguage_JA = 0, ///< Japanese - SetLanguage_ENUS = 1, ///< US English ("AmericanEnglish") - SetLanguage_FR = 2, ///< French - SetLanguage_DE = 3, ///< German - SetLanguage_IT = 4, ///< Italian - SetLanguage_ES = 5, ///< Spanish - SetLanguage_ZHCN = 6, ///< Simplified Chinese ("Chinese") - SetLanguage_KO = 7, ///< Korean - SetLanguage_NL = 8, ///< Dutch - SetLanguage_PT = 9, ///< Portuguese - SetLanguage_RU = 10, ///< Russian - SetLanguage_ZHTW = 11, ///< Traditional Chinese ("Taiwanese") - SetLanguage_ENGB = 12, ///< GB English ("BritishEnglish") - SetLanguage_FRCA = 13, ///< CA French ("CanadianFrench") - SetLanguage_ES419 = 14, ///< "LatinAmericanSpanish" - SetLanguage_Total, ///< Total languages supported by this enum. + SetLanguage_JA = 0, ///< Japanese + SetLanguage_ENUS = 1, ///< US English ("AmericanEnglish") + SetLanguage_FR = 2, ///< French + SetLanguage_DE = 3, ///< German + SetLanguage_IT = 4, ///< Italian + SetLanguage_ES = 5, ///< Spanish + SetLanguage_ZHCN = 6, ///< Simplified Chinese ("Chinese") + SetLanguage_KO = 7, ///< Korean + SetLanguage_NL = 8, ///< Dutch + SetLanguage_PT = 9, ///< Portuguese + SetLanguage_RU = 10, ///< Russian + SetLanguage_ZHTW = 11, ///< Traditional Chinese ("Taiwanese") + SetLanguage_ENGB = 12, ///< GB English ("BritishEnglish") + SetLanguage_FRCA = 13, ///< CA French ("CanadianFrench") + SetLanguage_ES419 = 14, ///< "LatinAmericanSpanish" + SetLanguage_ZHHANS = 15, ///< [4.0.0+] ChineseSimplified + SetLanguage_ZHHANT = 16, ///< [4.0.0+] ChineseTraditional + SetLanguage_Total, ///< Total languages supported by this enum. } SetLanguage; /// Region codes. @@ -46,27 +48,30 @@ typedef enum { SetRegion_USA = 1, ///< The Americas SetRegion_EUR = 2, ///< Europe SetRegion_AUS = 3, ///< Australia/New Zealand + SetRegion_CHN = 4, ///< China + SetRegion_KOR = 5, ///< Korea + SetRegion_TWN = 6, ///< Taiwan } SetRegion; /// Command IDs for setsysGetFlag/setsysSetFlag. typedef enum { - SetSysFlag_LockScreen = 7, - SetSysFlag_ConsoleInformationUpload = 25, + SetSysFlag_LockScreen = 7, + SetSysFlag_ConsoleInformationUpload = 25, SetSysFlag_AutomaticApplicationDownload = 27, - SetSysFlag_Quest = 47, - SetSysFlag_Usb30Enable = 65, - SetSysFlag_NfcEnable = 69, - SetSysFlag_WirelessLanEnable = 73, - SetSysFlag_BluetoothEnable = 88, - SetSysFlag_AutoUpdateEnable = 95, - SetSysFlag_BatteryPercentage = 99, - SetSysFlag_ExternalRtcReset = 101, - SetSysFlag_UsbFullKeyEnable = 103, - SetSysFlag_BluetoothAfhEnable = 111, - SetSysFlag_BluetoothBoostEnable = 113, - SetSysFlag_InRepairProcessEnable = 115, - SetSysFlag_HeadphoneVolumeUpdate = 117, - SetSysFlag_RequiresRunRepairTimeReviser = 141, + SetSysFlag_Quest = 47, + SetSysFlag_Usb30Enable = 65, + SetSysFlag_NfcEnable = 69, + SetSysFlag_WirelessLanEnable = 73, + SetSysFlag_BluetoothEnable = 88, + SetSysFlag_AutoUpdateEnable = 95, ///< [2.0.0+] + SetSysFlag_BatteryPercentage = 99, ///< [2.0.0+] + SetSysFlag_ExternalRtcReset = 101, ///< [2.0.0+] + SetSysFlag_UsbFullKeyEnable = 103, ///< [3.0.0+] + SetSysFlag_BluetoothAfhEnable = 111, ///< [3.0.0+] + SetSysFlag_BluetoothBoostEnable = 113, ///< [3.0.0+] + SetSysFlag_InRepairProcessEnable = 115, ///< [3.0.0+] + SetSysFlag_HeadphoneVolumeUpdate = 117, ///< [3.0.0+] + SetSysFlag_RequiresRunRepairTimeReviser = 141, ///< [5.0.0+] } SetSysFlag; /// Structure returned by \ref setsysGetFirmwareVersion @@ -89,11 +94,11 @@ Result setInitialize(void); void setExit(void); Service* setGetServiceSession(void); -/// Converts LanguageCode to Language. -Result setMakeLanguage(u64 LanguageCode, s32 *Language); +/// Converts LanguageCode to \ref SetLanguage. +Result setMakeLanguage(u64 LanguageCode, SetLanguage *Language); -/// Converts Language to LanguageCode. -Result setMakeLanguageCode(s32 Language, u64 *LanguageCode); +/// Converts \ref SetLanguage to LanguageCode. +Result setMakeLanguageCode(SetLanguage Language, u64 *LanguageCode); /// Gets the current system LanguageCode. /// Normally this should be used instead of \ref setGetLanguageCode. @@ -138,8 +143,9 @@ Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u6 * @param item_key Item key string. * @param value_out Pointer to output the value to. * @param value_out_size Size of the value_out buffer. + * @param size_out Total size which was copied to value_out. */ -Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size); +Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out); /** * @brief Gets the system's serial number. @@ -169,9 +175,9 @@ Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out); /** * @brief Gets an event that settings will signal on flag change. - * @param out Event to bind. Output event will have autoclear=false. + * @param out_event Event to bind. Output event will have autoclear=false. */ -Result setsysBindFatalDirtyFlagEvent(Event *out); +Result setsysBindFatalDirtyFlagEvent(Event *out_event); /** * @brief Gets the settings flags that have changed. diff --git a/nx/include/switch/services/sm.h b/nx/include/switch/services/sm.h index ac2461de..366e94f1 100644 --- a/nx/include/switch/services/sm.h +++ b/nx/include/switch/services/sm.h @@ -9,67 +9,10 @@ #include "../types.h" #include "../kernel/svc.h" #include "../kernel/ipc.h" +#include "../sf/service.h" -/// Service type. -typedef enum { - ServiceType_Uninitialized, ///< Uninitialized service. - ServiceType_Normal, ///< Normal service. - ServiceType_Domain, ///< Domain. - ServiceType_DomainSubservice, ///< Domain subservice; - ServiceType_Override, ///< Service overriden in the homebrew environment. -} ServiceType; - -/// Service object structure. -typedef struct { - Handle handle; - u32 object_id; - ServiceType type; -} Service; - -/** - * @brief Returns whether a service is overriden in the homebrew environment. - * @param[in] s Service object. - * @return true if overriden. - */ -static inline bool serviceIsOverride(Service* s) { - return s->type == ServiceType_Override; -} - -/** - * @brief Returns whether a service has been initialized. - * @param[in] s Service object. - * @return true if initialized. - */ -static inline bool serviceIsActive(Service* s) { - return s->type != ServiceType_Uninitialized; -} - -/** - * @brief Returns whether a service is a domain. - * @param[in] s Service object. - * @return true if a domain. - */ -static inline bool serviceIsDomain(Service* s) { - return s->type == ServiceType_Domain; -} - -/** - * @brief Returns whether a service is a domain subservice. - * @param[in] s Service object. - * @return true if a domain subservice. - */ -static inline bool serviceIsDomainSubservice(Service* s) { - return s->type == ServiceType_DomainSubservice; -} - -/** - * @brief For a domain/domain subservice, return the associated object ID. - * @param[in] s Service object, necessarily a domain or domain subservice. - * @return The object ID. - */ -static inline u32 serviceGetObjectId(Service* s) { - return s->object_id; -} +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" /** * @brief Closes a domain object by ID. @@ -77,8 +20,9 @@ static inline u32 serviceGetObjectId(Service* s) { * @param object_id ID of the object to close. * @return Result code. */ +DEPRECATED static inline Result serviceCloseObjectById(Service* s, u32 object_id) { - return ipcCloseObjectById(s->handle, object_id); + return ipcCloseObjectById(s->session, object_id); } /** @@ -86,31 +30,9 @@ static inline Result serviceCloseObjectById(Service* s, u32 object_id) { * @param[in] s Service object. * @return Result code. */ +DEPRECATED static inline Result serviceIpcDispatch(Service* s) { - return ipcDispatch(s->handle); -} - -/** - * @brief Creates a service object from an IPC session handle. - * @param[out] s Service object. - * @param[in] h IPC session handle. - */ -static inline void serviceCreate(Service* s, Handle h) { - s->handle = h; - s->type = ServiceType_Normal; - s->object_id = IPC_INVALID_OBJECT_ID; -} - -/** - * @brief Creates a domain subservice object from a parent service. - * @param[out] s Service object. - * @param[in] parent Parent service, necessarily a domain or domain subservice. - * @param[in] object_id Object ID for this subservice. - */ -static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) { - s->handle = parent->handle; - s->type = ServiceType_DomainSubservice; - s->object_id = object_id; + return ipcDispatch(s->session); } /** @@ -120,6 +42,7 @@ static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u3 * @param[in] r Parsed IPC command containing handles/object IDs to create subservice from. * @param[in] i The index of the handle/object ID to create subservice from. */ +DEPRECATED static inline void serviceCreateSubservice(Service* s, Service* parent, IpcParsedCommand* r, int i) { if (r->IsDomainResponse) { return serviceCreateDomainSubservice(s, parent, r->OutObjectIds[i]); @@ -133,63 +56,13 @@ static inline void serviceCreateSubservice(Service* s, Service* parent, IpcParse * @param[in] s Service object to send. * @param[in] cmd IPC command structure. */ +DEPRECATED static inline void serviceSendObject(Service* s, IpcCommand* cmd) { if (serviceIsDomain(s) || serviceIsDomainSubservice(s)) { ipcSendObjectId(cmd, s->object_id); } } -/** - * @brief Converts a regular service to a domain. - * @param[in] s Service object. - * @return Result code. - */ -static inline Result serviceConvertToDomain(Service* s) { - Result rc = 0; - if (serviceIsOverride(s)) { - rc = ipcCloneSession(s->handle, 1, &s->handle); - if (R_FAILED(rc)) { - return rc; - } - s->type = ServiceType_Normal; - } - rc = ipcConvertSessionToDomain(s->handle, &s->object_id); - if (R_SUCCEEDED(rc)) { - s->type = ServiceType_Domain; - } - return rc; -} - -/** - * @brief Closes a service. - * @param[in] s Service object. - */ -static inline void serviceClose(Service* s) { - switch (s->type) { - - case ServiceType_Normal: - case ServiceType_Domain: - ipcCloseSession(s->handle); - svcCloseHandle(s->handle); - break; - - case ServiceType_DomainSubservice: - serviceCloseObjectById(s, s->object_id); - break; - - case ServiceType_Override: - // Don't close because we don't own the overridden handle. - break; - - case ServiceType_Uninitialized: - break; - } - - s->type = ServiceType_Uninitialized; -} - - - /** * @brief Prepares the header of an IPC command structure for a service. * @param s Service to prepare message header for @@ -197,6 +70,7 @@ static inline void serviceClose(Service* s) { * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request * @return Pointer to the raw embedded data structure in the request, ready to be filled out. */ +DEPRECATED static inline void* serviceIpcPrepareHeader(Service* s, IpcCommand* cmd, size_t sizeof_raw) { if (serviceIsDomain(s) || serviceIsDomainSubservice(s)) { return ipcPrepareHeaderForDomain(cmd, sizeof_raw, serviceGetObjectId(s)); @@ -212,6 +86,7 @@ static inline void* serviceIpcPrepareHeader(Service* s, IpcCommand* cmd, size_t * @param sizeof_raw Size in bytes of the raw data structure. * @return Result code. */ +DEPRECATED static inline Result serviceIpcParse(Service* s, IpcParsedCommand* r, size_t sizeof_raw) { if (serviceIsDomain(s) || serviceIsDomainSubservice(s)) { return ipcParseDomainResponse(r, sizeof_raw); @@ -220,6 +95,8 @@ static inline Result serviceIpcParse(Service* s, IpcParsedCommand* r, size_t siz } } +#pragma GCC diagnostic pop + /** * @brief Initializes SM. * @return Result code. @@ -274,12 +151,6 @@ Result smRegisterService(Handle* handle_out, const char* name, bool is_light, in */ Result smUnregisterService(const char* name); -/** - * @brief Check whether SM is initialized. - * @return true if initialized. - */ -bool smHasInitialized(void); - /** * @brief Gets the Service session used to communicate with SM. * @return Pointer to service session used to communicate with SM. @@ -291,7 +162,13 @@ Service *smGetServiceSession(void); * @param[in] name Name of the service. * @return Encoded name. */ -u64 smEncodeName(const char* name); +NX_CONSTEXPR u64 smEncodeName(const char* name) +{ + u64 name_encoded = 0; + for (unsigned i = 0; name[i] && i < 8; i ++) + name_encoded |= ((u64) name[i]) << (8*i); + return name_encoded; +} /** * @brief Overrides a service with a custom IPC service handle. diff --git a/nx/include/switch/services/spl.h b/nx/include/switch/services/spl.h index 4f897d8e..8ed557c1 100644 --- a/nx/include/switch/services/spl.h +++ b/nx/include/switch/services/spl.h @@ -6,6 +6,7 @@ */ #pragma once #include "../types.h" +#include "../kernel/event.h" #define SPL_RSA_BUFFER_SIZE (0x100) @@ -74,7 +75,7 @@ Result splCryptoCryptAesCtr(const void *input, void *output, size_t size, u32 ke Result splCryptoComputeCmac(const void *input, size_t size, u32 keyslot, void *out_cmac); Result splCryptoLockAesEngine(u32 *out_keyslot); Result splCryptoUnlockAesEngine(u32 keyslot); -Result splCryptoGetSecurityEngineEvent(Handle *out_event); +Result splCryptoGetSecurityEngineEvent(Event *out_event); Result splRsaDecryptPrivateKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version, void *dst, size_t dst_size); @@ -86,6 +87,8 @@ Result splEsUnwrapRsaOaepWrappedTitlekey(const void *rsa_wrapped_titlekey, const Result splEsUnwrapAesWrappedTitlekey(const void *aes_wrapped_titlekey, u32 key_generation, void *out_sealed_titlekey); Result splEsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version); Result splEsSecureExpMod(const void *input, const void *modulus, void *dst); +Result splEsUnwrapElicenseKey(const void *rsa_wrapped_elicense_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_elicense_key); +Result splEsLoadElicenseKey(const void *sealed_elicense_key, u32 keyslot); Result splFsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version); Result splFsSecureExpMod(const void *input, const void *modulus, void *dst); diff --git a/nx/include/switch/services/time.h b/nx/include/switch/services/time.h index da3d644f..6e97c828 100644 --- a/nx/include/switch/services/time.h +++ b/nx/include/switch/services/time.h @@ -7,7 +7,7 @@ #pragma once #include "../types.h" -#include "../services/sm.h" +#include "../sf/service.h" /// Time clock type. typedef enum { @@ -28,11 +28,11 @@ typedef struct { } TimeCalendarTime; typedef struct { - u32 wday; ///< 0-based day-of-week. - u32 yday; ///< 0-based day-of-year. - char timezoneName[8]; ///< Timezone name string. - u32 DST; ///< 0 = no DST, 1 = DST. - s32 offset; ///< Seconds relative to UTC for this timezone. + u32 wday; ///< 0-based day-of-week. + u32 yday; ///< 0-based day-of-year. + char timezoneName[8]; ///< Timezone name string. + u32 DST; ///< 0 = no DST, 1 = DST. + s32 offset; ///< Seconds relative to UTC for this timezone. } TimeCalendarAdditionalInfo; typedef struct { @@ -43,11 +43,27 @@ typedef struct { char name[0x24]; } TimeLocationName; +/// Initialize time. Used automatically during app startup. Result timeInitialize(void); + +/// Exit time. Used automatically during app startup. void timeExit(void); +/// Gets the Service object for the actual time service session. Service* timeGetServiceSession(void); +/// Gets the Service object for ISystemClock with the specified \ref TimeType. This will return NULL when the type is invalid. +Service* timeGetServiceSession_SystemClock(TimeType type); + +/// Gets the Service object for ITimeZoneService. +Service* timeGetServiceSession_TimeZoneService(void); + +/** + * @brief Gets the time for the specified clock. + * @param[in] type Clock to use. + * @param[out] timestamp POSIX UTC timestamp. + * @return Result code. + */ Result timeGetCurrentTime(TimeType type, u64 *timestamp); /** @@ -60,13 +76,13 @@ Result timeSetCurrentTime(TimeType type, u64 timestamp); Result timeGetDeviceLocationName(TimeLocationName *name); Result timeSetDeviceLocationName(const TimeLocationName *name); -Result timeGetTotalLocationNameCount(u32 *total_location_name_count); -Result timeLoadLocationNameList(u32 index, TimeLocationName *location_name_array, size_t location_name_size, u32 *location_name_count); +Result timeGetTotalLocationNameCount(s32 *total_location_name_count); +Result timeLoadLocationNameList(s32 index, TimeLocationName *location_name_array, s32 location_name_max, s32 *location_name_count); Result timeLoadTimeZoneRule(const TimeLocationName *name, TimeZoneRule *rule); -Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_size, u32 *timestamp_count); -Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_size, u32 *timestamp_count); Result timeToCalendarTime(const TimeZoneRule *rule, u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info); Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info); +Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count); +Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count); diff --git a/nx/include/switch/services/ts.h b/nx/include/switch/services/ts.h new file mode 100644 index 00000000..cc85b0c8 --- /dev/null +++ b/nx/include/switch/services/ts.h @@ -0,0 +1,47 @@ +/** + * @file ts.h + * @brief Temperature measurement (ts) service IPC wrapper. + * @author yellows8 + * @copyright libnx Authors + */ +#pragma once +#include "../types.h" +#include "../sf/service.h" + +/// Location +typedef enum { + TsLocation_Internal = 0, ///< Internal + TsLocation_External = 1, ///< External +} TsLocation; + +/// Initialize ts. +Result tsInitialize(void); + +/// Exit ts. +void tsExit(void); + +/// Gets the Service for ts. +Service* tsGetServiceSession(void); + +/** + * @brief Gets the min/max temperature for the specified \ref TsLocation. + * @param[in] location \ref TsLocation + * @param[out] min_temperature Output minimum temperature in Celsius. + * @param[out] max_temperature Output maximum temperature in Celsius. + */ +Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature); + +/** + * @brief Gets the temperature for the specified \ref TsLocation. + * @param[in] location \ref TsLocation + * @param[out] temperature Output temperature in Celsius. + */ +Result tsGetTemperature(TsLocation location, s32 *temperature); + +/** + * @brief Gets the temperature for the specified \ref TsLocation, in MilliC. + * @param[in] location \ref TsLocation + * @param[out] temperature Output temperature in MilliC. + */ +Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature); + diff --git a/nx/include/switch/services/usbhs.h b/nx/include/switch/services/usbhs.h index b6937767..22ae0114 100644 --- a/nx/include/switch/services/usbhs.h +++ b/nx/include/switch/services/usbhs.h @@ -96,7 +96,6 @@ typedef struct { typedef struct { Service s; Event eventXfer; ///< [2.0.0+] Signaled when PostBufferAsync finishes. - size_t ptrbufsize; ///< [3.0.0+] IPC pointer buffer size. struct usb_endpoint_descriptor desc; } UsbHsClientEpSession; diff --git a/nx/include/switch/services/wlaninf.h b/nx/include/switch/services/wlaninf.h index b3eb0006..ddb4b4f6 100644 --- a/nx/include/switch/services/wlaninf.h +++ b/nx/include/switch/services/wlaninf.h @@ -1,13 +1,13 @@ /** * @file wlaninf.h * @brief WLAN InfraManager service IPC wrapper. - * @author natinusala + * @author natinusala, yellows8 * @copyright libnx Authors */ #pragma once -#include "../kernel/ipc.h" -#include "../services/sm.h" +#include "../types.h" +#include "../sf/service.h" /// WLAN State. typedef enum { @@ -20,6 +20,7 @@ Result wlaninfInitialize(void); void wlaninfExit(void); Service* wlaninfGetServiceSession(void); +/// Gets \ref WlanInfState. Result wlaninfGetState(WlanInfState* out); /// Value goes from -30 (really good signal) to -90 (barely enough to stay connected) diff --git a/nx/include/switch/sf/cmif.h b/nx/include/switch/sf/cmif.h new file mode 100644 index 00000000..d4d14dcb --- /dev/null +++ b/nx/include/switch/sf/cmif.h @@ -0,0 +1,370 @@ +/** + * @file cmif.h + * @brief Common Message Interface Framework protocol + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "hipc.h" + +#define CMIF_IN_HEADER_MAGIC 0x49434653 // "SFCI" +#define CMIF_OUT_HEADER_MAGIC 0x4F434653 // "SFCO" + +typedef enum CmifCommandType { + CmifCommandType_Invalid = 0, + CmifCommandType_LegacyRequest = 1, + CmifCommandType_Close = 2, + CmifCommandType_LegacyControl = 3, + CmifCommandType_Request = 4, + CmifCommandType_Control = 5, + CmifCommandType_RequestWithContext = 6, + CmifCommandType_ControlWithContext = 7, +} CmifCommandType; + +typedef enum CmifDomainRequestType { + CmifDomainRequestType_Invalid = 0, + CmifDomainRequestType_SendMessage = 1, + CmifDomainRequestType_Close = 2, +} CmifDomainRequestType; + +typedef struct CmifInHeader { + u32 magic; + u32 version; + u32 command_id; + u32 token; +} CmifInHeader; + +typedef struct CmifOutHeader { + u32 magic; + u32 version; + Result result; + u32 token; +} CmifOutHeader; + +typedef struct CmifDomainInHeader { + u8 type; + u8 num_in_objects; + u16 data_size; + u32 object_id; + u32 padding; + u32 token; +} CmifDomainInHeader; + +typedef struct CmifDomainOutHeader { + u32 num_out_objects; + u32 padding[3]; +} CmifDomainOutHeader; + +typedef struct CmifRequestFormat { + u32 object_id; + u32 request_id; + u32 context; + u32 data_size; + u32 server_pointer_size; + u32 num_in_auto_buffers; + u32 num_out_auto_buffers; + u32 num_in_buffers; + u32 num_out_buffers; + u32 num_inout_buffers; + u32 num_in_pointers; + u32 num_out_pointers; + u32 num_out_fixed_pointers; + u32 num_objects; + u32 num_handles; + u32 send_pid; +} CmifRequestFormat; + +typedef struct CmifRequest { + HipcRequest hipc; + void* data; + u16* out_pointer_sizes; + u32* objects; + u32 server_pointer_size; + u32 cur_in_ptr_id; +} CmifRequest; + +typedef struct CmifResponse { + void* data; + u32* objects; + Handle* copy_handles; + Handle* move_handles; +} CmifResponse; + +NX_CONSTEXPR void* cmifGetAlignedDataStart(u32* data_words, void* base) +{ + intptr_t data_start = ((u8*)data_words - (u8*)base + 15) &~ 15; + return (u8*)base + data_start; +} + +NX_CONSTEXPR CmifRequest cmifMakeRequest(void* base, CmifRequestFormat fmt) +{ + // First of all, we need to figure out what size we need. + u32 actual_size = 16; + if (fmt.object_id) + actual_size += sizeof(CmifDomainInHeader) + fmt.num_objects*sizeof(u32); + actual_size += sizeof(CmifInHeader) + fmt.data_size; + actual_size = (actual_size + 1) &~ 1; // hword-align + u32 out_pointer_size_table_offset = actual_size; + u32 out_pointer_size_table_size = fmt.num_out_auto_buffers + fmt.num_out_pointers; + actual_size += sizeof(u16)*out_pointer_size_table_size; + u32 num_data_words = (actual_size + 3) / 4; + + CmifRequest req = {}; + req.hipc = hipcMakeRequestInline(base, + .type = fmt.context ? CmifCommandType_RequestWithContext : CmifCommandType_Request, + .num_send_statics = fmt.num_in_auto_buffers + fmt.num_in_pointers, + .num_send_buffers = fmt.num_in_auto_buffers + fmt.num_in_buffers, + .num_recv_buffers = fmt.num_out_auto_buffers + fmt.num_out_buffers, + .num_exch_buffers = fmt.num_inout_buffers, + .num_data_words = num_data_words, + .num_recv_statics = out_pointer_size_table_size + fmt.num_out_fixed_pointers, + .send_pid = fmt.send_pid, + .num_copy_handles = fmt.num_handles, + .num_move_handles = 0, + ); + + CmifInHeader* hdr = NULL; + void* start = cmifGetAlignedDataStart(req.hipc.data_words, base); + if (fmt.object_id) { + CmifDomainInHeader* domain_hdr = (CmifDomainInHeader*)start; + u32 payload_size = sizeof(CmifInHeader) + fmt.data_size; + *domain_hdr = (CmifDomainInHeader){ + .type = CmifDomainRequestType_SendMessage, + .num_in_objects = (u8)fmt.num_objects, + .data_size = (u16)payload_size, + .object_id = fmt.object_id, + .padding = 0, + .token = fmt.context, + }; + hdr = (CmifInHeader*)(domain_hdr+1); + req.objects = (u32*)((u8*)hdr + payload_size); + } else + hdr = (CmifInHeader*)start; + + *hdr = (CmifInHeader){ + .magic = CMIF_IN_HEADER_MAGIC, + .version = fmt.context ? 1U : 0U, + .command_id = fmt.request_id, + .token = fmt.object_id ? 0U : fmt.context, + }; + + req.data = hdr+1; + req.out_pointer_sizes = (u16*)(void*)((u8*)(void*)req.hipc.data_words + out_pointer_size_table_offset); + req.server_pointer_size = fmt.server_pointer_size; + + return req; +} + +NX_CONSTEXPR void* cmifMakeControlRequest(void* base, u32 request_id, u32 size) +{ + u32 actual_size = 16 + sizeof(CmifInHeader) + size; + HipcRequest hipc = hipcMakeRequestInline(base, + .type = CmifCommandType_Control, + .num_data_words = (actual_size + 3) / 4, + ); + CmifInHeader* hdr = (CmifInHeader*)cmifGetAlignedDataStart(hipc.data_words, base); + *hdr = (CmifInHeader){ + .magic = CMIF_IN_HEADER_MAGIC, + .version = 0, + .command_id = request_id, + .token = 0, + }; + return hdr+1; +} + +NX_CONSTEXPR void cmifMakeCloseRequest(void* base, u32 object_id) +{ + if (object_id) { + HipcRequest hipc = hipcMakeRequestInline(base, + .type = CmifCommandType_Request, + .num_data_words = (16 + sizeof(CmifDomainInHeader)) / 4, + ); + CmifDomainInHeader* domain_hdr = (CmifDomainInHeader*)cmifGetAlignedDataStart(hipc.data_words, base); + *domain_hdr = (CmifDomainInHeader){ + .type = CmifDomainRequestType_Close, + .object_id = object_id, + }; + } else { + hipcMakeRequestInline(base, + .type = CmifCommandType_Close, + ); + } +} + +NX_CONSTEXPR void cmifRequestInBuffer(CmifRequest* req, const void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.send_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestOutBuffer(CmifRequest* req, void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.recv_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestInOutBuffer(CmifRequest* req, void* buffer, size_t size, HipcBufferMode mode) +{ + *req->hipc.exch_buffers++ = hipcMakeBuffer(buffer, size, mode); +} + +NX_CONSTEXPR void cmifRequestInPointer(CmifRequest* req, const void* buffer, size_t size) +{ + *req->hipc.send_statics++ = hipcMakeSendStatic(buffer, size, req->cur_in_ptr_id++); + req->server_pointer_size -= size; +} + +NX_CONSTEXPR void cmifRequestOutFixedPointer(CmifRequest* req, void* buffer, size_t size) +{ + *req->hipc.recv_list++ = hipcMakeRecvStatic(buffer, size); + req->server_pointer_size -= size; +} + +NX_CONSTEXPR void cmifRequestOutPointer(CmifRequest* req, void* buffer, size_t size) +{ + cmifRequestOutFixedPointer(req, buffer, size); + *req->out_pointer_sizes++ = size; +} + +NX_CONSTEXPR void cmifRequestInAutoBuffer(CmifRequest* req, const void* buffer, size_t size) +{ + if (req->server_pointer_size && size <= req->server_pointer_size) { + cmifRequestInPointer(req, buffer, size); + cmifRequestInBuffer(req, NULL, 0, HipcBufferMode_Normal); + } else { + cmifRequestInPointer(req, NULL, 0); + cmifRequestInBuffer(req, buffer, size, HipcBufferMode_Normal); + } +} + +NX_CONSTEXPR void cmifRequestOutAutoBuffer(CmifRequest* req, void* buffer, size_t size) +{ + if (req->server_pointer_size && size <= req->server_pointer_size) { + cmifRequestOutPointer(req, buffer, size); + cmifRequestOutBuffer(req, NULL, 0, HipcBufferMode_Normal); + } else { + cmifRequestOutPointer(req, NULL, 0); + cmifRequestOutBuffer(req, buffer, size, HipcBufferMode_Normal); + } +} + +NX_CONSTEXPR void cmifRequestObject(CmifRequest* req, u32 object_id) +{ + *req->objects++ = object_id; +} + +NX_CONSTEXPR void cmifRequestHandle(CmifRequest* req, Handle handle) +{ + *req->hipc.copy_handles++ = handle; +} + +NX_CONSTEXPR Result cmifParseResponse(CmifResponse* res, void* base, bool is_domain, u32 size) +{ + HipcResponse hipc = hipcParseResponse(base); + void* start = cmifGetAlignedDataStart(hipc.data_words, base); + + CmifOutHeader* hdr = NULL; + u32* objects = NULL; + if (is_domain) { + CmifDomainOutHeader* domain_hdr = (CmifDomainOutHeader*)start; + hdr = (CmifOutHeader*)(domain_hdr+1); + objects = (u32*)((u8*)hdr + sizeof(CmifOutHeader) + size); + } + else + hdr = (CmifOutHeader*)start; + + if (hdr->magic != CMIF_OUT_HEADER_MAGIC) + return MAKERESULT(Module_Libnx, LibnxError_InvalidCmifOutHeader); + if (R_FAILED(hdr->result)) + return hdr->result; + + *res = (CmifResponse){ + .data = hdr+1, + .objects = objects, + .copy_handles = hipc.copy_handles, + .move_handles = hipc.move_handles, + }; + + return 0; +} + +NX_CONSTEXPR u32 cmifResponseGetObject(CmifResponse* res) +{ + return *res->objects++; +} + +NX_CONSTEXPR Handle cmifResponseGetCopyHandle(CmifResponse* res) +{ + return *res->copy_handles++; +} + +NX_CONSTEXPR Handle cmifResponseGetMoveHandle(CmifResponse* res) +{ + return *res->move_handles++; +} + +NX_INLINE Result cmifConvertCurrentObjectToDomain(Handle h, u32* out_object_id) +{ + cmifMakeControlRequest(armGetTls(), 0, 0); + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, sizeof(u32)); + if (R_SUCCEEDED(rc) && out_object_id) + *out_object_id = *(u32*)resp.data; + } + return rc; +} + +NX_INLINE Result cmifCopyFromCurrentDomain(Handle h, u32 object_id, Handle* out_h) +{ + void* raw = cmifMakeControlRequest(armGetTls(), 1, sizeof(u32)); + *(u32*)raw = object_id; + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, 0); + if (R_SUCCEEDED(rc) && out_h) + *out_h = resp.move_handles[0]; + } + return rc; +} + +NX_INLINE Result cmifCloneCurrentObject(Handle h, Handle* out_h) +{ + cmifMakeControlRequest(armGetTls(), 2, 0); + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, 0); + if (R_SUCCEEDED(rc) && out_h) + *out_h = resp.move_handles[0]; + } + return rc; +} + +NX_INLINE Result cmifQueryPointerBufferSize(Handle h, u16* out_size) +{ + cmifMakeControlRequest(armGetTls(), 3, 0); + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, sizeof(u16)); + if (R_SUCCEEDED(rc) && out_size) + *out_size = *(u16*)resp.data; + } + return rc; +} + +NX_INLINE Result cmifCloneCurrentObjectEx(Handle h, u32 tag, Handle* out_h) +{ + void* raw = cmifMakeControlRequest(armGetTls(), 4, sizeof(u32)); + *(u32*)raw = tag; + Result rc = svcSendSyncRequest(h); + if (R_SUCCEEDED(rc)) { + CmifResponse resp = {}; + rc = cmifParseResponse(&resp, armGetTls(), false, 0); + if (R_SUCCEEDED(rc) && out_h) + *out_h = resp.move_handles[0]; + } + return rc; +} diff --git a/nx/include/switch/sf/hipc.h b/nx/include/switch/sf/hipc.h new file mode 100644 index 00000000..e3836007 --- /dev/null +++ b/nx/include/switch/sf/hipc.h @@ -0,0 +1,363 @@ +/** + * @file hipc.h + * @brief Horizon Inter-Process Communication protocol + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "../result.h" +#include "../arm/tls.h" +#include "../kernel/svc.h" + +#define HIPC_AUTO_RECV_STATIC UINT8_MAX +#define HIPC_RESPONSE_NO_PID UINT32_MAX + +typedef struct HipcMetadata { + u32 type; + u32 num_send_statics; + u32 num_send_buffers; + u32 num_recv_buffers; + u32 num_exch_buffers; + u32 num_data_words; + u32 num_recv_statics; // also accepts HIPC_AUTO_RECV_STATIC + u32 send_pid; + u32 num_copy_handles; + u32 num_move_handles; +} HipcMetadata; + +typedef struct HipcHeader { + u32 type : 16; + u32 num_send_statics : 4; + u32 num_send_buffers : 4; + u32 num_recv_buffers : 4; + u32 num_exch_buffers : 4; + u32 num_data_words : 10; + u32 recv_static_mode : 4; + u32 padding : 6; + u32 recv_list_offset : 11; // Unused. + u32 has_special_header : 1; +} HipcHeader; + +typedef struct HipcSpecialHeader { + u32 send_pid : 1; + u32 num_copy_handles : 4; + u32 num_move_handles : 4; + u32 padding : 23; +} HipcSpecialHeader; + +typedef struct HipcStaticDescriptor { + u32 index : 6; + u32 address_high : 6; + u32 address_mid : 4; + u32 size : 16; + u32 address_low; +} HipcStaticDescriptor; + +typedef struct HipcBufferDescriptor { + u32 size_low; + u32 address_low; + u32 mode : 2; + u32 address_high : 22; + u32 size_high : 4; + u32 address_mid : 4; +} HipcBufferDescriptor; + +typedef struct HipcRecvListEntry { + u32 address_low; + u32 address_high : 16; + u32 size : 16; +} HipcRecvListEntry; + +typedef struct HipcRequest { + HipcStaticDescriptor* send_statics; + HipcBufferDescriptor* send_buffers; + HipcBufferDescriptor* recv_buffers; + HipcBufferDescriptor* exch_buffers; + u32* data_words; + HipcRecvListEntry* recv_list; + Handle* copy_handles; + Handle* move_handles; +} HipcRequest; + +typedef struct HipcParsedRequest { + HipcMetadata meta; + HipcRequest data; + u64 pid; +} HipcParsedRequest; + +typedef struct HipcResponse { + u64 pid; + u32 num_statics; + u32 num_data_words; + u32 num_copy_handles; + u32 num_move_handles; + HipcStaticDescriptor* statics; + u32* data_words; + Handle* copy_handles; + Handle* move_handles; +} HipcResponse; + +typedef enum HipcBufferMode { + HipcBufferMode_Normal = 0, + HipcBufferMode_NonSecure = 1, + HipcBufferMode_Invalid = 2, + HipcBufferMode_NonDevice = 3, +} HipcBufferMode; + +NX_CONSTEXPR HipcStaticDescriptor hipcMakeSendStatic(const void* buffer, size_t size, u8 index) +{ + return (HipcStaticDescriptor){ + .index = index, + .address_high = (u32)((uintptr_t)buffer >> 36), + .address_mid = (u32)((uintptr_t)buffer >> 32), + .size = (u32)size, + .address_low = (u32)(uintptr_t)buffer, + }; +} + +NX_CONSTEXPR HipcBufferDescriptor hipcMakeBuffer(const void* buffer, size_t size, HipcBufferMode mode) +{ + return (HipcBufferDescriptor){ + .size_low = (u32)size, + .address_low = (u32)(uintptr_t)buffer, + .mode = mode, + .address_high = (u32)((uintptr_t)buffer >> 36), + .size_high = (u32)(size >> 32), + .address_mid = (u32)((uintptr_t)buffer >> 32), + }; +} + +NX_CONSTEXPR HipcRecvListEntry hipcMakeRecvStatic(void* buffer, size_t size) +{ + return (HipcRecvListEntry){ + .address_low = (u32)((uintptr_t)buffer), + .address_high = (u32)((uintptr_t)buffer >> 32), + .size = (u32)size, + }; +} + +NX_CONSTEXPR void* hipcGetStaticAddress(const HipcStaticDescriptor* desc) +{ + return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36)); +} + +NX_CONSTEXPR size_t hipcGetStaticSize(const HipcStaticDescriptor* desc) +{ + return desc->size; +} + +NX_CONSTEXPR void* hipcGetBufferAddress(const HipcBufferDescriptor* desc) +{ + return (void*)(desc->address_low | ((uintptr_t)desc->address_mid << 32) | ((uintptr_t)desc->address_high << 36)); +} + +NX_CONSTEXPR size_t hipcGetBufferSize(const HipcBufferDescriptor* desc) +{ + return desc->size_low | ((size_t)desc->size_high << 32); +} + +NX_CONSTEXPR HipcRequest hipcCalcRequestLayout(HipcMetadata meta, void* base) +{ + // Copy handles + Handle* copy_handles = NULL; + if (meta.num_copy_handles) { + copy_handles = (Handle*)base; + base = copy_handles + meta.num_copy_handles; + } + + // Move handles + Handle* move_handles = NULL; + if (meta.num_move_handles) { + move_handles = (Handle*)base; + base = move_handles + meta.num_move_handles; + } + + // Send statics + HipcStaticDescriptor* send_statics = NULL; + if (meta.num_send_statics) { + send_statics = (HipcStaticDescriptor*)base; + base = send_statics + meta.num_send_statics; + } + + // Send buffers + HipcBufferDescriptor* send_buffers = NULL; + if (meta.num_send_buffers) { + send_buffers = (HipcBufferDescriptor*)base; + base = send_buffers + meta.num_send_buffers; + } + + // Recv buffers + HipcBufferDescriptor* recv_buffers = NULL; + if (meta.num_recv_buffers) { + recv_buffers = (HipcBufferDescriptor*)base; + base = recv_buffers + meta.num_recv_buffers; + } + + // Exch buffers + HipcBufferDescriptor* exch_buffers = NULL; + if (meta.num_exch_buffers) { + exch_buffers = (HipcBufferDescriptor*)base; + base = exch_buffers + meta.num_exch_buffers; + } + + // Data words + u32* data_words = NULL; + if (meta.num_data_words) { + data_words = (u32*)base; + base = data_words + meta.num_data_words; + } + + // Recv list + HipcRecvListEntry* recv_list = NULL; + if (meta.num_recv_statics) + recv_list = (HipcRecvListEntry*)base; + + return (HipcRequest){ + .send_statics = send_statics, + .send_buffers = send_buffers, + .recv_buffers = recv_buffers, + .exch_buffers = exch_buffers, + .data_words = data_words, + .recv_list = recv_list, + .copy_handles = copy_handles, + .move_handles = move_handles, + }; +} + +NX_CONSTEXPR HipcRequest hipcMakeRequest(void* base, HipcMetadata meta) +{ + // Write message header + bool has_special_header = meta.send_pid || meta.num_copy_handles || meta.num_move_handles; + HipcHeader* hdr = (HipcHeader*)base; + base = hdr+1; + *hdr = (HipcHeader){ + .type = meta.type, + .num_send_statics = meta.num_send_statics, + .num_send_buffers = meta.num_send_buffers, + .num_recv_buffers = meta.num_recv_buffers, + .num_exch_buffers = meta.num_exch_buffers, + .num_data_words = meta.num_data_words, + .recv_static_mode = meta.num_recv_statics ? (meta.num_recv_statics != HIPC_AUTO_RECV_STATIC ? 2u + meta.num_recv_statics : 2u) : 0u, + .padding = 0, + .recv_list_offset = 0, + .has_special_header = has_special_header, + }; + + // Write special header + if (has_special_header) { + HipcSpecialHeader* sphdr = (HipcSpecialHeader*)base; + base = sphdr+1; + *sphdr = (HipcSpecialHeader){ + .send_pid = meta.send_pid, + .num_copy_handles = meta.num_copy_handles, + .num_move_handles = meta.num_move_handles, + }; + if (meta.send_pid) + base = (u8*)base + sizeof(u64); + } + + // Calculate layout + return hipcCalcRequestLayout(meta, base); +} + +#define hipcMakeRequestInline(_base,...) hipcMakeRequest((_base),(HipcMetadata){ __VA_ARGS__ }) + +NX_CONSTEXPR HipcParsedRequest hipcParseRequest(void* base) +{ + // Parse message header + HipcHeader hdr = {}; + __builtin_memcpy(&hdr, base, sizeof(hdr)); + base = (u8*)base + sizeof(hdr); + u32 num_recv_statics = 0; + u64 pid = 0; + + // Parse recv static mode + if (hdr.recv_static_mode) { + if (hdr.recv_static_mode == 2u) + num_recv_statics = HIPC_AUTO_RECV_STATIC; + else if (hdr.recv_static_mode > 2u) + num_recv_statics = hdr.recv_static_mode - 2u; + } + + // Parse special header + HipcSpecialHeader sphdr = {}; + if (hdr.has_special_header) { + __builtin_memcpy(&sphdr, base, sizeof(sphdr)); + base = (u8*)base + sizeof(sphdr); + + // Read PID descriptor + if (sphdr.send_pid) { + pid = *(u64*)base; + base = (u8*)base + sizeof(u64); + } + } + + const HipcMetadata meta = { + .type = hdr.type, + .num_send_statics = hdr.num_send_statics, + .num_send_buffers = hdr.num_send_buffers, + .num_recv_buffers = hdr.num_recv_buffers, + .num_exch_buffers = hdr.num_exch_buffers, + .num_data_words = hdr.num_data_words, + .num_recv_statics = num_recv_statics, + .send_pid = sphdr.send_pid, + .num_copy_handles = sphdr.num_copy_handles, + .num_move_handles = sphdr.num_move_handles, + }; + + return (HipcParsedRequest){ + .meta = meta, + .data = hipcCalcRequestLayout(meta, base), + .pid = pid, + }; +} + +NX_CONSTEXPR HipcResponse hipcParseResponse(void* base) +{ + // Parse header + HipcHeader hdr = {}; + __builtin_memcpy(&hdr, base, sizeof(hdr)); + base = (u8*)base + sizeof(hdr); + + // Initialize response + HipcResponse response = {}; + response.num_statics = hdr.num_send_statics; + response.num_data_words = hdr.num_data_words; + response.pid = HIPC_RESPONSE_NO_PID; + + // Parse special header + if (hdr.has_special_header) + { + HipcSpecialHeader sphdr = {}; + __builtin_memcpy(&sphdr, base, sizeof(sphdr)); + base = (u8*)base + sizeof(sphdr); + + // Update response + response.num_copy_handles = sphdr.num_copy_handles; + response.num_move_handles = sphdr.num_move_handles; + + // Parse PID descriptor + if (sphdr.send_pid) { + response.pid = *(u64*)base; + base = (u8*)base + sizeof(u64); + } + } + + // Copy handles + response.copy_handles = (Handle*)base; + base = response.copy_handles + response.num_copy_handles; + + // Move handles + response.move_handles = (Handle*)base; + base = response.move_handles + response.num_move_handles; + + // Send statics + response.statics = (HipcStaticDescriptor*)base; + base = response.statics + response.num_statics; + + // Data words + response.data_words = (u32*)base; + + return response; +} diff --git a/nx/include/switch/sf/service.h b/nx/include/switch/sf/service.h new file mode 100644 index 00000000..55e268e8 --- /dev/null +++ b/nx/include/switch/sf/service.h @@ -0,0 +1,459 @@ +/** + * @file service.h + * @brief Service wrapper object + * @author fincs + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include "hipc.h" +#include "cmif.h" + +/// Service object structure +typedef struct Service { + Handle session; + u32 own_handle; + u32 object_id; + u16 pointer_buffer_size; +} Service; + +enum { + SfBufferAttr_In = BIT(0), + SfBufferAttr_Out = BIT(1), + SfBufferAttr_HipcMapAlias = BIT(2), + SfBufferAttr_HipcPointer = BIT(3), + SfBufferAttr_FixedSize = BIT(4), + SfBufferAttr_HipcAutoSelect = BIT(5), + SfBufferAttr_HipcMapTransferAllowsNonSecure = BIT(6), + SfBufferAttr_HipcMapTransferAllowsNonDevice = BIT(7), +}; + +typedef struct SfBufferAttrs { + u32 attr0; + u32 attr1; + u32 attr2; + u32 attr3; + u32 attr4; + u32 attr5; + u32 attr6; + u32 attr7; +} SfBufferAttrs; + +typedef struct SfBuffer { + const void* ptr; + size_t size; +} SfBuffer; + +typedef enum SfOutHandleAttr { + SfOutHandleAttr_None = 0, + SfOutHandleAttr_HipcCopy = 1, + SfOutHandleAttr_HipcMove = 2, +} SfOutHandleAttr; + +typedef struct SfOutHandleAttrs { + SfOutHandleAttr attr0; + SfOutHandleAttr attr1; + SfOutHandleAttr attr2; + SfOutHandleAttr attr3; + SfOutHandleAttr attr4; + SfOutHandleAttr attr5; + SfOutHandleAttr attr6; + SfOutHandleAttr attr7; +} SfOutHandleAttrs; + +typedef struct SfDispatchParams { + Handle target_session; + u32 context; + + SfBufferAttrs buffer_attrs; + SfBuffer buffers[8]; + + bool in_send_pid; + + u32 in_num_objects; + const Service* in_objects[8]; + + u32 in_num_handles; + Handle in_handles[8]; + + u32 out_num_objects; + Service* out_objects; + + SfOutHandleAttrs out_handle_attrs; + Handle* out_handles; +} SfDispatchParams; + +/** + * @brief Returns whether a service has been initialized. + * @param[in] s Service object. + * @return true if initialized. + */ +NX_CONSTEXPR bool serviceIsActive(Service* s) { + return s->session != INVALID_HANDLE; +} + +/** + * @brief Returns whether a service is overriden in the homebrew environment. + * @param[in] s Service object. + * @return true if overriden. + */ +NX_CONSTEXPR bool serviceIsOverride(Service* s) { + return serviceIsActive(s) && !s->own_handle && !s->object_id; +} + +/** + * @brief Returns whether a service is a domain. + * @param[in] s Service object. + * @return true if a domain. + */ +NX_CONSTEXPR bool serviceIsDomain(Service* s) { + return serviceIsActive(s) && s->own_handle && s->object_id; +} + +/** + * @brief Returns whether a service is a domain subservice. + * @param[in] s Service object. + * @return true if a domain subservice. + */ +NX_CONSTEXPR bool serviceIsDomainSubservice(Service* s) { + return serviceIsActive(s) && !s->own_handle && s->object_id; +} + +/** + * @brief For a domain/domain subservice, return the associated object ID. + * @param[in] s Service object, necessarily a domain or domain subservice. + * @return The object ID. + */ +NX_CONSTEXPR u32 serviceGetObjectId(Service* s) { + return s->object_id; +} + +/** + * @brief Creates a service object from an IPC session handle. + * @param[out] s Service object. + * @param[in] h IPC session handle. + */ +NX_INLINE void serviceCreate(Service* s, Handle h) +{ + s->session = h; + s->own_handle = 1; + s->object_id = 0; + s->pointer_buffer_size = 0; + cmifQueryPointerBufferSize(h, &s->pointer_buffer_size); +} + +/** + * @brief Creates a domain subservice object from a parent service. + * @param[out] s Service object. + * @param[in] parent Parent service, necessarily a domain or domain subservice. + * @param[in] object_id Object ID for this subservice. + */ +NX_CONSTEXPR void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) +{ + s->session = parent->session; + s->own_handle = 0; + s->object_id = object_id; + s->pointer_buffer_size = parent->pointer_buffer_size; +} + +/** + * @brief Hints the compiler that a service will always contain a domain object. + * @param[in] _s Service object. + */ +#define serviceAssumeDomain(_s) do { \ + if (!(_s)->object_id) \ + __builtin_unreachable(); \ +} while(0) + +/** + * @brief Closes a service. + * @param[in] s Service object. + */ +NX_INLINE void serviceClose(Service* s) +{ +#if defined(NX_SERVICE_ASSUME_NON_DOMAIN) + if (s->object_id) + __builtin_unreachable(); +#endif + + if (s->own_handle || s->object_id) { + cmifMakeCloseRequest(armGetTls(), s->own_handle ? 0 : s->object_id); + svcSendSyncRequest(s->session); + if (s->own_handle) + svcCloseHandle(s->session); + } + *s = (Service){}; +} + +/** + * @brief Clones a service. + * @param[in] s Service object. + * @param[out] out_s Output service object. + */ +NX_INLINE Result serviceClone(Service* s, Service* out_s) +{ +#if defined(NX_SERVICE_ASSUME_NON_DOMAIN) + if (s->object_id) + __builtin_unreachable(); +#endif + + out_s->session = 0; + out_s->own_handle = 1; + out_s->object_id = s->object_id; + out_s->pointer_buffer_size = s->pointer_buffer_size; + return cmifCloneCurrentObject(s->session, &out_s->session); +} + +/** + * @brief Clones a service with a session manager tag. + * @param[in] s Service object. + * @param[in] tag Session manager tag (unused in current official server code) + * @param[out] out_s Output service object. + */ +NX_INLINE Result serviceCloneEx(Service* s, u32 tag, Service* out_s) +{ +#if defined(NX_SERVICE_ASSUME_NON_DOMAIN) + if (s->object_id) + __builtin_unreachable(); +#endif + + out_s->session = 0; + out_s->own_handle = 1; + out_s->object_id = s->object_id; + out_s->pointer_buffer_size = s->pointer_buffer_size; + return cmifCloneCurrentObjectEx(s->session, tag, &out_s->session); +} + +/** + * @brief Converts a regular service to a domain. + * @param[in] s Service object. + * @return Result code. + */ +NX_INLINE Result serviceConvertToDomain(Service* s) +{ + if (!s->own_handle) { + // For overridden services, create a clone first. + Result rc = cmifCloneCurrentObjectEx(s->session, 0, &s->session); + if (R_FAILED(rc)) + return rc; + s->own_handle = 1; + } + + return cmifConvertCurrentObjectToDomain(s->session, &s->object_id); +} + +NX_CONSTEXPR void _serviceRequestFormatProcessBuffer(CmifRequestFormat* fmt, u32 attr) +{ + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In) != 0; + const bool is_out = (attr & SfBufferAttr_Out) != 0; + + if (attr & SfBufferAttr_HipcAutoSelect) { + if (is_in) + fmt->num_in_auto_buffers ++; + if (is_out) + fmt->num_out_auto_buffers ++; + } else if (attr & SfBufferAttr_HipcPointer) { + if (is_in) + fmt->num_in_pointers ++; + if (is_out) { + if (attr & SfBufferAttr_FixedSize) + fmt->num_out_fixed_pointers ++; + else + fmt->num_out_pointers ++; + } + } else if (attr & SfBufferAttr_HipcMapAlias) { + if (is_in && is_out) + fmt->num_inout_buffers ++; + else if (is_in) + fmt->num_in_buffers ++; + else if (is_out) + fmt->num_out_buffers ++; + } +} + +NX_CONSTEXPR void _serviceRequestProcessBuffer(CmifRequest* req, const SfBuffer* buf, u32 attr) +{ + if (!attr) return; + const bool is_in = (attr & SfBufferAttr_In); + const bool is_out = (attr & SfBufferAttr_Out); + + if (attr & SfBufferAttr_HipcAutoSelect) { + if (is_in) + cmifRequestInAutoBuffer(req, buf->ptr, buf->size); + if (is_out) + cmifRequestOutAutoBuffer(req, (void*)buf->ptr, buf->size); + } else if (attr & SfBufferAttr_HipcPointer) { + if (is_in) + cmifRequestInPointer(req, buf->ptr, buf->size); + if (is_out) { + if (attr & SfBufferAttr_FixedSize) + cmifRequestOutFixedPointer(req, (void*)buf->ptr, buf->size); + else + cmifRequestOutPointer(req, (void*)buf->ptr, buf->size); + } + } else if (attr & SfBufferAttr_HipcMapAlias) { + HipcBufferMode mode = HipcBufferMode_Normal; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonSecure) + mode = HipcBufferMode_NonSecure; + if (attr & SfBufferAttr_HipcMapTransferAllowsNonDevice) + mode = HipcBufferMode_NonDevice; + + if (is_in && is_out) + cmifRequestInOutBuffer(req, (void*)buf->ptr, buf->size, mode); + else if (is_in) + cmifRequestInBuffer(req, buf->ptr, buf->size, mode); + else if (is_out) + cmifRequestOutBuffer(req, (void*)buf->ptr, buf->size, mode); + } +} + +NX_INLINE void* serviceMakeRequest( + Service* s, u32 request_id, u32 context, u32 data_size, bool send_pid, + const SfBufferAttrs buffer_attrs, const SfBuffer* buffers, + u32 num_objects, const Service* const* objects, + u32 num_handles, const Handle* handles +) { +#if defined(NX_SERVICE_ASSUME_NON_DOMAIN) + if (s->object_id) + __builtin_unreachable(); +#endif + + CmifRequestFormat fmt = {}; + fmt.object_id = s->object_id; + fmt.request_id = request_id; + fmt.context = context; + fmt.data_size = data_size; + fmt.server_pointer_size = s->pointer_buffer_size; + fmt.num_objects = num_objects; + fmt.num_handles = num_handles; + fmt.send_pid = send_pid; + + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr0); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr1); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr2); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr3); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr4); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr5); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr6); + _serviceRequestFormatProcessBuffer(&fmt, buffer_attrs.attr7); + + CmifRequest req = cmifMakeRequest(armGetTls(), fmt); + + if (s->object_id) // TODO: Check behavior of input objects in non-domain sessions + for (u32 i = 0; i < num_objects; i ++) + cmifRequestObject(&req, objects[i]->object_id); + + for (u32 i = 0; i < num_handles; i ++) + cmifRequestHandle(&req, handles[i]); + + _serviceRequestProcessBuffer(&req, &buffers[0], buffer_attrs.attr0); + _serviceRequestProcessBuffer(&req, &buffers[1], buffer_attrs.attr1); + _serviceRequestProcessBuffer(&req, &buffers[2], buffer_attrs.attr2); + _serviceRequestProcessBuffer(&req, &buffers[3], buffer_attrs.attr3); + _serviceRequestProcessBuffer(&req, &buffers[4], buffer_attrs.attr4); + _serviceRequestProcessBuffer(&req, &buffers[5], buffer_attrs.attr5); + _serviceRequestProcessBuffer(&req, &buffers[6], buffer_attrs.attr6); + _serviceRequestProcessBuffer(&req, &buffers[7], buffer_attrs.attr7); + + return req.data; +} + +NX_CONSTEXPR void _serviceResponseGetHandle(CmifResponse* res, SfOutHandleAttr type, Handle* out) +{ + switch (type) { + default: + case SfOutHandleAttr_None: + break; + case SfOutHandleAttr_HipcCopy: + *out = cmifResponseGetCopyHandle(res); + break; + case SfOutHandleAttr_HipcMove: + *out = cmifResponseGetMoveHandle(res); + break; + } +} + +NX_INLINE Result serviceParseResponse( + Service* s, u32 out_size, void** out_data, + u32 num_out_objects, Service* out_objects, + const SfOutHandleAttrs out_handle_attrs, Handle* out_handles +) { +#if defined(NX_SERVICE_ASSUME_NON_DOMAIN) + if (s->object_id) + __builtin_unreachable(); +#endif + + CmifResponse res = {}; + bool is_domain = s->object_id != 0; + Result rc = cmifParseResponse(&res, armGetTls(), is_domain, out_size); + if (R_FAILED(rc)) + return rc; + + if (out_size) + *out_data = res.data; + + for (u32 i = 0; i < num_out_objects; i ++) { + if (is_domain) + serviceCreateDomainSubservice(&out_objects[i], s, cmifResponseGetObject(&res)); + else // Output objects are marshalled as move handles at the beginning of the list. + serviceCreate(&out_objects[i], cmifResponseGetMoveHandle(&res)); + } + + _serviceResponseGetHandle(&res, out_handle_attrs.attr0, &out_handles[0]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr1, &out_handles[1]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr2, &out_handles[2]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr3, &out_handles[3]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr4, &out_handles[4]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr5, &out_handles[5]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr6, &out_handles[6]); + _serviceResponseGetHandle(&res, out_handle_attrs.attr7, &out_handles[7]); + + return 0; +} + +NX_INLINE Result serviceDispatchImpl( + Service* s, u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + SfDispatchParams disp +) +{ + // Make a copy of the service struct, so that the compiler can assume that it won't be modified by function calls. + Service srv = *s; + + void* in = serviceMakeRequest(&srv, request_id, disp.context, + in_data_size, disp.in_send_pid, + disp.buffer_attrs, disp.buffers, + disp.in_num_objects, disp.in_objects, + disp.in_num_handles, disp.in_handles); + + if (in_data_size) + __builtin_memcpy(in, in_data, in_data_size); + + Result rc = svcSendSyncRequest(disp.target_session == INVALID_HANDLE ? s->session : disp.target_session); + if (R_SUCCEEDED(rc)) { + void* out = NULL; + rc = serviceParseResponse(&srv, + out_data_size, &out, + disp.out_num_objects, disp.out_objects, + disp.out_handle_attrs, disp.out_handles); + + if (R_SUCCEEDED(rc) && out_data && out_data_size) + __builtin_memcpy(out_data, out, out_data_size); + } + + return rc; +} + +#define serviceDispatch(_s,_rid,...) \ + serviceDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchIn(_s,_rid,_in,...) \ + serviceDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchOut(_s,_rid,_out,...) \ + serviceDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +#define serviceDispatchInOut(_s,_rid,_in,_out,...) \ + serviceDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) diff --git a/nx/include/switch/types.h b/nx/include/switch/types.h index 5de2188f..d28e9b9e 100644 --- a/nx/include/switch/types.h +++ b/nx/include/switch/types.h @@ -77,5 +77,15 @@ typedef void (*VoidFn)(void); ///< Function without arguments nor return v #endif #endif +/// Flags a function as (always) inline. +#define NX_INLINE __attribute__((always_inline)) static inline + +/// Flags a function as constexpr in C++14 and above; or as (always) inline otherwise. +#if __cplusplus >= 201402L +#define NX_CONSTEXPR NX_INLINE constexpr +#else +#define NX_CONSTEXPR NX_INLINE +#endif + /// Invalid handle. #define INVALID_HANDLE ((Handle) 0) diff --git a/nx/source/applets/album_la.c b/nx/source/applets/album_la.c new file mode 100644 index 00000000..64fef72d --- /dev/null +++ b/nx/source/applets/album_la.c @@ -0,0 +1,31 @@ +#include +#include "types.h" +#include "result.h" +#include "services/applet.h" +#include "applets/libapplet.h" +#include "applets/album_la.h" + +static Result _albumLaShow(u8 arg, bool playStartupSound) { + Result rc=0; + LibAppletArgs commonargs; + + libappletArgsCreate(&commonargs, 0x10000); + libappletArgsSetPlayStartupSound(&commonargs, playStartupSound); + + rc = libappletLaunch(AppletId_photoViewer, &commonargs, &arg, sizeof(arg), NULL, 0, NULL); + + return rc; +} + +Result albumLaShowAlbumFiles(void) { + return _albumLaShow(AlbumLaArg_ShowAlbumFiles, false); +} + +Result albumLaShowAllAlbumFiles(void) { + return _albumLaShow(AlbumLaArg_ShowAllAlbumFiles, false); +} + +Result albumLaShowAllAlbumFilesForHomeMenu(void) { + return _albumLaShow(AlbumLaArg_ShowAllAlbumFilesForHomeMenu, true); +} + diff --git a/nx/source/applets/error.c b/nx/source/applets/error.c index a5df8326..ac7bc7c9 100644 --- a/nx/source/applets/error.c +++ b/nx/source/applets/error.c @@ -214,7 +214,9 @@ Result errorSystemCreate(ErrorSystemConfig* c, const char* dialog_message, const if (hosversionBefore(5,0,0)) { rc = setInitialize(); - if (R_SUCCEEDED(rc)) rc = setMakeLanguageCode(SetLanguage_ENUS, &c->arg.languageCode); + u64 languageCode = 0; + if (R_SUCCEEDED(rc)) rc = setMakeLanguageCode(SetLanguage_ENUS, &languageCode); + if (R_SUCCEEDED(rc)) c->arg.languageCode = languageCode; setExit(); } @@ -247,7 +249,9 @@ Result errorApplicationCreate(ErrorApplicationConfig* c, const char* dialog_mess if (hosversionBefore(5,0,0)) { rc = setInitialize(); - if (R_SUCCEEDED(rc)) rc = setMakeLanguageCode(SetLanguage_ENUS, &c->arg.languageCode); + u64 languageCode = 0; + if (R_SUCCEEDED(rc)) rc = setMakeLanguageCode(SetLanguage_ENUS, &languageCode); + if (R_SUCCEEDED(rc)) c->arg.languageCode = languageCode; setExit(); } diff --git a/nx/source/applets/friends_la.c b/nx/source/applets/friends_la.c new file mode 100644 index 00000000..8158cef1 --- /dev/null +++ b/nx/source/applets/friends_la.c @@ -0,0 +1,76 @@ +#include +#include "types.h" +#include "result.h" +#include "services/acc.h" +#include "services/applet.h" +#include "applets/libapplet.h" +#include "applets/friends_la.h" + +static Result _friendsLaShow(const FriendsLaArg *arg, bool playStartupSound) { + Result rc=0; + Result rc2=0; + size_t readsize=0; + LibAppletArgs commonargs; + + libappletArgsCreate(&commonargs, 0x1); + libappletArgsSetPlayStartupSound(&commonargs, playStartupSound); + + if (arg->type != FriendsLaArgType_StartSendingFriendRequest) + rc = libappletLaunch(AppletId_myPage, &commonargs, arg, sizeof(*arg), NULL, 0, NULL); + else { + rc = libappletLaunch(AppletId_myPage, &commonargs, arg, sizeof(*arg), &rc2, sizeof(rc2), &readsize); + if (R_SUCCEEDED(rc) && readsize!=sizeof(rc2)) rc = MAKERESULT(Module_Libnx, LibnxError_BadInput); + if (R_SUCCEEDED(rc)) rc = rc2; + } + + return rc; +} + +static Result _friendsLaShowSimple(FriendsLaArgType type, AccountUid *userID, bool playStartupSound) { + FriendsLaArg arg = {.type = type, .userID = *userID}; + + return _friendsLaShow(&arg, playStartupSound); +} + +static Result _friendsLaShowAll(FriendsLaArgType type, AccountUid *userID, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName, bool playStartupSound) { + FriendsLaArg arg = {.type = type, .userID = *userID, .networkServiceAccountId = networkServiceAccountId, .first_inAppScreenName = *first_inAppScreenName, .second_inAppScreenName = *second_inAppScreenName}; + + return _friendsLaShow(&arg, playStartupSound); +} + +Result friendsLaShowFriendList(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowFriendList, userID, false); +} + +Result friendsLaShowUserDetailInfo(AccountUid *userID, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) { + return _friendsLaShowAll(FriendsLaArgType_ShowUserDetailInfo, userID, networkServiceAccountId, first_inAppScreenName, second_inAppScreenName, false); +} + +Result friendsLaStartSendingFriendRequest(AccountUid *userID, u64 networkServiceAccountId, const FriendsInAppScreenName *first_inAppScreenName, const FriendsInAppScreenName *second_inAppScreenName) { + return _friendsLaShowAll(FriendsLaArgType_StartSendingFriendRequest, userID, networkServiceAccountId, first_inAppScreenName, second_inAppScreenName, false); +} + +Result friendsLaShowMethodsOfSendingFriendRequest(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowMethodsOfSendingFriendRequest, userID, false); +} + +Result friendsLaStartFacedFriendRequest(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_StartFacedFriendRequest, userID, false); +} + +Result friendsLaShowReceivedFriendRequestList(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowReceivedFriendRequestList, userID, false); +} + +Result friendsLaShowBlockedUserList(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowBlockedUserList, userID, false); +} + +Result friendsLaShowMyProfile(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowMyProfile, userID, false); +} + +Result friendsLaShowMyProfileForHomeMenu(AccountUid *userID) { + return _friendsLaShowSimple(FriendsLaArgType_ShowMyProfile, userID, true); +} + diff --git a/nx/source/applets/web.c b/nx/source/applets/web.c index 50878008..e7126892 100644 --- a/nx/source/applets/web.c +++ b/nx/source/applets/web.c @@ -350,11 +350,12 @@ Result webOfflineCreate(WebCommonConfig* config, WebDocumentKind docKind, u64 ti Result webShareCreate(WebCommonConfig* config, WebShareStartPage page) { Result rc=0; + AccountUid uid={0}; _webArgInitialize(config, AppletId_loginShare, WebShimKind_Share); rc = webConfigSetLeftStickMode(config, WebLeftStickMode_Cursor); - if (R_SUCCEEDED(rc)) rc = webConfigSetUserID(config, 0); + if (R_SUCCEEDED(rc)) rc = webConfigSetUid(config, &uid); if (R_SUCCEEDED(rc)) rc = webConfigSetDisplayUrlKind(config, true); if (R_SUCCEEDED(rc)) rc = _webConfigSetU8(config, WebArgType_Unknown14, 1); @@ -368,6 +369,7 @@ Result webShareCreate(WebCommonConfig* config, WebShareStartPage page) { Result webLobbyCreate(WebCommonConfig* config) { Result rc=0; + AccountUid uid={0}; if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); _webArgInitialize(config, AppletId_loginShare, WebShimKind_Lobby); @@ -375,7 +377,7 @@ Result webLobbyCreate(WebCommonConfig* config) { rc = webConfigSetLeftStickMode(config, WebLeftStickMode_Cursor); if (R_SUCCEEDED(rc) && config->version >= 0x30000) rc = webConfigSetPointer(config, false); // Added to user-process init with [3.0.0+]. - if (R_SUCCEEDED(rc)) rc = webConfigSetUserID(config, 0); + if (R_SUCCEEDED(rc)) rc = webConfigSetUid(config, &uid); if (R_SUCCEEDED(rc)) rc = _webConfigSetU8(config, WebArgType_Unknown14, 1); if (R_SUCCEEDED(rc)) rc = _webConfigSetU8(config, WebArgType_Unknown15, 1); @@ -402,10 +404,10 @@ Result webConfigSetWhitelist(WebCommonConfig* config, const char* whitelist) { return _webConfigSetString(config, WebArgType_Whitelist, whitelist, 0x1000); } -Result webConfigSetUserID(WebCommonConfig* config, u128 userID) { +Result webConfigSetUid(WebCommonConfig* config, AccountUid *uid) { WebShimKind shim = _webGetShimKind(config); if (shim != WebShimKind_Share && shim != WebShimKind_Web && shim != WebShimKind_Lobby) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - return _webTLVSet(config, WebArgType_UserID, &userID, sizeof(userID)); + return _webTLVSet(config, WebArgType_Uid, uid, sizeof(*uid)); } static Result _webConfigSetAlbumEntryTLV(WebCommonConfig* config, WebArgType type, const CapsAlbumEntry *entry) { diff --git a/nx/source/display/binder.c b/nx/source/display/binder.c index 6d180dec..3d0ad528 100644 --- a/nx/source/display/binder.c +++ b/nx/source/display/binder.c @@ -5,11 +5,21 @@ #include "runtime/hosversion.h" #include "display/binder.h" +static void* _binderIpcPrepareHeader(Binder* b, IpcCommand* cmd, size_t sizeof_raw) +{ + return serviceIpcPrepareHeader(b->relay, cmd, sizeof_raw); +} + static Result _binderIpcDispatch(Binder* b) { return serviceIpcDispatch(b->relay); } +static Result _binderIpcParse(Binder* b, IpcParsedCommand* r, size_t sizeof_raw) +{ + return serviceIpcParse(b->relay, r, sizeof_raw); +} + void binderCreate(Binder* b, s32 id) { memset(b, 0, sizeof(Binder)); @@ -41,12 +51,6 @@ Result binderInitSession(Binder* b, Service* relay) b->initialized = true; - rc = ipcQueryPointerBufferSize(b->relay->handle, &b->ipc_buffer_size); - if (R_FAILED(rc)) { - binderClose(b); - return rc; - } - // Use TransactParcelAuto when available. if (hosversionAtLeast(3,0,0)) b->has_transact_auto = true; @@ -93,7 +97,7 @@ static Result _binderTransactParcel( ipcAddSendBuffer(&c, parcel_data, parcel_data_size, 0); ipcAddRecvBuffer(&c, parcel_reply, parcel_reply_size, 0); - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 0; raw->session_id = b->id; @@ -104,12 +108,13 @@ static Result _binderTransactParcel( if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; - } *resp = r.Raw; + } *resp; + + _binderIpcParse(b, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; } @@ -137,10 +142,10 @@ static Result _binderTransactParcelAuto( u32 flags; } PACKED *raw; - ipcAddSendSmart(&c, b->ipc_buffer_size, parcel_data, parcel_data_size, 0); - ipcAddRecvSmart(&c, b->ipc_buffer_size, parcel_reply, parcel_reply_size, 0); + ipcAddSendSmart(&c, b->relay->pointer_buffer_size, parcel_data, parcel_data_size, 0); + ipcAddRecvSmart(&c, b->relay->pointer_buffer_size, parcel_reply, parcel_reply_size, 0); - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 3; raw->session_id = b->id; @@ -151,12 +156,13 @@ static Result _binderTransactParcelAuto( if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; - } *resp = r.Raw; + } *resp; + + _binderIpcParse(b, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; } @@ -222,7 +228,7 @@ Result binderAdjustRefcount(Binder* b, s32 addval, s32 type) s32 type; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 1; raw->session_id = b->id; @@ -233,12 +239,13 @@ Result binderAdjustRefcount(Binder* b, s32 addval, s32 type) if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; - } *resp = r.Raw; + } *resp; + + _binderIpcParse(b, &r, sizeof(*resp)); + resp = r.Raw; rc = resp->result; } @@ -261,7 +268,7 @@ Result binderGetNativeHandle(Binder* b, u32 inval, Event *event_out) u32 inval; } *raw; - raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw = _binderIpcPrepareHeader(b, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 2; @@ -272,13 +279,14 @@ Result binderGetNativeHandle(Binder* b, u32 inval, Event *event_out) if (R_SUCCEEDED(rc)) { IpcParsedCommand r; - ipcParse(&r); - struct { u64 magic; u64 result; } *resp = r.Raw; + _binderIpcParse(b, &r, sizeof(*resp)); + resp = r.Raw; + rc = resp->result; if (R_SUCCEEDED(rc)) { diff --git a/nx/source/runtime/argv.c b/nx/source/runtime/argv.c index 6796621b..00c0346e 100644 --- a/nx/source/runtime/argv.c +++ b/nx/source/runtime/argv.c @@ -15,7 +15,7 @@ struct in_addr __nxlink_host; extern char* fake_heap_start; extern char* fake_heap_end; -extern u32 __argdata__; +extern u8 __argdata__[]; static char* g_argv_empty = NULL; @@ -27,7 +27,7 @@ void argvSetup(void) MemoryInfo meminfo; u32 pageinfo=0; - u8 *argdata = (u8*)&__argdata__; + u8 *argdata = __argdata__; u32 *arg32 = (u32*)argdata; u64 argdata_allocsize=0; u64 argdata_strsize=0; @@ -94,7 +94,7 @@ void argvSetup(void) argstart = NULL; for(argi=0; argi #include #include +#include #include "runtime/devices/fs_dev.h" #include "runtime/util/utf.h" #include "services/fs.h" +#include "services/time.h" /*! @internal @@ -256,6 +258,28 @@ static ssize_t fsdev_convertfromfspath(uint8_t *out, uint8_t *in, size_t len) return strnlen((char*)out, len); } +static time_t fsdev_converttimetoutc(u64 timestamp) +{ + // Parse timestamp into y/m/d h:m:s + time_t posixtime = (time_t)timestamp; + struct tm *t = gmtime(&posixtime); + + // Convert time/date into an actual UTC POSIX timestamp using the system's timezone rules + TimeCalendarTime caltime; + caltime.year = 1900 + t->tm_year; + caltime.month = 1 + t->tm_mon; + caltime.day = t->tm_mday; + caltime.hour = t->tm_hour; + caltime.minute = t->tm_min; + caltime.second = t->tm_sec; + u64 new_timestamp; + Result rc = timeToPosixTimeWithMyRule(&caltime, &new_timestamp, 1, NULL); + if (R_SUCCEEDED(rc)) + posixtime = (time_t)new_timestamp; + + return posixtime; +} + extern int __system_argc; extern char** __system_argv; @@ -381,7 +405,7 @@ Result fsdevSetArchiveBit(const char *path) { return fsFsSetArchiveBit(&device->fs, fs_path); } -Result fsdevCreateFile(const char* path, size_t size, int flags) { +Result fsdevCreateFile(const char* path, size_t size, u32 flags) { char fs_path[FS_MAX_PATH]; fsdev_fsdevice *device = NULL; @@ -555,7 +579,7 @@ fsdev_open(struct _reent *r, { /* read-only: do not allow O_APPEND */ case O_RDONLY: - fsdev_flags |= FS_OPEN_READ; + fsdev_flags |= FsOpenMode_Read; if(flags & O_APPEND) { r->_errno = EINVAL; @@ -565,12 +589,12 @@ fsdev_open(struct _reent *r, /* write-only */ case O_WRONLY: - fsdev_flags |= FS_OPEN_WRITE | FS_OPEN_APPEND; + fsdev_flags |= FsOpenMode_Write | FsOpenMode_Append; break; /* read and write */ case O_RDWR: - fsdev_flags |= (FS_OPEN_READ | FS_OPEN_WRITE | FS_OPEN_APPEND); + fsdev_flags |= (FsOpenMode_Read | FsOpenMode_Write | FsOpenMode_Append); break; /* an invalid option was supplied */ @@ -690,7 +714,7 @@ fsdev_write(struct _reent *r, } } - rc = fsFileWrite(&file->fd, file->offset, ptr, len, FS_WRITEOPTION_NONE); + rc = fsFileWrite(&file->fd, file->offset, ptr, len, FsWriteOption_None); if(rc == 0xD401) return fsdev_write_safe(r, fd, ptr, len); if(R_FAILED(rc)) @@ -744,7 +768,7 @@ fsdev_write_safe(struct _reent *r, memcpy(tmp_buffer, ptr, toWrite); /* write the data */ - rc = fsFileWrite(&file->fd, file->offset, tmp_buffer, toWrite, FS_WRITEOPTION_NONE); + rc = fsFileWrite(&file->fd, file->offset, tmp_buffer, toWrite, FsWriteOption_None); if(R_FAILED(rc)) { @@ -786,7 +810,7 @@ fsdev_read(struct _reent *r, size_t len) { Result rc; - size_t bytes; + u64 bytes; /* get pointer to our data */ fsdev_file_t *file = (fsdev_file_t*)fd; @@ -799,7 +823,7 @@ fsdev_read(struct _reent *r, } /* read the data */ - rc = fsFileRead(&file->fd, file->offset, ptr, len, FS_READOPTION_NONE, &bytes); + rc = fsFileRead(&file->fd, file->offset, ptr, len, FsReadOption_None, &bytes); if(rc == 0xD401) return fsdev_read_safe(r, fd, ptr, len); if(R_SUCCEEDED(rc)) @@ -830,7 +854,7 @@ fsdev_read_safe(struct _reent *r, size_t len) { Result rc; - size_t bytesRead = 0, bytes = 0; + u64 bytesRead = 0, bytes = 0; /* get pointer to our data */ fsdev_file_t *file = (fsdev_file_t*)fd; @@ -841,12 +865,12 @@ fsdev_read_safe(struct _reent *r, static __thread char tmp_buffer[8192]; while(len > 0) { - size_t toRead = len; + u64 toRead = len; if(toRead > sizeof(tmp_buffer)) toRead = sizeof(tmp_buffer); /* read the data */ - rc = fsFileRead(&file->fd, file->offset, tmp_buffer, toRead, FS_READOPTION_NONE, &bytes); + rc = fsFileRead(&file->fd, file->offset, tmp_buffer, toRead, FsReadOption_None, &bytes); if(bytes > toRead) bytes = toRead; @@ -965,9 +989,9 @@ fsdev_fstat(struct _reent *r, if(file->timestamps.is_valid) { - st->st_ctime = file->timestamps.created; - st->st_mtime = file->timestamps.modified; - st->st_atime = file->timestamps.accessed; + st->st_ctime = fsdev_converttimetoutc(file->timestamps.created); + st->st_mtime = fsdev_converttimetoutc(file->timestamps.modified); + st->st_atime = fsdev_converttimetoutc(file->timestamps.accessed); } return 0; @@ -998,7 +1022,7 @@ fsdev_stat(struct _reent *r, char fs_path[FS_MAX_PATH]; fsdev_fsdevice *device = NULL; FsTimeStampRaw timestamps = {0}; - FsEntryType type; + FsDirEntryType type; if(fsdev_getfspath(r, file, &device, fs_path)==-1) return -1; @@ -1006,9 +1030,9 @@ fsdev_stat(struct _reent *r, rc = fsFsGetEntryType(&device->fs, fs_path, &type); if(R_SUCCEEDED(rc)) { - if(type == ENTRYTYPE_DIR) + if(type == FsDirEntryType_Dir) { - if(R_SUCCEEDED(rc = fsFsOpenDirectory(&device->fs, fs_path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, &fdir))) + if(R_SUCCEEDED(rc = fsFsOpenDirectory(&device->fs, fs_path, FsDirOpenMode_ReadDirs | FsDirOpenMode_ReadFiles, &fdir))) { memset(st, 0, sizeof(struct stat)); st->st_nlink = 1; @@ -1017,9 +1041,9 @@ fsdev_stat(struct _reent *r, return 0; } } - else if(type == ENTRYTYPE_FILE) + else if(type == FsDirEntryType_File) { - if(R_SUCCEEDED(rc = fsFsOpenFile(&device->fs, fs_path, FS_OPEN_READ, &fd))) + if(R_SUCCEEDED(rc = fsFsOpenFile(&device->fs, fs_path, FsOpenMode_Read, &fd))) { fsdev_file_t tmpfd = { .fd = fd }; ret = fsdev_fstat(r, &tmpfd, st); @@ -1030,9 +1054,9 @@ fsdev_stat(struct _reent *r, rc = fsFsGetFileTimeStampRaw(&device->fs, fs_path, ×tamps); if(R_SUCCEEDED(rc) && timestamps.is_valid) { - st->st_ctime = timestamps.created; - st->st_mtime = timestamps.modified; - st->st_atime = timestamps.accessed; + st->st_ctime = fsdev_converttimetoutc(timestamps.created); + st->st_mtime = fsdev_converttimetoutc(timestamps.modified); + st->st_atime = fsdev_converttimetoutc(timestamps.accessed); } } @@ -1115,7 +1139,7 @@ fsdev_chdir(struct _reent *r, if(fsdev_getfspath(r, name, &device, fs_path)==-1) return -1; - rc = fsFsOpenDirectory(&device->fs, fs_path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, &fd); + rc = fsFsOpenDirectory(&device->fs, fs_path, FsDirOpenMode_ReadDirs | FsDirOpenMode_ReadFiles, &fd); if(R_SUCCEEDED(rc)) { fsDirClose(&fd); @@ -1153,7 +1177,7 @@ fsdev_rename(struct _reent *r, const char *newName) { Result rc; - FsEntryType type; + FsDirEntryType type; fsdev_fsdevice *device_old = NULL, *device_new = NULL; char fs_path_old[FS_MAX_PATH]; char fs_path_new[FS_MAX_PATH]; @@ -1173,13 +1197,13 @@ fsdev_rename(struct _reent *r, rc = fsFsGetEntryType(&device_old->fs, fs_path_old, &type); if(R_SUCCEEDED(rc)) { - if(type == ENTRYTYPE_DIR) + if(type == FsDirEntryType_Dir) { rc = fsFsRenameDirectory(&device_old->fs, fs_path_old, fs_path_new); if(R_SUCCEEDED(rc)) return 0; } - else if(type == ENTRYTYPE_FILE) + else if(type == FsDirEntryType_File) { rc = fsFsRenameFile(&device_old->fs, fs_path_old, fs_path_new); if(R_SUCCEEDED(rc)) @@ -1251,7 +1275,7 @@ fsdev_diropen(struct _reent *r, fsdev_dir_t *dir = (fsdev_dir_t*)(dirState->dirStruct); /* open the directory */ - rc = fsFsOpenDirectory(&device->fs, fs_path, FS_DIROPEN_DIRECTORY | FS_DIROPEN_FILE, &fd); + rc = fsFsOpenDirectory(&device->fs, fs_path, FsDirOpenMode_ReadDirs | FsDirOpenMode_ReadFiles, &fd); if(R_SUCCEEDED(rc)) { dir->magic = FSDEV_DIRITER_MAGIC; @@ -1299,7 +1323,7 @@ fsdev_dirnext(struct _reent *r, struct stat *filestat) { Result rc; - size_t entries; + u64 entries; ssize_t units; FsDirectoryEntry *entry; @@ -1342,9 +1366,9 @@ fsdev_dirnext(struct _reent *r, /* fill in the stat info */ filestat->st_ino = 0; - if(entry->type == ENTRYTYPE_DIR) + if(entry->type == FsDirEntryType_Dir) filestat->st_mode = S_IFDIR; - else if(entry->type == ENTRYTYPE_FILE) + else if(entry->type == FsDirEntryType_File) { filestat->st_mode = S_IFREG; filestat->st_size = entry->fileSize; diff --git a/nx/source/runtime/devices/romfs_dev.c b/nx/source/runtime/devices/romfs_dev.c index 85940792..459f6f63 100644 --- a/nx/source/runtime/devices/romfs_dev.c +++ b/nx/source/runtime/devices/romfs_dev.c @@ -52,11 +52,11 @@ static char __thread __component[PATH_MAX+1]; static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 size) { u64 pos = mount->offset + offset; - size_t read = 0; + u64 read = 0; Result rc = 0; if(mount->fd_type == RomfsSource_FsFile) { - rc = fsFileRead(&mount->fd, pos, buffer, size, FS_READOPTION_NONE, &read); + rc = fsFileRead(&mount->fd, pos, buffer, size, FsReadOption_None, &read); } else if(mount->fd_type == RomfsSource_FsStorage) { @@ -170,7 +170,7 @@ static romfs_mount *romfsFindMount(const char *name) } else if(mount->setup) //Find the mount with the input name. { - if(strncmp(mount->name, name, strlen(mount->name))==0) + if(strncmp(mount->name, name, sizeof(mount->name))==0) return mount; } } @@ -244,7 +244,7 @@ Result romfsMount(const char *name) return 2; } - Result rc = fsFsOpenFile(sdfs, filename, FS_OPEN_READ, &mount->fd); + Result rc = fsFsOpenFile(sdfs, filename, FsOpenMode_Read, &mount->fd); if (R_FAILED(rc)) { romfs_free(mount); @@ -344,7 +344,7 @@ Result romfsMountFromFsdev(const char *path, u64 offset, const char *name) mount->fd_type = RomfsSource_FsFile; mount->offset = offset; - Result rc = fsFsOpenFile(tmpfs, filepath, FS_OPEN_READ, &mount->fd); + Result rc = fsFsOpenFile(tmpfs, filepath, FsOpenMode_Read, &mount->fd); if (R_FAILED(rc)) { romfs_free(mount); diff --git a/nx/source/runtime/env.c b/nx/source/runtime/env.c index 36d5209e..740c8158 100644 --- a/nx/source/runtime/env.c +++ b/nx/source/runtime/env.c @@ -5,6 +5,7 @@ #include "services/sm.h" #include "services/fatal.h" #include "services/applet.h" +#include "services/acc.h" void NORETURN __nx_exit(Result rc, LoaderReturnFn retaddr); @@ -23,7 +24,7 @@ static char* g_nextLoadArgv = NULL; static Result g_lastLoadResult = 0; static bool g_hasRandomSeed = false; static u64 g_randomSeed[2] = { 0, 0 }; -static u128* g_userIdStorage = NULL; +static AccountUid* g_userIdStorage = NULL; extern __attribute__((weak)) u32 __nx_applet_type; @@ -104,7 +105,7 @@ void envSetup(void* ctx, Handle main_thread, LoaderReturnFn saved_lr) break; case EntryType_UserIdStorage: - g_userIdStorage = (u128*)(uintptr_t)ent->Value[0]; + g_userIdStorage = (AccountUid*)(uintptr_t)ent->Value[0]; break; case EntryType_HosVersion: @@ -222,6 +223,6 @@ void envGetRandomSeed(u64 out[2]) { out[1] = g_randomSeed[1]; } -u128* envGetUserIdStorage(void) { +AccountUid* envGetUserIdStorage(void) { return g_userIdStorage; } diff --git a/nx/source/runtime/nacp.c b/nx/source/runtime/nacp.c index c63ea3fc..6d31c529 100644 --- a/nx/source/runtime/nacp.c +++ b/nx/source/runtime/nacp.c @@ -29,7 +29,7 @@ static u32 g_nacpLanguageTable[15] = { Result nacpGetLanguageEntry(NacpStruct* nacp, NacpLanguageEntry** langentry) { Result rc=0; u64 LanguageCode=0; - s32 Language=0; + SetLanguage Language=0; NacpLanguageEntry *entry = NULL; u32 i=0; diff --git a/nx/source/services/acc.c b/nx/source/services/acc.c index 7c0c8d6d..03742724 100644 --- a/nx/source/services/acc.c +++ b/nx/source/services/acc.c @@ -1,37 +1,44 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include - -#include "types.h" -#include "arm/atomics.h" +#include "service_guard.h" #include "services/acc.h" -#include "services/sm.h" #include "services/applet.h" #include "runtime/env.h" #include "runtime/hosversion.h" +static AccountServiceType g_accServiceType = AccountServiceType_NotInitialized; static Service g_accSrv; -static u64 g_refCnt; -static u128 g_accPreselectedUserID; +static AccountUid g_accPreselectedUserID; static bool g_accPreselectedUserInitialized; static Result _accountInitializeApplicationInfo(void); -static Result _accountGetPreselectedUser(u128 *userID); +static Result _accountGetPreselectedUser(AccountUid *userID); -Result accountInitialize(void) -{ +NX_GENERATE_SERVICE_GUARD(account); + +void accountSetServiceType(AccountServiceType serviceType) { + g_accServiceType = serviceType; +} + +Result _accountInitialize(void) { Result rc=0; Result rc2=0; - u128 *userIdEnv = envGetUserIdStorage(); + AccountUid *userIdEnv = envGetUserIdStorage(); - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_accSrv)) - return 0; - - rc = smGetService(&g_accSrv, "acc:u1"); - if (R_FAILED(rc)) { - rc = smGetService(&g_accSrv, "acc:u0"); - if (R_SUCCEEDED(rc)) rc = _accountInitializeApplicationInfo(); + switch (g_accServiceType) { + case AccountServiceType_NotInitialized: + case AccountServiceType_Application: + g_accServiceType = AccountServiceType_Application; + rc = smGetService(&g_accSrv, "acc:u0"); + if (R_SUCCEEDED(rc)) rc = _accountInitializeApplicationInfo(); + break; + case AccountServiceType_System: + rc = smGetService(&g_accSrv, "acc:u1"); + break; + case AccountServiceType_Administrator: + rc = smGetService(&g_accSrv, "acc:su"); + break; } if (R_SUCCEEDED(rc)) { @@ -42,354 +49,128 @@ Result accountInitialize(void) } else if (userIdEnv) { g_accPreselectedUserID = *userIdEnv; - if (g_accPreselectedUserID) g_accPreselectedUserInitialized = true; + if (accountUidIsValid(&g_accPreselectedUserID)) g_accPreselectedUserInitialized = true; } } - if (R_FAILED(rc)) accountExit(); - return rc; } -void accountExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) - serviceClose(&g_accSrv); +void _accountCleanup(void) { + serviceClose(&g_accSrv); + g_accServiceType = AccountServiceType_NotInitialized; } Service* accountGetServiceSession(void) { return &g_accSrv; } +static Result _accountCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + static Result _accountInitializeApplicationInfo(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid_placeholder; - } *raw; - - ipcSendPid(&c); - - raw = serviceIpcPrepareHeader(&g_accSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionBefore(6,0,0) ? 100 : 140; - raw->pid_placeholder = 0; - - Result rc = serviceIpcDispatch(&g_accSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_accSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + u64 pid_placeholder=0; + return serviceDispatchIn(&g_accSrv, hosversionBefore(6,0,0) ? 100 : 140, pid_placeholder, + .in_send_pid = true, + ); } -Result accountGetUserCount(s32* user_count) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_accSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 user_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *user_count = resp->user_count; - } - } - - return rc; +Result accountGetUserCount(s32* user_count) { + return _accountCmdNoInOutU32(&g_accSrv, (u32*)user_count, 0); } -static Result _accountListAllUsers(u128* userIDs) -{ - IpcCommand c; - ipcInitialize(&c); +static Result _accountListAllUsers(AccountUid* userIDs) { + return serviceDispatch(&g_accSrv, 2, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { userIDs, sizeof(AccountUid)*ACC_USER_LIST_SIZE } }, + ); +} +Result accountListAllUsers(AccountUid* userIDs, s32 max_userIDs, s32 *actual_total) { Result rc=0; - - size_t bufsize = ACC_USER_LIST_SIZE * sizeof(u128); - - ipcAddRecvStatic(&c, userIDs, bufsize, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - rc = serviceIpcDispatch(&g_accSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -Result accountListAllUsers(u128* userIDs, size_t max_userIDs, size_t *actual_total) -{ - Result rc=0; - u128 temp_userIDs[ACC_USER_LIST_SIZE]; + AccountUid temp_userIDs[ACC_USER_LIST_SIZE]; memset(temp_userIDs, 0, sizeof(temp_userIDs)); rc = _accountListAllUsers(temp_userIDs); if (R_SUCCEEDED(rc)) { - size_t total_userIDs; - for (total_userIDs = 0; total_userIDs < ACC_USER_LIST_SIZE; total_userIDs++) { - if (!temp_userIDs[total_userIDs]) - break; + s32 total_userIDs; + for (total_userIDs=0; total_userIDs total_userIDs) { max_userIDs = total_userIDs; } - memcpy(userIDs, temp_userIDs, sizeof(u128) * max_userIDs); + memcpy(userIDs, temp_userIDs, sizeof(AccountUid)*max_userIDs); *actual_total = max_userIDs; } return rc; } -Result accountGetLastOpenedUser(u128 *userID, bool *account_selected) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&g_accSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u128 userID; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && userID) { - *userID = resp->userID; - if (account_selected) { - *account_selected = 0; - if (*userID != 0) *account_selected = 1; - } - } - } - - return rc; +Result accountGetLastOpenedUser(AccountUid *userID) { + return serviceDispatchOut(&g_accSrv, 4, *userID); } -Result accountGetProfile(AccountProfile* out, u128 userID) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u128 userID; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->userID = userID; - - Result rc = serviceIpcDispatch(&g_accSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(&out->s, r.Handles[0]); - } - } - - return rc; +Result accountGetProfile(AccountProfile* out, const AccountUid *userID) { + return serviceDispatchIn(&g_accSrv, 5, *userID, + .out_num_objects = 1, + .out_objects = &out->s, + ); } -//IProfile implementation -Result accountProfileGet(AccountProfile* profile, AccountUserData* userdata, AccountProfileBase* profilebase) { - IpcCommand c; - ipcInitialize(&c); - if (userdata) ipcAddRecvStatic(&c, userdata, sizeof(AccountUserData), 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = userdata==NULL ? 1 : 0; - - Result rc = serviceIpcDispatch(&profile->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - AccountProfileBase profilebase; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && profilebase) memcpy(profilebase, &resp->profilebase, sizeof(AccountProfileBase)); - } - - return rc; -} - -Result accountProfileGetImageSize(AccountProfile* profile, size_t* image_size) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - - Result rc = serviceIpcDispatch(&profile->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 image_size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *image_size = resp->image_size; - } - } - - return rc; -} - -Result accountProfileLoadImage(AccountProfile* profile, void* buf, size_t len, size_t* image_size) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, len, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - - Result rc = serviceIpcDispatch(&profile->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 image_size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *image_size = resp->image_size; - } - } - - return rc; -} +// IProfile void accountProfileClose(AccountProfile* profile) { serviceClose(&profile->s); } -static Result _accountGetPreselectedUser(u128 *userID) { +static Result _accountProfileGet(AccountProfile* profile, AccountUserData* userdata, AccountProfileBase* profilebase) { + return serviceDispatchOut(&profile->s, 0, *profilebase, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { userdata, sizeof(AccountUserData) } }, + ); +} + +static Result _accountProfileGetBase(AccountProfile* profile, AccountProfileBase* profilebase) { + return serviceDispatchOut(&profile->s, 1, *profilebase); +} + +Result accountProfileGet(AccountProfile* profile, AccountUserData* userdata, AccountProfileBase* profilebase) { + Result rc=0; + + if (!serviceIsActive(&profile->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + if (userdata) + rc = _accountProfileGet(profile, userdata, profilebase); + else + rc = _accountProfileGetBase(profile, profilebase); + + return rc; +} + +Result accountProfileGetImageSize(AccountProfile* profile, u32* image_size) { + if (!serviceIsActive(&profile->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _accountCmdNoInOutU32(&profile->s, image_size, 10); +} + +Result accountProfileLoadImage(AccountProfile* profile, void* buf, size_t len, u32* image_size) { + if (!serviceIsActive(&profile->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchOut(&profile->s, 11, *image_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, len } }, + ); +} + +static Result _accountGetPreselectedUser(AccountUid *userID) { Result rc=0; AppletStorage storage; s64 tmpsize=0; @@ -398,9 +179,9 @@ static Result _accountGetPreselectedUser(u128 *userID) { u32 magicnum;//These two fields must match fixed values. u8 unk_x4; u8 pad[3]; - u128 userID; + AccountUid userID; u8 unk_x18[0x70];//unused - } PACKED storagedata; + } storagedata; memset(&storagedata, 0, sizeof(storagedata)); @@ -424,7 +205,7 @@ static Result _accountGetPreselectedUser(u128 *userID) { return rc; } -Result accountGetPreselectedUser(u128 *userID) { +Result accountGetPreselectedUser(AccountUid *userID) { if (!g_accPreselectedUserInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); *userID = g_accPreselectedUserID; diff --git a/nx/source/services/apm.c b/nx/source/services/apm.c index 155cd3a1..1eddb72e 100644 --- a/nx/source/services/apm.c +++ b/nx/source/services/apm.c @@ -1,153 +1,55 @@ -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/apm.h" -#include "services/sm.h" static Service g_apmSrv; static Service g_apmISession; -static u64 g_refCnt; -static Result _apmGetSession(Service* srv, Service* srv_out, u64 cmd_id); +static Result _apmCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id); -Result apmInitialize(void) -{ - atomicIncrement64(&g_refCnt); +NX_GENERATE_SERVICE_GUARD(apm); - if (serviceIsActive(&g_apmSrv)) - return 0; - - Result rc = 0; - - rc = smGetService(&g_apmSrv, "apm"); +Result _apmInitialize(void) { + Result rc = smGetService(&g_apmSrv, "apm"); // OpenSession. // Official sw doesn't open this until using commands which need it, when it wasn't already opened. - if (R_SUCCEEDED(rc)) - rc = _apmGetSession(&g_apmSrv, &g_apmISession, 0); - - if (R_FAILED(rc)) - apmExit(); + if (R_SUCCEEDED(rc)) rc = _apmCmdGetSession(&g_apmSrv, &g_apmISession, 0); return rc; } -void apmExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_apmISession); - serviceClose(&g_apmSrv); - } +void _apmCleanup(void) { + serviceClose(&g_apmISession); + serviceClose(&g_apmSrv); } Service* apmGetServiceSession(void) { return &g_apmSrv; } -static Result _apmGetSession(Service* srv, Service* srv_out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(srv_out, r.Handles[0]); - } - } - - return rc; +Service* apmGetServiceSession_Session(void) { + return &g_apmISession; } -Result apmSetPerformanceConfiguration(u32 PerformanceMode, u32 PerformanceConfiguration) { - IpcCommand c; - ipcInitialize(&c); +static Result _apmCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} - struct { - u64 magic; - u64 cmd_id; +Result apmSetPerformanceConfiguration(ApmPerformanceMode PerformanceMode, u32 PerformanceConfiguration) { + const struct { u32 PerformanceMode; u32 PerformanceConfiguration; - } *raw; + } in = { PerformanceMode, PerformanceConfiguration }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->PerformanceMode = PerformanceMode; - raw->PerformanceConfiguration = PerformanceConfiguration; - - Result rc = serviceIpcDispatch(&g_apmISession); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_apmISession, 0, in); } -Result apmGetPerformanceConfiguration(u32 PerformanceMode, u32 *PerformanceConfiguration) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 PerformanceMode; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->PerformanceMode = PerformanceMode; - - Result rc = serviceIpcDispatch(&g_apmISession); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 PerformanceConfiguration; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && PerformanceConfiguration) *PerformanceConfiguration = resp->PerformanceConfiguration; - } - - return rc; +Result apmGetPerformanceConfiguration(ApmPerformanceMode PerformanceMode, u32 *PerformanceConfiguration) { + u32 tmp=PerformanceMode; + return serviceDispatchInOut(&g_apmISession, 1, tmp, *PerformanceConfiguration); } diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index 76b4c257..f3aea127 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -1,9 +1,6 @@ #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" +#include "service_guard.h" #include "arm/counter.h" -#include "kernel/ipc.h" #include "kernel/tmem.h" #include "kernel/event.h" #include "services/fatal.h" @@ -11,8 +8,8 @@ #include "services/apm.h" #include "services/caps.h" #include "services/pm.h" -#include "services/sm.h" #include "services/fs.h" +#include "services/acc.h" #include "runtime/env.h" #include "runtime/hosversion.h" #include "nacp.h" @@ -27,7 +24,7 @@ __attribute__((weak)) u32 __nx_applet_exit_mode = 0; static Service g_appletSrv; static Service g_appletProxySession; -static u64 g_refCnt; +static bool g_appletLeftInitialized; static bool g_appletExitProcessFlag; static Result g_appletExitProcessResult; @@ -50,9 +47,6 @@ static Service g_appletIAudioController; static Service g_appletIDisplayController; static Service g_appletIDebugFunctions; -static size_t g_appletIAppletCommonFunctions_ptrbufsize; -static size_t g_appletISelfController_ptrbufsize; - static Event g_appletMessageEvent; static u64 g_appletResourceUserId = 0; @@ -84,10 +78,12 @@ static ApmCpuBoostMode g_appletCpuBoostMode = ApmCpuBoostMode_Disabled; static AppletInfo g_appletInfo; static bool g_appletInfoInitialized; -static Result _appletGetHandle(Service* srv, Handle* handle_out, u64 cmd_id); -static Result _appletGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear); -static Result _appletGetSession(Service* srv, Service* srv_out, u64 cmd_id); -static Result _appletGetSessionProxy(Service* srv_out, u64 cmd_id, Handle prochandle, const AppletAttribute *attr); +static Result _appletGetHandle(Service* srv, Handle* handle_out, u32 cmd_id); +static Result _appletGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id); +static Result _appletGetSession(Service* srv, Service* srv_out, u32 cmd_id); + +static Result _appletOpenLibraryAppletProxy(Service* srv_out, Handle prochandle, const AppletAttribute *attr); +static Result _appletGetSessionProxy(Service* srv_out, Handle prochandle, u32 cmd_id); static Result _appletGetAppletResourceUserId(u64 *out); @@ -115,16 +111,17 @@ static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason); static Result _appletOpenCallingLibraryApplet(AppletHolder *h); static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self); -static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u64 cmd_id); +static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u32 cmd_id); -Result appletInitialize(void) -{ +NX_GENERATE_SERVICE_GUARD(applet); + +Result _appletInitialize(void) { AppletAttribute *attr = NULL; - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_appletSrv)) + if (g_appletLeftInitialized) { + g_appletLeftInitialized = false; return 0; + } if (__nx_applet_type == AppletType_None) return 0; @@ -143,15 +140,15 @@ Result appletInitialize(void) memset(&g_appletInfo, 0, sizeof(g_appletInfo)); switch (__nx_applet_type) { - case AppletType_Default: - __nx_applet_type = AppletType_Application; - // Fallthrough. - case AppletType_Application: - rc = smGetService(&g_appletSrv, "appletOE"); - break; - default: - rc = smGetService(&g_appletSrv, "appletAE"); - break; + case AppletType_Default: + __nx_applet_type = AppletType_Application; + // Fallthrough. + case AppletType_Application: + rc = smGetService(&g_appletSrv, "appletOE"); + break; + default: + rc = smGetService(&g_appletSrv, "appletAE"); + break; } if (R_SUCCEEDED(rc)) { @@ -165,13 +162,13 @@ Result appletInitialize(void) u32 cmd_id; switch(__nx_applet_type) { - case AppletType_Application: cmd_id = 0; break; - case AppletType_SystemApplet: cmd_id = 100; break; - case AppletType_LibraryApplet: cmd_id = 200; break; - case AppletType_OverlayApplet: cmd_id = 300; break; - case AppletType_SystemApplication: cmd_id = 350; break; - // TODO: Replace error code - default: fatalSimple(MAKERESULT(Module_Libnx, LibnxError_AppletCmdidNotFound)); + case AppletType_Application: cmd_id = 0; break; + case AppletType_SystemApplet: cmd_id = 100; break; + case AppletType_LibraryApplet: cmd_id = 200; break; + case AppletType_OverlayApplet: cmd_id = 300; break; + case AppletType_SystemApplication: cmd_id = 350; break; + // TODO: Replace error code + default: fatalSimple(MAKERESULT(Module_Libnx, LibnxError_AppletCmdidNotFound)); } if (__nx_applet_type == AppletType_LibraryApplet && hosversionAtLeast(3,0,0)) { @@ -179,7 +176,10 @@ Result appletInitialize(void) attr = &__nx_applet_AppletAttribute; } - rc = _appletGetSessionProxy(&g_appletProxySession, cmd_id, CUR_PROCESS_HANDLE, attr); + if (attr==NULL) + rc = _appletGetSessionProxy(&g_appletProxySession, CUR_PROCESS_HANDLE, cmd_id); + else + rc = _appletOpenLibraryAppletProxy(&g_appletProxySession, CUR_PROCESS_HANDLE, attr); if (rc == AM_BUSY_ERROR) { svcSleepThread(10000000); @@ -192,7 +192,6 @@ Result appletInitialize(void) if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) { if (__nx_applet_type == AppletType_SystemApplet || __nx_applet_type == AppletType_LibraryApplet || __nx_applet_type == AppletType_OverlayApplet) { rc = _appletGetSession(&g_appletProxySession, &g_appletIAppletCommonFunctions, __nx_applet_type == AppletType_SystemApplet ? 23 : 21); - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_appletIAppletCommonFunctions.handle, &g_appletIAppletCommonFunctions_ptrbufsize); } } @@ -243,9 +242,6 @@ Result appletInitialize(void) if (R_SUCCEEDED(rc)) rc = _appletGetSession(&g_appletProxySession, &g_appletIDebugFunctions, 1000); - if (R_SUCCEEDED(rc)) - rc = ipcQueryPointerBufferSize(g_appletISelfController.handle, &g_appletISelfController_ptrbufsize); - Result rc2 = _appletGetAccumulatedSuspendedTickChangedEvent(&g_appletSuspendedTickEvent); if (R_SUCCEEDED(rc2)) { g_appletInitTickBase = armGetSystemTick(); @@ -255,7 +251,7 @@ Result appletInitialize(void) // ICommonStateGetter::GetEventHandle if (R_SUCCEEDED(rc)) - rc = _appletGetEvent(&g_appletICommonStateGetter, &g_appletMessageEvent, 0, false); + rc = _appletGetEvent(&g_appletICommonStateGetter, &g_appletMessageEvent, false, 0); if (R_SUCCEEDED(rc) && (__nx_applet_type == AppletType_Application)) { @@ -365,92 +361,89 @@ static bool _appletIsRegularApplication(void) { return __nx_applet_type == AppletType_Application; } -void appletExit(void) +void _appletCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) - { - if (!g_appletExitProcessFlag) { - if (g_appletRecordingInitialized > 0) { - if (g_appletRecordingInitialized == 2) appletSetGamePlayRecordingState(0); - } - - if (__nx_applet_type == AppletType_Application) appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend); - - if (g_appletCpuBoostMode != ApmCpuBoostMode_Disabled) appletSetCpuBoostMode(ApmCpuBoostMode_Disabled); - } - - if ((envIsNso() && __nx_applet_exit_mode==0) || __nx_applet_exit_mode==1) { - if (_appletIsApplication() || - __nx_applet_type == AppletType_LibraryApplet) { - if (!g_appletExitProcessFlag) { - g_appletExitProcessFlag = 1; - atomicIncrement64(&g_refCnt); - envSetExitFuncPtr(_appletExitProcess); - return; - } - else { - if (_appletIsApplication()) - g_appletExitProcessResult = _appletSelfExit(); - if (__nx_applet_type == AppletType_LibraryApplet) - g_appletExitProcessResult = _appletExitProcessAndReturn(); - } - } - } - - if (g_appletInfoInitialized) { - if (g_appletInfo.caller_flag) appletHolderClose(&g_appletInfo.caller); - g_appletInfoInitialized = 0; - memset(&g_appletInfo, 0, sizeof(g_appletInfo)); - } - - eventClose(&g_appletLibraryAppletLaunchableEvent); - - eventClose(&g_appletMessageEvent); - - if (g_appletSuspendedTickInitialized) { - eventClose(&g_appletSuspendedTickEvent); - g_appletSuspendedTickInitialized = false; - } - - serviceClose(&g_appletIDebugFunctions); - serviceClose(&g_appletIDisplayController); - serviceClose(&g_appletIAudioController); - serviceClose(&g_appletIWindowController); - serviceClose(&g_appletISelfController); - serviceClose(&g_appletICommonStateGetter); - serviceClose(&g_appletILibraryAppletCreator); - - if (__nx_applet_type == AppletType_SystemApplet) { - serviceClose(&g_appletIApplicationCreator); - serviceClose(&g_appletIGlobalStateController); - } - - if (__nx_applet_type != AppletType_LibraryApplet) - serviceClose(&g_appletIFunctions); - - if (__nx_applet_type == AppletType_LibraryApplet) { - serviceClose(&g_appletIProcessWindingController); - serviceClose(&g_appletILibraryAppletSelfAccessor); - } - - serviceClose(&g_appletIAppletCommonFunctions); - - serviceClose(&g_appletProxySession); - serviceClose(&g_appletSrv); - g_appletResourceUserId = 0; - - apmExit(); - + if (!g_appletExitProcessFlag) { if (g_appletRecordingInitialized > 0) { - tmemClose(&g_appletRecordingTmem); - g_appletRecordingInitialized = 0; + if (g_appletRecordingInitialized == 2) appletSetGamePlayRecordingState(0); } - if (g_appletCopyrightInitialized) { - tmemClose(&g_appletCopyrightTmem); - g_appletCopyrightInitialized = 0; + if (__nx_applet_type == AppletType_Application) appletSetFocusHandlingMode(AppletFocusHandlingMode_NoSuspend); + + if (g_appletCpuBoostMode != ApmCpuBoostMode_Disabled) appletSetCpuBoostMode(ApmCpuBoostMode_Disabled); + } + + if ((envIsNso() && __nx_applet_exit_mode==0) || __nx_applet_exit_mode==1) { + if (_appletIsApplication() || + __nx_applet_type == AppletType_LibraryApplet) { + if (!g_appletExitProcessFlag) { + g_appletExitProcessFlag = 1; + g_appletLeftInitialized = true; + envSetExitFuncPtr(_appletExitProcess); + return; + } + else { + if (_appletIsApplication()) + g_appletExitProcessResult = _appletSelfExit(); + if (__nx_applet_type == AppletType_LibraryApplet) + g_appletExitProcessResult = _appletExitProcessAndReturn(); + } } } + + if (g_appletInfoInitialized) { + if (g_appletInfo.caller_flag) appletHolderClose(&g_appletInfo.caller); + g_appletInfoInitialized = 0; + memset(&g_appletInfo, 0, sizeof(g_appletInfo)); + } + + eventClose(&g_appletLibraryAppletLaunchableEvent); + + eventClose(&g_appletMessageEvent); + + if (g_appletSuspendedTickInitialized) { + eventClose(&g_appletSuspendedTickEvent); + g_appletSuspendedTickInitialized = false; + } + + serviceClose(&g_appletIDebugFunctions); + serviceClose(&g_appletIDisplayController); + serviceClose(&g_appletIAudioController); + serviceClose(&g_appletIWindowController); + serviceClose(&g_appletISelfController); + serviceClose(&g_appletICommonStateGetter); + serviceClose(&g_appletILibraryAppletCreator); + + if (__nx_applet_type == AppletType_SystemApplet) { + serviceClose(&g_appletIApplicationCreator); + serviceClose(&g_appletIGlobalStateController); + } + + if (__nx_applet_type != AppletType_LibraryApplet) + serviceClose(&g_appletIFunctions); + + if (__nx_applet_type == AppletType_LibraryApplet) { + serviceClose(&g_appletIProcessWindingController); + serviceClose(&g_appletILibraryAppletSelfAccessor); + } + + serviceClose(&g_appletIAppletCommonFunctions); + + serviceClose(&g_appletProxySession); + serviceClose(&g_appletSrv); + g_appletResourceUserId = 0; + + apmExit(); + + if (g_appletRecordingInitialized > 0) { + tmemClose(&g_appletRecordingTmem); + g_appletRecordingInitialized = 0; + } + + if (g_appletCopyrightInitialized) { + tmemClose(&g_appletCopyrightTmem); + g_appletCopyrightInitialized = 0; + } } Service* appletGetServiceSession_Proxy(void) { @@ -594,44 +587,49 @@ Result appletSetFocusHandlingMode(AppletFocusHandlingMode mode) { return rc; } -static Result _appletGetHandle(Service* srv, Handle* handle_out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; +// Helper macros for use with the below ipc helper funcs. +#define IPC_MAKE_CMD_IMPL(proto,_s,_rid,func,...) \ +proto { \ + if (!serviceIsActive((_s))) \ + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \ + return func((_s), ##__VA_ARGS__, (_rid)); \ } -static Result _appletGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear) { - Handle tmp_handle=0; +#define IPC_MAKE_CMD_IMPL_HOSVER(proto,_s,_rid,func,_hosver,...) \ +proto { \ + if (!serviceIsActive((_s))) \ + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \ + if (hosversionBefore _hosver) \ + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); \ + return func((_s), ##__VA_ARGS__, (_rid)); \ +} + +#define IPC_MAKE_CMD_IMPL_INITEXPR(proto,_s,_rid,func,initexpr,...) \ +proto { \ + if (!serviceIsActive((_s)) || initexpr) \ + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \ + return func((_s), ##__VA_ARGS__, (_rid)); \ +} + +#define IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(proto,_s,_rid,func,initexpr,_hosver,...) \ +proto { \ + if (!serviceIsActive((_s)) || initexpr) \ + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); \ + if (hosversionBefore _hosver) \ + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); \ + return func((_s), ##__VA_ARGS__, (_rid)); \ +} + +static Result _appletGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = handle_out, + ); +} + +static Result _appletGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) { + Handle tmp_handle = INVALID_HANDLE; Result rc = 0; rc = _appletGetHandle(srv, &tmp_handle, cmd_id); @@ -639,705 +637,204 @@ static Result _appletGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool a return rc; } -static Result _appletGetSession(Service* srv, Service* srv_out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(srv_out, srv, &r, 0); - } - } - - return rc; +static Result _appletGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletGetSessionProxy(Service* srv_out, u64 cmd_id, Handle prochandle, const AppletAttribute *attr) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 reserved; - } *raw; - - ipcSendPid(&c); - ipcSendHandleCopy(&c, prochandle); - if (attr) ipcAddSendBuffer(&c, attr, sizeof(AppletAttribute), BufferType_Normal); - - raw = serviceIpcPrepareHeader(&g_appletSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->reserved = 0; - - Result rc = serviceIpcDispatch(&g_appletSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(srv_out, &g_appletSrv, &r, 0); - } - } - - return rc; +static Result _appletOpenLibraryAppletProxy(Service* srv_out, Handle prochandle, const AppletAttribute *attr) { + u64 reserved=0; + serviceAssumeDomain(&g_appletSrv); + return serviceDispatchIn(&g_appletSrv, 201, reserved, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { attr, sizeof(*attr) } }, + .in_send_pid = true, + .in_num_handles = 1, + .in_handles = { prochandle }, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletGetSessionIn64(Service* srv, Service* srv_out, u64 cmd_id, u64 inval) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 inval; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(srv_out, srv, &r, 0); - } - } - - return rc; +static Result _appletGetSessionProxy(Service* srv_out, Handle prochandle, u32 cmd_id) { + u64 reserved=0; + serviceAssumeDomain(&g_appletSrv); + return serviceDispatchIn(&g_appletSrv, cmd_id, reserved, + .in_send_pid = true, + .in_num_handles = 1, + .in_handles = { prochandle }, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletGetSessionIn32(Service* srv, Service* srv_out, u64 cmd_id, u32 inval) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 inval; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(srv_out, srv, &r, 0); - } - } - - return rc; +static Result _appletGetSessionIn64(Service* srv, Service* srv_out, u64 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletCmdNoIO(Service* session, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(session, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(session); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(session, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletGetSessionIn32(Service* srv, Service* srv_out, u32 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletCmdNoInOut64(Service* srv, u64 *out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 out; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) { - *out = resp->out; - } - } - - return rc; +static Result _appletCmdNoIO(Service* srv, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id); } -static Result _appletCmdNoInOut32(Service* srv, u32 *out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 out; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) { - *out = resp->out; - } - } - - return rc; +static Result _appletCmdNoInOut64(Service* srv, u64 *out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *out); } -static Result _appletCmdNoInOutU8(Service* srv, u8 *out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 out; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) { - *out = resp->out; - } - } - - return rc; +static Result _appletCmdNoInOut32(Service* srv, u32 *out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *out); } -static Result _appletCmdNoInOutBool(Service* srv, bool *out, u64 cmd_id) { +static Result _appletCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _appletCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) { u8 tmp=0; + serviceAssumeDomain(srv); Result rc = _appletCmdNoInOutU8(srv, &tmp, cmd_id); if (R_SUCCEEDED(rc) && out) *out = tmp!=0; return rc; } static Result _appletCmdInU8(Service* srv, u8 inval, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 inval; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval); } -static Result _appletCmdInU32(Service* srv, u32 inval, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 inval; - } PACKED *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCmdInU32(Service* srv, u32 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval); } -static Result _appletCmdInU64(Service* srv, u64 inval, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 inval; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCmdInU64(Service* srv, u64 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval); } -static Result _appletCmdInBool(Service* srv, bool inval, u64 cmd_id) { +static Result _appletCmdInBool(Service* srv, bool inval, u32 cmd_id) { + serviceAssumeDomain(srv); return _appletCmdInU8(srv, inval!=0, cmd_id); } -static Result _appletCmdInHandle64(Service* srv, Service* srv_out, u64 cmd_id, Handle handle, u64 inval) { - IpcCommand c; - ipcInitialize(&c); - - ipcSendHandleCopy(&c, handle); - - struct { - u64 magic; - u64 cmd_id; - u64 inval; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->inval = inval; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && srv_out) { - serviceCreateSubservice(srv_out, srv, &r, 0); - } - } - - return rc; +static Result _appletCmdInHandle64NoOut(Service* srv, Handle handle, u64 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval, + .in_num_handles = 1, + .in_handles = { handle }, + ); } -static Result _appletCmdInTmem(Service* srv, Service* srv_out, u64 cmd_id, TransferMemory *tmem) { - return _appletCmdInHandle64(srv, srv_out, cmd_id, tmem->handle, tmem->size); +static Result _appletCmdInHandle64OutSession(Service* srv, Service* srv_out, Handle handle, u64 inval, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval, + .in_num_handles = 1, + .in_handles = { handle }, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -static Result _appletCmdInSession(Service* srv, Service* srv_in, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - serviceSendObject(srv_in, &c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCmdInTmemNoOut(Service* srv, TransferMemory *tmem, u32 cmd_id) { + serviceAssumeDomain(srv); + return _appletCmdInHandle64NoOut(srv, tmem->handle, tmem->size, cmd_id); } -static Result _appletCmdInStorage(Service* srv, AppletStorage* s, u64 cmd_id) { +static Result _appletCmdInTmemOutSession(Service* srv, Service* srv_out, TransferMemory *tmem, u32 cmd_id) { + serviceAssumeDomain(srv); + return _appletCmdInHandle64OutSession(srv, srv_out, tmem->handle, tmem->size, cmd_id); +} + +static Result _appletCmdInSession(Service* srv, Service* srv_in, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .in_num_objects = 1, + .in_objects = { srv_in }, + ); +} + +static Result _appletCmdInStorage(Service* srv, AppletStorage* s, u32 cmd_id) { Result rc=0; if (!serviceIsActive(&s->s)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + serviceAssumeDomain(srv); rc =_appletCmdInSession(srv, &s->s, cmd_id); appletStorageClose(s); return rc; } -static Result _appletCmdNoInOutStorage(Service* srv, AppletStorage* s, u64 cmd_id) { +static Result _appletCmdNoInOutStorage(Service* srv, AppletStorage* s, u32 cmd_id) { memset(s, 0, sizeof(AppletStorage)); + serviceAssumeDomain(srv); return _appletGetSession(srv, &s->s, cmd_id); } -static Result _appletCmdSendBufNoOut(Service* srv, const void* buffer, size_t size, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, buffer, size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCmdSendBufNoOut(Service* srv, const void* buffer, size_t size, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); } -static Result _appletCmdNoInRecvBuf(Service* srv, void* buffer, size_t size, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCmdNoInRecvBuf(Service* srv, void* buffer, size_t size, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); } -static Result _appletGetLibraryAppletInfo(Service* srv, LibAppletInfo *info, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - LibAppletInfo info; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(LibAppletInfo)); - } - - return rc; +static Result _appletGetLibraryAppletInfo(Service* srv, LibAppletInfo *info, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *info); } -static Result _appletGetIdentityInfo(Service* srv, AppletIdentityInfo *info, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - AppletIdentityInfo info; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(AppletIdentityInfo)); - } - - return rc; +static Result _appletGetIdentityInfo(Service* srv, AppletIdentityInfo *info, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *info); } -static Result _appletGetResolution(Service* srv, s32 *width, s32 *height, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - +static Result _appletGetResolution(Service* srv, s32 *width, s32 *height, u32 cmd_id) { struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s32 width; - s32 height; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (width) *width = resp->width; - if (height) *height = resp->height; - } - } + s32 width; + s32 height; + } out; + serviceAssumeDomain(srv); + Result rc = serviceDispatchOut(srv, cmd_id, out); + if (R_SUCCEEDED(rc) && width) *width = out.width; + if (R_SUCCEEDED(rc) && height) *height = out.height; return rc; } // ICommonStateGetter -static Result _appletReceiveMessage(u32 *out) { - return _appletCmdNoInOut32(&g_appletICommonStateGetter, out, 1); -} - -static Result _appletGetOperationMode(u8 *out) { - return _appletCmdNoInOutU8(&g_appletICommonStateGetter, out, 5); -} - -static Result _appletGetPerformanceMode(u32 *out) { - return _appletCmdNoInOut32(&g_appletICommonStateGetter, out, 6); -} - -Result appletGetCradleStatus(u8 *status) { - return _appletCmdNoInOutU8(&g_appletICommonStateGetter, status, 7); -} +IPC_MAKE_CMD_IMPL(static Result _appletReceiveMessage(u32 *out), &g_appletICommonStateGetter, 1, _appletCmdNoInOut32, out) +IPC_MAKE_CMD_IMPL(static Result _appletGetOperationMode(u8 *out), &g_appletICommonStateGetter, 5, _appletCmdNoInOutU8, out) +IPC_MAKE_CMD_IMPL(static Result _appletGetPerformanceMode(u32 *out), &g_appletICommonStateGetter, 6, _appletCmdNoInOut32, out) +IPC_MAKE_CMD_IMPL( Result appletGetCradleStatus(u8 *status), &g_appletICommonStateGetter, 7, _appletCmdNoInOutU8, status) Result appletGetBootMode(PmBootMode *mode) { u8 tmp=0; @@ -1346,13 +843,8 @@ Result appletGetBootMode(PmBootMode *mode) { return rc; } -static Result _appletGetCurrentFocusState(u8 *out) { - return _appletCmdNoInOutU8(&g_appletICommonStateGetter, out, 9); -} - -static Result _appletGetAcquiredSleepLockEvent(Event *out_event) { - return _appletGetEvent(&g_appletICommonStateGetter, out_event, 13, false); -} +IPC_MAKE_CMD_IMPL(static Result _appletGetCurrentFocusState(u8 *out), &g_appletICommonStateGetter, 9, _appletCmdNoInOutU8, out) +IPC_MAKE_CMD_IMPL(static Result _appletGetAcquiredSleepLockEvent(Event *out_event), &g_appletICommonStateGetter, 13, _appletGetEvent, out_event, false) static Result _appletWaitAcquiredSleepLockEvent(void) { Result rc=0; @@ -1370,9 +862,7 @@ Result appletRequestToAcquireSleepLock(void) { return rc; } -Result appletReleaseSleepLock(void) { - return _appletCmdNoIO(&g_appletICommonStateGetter, 11); -} +IPC_MAKE_CMD_IMPL(Result appletReleaseSleepLock(void), &g_appletICommonStateGetter, 11, _appletCmdNoIO) Result appletReleaseSleepLockTransiently(void) { Result rc = _appletCmdNoIO(&g_appletICommonStateGetter, 12); @@ -1380,104 +870,66 @@ Result appletReleaseSleepLockTransiently(void) { return rc; } -Result appletPushToGeneralChannel(AppletStorage *s) { - return _appletCmdInStorage(&g_appletICommonStateGetter, s, 20); -} +IPC_MAKE_CMD_IMPL(Result appletPushToGeneralChannel(AppletStorage *s), &g_appletICommonStateGetter, 20, _appletCmdInStorage, s) -static Result _appletGetHomeButtonRwLockAccessor(Service* srv, AppletLockAccessor *a, u64 cmd_id) { +static Result _appletGetHomeButtonRwLockAccessor(Service* srv, AppletLockAccessor *a, u32 cmd_id) { Result rc = _appletGetSession(srv, &a->s, cmd_id); if (R_FAILED(rc)) return rc; - rc = _appletGetEvent(&a->s, &a->event, 3, false); + rc = _appletGetEvent(&a->s, &a->event, false, 3); if (R_FAILED(rc)) serviceClose(&a->s); return rc; } -Result appletGetHomeButtonReaderLockAccessor(AppletLockAccessor *a) { - return _appletGetHomeButtonRwLockAccessor(&g_appletICommonStateGetter, a, 30); -} +IPC_MAKE_CMD_IMPL(Result appletGetHomeButtonReaderLockAccessor(AppletLockAccessor *a), &g_appletICommonStateGetter, 30, _appletGetHomeButtonRwLockAccessor, a) -static Result _appletGetRwLockAccessor(Service* srv, AppletLockAccessor *a, u64 cmd_id, s32 inval) { - Result rc = _appletGetSessionIn32(srv, &a->s, cmd_id, inval); +static Result _appletGetRwLockAccessor(Service* srv, AppletLockAccessor *a, s32 inval, u32 cmd_id) { + Result rc = _appletGetSessionIn32(srv, &a->s, inval, cmd_id); if (R_FAILED(rc)) return rc; - rc = _appletGetEvent(&a->s, &a->event, 3, false); + rc = _appletGetEvent(&a->s, &a->event, false, 3); if (R_FAILED(rc)) serviceClose(&a->s); return rc; } -Result appletGetReaderLockAccessorEx(AppletLockAccessor *a, u32 inval) { - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, 31, inval); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetReaderLockAccessorEx(AppletLockAccessor *a, u32 inval), &g_appletICommonStateGetter, 31, _appletGetRwLockAccessor, (2,0,0), a, inval) Result appletGetWriterLockAccessorEx(AppletLockAccessor *a, u32 inval) { if (hosversionBefore(7,0,0)) { if (__nx_applet_type == AppletType_SystemApplet && hosversionAtLeast(2,0,0)) - return _appletGetRwLockAccessor(&g_appletIFunctions, a, 31, inval); + return _appletGetRwLockAccessor(&g_appletIFunctions, a, inval, 31); return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, 32, inval); + return _appletGetRwLockAccessor(&g_appletICommonStateGetter, a, inval, 32); } Result appletGetCradleFwVersion(u32 *out0, u32 *out1, u32 *out2, u32 *out3) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletICommonStateGetter, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 40; - - Result rc = serviceIpcDispatch(&g_appletICommonStateGetter); + u32 out0; + u32 out1; + u32 out2; + u32 out3; + } out; + serviceAssumeDomain(&g_appletICommonStateGetter); + Result rc = serviceDispatchOut(&g_appletICommonStateGetter, 40, out); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 out0; - u32 out1; - u32 out2; - u32 out3; - } *resp; - - serviceIpcParse(&g_appletICommonStateGetter, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out0) *out0 = resp->out0; - if (out1) *out1 = resp->out1; - if (out2) *out2 = resp->out2; - if (out3) *out3 = resp->out3; - } + if (out0) *out0 = out.out0; + if (out1) *out1 = out.out1; + if (out2) *out2 = out.out2; + if (out3) *out3 = out.out3; } - return rc; } -Result appletIsVrModeEnabled(bool *out) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletICommonStateGetter, out, 50); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsVrModeEnabled(bool *out), &g_appletICommonStateGetter, 50, _appletCmdNoInOutBool, (3,0,0), out) Result appletSetVrModeEnabled(bool flag) { if (hosversionBefore(6,0,0)) @@ -1489,93 +941,23 @@ Result appletSetVrModeEnabled(bool flag) { return _appletCmdNoIO(&g_appletICommonStateGetter, flag ? 53 : 54); } -Result appletSetLcdBacklightOffEnabled(bool flag) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletICommonStateGetter, flag, 52); -} - -Result appletIsInControllerFirmwareUpdateSection(bool *out) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletICommonStateGetter, out, 55); -} - -Result appletGetDefaultDisplayResolution(s32 *width, s32 *height) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetResolution(&g_appletICommonStateGetter, width, height, 60); -} - -Result appletGetDefaultDisplayResolutionChangeEvent(Event *out_event) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetEvent(&g_appletICommonStateGetter, out_event, 61, true); -} - -Result appletGetHdcpAuthenticationState(s32 *state) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut32(&g_appletICommonStateGetter, (u32*)state, 62); -} - -Result appletGetHdcpAuthenticationStateChangeEvent(Event *out_event) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetEvent(&g_appletICommonStateGetter, out_event, 63, true); -} - -Result appletSetTvPowerStateMatchingMode(AppletTvPowerStateMatchingMode mode) { - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletICommonStateGetter, mode, 64); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetLcdBacklightOffEnabled(bool flag), &g_appletICommonStateGetter, 52, _appletCmdInBool, (4,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsInControllerFirmwareUpdateSection(bool *out), &g_appletICommonStateGetter, 55, _appletCmdNoInOutBool, (3,0,0), out) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDefaultDisplayResolution(s32 *width, s32 *height), &g_appletICommonStateGetter, 60, _appletGetResolution, (3,0,0), width, height) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDefaultDisplayResolutionChangeEvent(Event *out_event), &g_appletICommonStateGetter, 61, _appletGetEvent, (3,0,0), out_event, true) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHdcpAuthenticationState(s32 *state), &g_appletICommonStateGetter, 62, _appletCmdNoInOut32, (4,0,0), (u32*)state) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHdcpAuthenticationStateChangeEvent(Event *out_event), &g_appletICommonStateGetter, 63, _appletGetEvent, (4,0,0), out_event, true) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetTvPowerStateMatchingMode(AppletTvPowerStateMatchingMode mode), &g_appletICommonStateGetter, 64, _appletCmdInU32, (5,0,0), mode) Result appletGetApplicationIdByContentActionName(u64 *titleID, const char *name) { if (hosversionBefore(5,1,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, name, strlen(name)+1, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletICommonStateGetter, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65; - - Result rc = serviceIpcDispatch(&g_appletICommonStateGetter); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 titleID; - } *resp; - - serviceIpcParse(&g_appletICommonStateGetter, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && titleID) *titleID = resp->titleID; - } - - return rc; + serviceAssumeDomain(&g_appletICommonStateGetter); + return serviceDispatchOut(&g_appletICommonStateGetter, 65, *titleID, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { name, strlen(name)+1 } }, + ); } Result appletSetCpuBoostMode(ApmCpuBoostMode mode) { @@ -1588,441 +970,131 @@ Result appletSetCpuBoostMode(ApmCpuBoostMode mode) { return rc; } -Result appletPerformSystemButtonPressingIfInFocus(AppletSystemButtonType type) { - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletICommonStateGetter, type, 80); -} - -Result appletSetPerformanceConfigurationChangedNotification(bool flag) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletICommonStateGetter, flag, 90); -} - -Result appletGetCurrentPerformanceConfiguration(u32 *PerformanceConfiguration) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut32(&g_appletICommonStateGetter, PerformanceConfiguration, 91); -} - -Result appletGetOperationModeSystemInfo(u32 *info) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut32(&g_appletICommonStateGetter, info, 200); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletPerformSystemButtonPressingIfInFocus(AppletSystemButtonType type), &g_appletICommonStateGetter, 80, _appletCmdInU32, (6,0,0), type) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetPerformanceConfigurationChangedNotification(bool flag), &g_appletICommonStateGetter, 90, _appletCmdInBool, (7,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetCurrentPerformanceConfiguration(u32 *PerformanceConfiguration), &g_appletICommonStateGetter, 91, _appletCmdNoInOut32, (7,0,0), PerformanceConfiguration) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetOperationModeSystemInfo(u32 *info), &g_appletICommonStateGetter, 200, _appletCmdNoInOut32, (7,0,0), info) // ISelfController -static Result _appletSelfExit(void) { - return _appletCmdNoIO(&g_appletISelfController, 0); -} - -Result appletLockExit(void) { - return _appletCmdNoIO(&g_appletISelfController, 1); -} - -Result appletUnlockExit(void) { - return _appletCmdNoIO(&g_appletISelfController, 2); -} - -Result appletEnterFatalSection(void) { - return _appletCmdNoIO(&g_appletISelfController, 3); -} - -Result appletLeaveFatalSection(void) { - return _appletCmdNoIO(&g_appletISelfController, 4); -} +IPC_MAKE_CMD_IMPL(static Result _appletSelfExit(void), &g_appletISelfController, 0, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL( Result appletLockExit(void), &g_appletISelfController, 1, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL( Result appletUnlockExit(void), &g_appletISelfController, 2, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL( Result appletEnterFatalSection(void), &g_appletISelfController, 3, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL( Result appletLeaveFatalSection(void), &g_appletISelfController, 4, _appletCmdNoIO) static Result _appletWaitLibraryAppletLaunchableEvent(void) { Result rc=0; if (!eventActive(&g_appletLibraryAppletLaunchableEvent)) - rc = _appletGetEvent(&g_appletISelfController, &g_appletLibraryAppletLaunchableEvent, 9, false); + rc = _appletGetEvent(&g_appletISelfController, &g_appletLibraryAppletLaunchableEvent, false, 9); if (R_SUCCEEDED(rc)) rc = eventWait(&g_appletLibraryAppletLaunchableEvent, U64_MAX); return rc; } -Result appletSetScreenShotPermission(AppletScreenShotPermission permission) { - return _appletCmdInU32(&g_appletISelfController, permission, 10); -} - -static Result _appletSetOperationModeChangedNotification(bool flag) { - return _appletCmdInBool(&g_appletISelfController, flag, 11); -} - -static Result _appletSetPerformanceModeChangedNotification(bool flag) { - return _appletCmdInBool(&g_appletISelfController, flag, 12); -} +IPC_MAKE_CMD_IMPL( Result appletSetScreenShotPermission(AppletScreenShotPermission permission), &g_appletISelfController, 10, _appletCmdInU32, permission) +IPC_MAKE_CMD_IMPL(static Result _appletSetOperationModeChangedNotification(bool flag), &g_appletISelfController, 11, _appletCmdInBool, flag) +IPC_MAKE_CMD_IMPL(static Result _appletSetPerformanceModeChangedNotification(bool flag), &g_appletISelfController, 12, _appletCmdInBool, flag) static Result _appletSetFocusHandlingMode(bool inval0, bool inval1, bool inval2) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 inval0; u8 inval1; u8 inval2; - } *raw; + } in = { inval0!=0, inval1!=0, inval2!=0 }; - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - raw->inval0 = inval0!=0; - raw->inval1 = inval1!=0; - raw->inval2 = inval2!=0; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletISelfController); + return serviceDispatchIn(&g_appletISelfController, 13, in); } -Result appletSetRestartMessageEnabled(bool flag) { - return _appletCmdInBool(&g_appletISelfController, flag, 14); -} +IPC_MAKE_CMD_IMPL(Result appletSetRestartMessageEnabled(bool flag), &g_appletISelfController, 14, _appletCmdInBool, flag) Result appletSetScreenShotAppletIdentityInfo(AppletIdentityInfo *info) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - AppletIdentityInfo info; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - memcpy(&raw->info, info, sizeof(AppletIdentityInfo)); - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletISelfController); + return serviceDispatchIn(&g_appletISelfController, 15, *info); } -static Result _appletSetOutOfFocusSuspendingEnabled(bool flag) { - return _appletCmdInBool(&g_appletISelfController, flag, 16); -} - -Result appletSetControllerFirmwareUpdateSection(bool flag) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletISelfController, flag, 17); -} - -Result appletSetRequiresCaptureButtonShortPressedMessage(bool flag) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletISelfController, flag, 18); -} - -Result appletSetAlbumImageOrientation(AlbumImageOrientation orientation) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletISelfController, orientation, 19); -} - -Result appletSetDesirableKeyboardLayout(u32 layout) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletISelfController, layout, 20); -} - -Result appletCreateManagedDisplayLayer(u64 *out) { - return _appletCmdNoInOut64(&g_appletISelfController, out, 40); -} - -Result appletIsSystemBufferSharingEnabled(void) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletISelfController, 41); -} +IPC_MAKE_CMD_IMPL(static Result _appletSetOutOfFocusSuspendingEnabled(bool flag), &g_appletISelfController, 16, _appletCmdInBool, flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetControllerFirmwareUpdateSection(bool flag), &g_appletISelfController, 17, _appletCmdInBool, (3,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetRequiresCaptureButtonShortPressedMessage(bool flag), &g_appletISelfController, 18, _appletCmdInBool, (3,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAlbumImageOrientation(AlbumImageOrientation orientation), &g_appletISelfController, 19, _appletCmdInU32, (3,0,0), orientation) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetDesirableKeyboardLayout(u32 layout), &g_appletISelfController, 20, _appletCmdInU32, (4,0,0), layout) +IPC_MAKE_CMD_IMPL( Result appletCreateManagedDisplayLayer(u64 *out), &g_appletISelfController, 40, _appletCmdNoInOut64, out) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsSystemBufferSharingEnabled(void), &g_appletISelfController, 41, _appletCmdNoIO, (4,0,0)) Result appletGetSystemSharedLayerHandle(u64 *SharedBufferHandle, u64 *SharedLayerHandle) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 42; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 SharedBufferHandle; - u64 SharedLayerHandle; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && SharedBufferHandle) *SharedBufferHandle = resp->SharedBufferHandle; - if (R_SUCCEEDED(rc) && SharedLayerHandle) *SharedLayerHandle = resp->SharedLayerHandle; - } + u64 SharedBufferHandle; + u64 SharedLayerHandle; + } out; + serviceAssumeDomain(&g_appletISelfController); + Result rc = serviceDispatchOut(&g_appletISelfController, 42, out); + if (R_SUCCEEDED(rc) && SharedBufferHandle) *SharedBufferHandle = out.SharedBufferHandle; + if (R_SUCCEEDED(rc) && SharedLayerHandle) *SharedLayerHandle = out.SharedLayerHandle; return rc; } -Result appletGetSystemSharedBufferHandle(u64 *SharedBufferHandle) { - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut64(&g_appletISelfController, SharedBufferHandle, 43); -} - -Result appletSetHandlesRequestToDisplay(bool flag) { - return _appletCmdInBool(&g_appletISelfController, flag, 50); -} - -Result appletApproveToDisplay(void) { - return _appletCmdNoIO(&g_appletISelfController, 51); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetSystemSharedBufferHandle(u64 *SharedBufferHandle) , &g_appletISelfController, 43, _appletCmdNoInOut64, (5,0,0), SharedBufferHandle) +IPC_MAKE_CMD_IMPL( Result appletSetHandlesRequestToDisplay(bool flag), &g_appletISelfController, 50, _appletCmdInBool, flag) +IPC_MAKE_CMD_IMPL( Result appletApproveToDisplay(void), &g_appletISelfController, 51, _appletCmdNoIO) Result appletOverrideAutoSleepTimeAndDimmingTime(s32 inval0, s32 inval1, s32 inval2, s32 inval3) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { s32 inval0; s32 inval1; s32 inval2; s32 inval3; - } *raw; + } in = { inval0, inval1, inval2, inval3 }; - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 60; - raw->inval0 = inval0; - raw->inval1 = inval1; - raw->inval2 = inval2; - raw->inval3 = inval3; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletISelfController); + return serviceDispatchIn(&g_appletISelfController, 60, in); } -Result appletSetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension ext) { - return _appletCmdInU32(&g_appletISelfController, ext, 62); -} - -Result appletGetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension *ext) { - return _appletCmdNoInOut32(&g_appletISelfController, ext, 63); -} - -Result appletSetInputDetectionSourceSet(u32 val) { - return _appletCmdInU32(&g_appletISelfController, val, 64); -} - -Result appletReportUserIsActive(void) { - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletISelfController, 65); -} +IPC_MAKE_CMD_IMPL( Result appletSetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension ext), &g_appletISelfController, 62, _appletCmdInU32, ext) +IPC_MAKE_CMD_IMPL( Result appletGetIdleTimeDetectionExtension(AppletIdleTimeDetectionExtension *ext), &g_appletISelfController, 63, _appletCmdNoInOut32, ext) +IPC_MAKE_CMD_IMPL( Result appletSetInputDetectionSourceSet(u32 val), &g_appletISelfController, 64, _appletCmdInU32, val) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletReportUserIsActive(void), &g_appletISelfController, 65, _appletCmdNoIO, (2,0,0)) Result appletGetCurrentIlluminance(float *fLux) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 66; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - float fLux; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && fLux) *fLux = resp->fLux; - } - - return rc; + serviceAssumeDomain(&g_appletISelfController); + return serviceDispatchOut(&g_appletISelfController, 66, *fLux); } -Result appletIsIlluminanceAvailable(bool *out) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletISelfController, out, 67); -} - -Result appletSetAutoSleepDisabled(bool flag) { - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletISelfController, flag, 68); -} - -Result appletIsAutoSleepDisabled(bool *out) { - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletISelfController, out, 69); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsIlluminanceAvailable(bool *out), &g_appletISelfController, 67, _appletCmdNoInOutBool, (3,0,0), out) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAutoSleepDisabled(bool flag), &g_appletISelfController, 68, _appletCmdInBool, (5,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletIsAutoSleepDisabled(bool *out), &g_appletISelfController, 69, _appletCmdNoInOutBool, (5,0,0), out) Result appletGetCurrentIlluminanceEx(bool *bOverLimit, float *fLux) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 71; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 bOverLimit; - float fLux; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && bOverLimit) *bOverLimit = resp->bOverLimit!=0; - if (R_SUCCEEDED(rc) && fLux) *fLux = resp->fLux; - } + u8 bOverLimit; + float fLux; + } out; + serviceAssumeDomain(&g_appletISelfController); + Result rc = serviceDispatchOut(&g_appletISelfController, 71, out); + if (R_SUCCEEDED(rc) && bOverLimit) *bOverLimit = out.bOverLimit!=0; + if (R_SUCCEEDED(rc) && fLux) *fLux = out.fLux; return rc; } -Result appletSetWirelessPriorityMode(AppletWirelessPriorityMode mode) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletISelfController, mode, 80); -} - -Result appletSetAlbumImageTakenNotificationEnabled(bool flag) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletISelfController, flag, 100); -} - -static Result _appletGetAccumulatedSuspendedTickValue(u64 *tick) { - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut64(&g_appletISelfController, tick, 90); -} - -static Result _appletGetAccumulatedSuspendedTickChangedEvent(Event *out_event) { - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetEvent(&g_appletISelfController, out_event, 91, true); -} +IPC_MAKE_CMD_IMPL_HOSVER( Result appletSetWirelessPriorityMode(AppletWirelessPriorityMode mode), &g_appletISelfController, 80, _appletCmdInU32, (4,0,0), mode) +IPC_MAKE_CMD_IMPL_HOSVER(static Result _appletGetAccumulatedSuspendedTickValue(u64 *tick), &g_appletISelfController, 90, _appletCmdNoInOut64, (6,0,0), tick) +IPC_MAKE_CMD_IMPL_HOSVER(static Result _appletGetAccumulatedSuspendedTickChangedEvent(Event *out_event), &g_appletISelfController, 91, _appletGetEvent, (6,0,0), out_event, true) Result appletGetProgramTotalActiveTime(u64 *activeTime) { if (!g_appletSuspendedTickInitialized) @@ -2043,48 +1115,22 @@ Result appletGetProgramTotalActiveTime(u64 *activeTime) { return rc; } +IPC_MAKE_CMD_IMPL_HOSVER( Result appletSetAlbumImageTakenNotificationEnabled(bool flag), &g_appletISelfController, 100, _appletCmdInBool, (7,0,0), flag) + Result appletSetApplicationAlbumUserData(const void* buffer, size_t size) { if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendSmart(&c, g_appletISelfController_ptrbufsize, buffer, size, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletISelfController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 110; - - Result rc = serviceIpcDispatch(&g_appletISelfController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletISelfController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletISelfController); + return serviceDispatch(&g_appletISelfController, 110, + .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); } // IWindowController -static Result _appletGetAppletResourceUserId(u64 *out) { - return _appletCmdNoInOut64(&g_appletIWindowController, out, 1); -} +IPC_MAKE_CMD_IMPL(static Result _appletGetAppletResourceUserId(u64 *out), &g_appletIWindowController, 1, _appletCmdNoInOut64, out) Result appletGetAppletResourceUserId(u64 *out) { if (!serviceIsActive(&g_appletSrv)) @@ -2094,69 +1140,21 @@ Result appletGetAppletResourceUserId(u64 *out) { return 0; } -Result appletGetAppletResourceUserIdOfCallerApplet(u64 *out) { - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - if (!serviceIsActive(&g_appletSrv)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOut64(&g_appletIWindowController, out, 2); -} - -static Result _appletAcquireForegroundRights(void) { - return _appletCmdNoIO(&g_appletIWindowController, 10); -} - -Result appletSetAppletWindowVisibility(bool flag) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletIWindowController, flag, 20); -} - -Result appletSetAppletGpuTimeSlice(s64 val) { - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU64(&g_appletIWindowController, val, 21); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetAppletResourceUserIdOfCallerApplet(u64 *out), &g_appletIWindowController, 2, _appletCmdNoInOut64, (6,0,0), out) +IPC_MAKE_CMD_IMPL(static Result _appletAcquireForegroundRights(void), &g_appletIWindowController, 10, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAppletWindowVisibility(bool flag), &g_appletIWindowController, 20, _appletCmdInBool, (7,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetAppletGpuTimeSlice(s64 val), &g_appletIWindowController, 21, _appletCmdInU64, (7,0,0), val) // IAudioController Result appletSetExpectedMasterVolume(float mainAppletVolume, float libraryAppletVolume) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { float mainAppletVolume; float libraryAppletVolume; - } *raw; + } in = { mainAppletVolume, libraryAppletVolume }; - raw = serviceIpcPrepareHeader(&g_appletIAudioController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->mainAppletVolume = mainAppletVolume; - raw->libraryAppletVolume = libraryAppletVolume; - - Result rc = serviceIpcDispatch(&g_appletIAudioController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIAudioController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIAudioController); + return serviceDispatchIn(&g_appletIAudioController, 0, in); } Result appletGetExpectedMasterVolume(float *mainAppletVolume, float *libraryAppletVolume) { @@ -2169,119 +1167,33 @@ Result appletGetExpectedMasterVolume(float *mainAppletVolume, float *libraryAppl } Result appletChangeMainAppletMasterVolume(float volume, u64 unk) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { float volume; u64 unk; - } *raw; + } in = { volume, unk }; - raw = serviceIpcPrepareHeader(&g_appletIAudioController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->volume = volume; - raw->unk = unk; - - Result rc = serviceIpcDispatch(&g_appletIAudioController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIAudioController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIAudioController); + return serviceDispatchIn(&g_appletIAudioController, 3, in); } Result appletSetTransparentVolumeRate(float val) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - float val; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIAudioController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - raw->val = val; - - Result rc = serviceIpcDispatch(&g_appletIAudioController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIAudioController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIAudioController); + return serviceDispatchIn(&g_appletIAudioController, 4, val); } // IDisplayController -Result appletUpdateLastForegroundCaptureImage(void) { - return _appletCmdNoIO(&g_appletIDisplayController, 1); -} - -Result appletUpdateCallerAppletCaptureImage(void) { - return _appletCmdNoIO(&g_appletIDisplayController, 4); -} - -static Result _appletGetCaptureImageEx(void* buffer, size_t size, bool *flag, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 flag; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && flag) *flag = resp->flag!=0; - } +IPC_MAKE_CMD_IMPL(Result appletUpdateLastForegroundCaptureImage(void), &g_appletIDisplayController, 1, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletUpdateCallerAppletCaptureImage(void), &g_appletIDisplayController, 4, _appletCmdNoIO) +static Result _appletGetCaptureImageEx(void* buffer, size_t size, bool *flag, u32 cmd_id) { + u8 tmp=0; + serviceAssumeDomain(&g_appletIDisplayController); + Result rc = serviceDispatchOut(&g_appletIDisplayController, cmd_id, tmp, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); + if (R_SUCCEEDED(rc) && flag) *flag = tmp!=0; return rc; } @@ -2301,162 +1213,54 @@ Result appletTakeScreenShotOfOwnLayer(bool flag, AppletCaptureSharedBuffer captu if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 flag; s32 captureBuf; - } *raw; + } in = { flag!=0, captureBuf }; - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - raw->flag = flag!=0; - raw->captureBuf = captureBuf; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIDisplayController); + return serviceDispatchIn(&g_appletIDisplayController, 8, in); } Result appletCopyBetweenCaptureBuffers(AppletCaptureSharedBuffer dstCaptureBuf, AppletCaptureSharedBuffer srcCaptureBuf) { if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { s32 dstCaptureBuf; s32 srcCaptureBuf; - } *raw; + } in = { dstCaptureBuf, srcCaptureBuf }; - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 9; - raw->dstCaptureBuf = dstCaptureBuf; - raw->srcCaptureBuf = srcCaptureBuf; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIDisplayController); + return serviceDispatchIn(&g_appletIDisplayController, 9, in); } Result appletClearCaptureBuffer(bool flag, AppletCaptureSharedBuffer captureBuf, u32 color) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 flag; s32 captureBuf; u32 color; - } *raw; + } in = { flag!=0, captureBuf, color }; - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 20; - raw->flag = flag!=0; - raw->captureBuf = captureBuf; - raw->color = color; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIDisplayController); + return serviceDispatchIn(&g_appletIDisplayController, 20, in); } -Result appletClearAppletTransitionBuffer(u32 color) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletIDisplayController, color, 21); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletClearAppletTransitionBuffer(u32 color), &g_appletIDisplayController, 21, _appletCmdInU32, (3,0,0), color) static Result _appletAcquireCaptureSharedBuffer(bool *flag, s32 *id, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 flag; - s32 id; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && flag) *flag = resp->flag!=0; - if (R_SUCCEEDED(rc) && id) *id = resp->id; - } + u8 flag; + s32 id; + } out; + serviceAssumeDomain(&g_appletIDisplayController); + Result rc = serviceDispatchOut(&g_appletIDisplayController, cmd_id, out); + if (R_SUCCEEDED(rc) && flag) *flag = out.flag!=0; + if (R_SUCCEEDED(rc) && id) *id = out.id; return rc; } @@ -2467,12 +1271,7 @@ Result appletAcquireLastApplicationCaptureSharedBuffer(bool *flag, s32 *id) { return _appletAcquireCaptureSharedBuffer(flag, id, 22); } -Result appletReleaseLastApplicationCaptureSharedBuffer(void) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIDisplayController, 23); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseLastApplicationCaptureSharedBuffer(void), &g_appletIDisplayController, 23, _appletCmdNoIO, (4,0,0)) Result appletAcquireLastForegroundCaptureSharedBuffer(bool *flag, s32 *id) { if (hosversionBefore(4,0,0)) @@ -2481,12 +1280,7 @@ Result appletAcquireLastForegroundCaptureSharedBuffer(bool *flag, s32 *id) { return _appletAcquireCaptureSharedBuffer(flag, id, 24); } -Result appletReleaseLastForegroundCaptureSharedBuffer(void) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIDisplayController, 25); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseLastForegroundCaptureSharedBuffer(void), &g_appletIDisplayController, 25, _appletCmdNoIO, (4,0,0)) Result appletAcquireCallerAppletCaptureSharedBuffer(bool *flag, s32 *id) { if (hosversionBefore(4,0,0)) @@ -2495,52 +1289,20 @@ Result appletAcquireCallerAppletCaptureSharedBuffer(bool *flag, s32 *id) { return _appletAcquireCaptureSharedBuffer(flag, id, 26); } -Result appletReleaseCallerAppletCaptureSharedBuffer(void) { - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIDisplayController, 27); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletReleaseCallerAppletCaptureSharedBuffer(void), &g_appletIDisplayController, 27, _appletCmdNoIO, (4,0,0)) Result appletTakeScreenShotOfOwnLayerEx(bool flag0, bool immediately, AppletCaptureSharedBuffer captureBuf) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 flag0; u8 immediately; s32 captureBuf; - } *raw; + } in = { flag0!=0, immediately!=0, captureBuf }; - raw = serviceIpcPrepareHeader(&g_appletIDisplayController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 28; - raw->flag0 = flag0!=0; - raw->immediately = immediately!=0; - raw->captureBuf = captureBuf; - - Result rc = serviceIpcDispatch(&g_appletIDisplayController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIDisplayController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIDisplayController); + return serviceDispatchIn(&g_appletIDisplayController, 28, in); } // IProcessWindingController @@ -2549,38 +1311,8 @@ static Result _appletGetLaunchReason(AppletProcessLaunchReason *reason) { if (__nx_applet_type != AppletType_LibraryApplet) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIProcessWindingController, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_appletIProcessWindingController); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - AppletProcessLaunchReason reason; - } *resp; - - serviceIpcParse(&g_appletIProcessWindingController, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && reason) *reason = resp->reason; - } - - return rc; + serviceAssumeDomain(&g_appletIProcessWindingController); + return serviceDispatchOut(&g_appletIProcessWindingController, 0, *reason); } static Result _appletOpenCallingLibraryApplet(AppletHolder *h) { @@ -2590,42 +1322,11 @@ static Result _appletOpenCallingLibraryApplet(AppletHolder *h) { return _appletOpenExistingLibraryApplet(h, &g_appletIProcessWindingController, 11); } -Result appletPushContext(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInStorage(&g_appletIProcessWindingController, s, 21); -} - -Result appletPopContext(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutStorage(&g_appletIProcessWindingController, s, 22); -} - -static Result _appletWindAndDoReserved(void) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIProcessWindingController, 30); -} - -static Result _appletReserveToStartAndWaitAndUnwindThis(AppletHolder *h) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInSession(&g_appletIProcessWindingController, &h->s, 40); -} - -static Result _appletReserveToStartAndWait(AppletHolder *h) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInSession(&g_appletIProcessWindingController, &h->s, 41); -} +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushContext(AppletStorage *s), &g_appletIProcessWindingController, 21, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopContext(AppletStorage *s), &g_appletIProcessWindingController, 22, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( static Result _appletWindAndDoReserved(void), &g_appletIProcessWindingController, 30, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet) +IPC_MAKE_CMD_IMPL_INITEXPR( static Result _appletReserveToStartAndWaitAndUnwindThis(AppletHolder *h), &g_appletIProcessWindingController, 40, _appletCmdInSession, __nx_applet_type != AppletType_LibraryApplet, &h->s) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletReserveToStartAndWait(AppletHolder *h), &g_appletIProcessWindingController, 41, _appletCmdInSession, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), &h->s) // LockAccessor void appletLockAccessorClose(AppletLockAccessor *a) { @@ -2634,42 +1335,16 @@ void appletLockAccessorClose(AppletLockAccessor *a) { } static Result _appletLockAccessorTryLock(AppletLockAccessor *a, bool get_handle, Handle* handle_out, bool *outflag) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 inflag; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->inflag = get_handle!=0; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 outflag; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (handle_out) *handle_out = r.Handles[0]; - if (outflag) *outflag = resp->outflag!=0; - } - } - + Handle tmphandle = INVALID_HANDLE; + u8 tmp = get_handle!=0; + u8 tmpout=0; + serviceAssumeDomain(&a->s); + Result rc = serviceDispatchInOut(&a->s, 1, tmp, tmpout, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmphandle, + ); + if (R_SUCCEEDED(rc) && outflag) *outflag = tmpout!=0; + if (R_SUCCEEDED(rc) && handle_out) *handle_out = tmphandle; return rc; } @@ -2700,53 +1375,21 @@ Result appletLockAccessorLock(AppletLockAccessor *a) { return rc; } -Result appletLockAccessorUnlock(AppletLockAccessor *a) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&a->s, 2); -} +IPC_MAKE_CMD_IMPL(Result appletLockAccessorUnlock(AppletLockAccessor *a), &a->s, 2, _appletCmdNoIO) // ILibraryAppletCreator static Result _appletCreateLibraryApplet(Service* srv_out, AppletId id, LibAppletMode mode) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 id; u32 mode; - } *raw; + } in = { id, mode }; - raw = serviceIpcPrepareHeader(&g_appletILibraryAppletCreator, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->id = id; - raw->mode = mode; - - Result rc = serviceIpcDispatch(&g_appletILibraryAppletCreator); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletILibraryAppletCreator, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && srv_out) { - serviceCreateSubservice(srv_out, &g_appletILibraryAppletCreator, &r, 0); - } - } - - return rc; + serviceAssumeDomain(&g_appletILibraryAppletCreator); + return serviceDispatchIn(&g_appletILibraryAppletCreator, 0, in, + .out_num_objects = 1, + .out_objects = srv_out, + ); } static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) { @@ -2756,42 +1399,10 @@ static Result _appletGetIndirectLayerConsumerHandle(Service* srv, u64 *out) { rc = appletGetAppletResourceUserId(&AppletResourceUserId); if (R_FAILED(rc)) return rc; - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 AppletResourceUserId; - } *raw; - - ipcSendPid(&c); - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 160; - raw->AppletResourceUserId = AppletResourceUserId; - - rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 out; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + serviceAssumeDomain(srv); + return serviceDispatchInOut(srv, 160, AppletResourceUserId, *out, + .in_send_pid = true, + ); } static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool creating_self) { @@ -2800,7 +1411,7 @@ static Result _appletHolderCreateState(AppletHolder *h, LibAppletMode mode, bool h->mode = mode; h->creating_self = creating_self; - if (R_SUCCEEDED(rc)) rc = _appletGetEvent(&h->s, &h->StateChangedEvent, 0, false);//GetAppletStateChangedEvent + if (R_SUCCEEDED(rc)) rc = _appletGetEvent(&h->s, &h->StateChangedEvent, false, 0);//GetAppletStateChangedEvent if (R_SUCCEEDED(rc) && hosversionAtLeast(2,0,0) && h->mode == LibAppletMode_BackgroundIndirect) rc = _appletGetIndirectLayerConsumerHandle(&h->s, &h->layer_handle); @@ -2821,7 +1432,7 @@ static Result _appletHolderCreate(AppletHolder *h, AppletId id, LibAppletMode mo return rc; } -static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u64 cmd_id) { +static Result _appletOpenExistingLibraryApplet(AppletHolder *h, Service* srv, u32 cmd_id) { if (__nx_applet_type != AppletType_LibraryApplet) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); @@ -2849,13 +1460,8 @@ Result appletCreateLibraryAppletSelf(AppletHolder *h, AppletId id, LibAppletMode return _appletHolderCreate(h, id, mode, true); } -Result appletTerminateAllLibraryApplets(void) { - return _appletCmdNoIO(&g_appletILibraryAppletCreator, 1); -} - -Result appletAreAnyLibraryAppletsLeft(bool *out) { - return _appletCmdNoInOutBool(&g_appletILibraryAppletCreator, out, 2); -} +IPC_MAKE_CMD_IMPL(Result appletTerminateAllLibraryApplets(void), &g_appletILibraryAppletCreator, 1, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletAreAnyLibraryAppletsLeft(bool *out), &g_appletILibraryAppletCreator, 2, _appletCmdNoInOutBool, out) // ILibraryAppletAccessor @@ -2928,16 +1534,7 @@ Result appletHolderRequestExit(AppletHolder *h) { return rc; } -Result appletHolderTerminate(AppletHolder *h) { - Result rc=0; - - if (!serviceIsActive(&h->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - rc = _appletCmdNoIO(&h->s, 25);//Terminate - - return rc; -} +IPC_MAKE_CMD_IMPL(Result appletHolderTerminate(AppletHolder *h), &h->s, 25, _appletCmdNoIO) static Result _appletAccessorRequestExitOrTerminate(Service* srv, u64 timeout) { Result rc=0; @@ -2946,7 +1543,7 @@ static Result _appletAccessorRequestExitOrTerminate(Service* srv, u64 timeout) { if (!serviceIsActive(srv)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - rc = _appletGetEvent(srv, &StateChangedEvent, 0, false);//GetAppletStateChangedEvent + rc = _appletGetEvent(srv, &StateChangedEvent, false, 0);//GetAppletStateChangedEvent if (R_SUCCEEDED(rc)) rc = _appletCmdNoIO(srv, 20);//RequestExit @@ -2996,21 +1593,12 @@ u32 appletHolderGetExitReason(AppletHolder *h) { return h->exitreason; } -Result appletHolderSetOutOfFocusApplicationSuspendingEnabled(AppletHolder *h, bool flag) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInBool(&h->s, flag, 50); -} +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletHolderSetOutOfFocusApplicationSuspendingEnabled(AppletHolder *h, bool flag), &h->s, 50, _appletCmdInBool, !_appletIsApplication(), flag) static Result _appletHolderGetPopInteractiveOutDataEvent(AppletHolder *h) { - Result rc=0; - if (eventActive(&h->PopInteractiveOutDataEvent)) return 0; - rc = _appletGetEvent(&h->s, &h->PopInteractiveOutDataEvent, 106, false); - - return rc; + return _appletGetEvent(&h->s, &h->PopInteractiveOutDataEvent, false, 106); } bool appletHolderWaitInteractiveOut(AppletHolder *h) { @@ -3026,78 +1614,34 @@ bool appletHolderWaitInteractiveOut(AppletHolder *h) { return idx==0; } -Result appletHolderPushInData(AppletHolder *h, AppletStorage *s) { - return _appletCmdInStorage(&h->s, s, 100); -} - -Result appletHolderPopOutData(AppletHolder *h, AppletStorage *s) { - return _appletCmdNoInOutStorage(&h->s, s, 101); -} - -Result appletHolderPushExtraStorage(AppletHolder *h, AppletStorage *s) { - return _appletCmdInStorage(&h->s, s, 102); -} - -Result appletHolderPushInteractiveInData(AppletHolder *h, AppletStorage *s) { - return _appletCmdInStorage(&h->s, s, 103); -} - -Result appletHolderPopInteractiveOutData(AppletHolder *h, AppletStorage *s) { - return _appletCmdNoInOutStorage(&h->s, s, 104); -} - -Result appletHolderGetLibraryAppletInfo(AppletHolder *h, LibAppletInfo *info) { - return _appletGetLibraryAppletInfo(&h->s, info, 120); -} +IPC_MAKE_CMD_IMPL(Result appletHolderPushInData(AppletHolder *h, AppletStorage *s), &h->s, 100, _appletCmdInStorage, s) +IPC_MAKE_CMD_IMPL(Result appletHolderPopOutData(AppletHolder *h, AppletStorage *s), &h->s, 101, _appletCmdNoInOutStorage, s) +IPC_MAKE_CMD_IMPL(Result appletHolderPushExtraStorage(AppletHolder *h, AppletStorage *s), &h->s, 102, _appletCmdInStorage, s) +IPC_MAKE_CMD_IMPL(Result appletHolderPushInteractiveInData(AppletHolder *h, AppletStorage *s), &h->s, 103, _appletCmdInStorage, s) +IPC_MAKE_CMD_IMPL(Result appletHolderPopInteractiveOutData(AppletHolder *h, AppletStorage *s), &h->s, 104, _appletCmdNoInOutStorage, s) +IPC_MAKE_CMD_IMPL(Result appletHolderGetLibraryAppletInfo(AppletHolder *h, LibAppletInfo *info), &h->s, 120, _appletGetLibraryAppletInfo, info) // (ILibraryAppletCreator ->) IStorage Result appletCreateStorage(AppletStorage *s, s64 size) { memset(s, 0, sizeof(AppletStorage)); - return _appletGetSessionIn64(&g_appletILibraryAppletCreator, &s->s, 10, size); + return _appletGetSessionIn64(&g_appletILibraryAppletCreator, &s->s, size, 10); } static Result _appletCreateTransferMemoryStorage(Service* srv_out, TransferMemory *tmem, bool writable) { - IpcCommand c; - ipcInitialize(&c); - - ipcSendHandleCopy(&c, tmem->handle); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 writable; u64 size; - } *raw; + } in = { writable!=0, tmem->size }; - raw = serviceIpcPrepareHeader(&g_appletILibraryAppletCreator, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->writable = writable!=0; - raw->size = tmem->size; - - Result rc = serviceIpcDispatch(&g_appletILibraryAppletCreator); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletILibraryAppletCreator, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && srv_out) { - serviceCreateSubservice(srv_out, &g_appletILibraryAppletCreator, &r, 0); - } - } - - return rc; + serviceAssumeDomain(&g_appletILibraryAppletCreator); + return serviceDispatchIn(&g_appletILibraryAppletCreator, 11, in, + .in_num_handles = 1, + .in_handles = { tmem->handle }, + .out_num_objects = 1, + .out_objects = srv_out, + ); } Result appletCreateTransferMemoryStorage(AppletStorage *s, void* buffer, s64 size, bool writable) { @@ -3119,7 +1663,7 @@ Result appletCreateHandleStorage(AppletStorage *s, s64 inval, Handle handle) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return _appletCmdInHandle64(&g_appletILibraryAppletCreator, &s->s, 12, handle, inval); + return _appletCmdInHandle64OutSession(&g_appletILibraryAppletCreator, &s->s, handle, inval, 12); } Result appletCreateHandleStorageTmem(AppletStorage *s, void* buffer, s64 size) { @@ -3146,40 +1690,11 @@ void appletStorageCloseTmem(AppletStorage *s) { } static Result _appletStorageAccessorRW(Service* srv, size_t ipcbufsize, s64 offset, void* buffer, size_t size, bool rw) { - IpcCommand c; - ipcInitialize(&c); - - if(!rw)ipcAddRecvSmart(&c, ipcbufsize, buffer, size, 0); - if(rw)ipcAddSendSmart(&c, ipcbufsize, buffer, size, 0); - - struct { - u64 magic; - u64 cmd_id; - s64 offset; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = rw!=0 ? 10 : 11; - raw->offset = offset; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, rw ? 10 : 11, offset, + .buffer_attrs = { SfBufferAttr_HipcAutoSelect | (rw ? SfBufferAttr_In : SfBufferAttr_Out) }, + .buffers = { { buffer, size } }, + ); } Result appletStorageGetSize(AppletStorage *s, s64 *size) { @@ -3200,7 +1715,6 @@ Result appletStorageGetSize(AppletStorage *s, s64 *size) { static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_t size, bool rw) { Result rc=0; - size_t ipcbufsize=0; Service tmp_srv;//IStorageAccessor if (!serviceIsActive(&s->s)) @@ -3209,9 +1723,7 @@ static Result _appletStorageRW(AppletStorage *s, s64 offset, void* buffer, size_ rc = _appletGetSession(&s->s, &tmp_srv, 0);//Open if (R_FAILED(rc)) return rc; - rc = ipcQueryPointerBufferSize(tmp_srv.handle, &ipcbufsize); - - if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, ipcbufsize, offset, buffer, size, rw); + if (R_SUCCEEDED(rc)) rc = _appletStorageAccessorRW(&tmp_srv, tmp_srv.pointer_buffer_size, offset, buffer, size, rw); serviceClose(&tmp_srv); return rc; @@ -3226,40 +1738,13 @@ Result appletStorageRead(AppletStorage *s, s64 offset, void* buffer, size_t size } static Result _appletStorageGetHandle(Service* srv, s64 *out, Handle *handle) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s64 out; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->out; - if (handle) *handle = r.Handles[0]; - } - } - + Handle tmphandle = INVALID_HANDLE; + serviceAssumeDomain(srv); + Result rc = serviceDispatchOut(srv, 1, *out, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &tmphandle, + ); + if (R_SUCCEEDED(rc) && handle) *handle = tmphandle; return rc; } @@ -3305,120 +1790,37 @@ Result appletStorageMap(AppletStorage *s, void** addr, size_t *size) { // IApplicationFunctions Result appletPopLaunchParameter(AppletStorage *s, AppletLaunchParameterKind kind) { - IpcCommand c; - ipcInitialize(&c); - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - u32 kind; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->kind = kind; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - memset(s, 0, sizeof(AppletStorage)); - serviceCreateSubservice(&s->s, &g_appletIFunctions, &r, 0); - } - } - - return rc; + u32 tmp=kind; + memset(s, 0, sizeof(AppletStorage)); + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 1, tmp, + .out_num_objects = 1, + .out_objects = &s->s, + ); } -static Result _appletCreateApplicationAndPushAndRequestToStart(Service* srv, u64 cmd_id, u64 titleID, AppletStorage* s) { - IpcCommand c; - ipcInitialize(&c); - - serviceSendObject(&s->s, &c); - - struct { - u64 magic; - u64 cmd_id; - u64 titleID; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _appletCreateApplicationAndPushAndRequestToStart(Service* srv, u64 titleID, AppletStorage* s, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, titleID, + .in_num_objects = 1, + .in_objects = { &s->s }, + ); } static Result _appletCreateApplicationAndPushAndRequestToStartForQuest(u64 titleID, AppletStorage* s, const AppletApplicationAttributeForQuest *attr) { // [2.0.0+] - IpcCommand c; - ipcInitialize(&c); - - serviceSendObject(&s->s, &c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 val0, val1; u64 titleID; - } PACKED *raw; + } in = { attr->unk_x0, attr->unk_x4, titleID }; - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->val0 = attr->unk_x0; - raw->val1 = attr->unk_x4; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 11, in, + .in_num_objects = 1, + .in_objects = { &s->s }, + ); } static Result _appletCreateApplicationAndRequestToStart(u64 titleID) { // [4.0.0+] @@ -3426,114 +1828,31 @@ static Result _appletCreateApplicationAndRequestToStart(u64 titleID) { // [4.0.0 } static Result _appletCreateApplicationAndRequestToStartForQuest(u64 titleID, const AppletApplicationAttributeForQuest *attr) { // [4.0.0+] - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 val0, val1; u64 titleID; - } PACKED *raw; + } in = { attr->unk_x0, attr->unk_x4, titleID }; - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - raw->val0 = attr->unk_x0; - raw->val1 = attr->unk_x4; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 13, in); } static Result _appletCreateApplicationWithAttributeAndPushAndRequestToStartForQuest(u64 titleID, AppletStorage* s, const AppletApplicationAttribute *attr) { // [7.0.0+] - IpcCommand c; - ipcInitialize(&c); - - serviceSendObject(&s->s, &c); - - ipcAddSendBuffer(&c, attr, sizeof(*attr), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u64 titleID; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 14; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 14, titleID, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { attr, sizeof(*attr) } }, + .in_num_objects = 1, + .in_objects = { &s->s }, + ); } static Result _appletCreateApplicationWithAttributeAndRequestToStartForQuest(u64 titleID, const AppletApplicationAttribute *attr) { // [7.0.0+] - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, attr, sizeof(*attr), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u64 titleID; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 15, titleID, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { attr, sizeof(*attr) } }, + ); } Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s) { @@ -3553,14 +1872,14 @@ Result appletRequestLaunchApplication(u64 titleID, AppletStorage* s) { } if (is_libraryapplet) { - rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletILibraryAppletSelfAccessor, 90, titleID, s); + rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletILibraryAppletSelfAccessor, titleID, s, 90); } else { if (hosversionAtLeast(4,0,0) && s==NULL) { rc = _appletCreateApplicationAndRequestToStart(titleID); } else { - rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletIFunctions, 10, titleID, s); + rc = _appletCreateApplicationAndPushAndRequestToStart(&g_appletIFunctions, titleID, s, 10); } } @@ -3612,90 +1931,23 @@ Result appletRequestLaunchApplicationForQuest(u64 titleID, AppletStorage* s, con return rc; } -Result appletGetDesiredLanguage(u64 *LanguageCode) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOut64(&g_appletIFunctions, LanguageCode, 21); -} - -Result appletSetTerminateResult(Result res) { - IpcCommand c; - ipcInitialize(&c); - - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - struct { - u64 magic; - u64 cmd_id; - Result res; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 22; - raw->res = res; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; -} +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetDesiredLanguage(u64 *LanguageCode), &g_appletIFunctions, 21, _appletCmdNoInOut64, !_appletIsApplication(), LanguageCode) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletSetTerminateResult(Result res), &g_appletIFunctions, 22, _appletCmdInU32, !_appletIsApplication(), res) Result appletGetDisplayVersion(char *displayVersion) { - IpcCommand c; - ipcInitialize(&c); + char out[0x10]={0}; if (displayVersion) memset(displayVersion, 0, 0x10); if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - char displayVersion[0x10]; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && displayVersion) { - strncpy(displayVersion, resp->displayVersion, 0x10); - displayVersion[0xf] = 0; - } + serviceAssumeDomain(&g_appletIFunctions); + Result rc = serviceDispatchOut(&g_appletIFunctions, 23, out); + if (R_SUCCEEDED(rc) && displayVersion) { + strncpy(displayVersion, out, 0x10); + displayVersion[0xf] = 0; } - return rc; } @@ -3705,69 +1957,22 @@ Result appletGetLaunchStorageInfoForDebug(FsStorageId *app_storageId, FsStorageI if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 24; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 app_storageId; - u8 update_storageId; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && app_storageId) *app_storageId = resp->app_storageId; - if (R_SUCCEEDED(rc) && update_storageId) *update_storageId = resp->update_storageId; - } + u8 app_storageId; + u8 update_storageId; + } out; + serviceAssumeDomain(&g_appletIFunctions); + Result rc = serviceDispatchOut(&g_appletIFunctions, 24, out); + if (R_SUCCEEDED(rc) && app_storageId) *app_storageId = out.app_storageId; + if (R_SUCCEEDED(rc) && update_storageId) *update_storageId = out.update_storageId; return rc; } -Result appletBeginBlockingHomeButtonShortAndLongPressed(s64 val) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInU64(&g_appletIFunctions, val, 30); -} - -Result appletEndBlockingHomeButtonShortAndLongPressed(void) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 31); -} - -Result appletBeginBlockingHomeButton(s64 val) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInU64(&g_appletIFunctions, val, 32); -} - -Result appletEndBlockingHomeButton(void) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 33); -} +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletBeginBlockingHomeButtonShortAndLongPressed(s64 val), &g_appletIFunctions, 30, _appletCmdInU64, !_appletIsApplication(), val) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletEndBlockingHomeButtonShortAndLongPressed(void), &g_appletIFunctions, 31, _appletCmdNoIO, !_appletIsApplication()) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletBeginBlockingHomeButton(s64 val), &g_appletIFunctions, 32, _appletCmdInU64, !_appletIsApplication(), val) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletEndBlockingHomeButton(void), &g_appletIFunctions, 33, _appletCmdNoIO, !_appletIsApplication()) void appletNotifyRunning(bool *out) { if (__nx_applet_type!=AppletType_Application || g_appletNotifiedRunning) return; @@ -3779,43 +1984,13 @@ void appletNotifyRunning(bool *out) { } Result appletGetPseudoDeviceId(u128 *out) { - IpcCommand c; - ipcInitialize(&c); - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 50; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u128 out; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchOut(&g_appletIFunctions, 50, *out); } Result appletSetMediaPlaybackState(bool state) { @@ -3828,97 +2003,9 @@ Result appletSetMediaPlaybackState(bool state) { return _appletCmdInBool(&g_appletIFunctions, state, 60);//SetMediaPlaybackStateForApplication } -Result appletIsGamePlayRecordingSupported(bool *flag) { - IpcCommand c; - ipcInitialize(&c); - - if (flag) *flag = 0; - - if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 65; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 flag; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && flag) *flag = resp->flag & 1; - } - - return rc; -} - -static Result _appletInitializeGamePlayRecording(TransferMemory *tmem) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInTmem(&g_appletIFunctions, NULL, 66, tmem); -} - -Result appletSetGamePlayRecordingState(bool state) { - IpcCommand c; - ipcInitialize(&c); - - if (!serviceIsActive(&g_appletSrv) || !_appletIsRegularApplication() || g_appletRecordingInitialized==0) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - struct { - u64 magic; - u64 cmd_id; - u32 state; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 67; - raw->state = state==0 ? 0 : 1; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; -} +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER( Result appletIsGamePlayRecordingSupported(bool *flag), &g_appletIFunctions, 65, _appletCmdNoInOutBool, !_appletIsRegularApplication(), (3,0,0), flag) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletInitializeGamePlayRecording(TransferMemory *tmem), &g_appletIFunctions, 66, _appletCmdInTmemNoOut, !_appletIsRegularApplication(), (3,0,0), tmem) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER( Result appletSetGamePlayRecordingState(bool state), &g_appletIFunctions, 67, _appletCmdInU32, !_appletIsRegularApplication() || g_appletRecordingInitialized==0, (3,0,0), state!=0) Result appletInitializeGamePlayRecording(void) { Result rc=0; @@ -3949,14 +2036,7 @@ Result appletInitializeGamePlayRecording(void) { return rc; } -Result appletRequestFlushGamePlayingMovieForDebug(void) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIFunctions, 68); -} +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletRequestFlushGamePlayingMovieForDebug(void), &g_appletIFunctions, 68, _appletCmdNoIO, !_appletIsApplication(), (4,0,0)) Result appletRequestToShutdown(void) { Result rc=0; @@ -3998,43 +2078,17 @@ Result appletExitAndRequestToShowThanksMessage(void) { } static Result _appletInitializeApplicationCopyrightFrameBuffer(TransferMemory *tmem, s32 width, s32 height) { - IpcCommand c; - ipcInitialize(&c); - - ipcSendHandleCopy(&c, tmem->handle); - - struct { - u64 magic; - u64 cmd_id; + const struct { s32 width; s32 height; u64 size; - } *raw; + } in = { width, height, tmem->size }; - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 100; - raw->width = width; - raw->height = height; - raw->size = tmem->size; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 100, in, + .in_num_handles = 1, + .in_handles = { tmem->handle }, + ); } Result appletInitializeApplicationCopyrightFrameBuffer(void) { @@ -4070,47 +2124,19 @@ Result appletSetApplicationCopyrightImage(const void* buffer, size_t size, s32 x if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, buffer, size, BufferType_Type1); - - struct { - u64 magic; - u64 cmd_id; + const struct { s32 x; s32 y; s32 width; s32 height; s32 mode; - } *raw; + } in = { x, y, width, height, mode }; - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 101; - raw->x = x; - raw->y = y; - raw->width = width; - raw->height = height; - raw->mode = mode; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 101, in, + .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); } Result appletSetApplicationCopyrightVisibility(bool visible) { @@ -4124,93 +2150,41 @@ Result appletSetApplicationCopyrightVisibility(bool visible) { //Official sw has these under 'pdm'. Result appletQueryApplicationPlayStatistics(PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out) { - IpcCommand c; - ipcInitialize(&c); - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - ipcAddSendBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal); - ipcAddRecvBuffer(&c, stats, count*sizeof(PdmApplicationPlayStatistics), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 110; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s32 total_out; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchOut(&g_appletIFunctions, 110, *total_out, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { stats, count*sizeof(PdmApplicationPlayStatistics) }, + { titleIDs, count*sizeof(u64) }, + }, + ); } -Result appletQueryApplicationPlayStatisticsByUid(u128 userID, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out) { - IpcCommand c; - ipcInitialize(&c); - +Result appletQueryApplicationPlayStatisticsByUid(AccountUid *uid, PdmApplicationPlayStatistics *stats, const u64 *titleIDs, s32 count, s32 *total_out) { if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - ipcAddSendBuffer(&c, titleIDs, count*sizeof(u64), BufferType_Normal); - ipcAddRecvBuffer(&c, stats, count*sizeof(PdmApplicationPlayStatistics), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u128 userID; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 111; - raw->userID = userID; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s32 total_out; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchInOut(&g_appletIFunctions, 111, *uid, *total_out, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { stats, count*sizeof(PdmApplicationPlayStatistics) }, + { titleIDs, count*sizeof(u64) }, + }, + ); } static Result _appletExecuteProgramCmd(AppletProgramSpecifyKind kind, u64 inval) { @@ -4219,58 +2193,17 @@ static Result _appletExecuteProgramCmd(AppletProgramSpecifyKind kind, u64 inval) if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 kind; u64 inval; - } *raw; + } in = { kind, inval }; - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 120; - raw->kind = kind; - raw->inval = inval; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIFunctions); + return serviceDispatchIn(&g_appletIFunctions, 120, in); } -static Result _appletClearUserChannel(void) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIFunctions, 121); -} - -static Result _appletUnpopToUserChannel(AppletStorage *s) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInStorage(&g_appletIFunctions, s, 122); -} +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletClearUserChannel(void), &g_appletIFunctions, 121, _appletCmdNoIO, !_appletIsApplication(), (5,0,0)) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(static Result _appletUnpopToUserChannel(AppletStorage *s), &g_appletIFunctions, 122, _appletCmdInStorage, !_appletIsApplication(), (5,0,0), s) static Result _appletExecuteProgram(AppletProgramSpecifyKind kind, u64 inval, const void* buffer, size_t size) { Result rc=0; @@ -4310,119 +2243,38 @@ Result appletRestartProgram(const void* buffer, size_t size) { return _appletExecuteProgram(AppletProgramSpecifyKind_RestartProgram, 0, buffer, size); } -Result appletGetPreviousProgramIndex(s32 *programIndex) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut32(&g_appletIFunctions, (u32*)programIndex, 123); -} - -Result appletGetGpuErrorDetectedSystemEvent(Event *out_event) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetEvent(&g_appletIFunctions, out_event, 130, false); -} - -Result appletPrepareForJit(void) { - if (!serviceIsActive(&g_appletSrv) || !_appletIsApplication()) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIFunctions, 1001); -} +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetPreviousProgramIndex(s32 *programIndex), &g_appletIFunctions, 123, _appletCmdNoInOut32, !_appletIsApplication(), (5,0,0), (u32*)programIndex) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetGpuErrorDetectedSystemEvent(Event *out_event), &g_appletIFunctions, 130, _appletGetEvent, !_appletIsApplication(), (8,0,0), out_event, false) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletCreateMovieMaker(Service* srv_out, TransferMemory *tmem), &g_appletIFunctions, 1000, _appletCmdInTmemOutSession, !_appletIsApplication(), (5,0,0), srv_out, tmem) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletPrepareForJit(void), &g_appletIFunctions, 1001, _appletCmdNoIO, !_appletIsApplication(), (5,0,0)) // IHomeMenuFunctions -Result appletRequestToGetForeground(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletRequestToGetForeground(void), &g_appletIFunctions, 10, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletLockForeground(void), &g_appletIFunctions, 11, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletUnlockForeground(void), &g_appletIFunctions, 12, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopFromGeneralChannel(AppletStorage *s), &g_appletIFunctions, 20, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_SystemApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetPopFromGeneralChannelEvent(Event *out_event), &g_appletIFunctions, 21, _appletGetEvent, __nx_applet_type != AppletType_SystemApplet, out_event, false) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a), &g_appletIFunctions, 30, _appletGetHomeButtonRwLockAccessor, __nx_applet_type != AppletType_SystemApplet, a) - return _appletCmdNoIO(&g_appletIFunctions, 10); -} - -Result appletLockForeground(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 11); -} - -Result appletUnlockForeground(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 12); -} - -Result appletPopFromGeneralChannel(AppletStorage *s) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutStorage(&g_appletIFunctions, s, 20); -} - -Result appletGetPopFromGeneralChannelEvent(Event *out_event) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetEvent(&g_appletIFunctions, out_event, 21, false); -} - -Result appletGetHomeButtonWriterLockAccessor(AppletLockAccessor *a) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetHomeButtonRwLockAccessor(&g_appletIFunctions, a, 30); -} - -Result appletPopRequestLaunchApplicationForDebug(u128 *userIDs, s32 count, u64 *titleID, s32 *total_out) { +Result appletPopRequestLaunchApplicationForDebug(AccountUid *userIDs, s32 count, u64 *titleID, s32 *total_out) { if (__nx_applet_type != AppletType_SystemApplet) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 100; - - Result rc = serviceIpcDispatch(&g_appletIFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 titleID; - s32 total_out; - } *resp; - - serviceIpcParse(&g_appletIFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && titleID) *titleID = resp->titleID; - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } + u64 titleID; + s32 total_out; + } out; + serviceAssumeDomain(&g_appletIFunctions); + Result rc = serviceDispatchOut(&g_appletIFunctions, 100, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { userIDs, count*sizeof(AccountUid) } }, + ); + if (R_SUCCEEDED(rc) && titleID) *titleID = out.titleID; + if (R_SUCCEEDED(rc) && total_out) *total_out = out.total_out; return rc; } @@ -4441,97 +2293,24 @@ Result appletLaunchDevMenu(void) { // IGlobalStateController -Result appletStartSleepSequence(bool flag) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInBool(&g_appletIGlobalStateController, flag, 2); -} - -Result appletStartShutdownSequence(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIGlobalStateController, 3); -} - -Result appletStartRebootSequence(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIGlobalStateController, 4); -} - -Result appletIsAutoPowerDownRequested(bool *out) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(7,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletIGlobalStateController, out, 9); -} - -Result appletLoadAndApplyIdlePolicySettings(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIGlobalStateController, 10); -} - -Result appletNotifyCecSettingsChanged(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIGlobalStateController, 11); -} - -Result appletSetDefaultHomeButtonLongPressTime(s64 val) { - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU64(&g_appletIGlobalStateController, val, 12); -} - -Result appletUpdateDefaultDisplayResolution(void) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIGlobalStateController, 13); -} - -Result appletShouldSleepOnBoot(bool *out) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletIGlobalStateController, out, 14); -} - -Result appletGetHdcpAuthenticationFailedEvent(Event *out_event) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetEvent(&g_appletIGlobalStateController, out_event, 15, false); -} +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartSleepSequence(bool flag), &g_appletIGlobalStateController, 2, _appletCmdInBool, __nx_applet_type != AppletType_SystemApplet, flag) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartShutdownSequence(void), &g_appletIGlobalStateController, 3, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletStartRebootSequence(void), &g_appletIGlobalStateController, 4, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletIsAutoPowerDownRequested(bool *out), &g_appletIGlobalStateController, 9, _appletCmdNoInOutBool, __nx_applet_type != AppletType_SystemApplet, (7,0,0), out) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletLoadAndApplyIdlePolicySettings(void), &g_appletIGlobalStateController, 10, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletNotifyCecSettingsChanged(void), &g_appletIGlobalStateController, 11, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet, (2,0,0)) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetDefaultHomeButtonLongPressTime(s64 val), &g_appletIGlobalStateController, 12, _appletCmdInU64, __nx_applet_type != AppletType_SystemApplet, (3,0,0), val) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletUpdateDefaultDisplayResolution(void), &g_appletIGlobalStateController, 13, _appletCmdNoIO, __nx_applet_type != AppletType_SystemApplet, (3,0,0)) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletShouldSleepOnBoot(bool *out), &g_appletIGlobalStateController, 14, _appletCmdNoInOutBool, __nx_applet_type != AppletType_SystemApplet, (3,0,0), out) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetHdcpAuthenticationFailedEvent(Event *out_event), &g_appletIGlobalStateController, 15, _appletGetEvent, __nx_applet_type != AppletType_SystemApplet, (4,0,0), out_event, false) // IApplicationCreator static Result _appletApplicationCreateState(AppletApplication *a) { - Result rc=0; - - rc = _appletGetEvent(&a->s, &a->StateChangedEvent, 0, false);//GetAppletStateChangedEvent - - return rc; + return _appletGetEvent(&a->s, &a->StateChangedEvent, false, 0);//GetAppletStateChangedEvent } -static Result _appletApplicationCreate(AppletApplication *a, Service* srv, u64 cmd_id) { +static Result _appletApplicationCreate(Service* srv, AppletApplication *a, u32 cmd_id) { Result rc=0; memset(a, 0, sizeof(AppletApplication)); @@ -4543,45 +2322,22 @@ static Result _appletApplicationCreate(AppletApplication *a, Service* srv, u64 c return rc; } -static Result _appletApplicationCreateIn64(AppletApplication *a, Service* srv, u64 cmd_id, u64 val) { +static Result _appletApplicationCreateIn64(Service* srv, AppletApplication *a, u64 val, u32 cmd_id) { Result rc=0; memset(a, 0, sizeof(AppletApplication)); - rc = _appletGetSessionIn64(srv, &a->s, cmd_id, val); + rc = _appletGetSessionIn64(srv, &a->s, val, cmd_id); if (R_SUCCEEDED(rc)) rc = _appletApplicationCreateState(a); return rc; } -Result appletCreateApplication(AppletApplication *a, u64 titleID) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletApplicationCreateIn64(a, &g_appletIApplicationCreator, 0, titleID); -} - -Result appletPopLaunchRequestedApplication(AppletApplication *a) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletApplicationCreate(a, &g_appletIApplicationCreator, 1); -} - -Result appletCreateSystemApplication(AppletApplication *a, u64 titleID) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletApplicationCreateIn64(a, &g_appletIApplicationCreator, 10, titleID); -} - -Result appletPopFloatingApplicationForDevelopment(AppletApplication *a) { - if (__nx_applet_type != AppletType_SystemApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletApplicationCreate(a, &g_appletIApplicationCreator, 100); -} +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletCreateApplication(AppletApplication *a, u64 titleID), &g_appletIApplicationCreator, 0, _appletApplicationCreateIn64, __nx_applet_type != AppletType_SystemApplet, a, titleID) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopLaunchRequestedApplication(AppletApplication *a), &g_appletIApplicationCreator, 1, _appletApplicationCreate, __nx_applet_type != AppletType_SystemApplet, a) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletCreateSystemApplication(AppletApplication *a, u64 titleID), &g_appletIApplicationCreator, 10, _appletApplicationCreateIn64, __nx_applet_type != AppletType_SystemApplet, a, titleID) +IPC_MAKE_CMD_IMPL_INITEXPR(Result appletPopFloatingApplicationForDevelopment(AppletApplication *a), &g_appletIApplicationCreator, 100, _appletApplicationCreate, __nx_applet_type != AppletType_SystemApplet, a) // IApplicationAccessor @@ -4595,38 +2351,9 @@ bool appletApplicationActive(AppletApplication *a) { return serviceIsActive(&a->s); } -Result appletApplicationStart(AppletApplication *a) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - rc = _appletCmdNoIO(&a->s, 10);//Start - - return rc; -} - -Result appletApplicationRequestExit(AppletApplication *a) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - rc = _appletCmdNoIO(&a->s, 20);//RequestExit - - return rc; -} - -Result appletApplicationTerminate(AppletApplication *a) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - rc = _appletCmdNoIO(&a->s, 25);//Terminate - - return rc; -} +IPC_MAKE_CMD_IMPL(Result appletApplicationStart(AppletApplication *a), &a->s, 10, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletApplicationRequestExit(AppletApplication *a), &a->s, 20, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletApplicationTerminate(AppletApplication *a), &a->s, 25, _appletCmdNoIO) void appletApplicationJoin(AppletApplication *a) { Result rc=0; @@ -4661,30 +2388,9 @@ AppletApplicationExitReason appletApplicationGetExitReason(AppletApplication *a) return a->exitreason; } -Result appletApplicationRequestForApplicationToGetForeground(AppletApplication *a) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - rc = _appletCmdNoIO(&a->s, 101);//RequestForApplicationToGetForeground - - return rc; -} - -Result appletApplicationTerminateAllLibraryApplets(AppletApplication *a) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&a->s, 110); -} - -Result appletApplicationAreAnyLibraryAppletsLeft(AppletApplication *a, bool *out) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutBool(&a->s, out, 111); -} +IPC_MAKE_CMD_IMPL(Result appletApplicationRequestForApplicationToGetForeground(AppletApplication *a), &a->s, 101, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletApplicationTerminateAllLibraryApplets(AppletApplication *a), &a->s, 110, _appletCmdNoIO) +IPC_MAKE_CMD_IMPL(Result appletApplicationAreAnyLibraryAppletsLeft(AppletApplication *a, bool *out), &a->s, 111, _appletCmdNoInOutBool, out) Result appletApplicationRequestExitLibraryAppletOrTerminate(AppletApplication *a, u64 timeout) { Result rc=0; @@ -4700,18 +2406,7 @@ Result appletApplicationRequestExitLibraryAppletOrTerminate(AppletApplication *a return rc; } -Result appletApplicationGetApplicationId(AppletApplication *a, u64 *titleID) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - rc = _appletCmdNoInOut64(&a->s, titleID, 120);//GetApplicationId - - return rc; -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetApplicationId(AppletApplication *a, u64 *titleID), &a->s, 120, _appletCmdNoInOut64, (6,0,0), titleID) Result appletApplicationPushLaunchParameter(AppletApplication *a, AppletLaunchParameterKind kind, AppletStorage* s) { if (!serviceIsActive(&a->s)) @@ -4719,58 +2414,18 @@ Result appletApplicationPushLaunchParameter(AppletApplication *a, AppletLaunchPa if (!serviceIsActive(&s->s)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - serviceSendObject(&s->s, &c); - - struct { - u64 magic; - u64 cmd_id; - u32 kind; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 121; - raw->kind = kind; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - + u32 tmpkind=kind; + serviceAssumeDomain(&a->s); + Result rc = serviceDispatchIn(&a->s, 121, tmpkind, + .in_num_objects = 1, + .in_objects = { &s->s }, + ); appletStorageClose(s); - return rc; } -Result appletApplicationGetApplicationControlProperty(AppletApplication *a, NacpStruct *nacp) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInRecvBuf(&a->s, nacp, sizeof(*nacp), 122);//GetApplicationControlProperty -} - -Result appletApplicationGetApplicationLaunchProperty(AppletApplication *a, AppletApplicationLaunchProperty *out) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInRecvBuf(&a->s, out, sizeof(*out), 123);//GetApplicationLaunchProperty -} +IPC_MAKE_CMD_IMPL( Result appletApplicationGetApplicationControlProperty(AppletApplication *a, NacpStruct *nacp), &a->s, 122, _appletCmdNoInRecvBuf, nacp, sizeof(*nacp)) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetApplicationLaunchProperty(AppletApplication *a, AppletApplicationLaunchProperty *out), &a->s, 123, _appletCmdNoInRecvBuf, (2,0,0), out, sizeof(*out)) Result appletApplicationGetApplicationLaunchRequestInfo(AppletApplication *a, AppletApplicationLaunchRequestInfo *out) { if (!serviceIsActive(&a->s)) @@ -4778,170 +2433,42 @@ Result appletApplicationGetApplicationLaunchRequestInfo(AppletApplication *a, Ap if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 124; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - AppletApplicationLaunchRequestInfo out; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + serviceAssumeDomain(&a->s); + return serviceDispatchOut(&a->s, 124, *out); } -Result appletApplicationSetUsers(AppletApplication *a, const u128 *userIDs, s32 count, bool flag) { +Result appletApplicationSetUsers(AppletApplication *a, const AccountUid *userIDs, s32 count, bool flag) { if (!serviceIsActive(&a->s)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u8 flag; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 130; - raw->flag = flag!=0; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + u8 tmp = flag!=0; + serviceAssumeDomain(&a->s); + return serviceDispatchIn(&a->s, 130, tmp, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { userIDs, count*sizeof(AccountUid) } }, + ); } -Result appletApplicationCheckRightsEnvironmentAvailable(AppletApplication *a, bool *out) { - Result rc=0; +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationCheckRightsEnvironmentAvailable(AppletApplication *a, bool *out), &a->s, 131, _appletCmdNoInOutBool, (6,0,0), out) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 *handle), &a->s, 132, _appletCmdNoInOut64, (6,0,0), handle) +Result appletApplicationGetDesirableUids(AppletApplication *a, AccountUid *userIDs, s32 count, s32 *total_out) { if (!serviceIsActive(&a->s)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - rc = _appletCmdNoInOutBool(&a->s, out, 131);//CheckRightsEnvironmentAvailable - - return rc; + serviceAssumeDomain(&a->s); + return serviceDispatchOut(&a->s, 140, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { userIDs, count*sizeof(AccountUid) } }, + ); } -Result appletApplicationGetNsRightsEnvironmentHandle(AppletApplication *a, u64 *handle) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - rc = _appletCmdNoInOut64(&a->s, handle, 132);//GetNsRightsEnvironmentHandle - - return rc; -} - -Result appletApplicationGetDesirableUids(AppletApplication *a, u128 *userIDs, s32 count, s32 *total_out) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 140; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s32 total_out; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } - - return rc; -} - -Result appletApplicationReportApplicationExitTimeout(AppletApplication *a) { - Result rc=0; - - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - rc = _appletCmdNoIO(&a->s, 150);//ReportApplicationExitTimeout - - return rc; -} - -Result appletApplicationSetApplicationAttribute(AppletApplication *a, const AppletApplicationAttribute *attr) { - if (!serviceIsActive(&a->s)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdSendBufNoOut(&a->s, attr, sizeof(*attr), 160);//SetApplicationAttribute -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationReportApplicationExitTimeout(AppletApplication *a), &a->s, 150, _appletCmdNoIO, (6,0,0)) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletApplicationSetApplicationAttribute(AppletApplication *a, const AppletApplicationAttribute *attr), &a->s, 160, _appletCmdSendBufNoOut, (8,0,0), attr, sizeof(*attr)) Result appletApplicationHasSaveDataAccessPermission(AppletApplication *a, u64 titleID, bool *out) { if (!serviceIsActive(&a->s)) @@ -4949,129 +2476,27 @@ Result appletApplicationHasSaveDataAccessPermission(AppletApplication *a, u64 ti if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 titleID; - } *raw; - - raw = serviceIpcPrepareHeader(&a->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 170; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&a->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 out; - } *resp; - - serviceIpcParse(&a->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out!=0; - } - + u8 tmpout=0; + serviceAssumeDomain(&a->s); + Result rc = serviceDispatchInOut(&a->s, 170, titleID, tmpout); + if (R_SUCCEEDED(rc) && out) *out = tmpout!=0; return rc; } // ILibraryAppletSelfAccessor -Result appletPopInData(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutStorage(&g_appletILibraryAppletSelfAccessor, s, 0); -} - -Result appletPushOutData(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInStorage(&g_appletILibraryAppletSelfAccessor, s, 1); -} - -Result appletPopInteractiveInData(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutStorage(&g_appletILibraryAppletSelfAccessor, s, 2); -} - -Result appletPushInteractiveOutData(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInStorage(&g_appletILibraryAppletSelfAccessor, s, 3); -} - -Result appletGetPopInDataEvent(Event *out_event) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetEvent(&g_appletILibraryAppletSelfAccessor, out_event, 5, false); -} - -Result appletGetPopInteractiveInDataEvent(Event *out_event) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetEvent(&g_appletILibraryAppletSelfAccessor, out_event, 6, false); -} - -static Result _appletExitProcessAndReturn(void) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 10); -} - -Result appletGetLibraryAppletInfo(LibAppletInfo *info) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetLibraryAppletInfo(&g_appletILibraryAppletSelfAccessor, info, 11); -} - -Result appletGetMainAppletIdentityInfo(AppletIdentityInfo *info) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetIdentityInfo(&g_appletILibraryAppletSelfAccessor, info, 12); -} - -Result appletCanUseApplicationCore(bool *out) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutBool(&g_appletILibraryAppletSelfAccessor, out, 13); -} - -Result appletGetCallerAppletIdentityInfo(AppletIdentityInfo *info) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetIdentityInfo(&g_appletILibraryAppletSelfAccessor, info, 14); -} - -Result appletGetMainAppletApplicationControlProperty(NacpStruct *nacp) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInRecvBuf(&g_appletILibraryAppletSelfAccessor, nacp, sizeof(*nacp), 15); -} +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 0, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushOutData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 1, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopInteractiveInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 2, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPushInteractiveOutData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 3, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopInDataEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 5, _appletGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopInteractiveInDataEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 6, _appletGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false) +IPC_MAKE_CMD_IMPL_INITEXPR(static Result _appletExitProcessAndReturn(void), &g_appletILibraryAppletSelfAccessor, 10, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetLibraryAppletInfo(LibAppletInfo *info), &g_appletILibraryAppletSelfAccessor, 11, _appletGetLibraryAppletInfo, __nx_applet_type != AppletType_LibraryApplet, info) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetMainAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 12, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, info) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletCanUseApplicationCore(bool *out), &g_appletILibraryAppletSelfAccessor, 13, _appletCmdNoInOutBool, __nx_applet_type != AppletType_LibraryApplet, out) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetCallerAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 14, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, info) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetMainAppletApplicationControlProperty(NacpStruct *nacp), &g_appletILibraryAppletSelfAccessor, 15, _appletCmdNoInRecvBuf, __nx_applet_type != AppletType_LibraryApplet, (2,0,0), nacp, sizeof(*nacp)) Result appletGetMainAppletStorageId(FsStorageId *storageId) { u8 tmp=0; @@ -5090,291 +2515,60 @@ Result appletGetMainAppletStorageId(FsStorageId *storageId) { Result appletGetCallerAppletIdentityInfoStack(AppletIdentityInfo *stack, s32 count, s32 *total_out) { if (__nx_applet_type != AppletType_LibraryApplet) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, stack, count*sizeof(AppletIdentityInfo), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletILibraryAppletSelfAccessor, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 17; - - Result rc = serviceIpcDispatch(&g_appletILibraryAppletSelfAccessor); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - s32 total_out; - } *resp; - - serviceIpcParse(&g_appletILibraryAppletSelfAccessor, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } - - return rc; + serviceAssumeDomain(&g_appletILibraryAppletSelfAccessor); + return serviceDispatchOut(&g_appletILibraryAppletSelfAccessor, 17, *total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { stack, count*sizeof(AppletIdentityInfo) } }, + ); } -Result appletGetNextReturnDestinationAppletIdentityInfo(AppletIdentityInfo *info) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetNextReturnDestinationAppletIdentityInfo(AppletIdentityInfo *info), &g_appletILibraryAppletSelfAccessor, 18, _appletGetIdentityInfo, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), info) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetDesirableKeyboardLayout(u32 *layout), &g_appletILibraryAppletSelfAccessor, 19, _appletCmdNoInOut32, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), layout) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletPopExtraStorage(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 20, _appletCmdNoInOutStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetPopExtraStorageEvent(Event *out_event), &g_appletILibraryAppletSelfAccessor, 25, _appletGetEvent, __nx_applet_type != AppletType_LibraryApplet, out_event, false) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletUnpopInData(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 30, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletUnpopExtraStorage(AppletStorage *s), &g_appletILibraryAppletSelfAccessor, 31, _appletCmdInStorage, __nx_applet_type != AppletType_LibraryApplet, s) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetIndirectLayerProducerHandle(u64 *out), &g_appletILibraryAppletSelfAccessor, 40, _appletCmdNoInOut64, __nx_applet_type != AppletType_LibraryApplet, (2,0,0), out) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetMainAppletApplicationDesiredLanguage(u64 *LanguageCode), &g_appletILibraryAppletSelfAccessor, 60, _appletCmdNoInOut64, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), LanguageCode) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletGetCurrentApplicationId(u64 *titleID), &g_appletILibraryAppletSelfAccessor, 70, _appletCmdNoInOut64, __nx_applet_type != AppletType_LibraryApplet, (8,0,0), titleID) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletRequestExitToSelf(void), &g_appletILibraryAppletSelfAccessor, 80, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (6,0,0)) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletCreateGameMovieTrimmer(Service* srv_out, TransferMemory *tmem), &g_appletILibraryAppletSelfAccessor, 100, _appletCmdInTmemOutSession, __nx_applet_type != AppletType_LibraryApplet, (4,0,0), srv_out, tmem) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletReserveResourceForMovieOperation(void), &g_appletILibraryAppletSelfAccessor, 101, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (5,0,0)) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletUnreserveResourceForMovieOperation(void), &g_appletILibraryAppletSelfAccessor, 102, _appletCmdNoIO, __nx_applet_type != AppletType_LibraryApplet, (5,0,0)) - return _appletGetIdentityInfo(&g_appletILibraryAppletSelfAccessor, info, 18); -} - -Result appletGetDesirableKeyboardLayout(u32 *layout) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut32(&g_appletILibraryAppletSelfAccessor, layout, 19); -} - -Result appletPopExtraStorage(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOutStorage(&g_appletILibraryAppletSelfAccessor, s, 20); -} - -Result appletGetPopExtraStorageEvent(Event *out_event) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletGetEvent(&g_appletILibraryAppletSelfAccessor, out_event, 25, false); -} - -Result appletUnpopInData(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInStorage(&g_appletILibraryAppletSelfAccessor, s, 30); -} - -Result appletUnpopExtraStorage(AppletStorage *s) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInStorage(&g_appletILibraryAppletSelfAccessor, s, 31); -} - -Result appletGetIndirectLayerProducerHandle(u64 *out) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut64(&g_appletILibraryAppletSelfAccessor, out, 40); -} - -Result appletGetMainAppletApplicationDesiredLanguage(u64 *LanguageCode) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut64(&g_appletILibraryAppletSelfAccessor, LanguageCode, 60); -} - -Result appletGetCurrentApplicationId(u64 *titleID) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOut64(&g_appletILibraryAppletSelfAccessor, titleID, 70); -} - -Result appletRequestExitToSelf(void) { +Result appletGetMainAppletAvailableUsers(AccountUid *userIDs, s32 count, bool *flag, s32 *total_out) { if (__nx_applet_type != AppletType_LibraryApplet) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 80); -} - -Result appletCreateGameMovieTrimmer(Service* srv_out, TransferMemory *tmem) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(4,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - ipcSendHandleCopy(&c, tmem->handle); - struct { - u64 magic; - u64 cmd_id; - u64 size; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletILibraryAppletSelfAccessor, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 100; - raw->size = tmem->size; - - Result rc = serviceIpcDispatch(&g_appletILibraryAppletSelfAccessor); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletILibraryAppletSelfAccessor, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && srv_out) { - serviceCreateSubservice(srv_out, &g_appletILibraryAppletSelfAccessor, &r, 0); - } - } - - return rc; -} - -Result appletReserveResourceForMovieOperation(void) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 101); -} - -Result appletUnreserveResourceForMovieOperation(void) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletILibraryAppletSelfAccessor, 102); -} - -Result appletGetMainAppletAvailableUsers(u128 *userIDs, s32 count, bool *flag, s32 *total_out) { - if (__nx_applet_type != AppletType_LibraryApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(6,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, userIDs, count*sizeof(u128), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletILibraryAppletSelfAccessor, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 110; - - Result rc = serviceIpcDispatch(&g_appletILibraryAppletSelfAccessor); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 flag; - s32 total_out; - } *resp; - - serviceIpcParse(&g_appletILibraryAppletSelfAccessor, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && flag) *flag = resp->flag!=0; - if (R_SUCCEEDED(rc) && total_out) *total_out = resp->total_out; - } + u8 flag; + s32 total_out; + } out; + serviceAssumeDomain(&g_appletILibraryAppletSelfAccessor); + Result rc = serviceDispatchOut(&g_appletILibraryAppletSelfAccessor, 110, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { userIDs, count*sizeof(AccountUid) } }, + ); + if (R_SUCCEEDED(rc) && flag) *flag = out.flag!=0; + if (R_SUCCEEDED(rc) && total_out) *total_out = out.total_out; return rc; } // IOverlayFunctions -Result appletBeginToWatchShortHomeButtonMessage(void) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 0); -} - -Result appletEndToWatchShortHomeButtonMessage(void) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoIO(&g_appletIFunctions, 1); -} - -Result appletGetApplicationIdForLogo(u64 *titleID) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdNoInOut64(&g_appletIFunctions, titleID, 2); -} - -Result appletSetGpuTimeSliceBoost(u64 val) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - - return _appletCmdInU64(&g_appletIFunctions, val, 3); -} - -Result appletSetAutoSleepTimeAndDimmingTimeEnabled(bool flag) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletIFunctions, flag, 4); -} - -Result appletTerminateApplicationAndSetReason(Result reason) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(2,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInU32(&g_appletIFunctions, reason, 5); -} - -Result appletSetScreenShotPermissionGlobally(bool flag) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(3,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletIFunctions, flag, 6); -} +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletBeginToWatchShortHomeButtonMessage(void), &g_appletIFunctions, 0, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletEndToWatchShortHomeButtonMessage(void), &g_appletIFunctions, 1, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletGetApplicationIdForLogo(u64 *titleID), &g_appletIFunctions, 2, _appletCmdNoInOut64, __nx_applet_type != AppletType_OverlayApplet, titleID) +IPC_MAKE_CMD_IMPL_INITEXPR( Result appletSetGpuTimeSliceBoost(u64 val), &g_appletIFunctions, 3, _appletCmdInU64, __nx_applet_type != AppletType_OverlayApplet, val) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetAutoSleepTimeAndDimmingTimeEnabled(bool flag), &g_appletIFunctions, 4, _appletCmdInBool, __nx_applet_type != AppletType_OverlayApplet, (2,0,0), flag) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletTerminateApplicationAndSetReason(Result reason), &g_appletIFunctions, 5, _appletCmdInU32, __nx_applet_type != AppletType_OverlayApplet, (2,0,0), reason) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetScreenShotPermissionGlobally(bool flag), &g_appletIFunctions, 6, _appletCmdInBool, __nx_applet_type != AppletType_OverlayApplet, (3,0,0), flag) Result appletStartShutdownSequenceForOverlay(void) { Result rc=0; @@ -5402,115 +2596,34 @@ Result appletStartRebootSequenceForOverlay(void) { return rc; } -Result appletSetHandlingHomeButtonShortPressedEnabled(bool flag) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletIFunctions, flag, 20); -} - -Result appletBeginToObserveHidInputForDevelop(void) { - if (__nx_applet_type != AppletType_OverlayApplet) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(5,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoIO(&g_appletIFunctions, 101); -} +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletSetHandlingHomeButtonShortPressedEnabled(bool flag), &g_appletIFunctions, 20, _appletCmdInBool, __nx_applet_type != AppletType_OverlayApplet, (8,0,0), flag) +IPC_MAKE_CMD_IMPL_INITEXPR_HOSVER(Result appletBeginToObserveHidInputForDevelop(void), &g_appletIFunctions, 101, _appletCmdNoIO, __nx_applet_type != AppletType_OverlayApplet, (5,0,0)) // IAppletCommonFunctions -Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, size_t *transfer_size) { +Result appletReadThemeStorage(void* buffer, size_t size, u64 offset, u64 *transfer_size) { if (!serviceIsActive(&g_appletIAppletCommonFunctions)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); - - struct { - u64 magic; - u64 cmd_id; - u64 offset; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIAppletCommonFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - raw->offset = offset; - - Result rc = serviceIpcDispatch(&g_appletIAppletCommonFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 transfer_size; - } *resp; - - serviceIpcParse(&g_appletIAppletCommonFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && transfer_size) *transfer_size = resp->transfer_size; - } - - return rc; + serviceAssumeDomain(&g_appletIAppletCommonFunctions); + return serviceDispatchInOut(&g_appletIAppletCommonFunctions, 10, offset, *transfer_size, + .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); } Result appletWriteThemeStorage(const void* buffer, size_t size, u64 offset) { if (!serviceIsActive(&g_appletIAppletCommonFunctions)) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendSmart(&c, g_appletIAppletCommonFunctions_ptrbufsize, buffer, size, 0); - - struct { - u64 magic; - u64 cmd_id; - u64 offset; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIAppletCommonFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->offset = offset; - - Result rc = serviceIpcDispatch(&g_appletIAppletCommonFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIAppletCommonFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIAppletCommonFunctions); + return serviceDispatchIn(&g_appletIAppletCommonFunctions, 11, offset, + .buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + ); } -Result appletGetDisplayLogicalResolution(s32 *width, s32 *height) { - if (!serviceIsActive(&g_appletIAppletCommonFunctions)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletGetResolution(&g_appletIAppletCommonFunctions, width, height, 40); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetDisplayLogicalResolution(s32 *width, s32 *height), &g_appletIAppletCommonFunctions, 40, _appletGetResolution, (8,0,0), width, height) Result appletSetDisplayMagnification(float x, float y, float width, float height) { if (!serviceIsActive(&g_appletIAppletCommonFunctions)) @@ -5518,164 +2631,63 @@ Result appletSetDisplayMagnification(float x, float y, float width, float height if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { float x; float y; float width; float height; - } *raw; + } in = { x, y, width, height }; - raw = serviceIpcPrepareHeader(&g_appletIAppletCommonFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 42; - raw->x = x; - raw->y = y; - raw->width = width; - raw->height = height; - - Result rc = serviceIpcDispatch(&g_appletIAppletCommonFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIAppletCommonFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIAppletCommonFunctions); + return serviceDispatchIn(&g_appletIAppletCommonFunctions, 42, in); } -Result appletSetHomeButtonDoubleClickEnabled(bool flag) { - if (!serviceIsActive(&g_appletIAppletCommonFunctions)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdInBool(&g_appletIAppletCommonFunctions, flag, 50); -} - -Result appletGetHomeButtonDoubleClickEnabled(bool *out) { - if (!serviceIsActive(&g_appletIAppletCommonFunctions)) - return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (hosversionBefore(8,0,0)) - return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - return _appletCmdNoInOutBool(&g_appletIAppletCommonFunctions, out, 51); -} +IPC_MAKE_CMD_IMPL_HOSVER(Result appletSetHomeButtonDoubleClickEnabled(bool flag), &g_appletIAppletCommonFunctions, 50, _appletCmdInBool, (8,0,0), flag) +IPC_MAKE_CMD_IMPL_HOSVER(Result appletGetHomeButtonDoubleClickEnabled(bool *out), &g_appletIAppletCommonFunctions, 51, _appletCmdNoInOutBool, (8,0,0), out) // IDebugFunctions -Result appletOpenMainApplication(AppletApplication *a) { - return _appletApplicationCreate(a, &g_appletIDebugFunctions, 1); -} +IPC_MAKE_CMD_IMPL(Result appletOpenMainApplication(AppletApplication *a), &g_appletIDebugFunctions, 1, _appletApplicationCreate, a) +IPC_MAKE_CMD_IMPL(Result appletPerformSystemButtonPressing(AppletSystemButtonType type), &g_appletIDebugFunctions, 10, _appletCmdInU32, type) +IPC_MAKE_CMD_IMPL(Result appletInvalidateTransitionLayer(void), &g_appletIDebugFunctions, 20, _appletCmdNoIO) -Result appletPerformSystemButtonPressing(AppletSystemButtonType type) { - return _appletCmdInU32(&g_appletIDebugFunctions, type, 10); -} - -Result appletInvalidateTransitionLayer(void) { - return _appletCmdNoIO(&g_appletIDebugFunctions, 20); -} - -Result appletRequestLaunchApplicationWithUserAndArgumentForDebug(u64 titleID, u128 *userIDs, size_t total_userIDs, bool flag, const void* buffer, size_t size) { +Result appletRequestLaunchApplicationWithUserAndArgumentForDebug(u64 titleID, AccountUid *userIDs, size_t total_userIDs, bool flag, const void* buffer, size_t size) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, userIDs, total_userIDs*sizeof(u128), BufferType_Normal); - ipcAddSendBuffer(&c, buffer, size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 flag; u64 titleID; - } *raw; + } in = { flag!=0, titleID }; - raw = serviceIpcPrepareHeader(&g_appletIDebugFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 30; - raw->flag = flag!=0; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_appletIDebugFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_appletIDebugFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + serviceAssumeDomain(&g_appletIDebugFunctions); + return serviceDispatchIn(&g_appletIDebugFunctions, 30, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { userIDs, total_userIDs*sizeof(AccountUid) }, + { buffer, size }, + }, + ); } Result appletGetAppletResourceUsageInfo(AppletResourceUsageInfo *info) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_appletIDebugFunctions, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 40; - - Result rc = serviceIpcDispatch(&g_appletIDebugFunctions); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - AppletResourceUsageInfo info; - } *resp; - - serviceIpcParse(&g_appletIDebugFunctions, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && info) *info = resp->info; - } - - return rc; + serviceAssumeDomain(&g_appletIDebugFunctions); + return serviceDispatchOut(&g_appletIDebugFunctions, 40, *info); } // State / other -u8 appletGetOperationMode(void) { +AppletOperationMode appletGetOperationMode(void) { return g_appletOperationMode; } -u32 appletGetPerformanceMode(void) { +ApmPerformanceMode appletGetPerformanceMode(void) { return g_appletPerformanceMode; } @@ -5709,7 +2721,7 @@ Result appletGetMessage(u32 *msg) { } bool appletProcessMessage(u32 msg) { - Result rc; + Result rc=0; switch(msg) { case AppletMessage_ExitRequested: diff --git a/nx/source/services/async.c b/nx/source/services/async.c new file mode 100644 index 00000000..b9c19987 --- /dev/null +++ b/nx/source/services/async.c @@ -0,0 +1,115 @@ +#include "sf/service.h" +#include "runtime/hosversion.h" +#include "services/async.h" +#include "applets/error.h" + +static Result _asyncCmdNoIO(Service* srv, u32 cmd_id) { + return serviceDispatch(srv, cmd_id); +} + +static Result _asyncCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _asyncCmdNoInOutBuf(Service* srv, void* buffer, size_t size, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); +} + +// IAsyncValue + +void asyncValueClose(AsyncValue *a) { + if (serviceIsActive(&a->s)) { + asyncValueCancel(a); // Official sw ignores rc from this prior to waiting on the event. + asyncValueWait(a, U64_MAX); + } + + serviceClose(&a->s); + eventClose(&a->event); +} + +Result asyncValueWait(AsyncValue *a, u64 timeout) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return eventWait(&a->event, timeout); +} + +Result asyncValueGetSize(AsyncValue *a, u64 *size) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _asyncCmdNoInOutU64(&a->s, size, 0); +} + +Result asyncValueGet(AsyncValue *a, void* buffer, size_t size) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + Result rc = asyncValueWait(a, U64_MAX); + if (R_SUCCEEDED(rc)) rc = _asyncCmdNoInOutBuf(&a->s, buffer, size, 1); + return rc; +} + +Result asyncValueCancel(AsyncValue *a) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _asyncCmdNoIO(&a->s, 2); +} + +Result asyncValueGetErrorContext(AsyncValue *a, ErrorContext *context) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _asyncCmdNoInOutBuf(&a->s, context, sizeof(*context), 3); +} + +// AsyncResult + +void asyncResultClose(AsyncResult *a) { + if (serviceIsActive(&a->s)) { + asyncResultCancel(a); // Official sw ignores rc from this prior to waiting on the event. + asyncResultWait(a, U64_MAX); + } + + serviceClose(&a->s); + eventClose(&a->event); +} + +Result asyncResultWait(AsyncResult *a, u64 timeout) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return eventWait(&a->event, timeout); +} + +Result asyncResultGet(AsyncResult *a) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + Result rc = asyncResultWait(a, U64_MAX); + if (R_SUCCEEDED(rc)) rc = _asyncCmdNoIO(&a->s, 0); + return rc; +} + +Result asyncResultCancel(AsyncResult *a) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _asyncCmdNoIO(&a->s, 1); +} + +Result asyncResultGetErrorContext(AsyncResult *a, ErrorContext *context) { + if (!serviceIsActive(&a->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _asyncCmdNoInOutBuf(&a->s, context, sizeof(*context), 2); +} + diff --git a/nx/source/services/auddev.c b/nx/source/services/auddev.c index 38a448ae..6e075abf 100644 --- a/nx/source/services/auddev.c +++ b/nx/source/services/auddev.c @@ -11,7 +11,6 @@ static Service g_auddevIAudioDevice; static u64 g_auddevRefCnt; -static size_t g_auddevIpcBufferSize; static Result _auddevGetAudioDeviceService(Service* srv, Service* out_srv, u64 aruid); @@ -32,8 +31,6 @@ Result auddevInitialize(void) { rc = _auddevGetAudioDeviceService(&audrenMgrSrv, &g_auddevIAudioDevice, aruid); serviceClose(&audrenMgrSrv); - - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_auddevIAudioDevice.handle, &g_auddevIpcBufferSize); } if (R_FAILED(rc)) auddevExit(); @@ -102,7 +99,7 @@ Result auddevListAudioDeviceName(AudioDeviceName *DeviceNames, s32 max_names, s3 } *raw; if (!new_cmd) ipcAddRecvBuffer(&c, DeviceNames, sizeof(AudioDeviceName) * max_names, BufferType_Normal); - if (new_cmd) ipcAddRecvSmart(&c, g_auddevIpcBufferSize, DeviceNames, sizeof(AudioDeviceName) * max_names, 0); + if (new_cmd) ipcAddRecvSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceNames, sizeof(AudioDeviceName) * max_names, 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); @@ -144,7 +141,7 @@ Result auddevSetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float } *raw; if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); - if (new_cmd) ipcAddSendSmart(&c, g_auddevIpcBufferSize, DeviceName, sizeof(AudioDeviceName), 0); + if (new_cmd) ipcAddSendSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceName, sizeof(AudioDeviceName), 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); @@ -183,7 +180,7 @@ Result auddevGetAudioDeviceOutputVolume(const AudioDeviceName *DeviceName, float } *raw; if (!new_cmd) ipcAddSendBuffer(&c, DeviceName, sizeof(AudioDeviceName), BufferType_Normal); - if (new_cmd) ipcAddSendSmart(&c, g_auddevIpcBufferSize, DeviceName, sizeof(AudioDeviceName), 0); + if (new_cmd) ipcAddSendSmart(&c, g_auddevIAudioDevice.pointer_buffer_size, DeviceName, sizeof(AudioDeviceName), 0); raw = serviceIpcPrepareHeader(&g_auddevIAudioDevice, &c, sizeof(*raw)); diff --git a/nx/source/services/bsd.c b/nx/source/services/bsd.c index 62ac7f3c..5a6d3253 100644 --- a/nx/source/services/bsd.c +++ b/nx/source/services/bsd.c @@ -24,7 +24,6 @@ __thread Result g_bsdResult; __thread int g_bsdErrno; static Service g_bsdSrv; -static size_t g_bsdSrvIpcBufferSize; static Service g_bsdMonitor; static u64 g_bsdClientPid = -1; @@ -189,7 +188,7 @@ static int _bsdNameGetterCommand(u32 cmd_id, int sockfd, struct sockaddr *addr, socklen_t maxaddrlen = addrlen == NULL ? 0 : *addrlen; - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, addr, maxaddrlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, addr, maxaddrlen, 0); struct { u64 magic; @@ -247,9 +246,6 @@ Result bsdInitialize(const BsdInitConfig *config) { } if(R_FAILED(rc)) goto error; - rc = ipcQueryPointerBufferSize(g_bsdSrv.handle, &g_bsdSrvIpcBufferSize); - if(R_FAILED(rc)) goto error; - rc = smGetService(&g_bsdMonitor, bsd_srv); if(R_FAILED(rc)) goto error; @@ -270,7 +266,6 @@ error: } void bsdExit(void) { - g_bsdSrvIpcBufferSize = 0; g_bsdClientPid = 0; serviceClose(&g_bsdMonitor); serviceClose(&g_bsdSrv); @@ -294,7 +289,7 @@ int bsdOpen(const char *pathname, int flags) { ipcInitialize(&c); size_t pathlen = strlen(pathname) + 1; - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, pathname, pathlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, pathname, pathlen, 0); struct { u64 magic; @@ -315,15 +310,15 @@ int bsdSelect(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, st IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, readfds, readfds == NULL ? 0 : sizeof(fd_set), 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, writefds, writefds == NULL ? 0 : sizeof(fd_set), 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 2); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, exceptfds, exceptfds == NULL ? 0 : sizeof(fd_set), 3); struct { @@ -349,8 +344,8 @@ int bsdPoll(struct pollfd *fds, nfds_t nfds, int timeout) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, fds, nfds * sizeof(struct pollfd), 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, fds, nfds * sizeof(struct pollfd), 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, fds, nfds * sizeof(struct pollfd), 0); struct { u64 magic; @@ -375,10 +370,10 @@ int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, name, 4 * namelen, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, newp, newlen, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, name, 4 * namelen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, newp, newlen, 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, oldp, inlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, oldp, inlen, 0); struct { u64 magic; @@ -405,7 +400,7 @@ int bsdSysctl(const int *name, unsigned int namelen, void *oldp, size_t *oldlenp ssize_t bsdRecv(int sockfd, void *buf, size_t len, int flags) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); struct { u64 magic; @@ -430,8 +425,8 @@ ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockadd ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, src_addr, inaddrlen, 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, src_addr, inaddrlen, 1); struct { u64 magic; @@ -453,7 +448,7 @@ ssize_t bsdRecvFrom(int sockfd, void *buf, size_t len, int flags, struct sockadd ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); struct { u64 magic; @@ -475,8 +470,8 @@ ssize_t bsdSend(int sockfd, const void* buf, size_t len, int flags) { ssize_t bsdSendTo(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, len, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, dest_addr, addrlen, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, len, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, dest_addr, addrlen, 1); struct { u64 magic; @@ -502,7 +497,7 @@ int bsdAccept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0); struct { u64 magic; @@ -522,7 +517,7 @@ int bsdBind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { int bsdConnect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, addr, addrlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, addr, addrlen, 0); struct { u64 magic; @@ -553,7 +548,7 @@ int bsdGetSockOpt(int sockfd, int level, int optname, void *optval, socklen_t *o socklen_t inoptlen = optlen == NULL ? 0 : *optlen; - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, optval, inoptlen, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, optval, inoptlen, 0); struct { u64 magic; @@ -645,15 +640,15 @@ int bsdIoctl(int fd, int request, void *data) { ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in1, in1sz, 0); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in2, in2sz, 1); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in3, in3sz, 2); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, in4, in4sz, 3); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in1, in1sz, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in2, in2sz, 1); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in3, in3sz, 2); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, in4, in4sz, 3); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out1, out1sz, 0); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out2, out2sz, 1); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out3, out3sz, 2); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, out4, out4sz, 3); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out1, out1sz, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out2, out2sz, 1); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out3, out3sz, 2); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, out4, out4sz, 3); struct { u64 magic; @@ -711,7 +706,7 @@ int bsdSetSockOpt(int sockfd, int level, int optname, const void *optval, sockle IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, optval, optlen, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, optval, optlen, 0); struct { u64 magic; @@ -775,7 +770,7 @@ int bsdShutdownAllSockets(int how) { ssize_t bsdWrite(int fd, const void *buf, size_t count) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); + ipcAddSendSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0); struct { u64 magic; @@ -795,7 +790,7 @@ ssize_t bsdWrite(int fd, const void *buf, size_t count) { ssize_t bsdRead(int fd, void *buf, size_t count) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_bsdSrvIpcBufferSize, buf, count, 0); + ipcAddRecvSmart(&c, g_bsdSrv.pointer_buffer_size, buf, count, 0); struct { u64 magic; diff --git a/nx/source/services/caps.c b/nx/source/services/caps.c new file mode 100644 index 00000000..11cef1cf --- /dev/null +++ b/nx/source/services/caps.c @@ -0,0 +1,17 @@ +#include +#include "types.h" +#include "result.h" +#include "arm/atomics.h" +#include "kernel/ipc.h" +#include "kernel/event.h" +#include "kernel/tmem.h" +#include "services/sm.h" +#include "services/caps.h" +#include "runtime/hosversion.h" + +u64 capsGetShimLibraryVersion(void) { + u64 version=1; // [7.0.0-8.1.0] + + return version; +} + diff --git a/nx/source/services/capssc.c b/nx/source/services/capssc.c index 10eedc6a..12169b8d 100644 --- a/nx/source/services/capssc.c +++ b/nx/source/services/capssc.c @@ -1,85 +1,45 @@ -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/caps.h" #include "services/capssc.h" -#include "services/sm.h" static Service g_capsscSrv; -static u64 g_capsscRefCnt; -Result capsscInitialize(void) { +NX_GENERATE_SERVICE_GUARD(capssc); + +Result _capsscInitialize(void) { Result rc=0; - atomicIncrement64(&g_capsscRefCnt); - - if (serviceIsActive(&g_capsscSrv)) - return 0; - if (hosversionBefore(2,0,0)) rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (R_SUCCEEDED(rc)) rc = smGetService(&g_capsscSrv, "caps:sc"); - if (R_FAILED(rc)) capsscExit(); - return rc; } -void capsscExit(void) { - if (atomicDecrement64(&g_capsscRefCnt) == 0) - serviceClose(&g_capsscSrv); +void _capsscCleanup(void) { + serviceClose(&g_capsscSrv); } Service* capsscGetServiceSession(void) { return &g_capsscSrv; } -Result capsscCaptureScreenshot(void* buf, size_t size, u32 inval, u64 width, u64 height, s64 buffer_count, s64 buffer_index, u64 timeout) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result capsscCaptureRawImageWithTimeout(void* buf, size_t size, u32 inval, u64 width, u64 height, s64 buffer_count, s64 buffer_index, u64 timeout) { + const struct { u32 inval; u64 width; u64 height; s64 buffer_count; s64 buffer_index; u64 timeout; - } *raw; + } in = { inval, width, height, buffer_count, buffer_index, timeout }; - ipcAddRecvBuffer(&c, buf, size, 1); - - raw = serviceIpcPrepareHeader(&g_capsscSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->inval = inval; - raw->width = width; - raw->height = height; - raw->buffer_count = buffer_count; - raw->buffer_index = buffer_index; - raw->timeout = timeout; - - Result rc = serviceIpcDispatch(&g_capsscSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_capsscSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_capsscSrv, 2, in, + .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, size } }, + ); } diff --git a/nx/source/services/capssu.c b/nx/source/services/capssu.c index 6cd109cd..c3c621fa 100644 --- a/nx/source/services/capssu.c +++ b/nx/source/services/capssu.c @@ -1,101 +1,157 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/applet.h" #include "services/caps.h" #include "services/capssu.h" -#include "services/sm.h" +#include "services/acc.h" static Service g_capssuSrv; -static u64 g_capssuRefCnt; -Result capssuInitialize(void) { +static Result _capssuSetShimLibraryVersion(u64 version); + +NX_GENERATE_SERVICE_GUARD(capssu); + +Result _capssuInitialize(void) { Result rc=0; - atomicIncrement64(&g_capssuRefCnt); - - if (serviceIsActive(&g_capssuSrv)) - return 0; - if (hosversionBefore(4,0,0)) rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); if (R_SUCCEEDED(rc)) rc = smGetService(&g_capssuSrv, "caps:su"); - if (R_FAILED(rc)) capssuExit(); + if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) rc = _capssuSetShimLibraryVersion(capsGetShimLibraryVersion()); return rc; } -void capssuExit(void) { - if (atomicDecrement64(&g_capssuRefCnt) == 0) - serviceClose(&g_capssuSrv); +void _capssuCleanup(void) { + serviceClose(&g_capssuSrv); } Service* capssuGetServiceSession(void) { return &g_capssuSrv; } -static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out) { +static Result _capssuSetShimLibraryVersion(u64 version) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + u64 AppletResourceUserId = 0; appletGetAppletResourceUserId(&AppletResourceUserId); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - CapsScreenShotAttribute attr; - u32 unk; + const struct { + u64 version; u64 AppletResourceUserId; - } *raw; + } in = { version, AppletResourceUserId }; - ipcSendPid(&c); - ipcAddSendBuffer(&c, buffer, size, 1); - - raw = serviceIpcPrepareHeader(&g_capssuSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 203; - raw->attr = *attr; - raw->unk = unk; - raw->AppletResourceUserId = AppletResourceUserId; - - Result rc = serviceIpcDispatch(&g_capssuSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - CapsApplicationAlbumEntry out; - } *resp; - - serviceIpcParse(&g_capssuSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + return serviceDispatchIn(&g_capssuSrv, 32, in, + .in_send_pid = true, + ); } -Result capssuSaveScreenShot(const void* buffer, size_t size, u32 unk, u32 attr_val, CapsApplicationAlbumEntry *out) { +static Result _capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsScreenShotAttribute attr; + u32 reportoption; + u64 AppletResourceUserId; + } in = { *attr, reportoption, AppletResourceUserId }; + + return serviceDispatchInOut(&g_capssuSrv, 203, in, *out, + .buffer_attrs = { SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buffer, size } }, + .in_send_pid = true, + ); +} + +static Result _capssuSaveScreenShotEx(u32 cmd_id, bool pid, const void* argbuf, size_t argbuf_size, const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsScreenShotAttribute attr; + u32 reportoption; + u64 AppletResourceUserId; + } in = { *attr, reportoption, AppletResourceUserId }; + + return serviceDispatchInOut(&g_capssuSrv, cmd_id, in, *out, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { argbuf, argbuf_size }, + { buffer, size }, + }, + .in_send_pid = pid, + ); +} + +Result capssuSaveScreenShot(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, CapsApplicationAlbumEntry *out) { CapsScreenShotAttribute attr; memset(&attr, 0, sizeof(attr)); - attr.unk_x0 = attr_val; + attr.orientation = orientation; + attr.unk_xc = 1; - return _capssuSaveScreenShotEx0(buffer, size, &attr, unk, out); + return _capssuSaveScreenShotEx0(buffer, size, &attr, reportoption, out); } -Result capssuSaveScreenShotEx0(const void* buffer, size_t size, CapsScreenShotAttribute *attr, u32 unk, CapsApplicationAlbumEntry *out) { - return _capssuSaveScreenShotEx0(buffer, size, attr, unk, out); +Result capssuSaveScreenShotWithUserData(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const void* userdata, size_t userdata_size, CapsApplicationAlbumEntry *out) { + CapsScreenShotAttribute attr; + CapsApplicationData appdata; + + if (userdata_size > sizeof(appdata).userdata) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + memset(&attr, 0, sizeof(attr)); + attr.orientation = orientation; + attr.unk_xc = 1; + + memset(&appdata, 0, sizeof(appdata)); + if (userdata && userdata_size) memcpy(appdata.userdata, userdata, userdata_size); + appdata.size = userdata_size; + + return capssuSaveScreenShotEx1(buffer, size, &attr, reportoption, &appdata, out); +} + +Result capssuSaveScreenShotWithUserIds(const void* buffer, size_t size, AlbumReportOption reportoption, AlbumImageOrientation orientation, const AccountUid* userIDs, size_t userID_count, CapsApplicationAlbumEntry *out) { + CapsScreenShotAttribute attr; + CapsUserIdList list; + + if (userID_count > ACC_USER_LIST_SIZE) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); + + memset(&attr, 0, sizeof(attr)); + attr.orientation = orientation; + attr.unk_xc = 1; + + memset(&list, 0, sizeof(list)); + if (userIDs && userID_count) memcpy(list.userIDs, userIDs, userID_count*sizeof(AccountUid)); + list.count = userID_count; + + return capssuSaveScreenShotEx2(buffer, size, &attr, reportoption, &list, out); +} + +Result capssuSaveScreenShotEx0(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationAlbumEntry *out) { + return _capssuSaveScreenShotEx0(buffer, size, attr, reportoption, out); +} + +Result capssuSaveScreenShotEx1(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsApplicationData *appdata, CapsApplicationAlbumEntry *out) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _capssuSaveScreenShotEx(205, true, appdata, sizeof(*appdata), buffer, size, attr, reportoption, out); +} + +Result capssuSaveScreenShotEx2(const void* buffer, size_t size, const CapsScreenShotAttribute *attr, AlbumReportOption reportoption, CapsUserIdList *list, CapsApplicationAlbumEntry *out) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _capssuSaveScreenShotEx(210, false, list, sizeof(*list), buffer, size, attr, reportoption, out); } diff --git a/nx/source/services/capsu.c b/nx/source/services/capsu.c new file mode 100644 index 00000000..6abc23c3 --- /dev/null +++ b/nx/source/services/capsu.c @@ -0,0 +1,380 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/applet.h" +#include "services/caps.h" +#include "services/capsu.h" +#include "services/acc.h" + +static Service g_capsuSrv; +static Service g_capsuAccessor; + +static Result _capsuSetShimLibraryVersion(u64 version); + +NX_GENERATE_SERVICE_GUARD(capsu); + +Result _capsuInitialize(void) { + Result rc=0; + + if (hosversionBefore(5,0,0)) + rc = MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + if (R_SUCCEEDED(rc)) rc = smGetService(&g_capsuSrv, "caps:u"); + + if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) rc = _capsuSetShimLibraryVersion(capsGetShimLibraryVersion()); + + return rc; +} + +void _capsuCleanup(void) { + serviceClose(&g_capsuAccessor); + serviceClose(&g_capsuSrv); +} + +Service* capsuGetServiceSession(void) { + return &g_capsuSrv; +} + +Service* capsuGetServiceSession_Accessor(void) { + return &g_capsuAccessor; +} + +static Result _capsuCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _capsuSetShimLibraryVersion(u64 version) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u64 version; + u64 AppletResourceUserId; + } in = { version, AppletResourceUserId }; + + return serviceDispatchIn(&g_capsuSrv, 32, in, + .in_send_pid = true, + ); +} + +static Result _capsuGetAlbumFileList0AafeAruidDeprecated(void* entries, size_t entrysize, s32 count, u8 type, u64 start_timestamp, u64 end_timestamp, s32 *total_entries) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u8 type; + u64 start_timestamp; + u64 end_timestamp; + u64 AppletResourceUserId; + } in = { type, start_timestamp, end_timestamp, AppletResourceUserId }; + + u64 total_out=0; + Result rc = serviceDispatchInOut(&g_capsuSrv, 102, in, total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { entries, count*entrysize } }, + .in_send_pid = true, + ); + if (R_SUCCEEDED(rc) && total_entries) *total_entries = total_out; + return rc; +} + +static Result _capsuDeleteAlbumFileByAruid(u32 cmd_id, u8 type, const CapsApplicationAlbumFileEntry *entry) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u8 type; + CapsApplicationAlbumFileEntry entry; + u64 AppletResourceUserId; + } in = { type, *entry, AppletResourceUserId }; + + return serviceDispatchIn(&g_capsuSrv, 103, in, + .in_send_pid = true, + ); +} + +static Result _capsuGetAlbumFileSizeByAruid(const CapsApplicationAlbumFileEntry *entry, u64 *size) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsApplicationAlbumFileEntry entry; + u64 AppletResourceUserId; + } in = { *entry, AppletResourceUserId }; + + return serviceDispatchInOut(&g_capsuSrv, 104, in, *size, + .in_send_pid = true, + ); +} + +static Result _capsuPrecheckToCreateContentsByAruid(u8 type, u64 unk) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u8 type; + u64 unk; + u64 AppletResourceUserId; + } in = { type, unk, AppletResourceUserId }; + + return serviceDispatchIn(&g_capsuSrv, 130, in, + .in_send_pid = true, + ); +} + +static Result _capsuLoadAlbumScreenShotImageByAruid(u32 cmd_id, CapsLoadAlbumScreenShotImageOutputForApplication *out, void* image, size_t image_size, void* workbuf, size_t workbuf_size, const CapsApplicationAlbumFileEntry *entry, const CapsScreenShotDecodeOption *option) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsApplicationAlbumFileEntry entry; + CapsScreenShotDecodeOption option; + u64 AppletResourceUserId; + } in = { *entry, *option, AppletResourceUserId }; + + return serviceDispatchIn(&g_capsuSrv, cmd_id, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapTransferAllowsNonSecure | SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { out, sizeof(*out) }, + { image, image_size }, + { workbuf, workbuf_size }, + }, + .in_send_pid = true, + ); +} + +static Result _capsuGetAlbumFileListAaeAruid(u32 cmd_id, void* entries, size_t entrysize, s32 count, u8 type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, s32 *total_entries) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u8 type; + CapsAlbumFileDateTime start_datetime; + CapsAlbumFileDateTime end_datetime; + u64 AppletResourceUserId; + } in = { type, *start_datetime, *end_datetime, AppletResourceUserId }; + + u64 total_out=0; + Result rc = serviceDispatchInOut(&g_capsuSrv, cmd_id, in, total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { entries, count*entrysize } }, + .in_send_pid = true, + ); + if (R_SUCCEEDED(rc) && total_entries) *total_entries = total_out; + return rc; +} + +static Result _capsuGetAlbumFileListAaeUidAruid(u32 cmd_id, void* entries, size_t entrysize, s32 count, u8 type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, AccountUid *userID, s32 *total_entries) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + u8 type; + CapsAlbumFileDateTime start_datetime; + CapsAlbumFileDateTime end_datetime; + AccountUid userID; + u64 AppletResourceUserId; + } in = { type, *start_datetime, *end_datetime, *userID, AppletResourceUserId }; + + u64 total_out=0; + Result rc = serviceDispatchInOut(&g_capsuSrv, cmd_id, in, total_out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { entries, count*entrysize } }, + .in_send_pid = true, + ); + if (R_SUCCEEDED(rc) && total_entries) *total_entries = total_out; + return rc; +} + +static Result _capsuOpenAccessorSessionForApplication(Service* srv_out, const CapsApplicationAlbumFileEntry *entry) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsApplicationAlbumFileEntry entry; + u64 AppletResourceUserId; + } in = { *entry, AppletResourceUserId }; + + return serviceDispatchIn(&g_capsuSrv, 60002, in, + .in_send_pid = true, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _capsuOpenAlbumMovieReadStream(u64 *stream, const CapsApplicationAlbumFileEntry *entry) { + u64 AppletResourceUserId = 0; + appletGetAppletResourceUserId(&AppletResourceUserId); + + const struct { + CapsApplicationAlbumFileEntry entry; + u64 AppletResourceUserId; + } in = { *entry, AppletResourceUserId }; + + return serviceDispatchInOut(&g_capsuAccessor, 2001, in, *stream, + .in_send_pid = true, + ); +} + +static Result _capsuGetAlbumMovieReadStreamMovieDataSize(u64 stream, u64 *size) { + return serviceDispatchInOut(&g_capsuAccessor, 2003, stream, *size); +} + +static Result _capsuReadMovieDataFromAlbumMovieReadStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + const struct { + u64 stream; + s64 offset; + } in = { stream, offset }; + + return serviceDispatchInOut(&g_capsuAccessor, 2004, in, *actual_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); +} + +static inline u64 _capsuMakeTimestamp(const CapsAlbumFileDateTime *datetime) { + struct tm tmptm = {.tm_sec = datetime->second, .tm_min = datetime->minute, .tm_hour = datetime->hour, + .tm_mday = datetime->day, .tm_mon = datetime->month, .tm_year = datetime->year - 1900}; + + return mktime(&tmptm); +} + +Result capsuGetAlbumFileListDeprecated1(CapsApplicationAlbumFileEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, s32 *total_entries) { + u64 start_timestamp = 0x386BF200; + u64 end_timestamp = 0xF4865700; + + CapsAlbumFileDateTime default_start = capsGetDefaultStartDateTime(); + CapsAlbumFileDateTime default_end = capsGetDefaultEndDateTime(); + + if (hosversionBefore(6,0,0)) { // GetAlbumFileListDeprecated0 + if (start_datetime) start_timestamp = _capsuMakeTimestamp(start_datetime); + if (end_datetime) end_timestamp = _capsuMakeTimestamp(end_datetime); + return _capsuGetAlbumFileList0AafeAruidDeprecated(entries, sizeof(CapsApplicationAlbumFileEntry), count, type, start_timestamp, end_timestamp, total_entries); + } + + return _capsuGetAlbumFileListAaeAruid(140, entries, sizeof(CapsApplicationAlbumFileEntry), count, type, start_datetime ? start_datetime : &default_start, end_datetime ? end_datetime : &default_end, total_entries); +} + +Result capsuGetAlbumFileListDeprecated2(CapsApplicationAlbumFileEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, AccountUid *userID, s32 *total_entries) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + CapsAlbumFileDateTime default_start = capsGetDefaultStartDateTime(); + CapsAlbumFileDateTime default_end = capsGetDefaultEndDateTime(); + + return _capsuGetAlbumFileListAaeUidAruid(141, entries, sizeof(CapsApplicationAlbumFileEntry), count, type, start_datetime ? start_datetime : &default_start, end_datetime ? end_datetime : &default_end, userID, total_entries); +} + +Result capsuGetAlbumFileList3(CapsApplicationAlbumEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, s32 *total_entries) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + CapsAlbumFileDateTime default_start = capsGetDefaultStartDateTime(); + CapsAlbumFileDateTime default_end = capsGetDefaultEndDateTime(); + + return _capsuGetAlbumFileListAaeAruid(142, entries, sizeof(CapsApplicationAlbumEntry), count, type, start_datetime ? start_datetime : &default_start, end_datetime ? end_datetime : &default_end, total_entries); +} + +Result capsuGetAlbumFileList4(CapsApplicationAlbumEntry *entries, s32 count, CapsContentType type, const CapsAlbumFileDateTime *start_datetime, const CapsAlbumFileDateTime *end_datetime, AccountUid *userID, s32 *total_entries) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + CapsAlbumFileDateTime default_start = capsGetDefaultStartDateTime(); + CapsAlbumFileDateTime default_end = capsGetDefaultEndDateTime(); + + return _capsuGetAlbumFileListAaeUidAruid(143, entries, sizeof(CapsApplicationAlbumEntry), count, type, start_datetime ? start_datetime : &default_start, end_datetime ? end_datetime : &default_end, userID, total_entries); +} + +Result capsuDeleteAlbumFile(CapsContentType type, const CapsApplicationAlbumFileEntry *entry) { + return _capsuDeleteAlbumFileByAruid(103, type, entry); +} + +Result capsuGetAlbumFileSize(const CapsApplicationAlbumFileEntry *entry, u64 *size) { + return _capsuGetAlbumFileSizeByAruid(entry, size); +} + +static void _capsuProcessImageOutput(CapsLoadAlbumScreenShotImageOutputForApplication *out, s32 *width, s32 *height, CapsScreenShotAttributeForApplication *attr, void* userdata, size_t userdata_maxsize, u32 *userdata_size) { + if (out==NULL) return; + + if (width) *width = out->width; + if (height) *height = out->height; + if (attr) memcpy(attr, &out->attr, sizeof(out->attr)); + + if (userdata && userdata_maxsize) { + memset(userdata, 0, userdata_maxsize); + if (userdata_maxsize > sizeof(out->appdata.userdata)) userdata_maxsize = sizeof(out->appdata.userdata); + if (userdata_maxsize > out->appdata.size) userdata_maxsize = out->appdata.size; + memcpy(userdata, out->appdata.userdata, userdata_maxsize); + } + if (userdata_size) *userdata_size = out->appdata.size > sizeof(out->appdata.userdata) ? sizeof(out->appdata.userdata) : out->appdata.size; +} + +Result capsuLoadAlbumScreenShotImage(s32 *width, s32 *height, CapsScreenShotAttributeForApplication *attr, void* userdata, size_t userdata_maxsize, u32 *userdata_size, void* image, size_t image_size, void* workbuf, size_t workbuf_size, const CapsApplicationAlbumFileEntry *entry, const CapsScreenShotDecodeOption *option) { + Result rc=0; + CapsLoadAlbumScreenShotImageOutputForApplication out={0}; + + rc = _capsuLoadAlbumScreenShotImageByAruid(110, &out, image, image_size, workbuf, workbuf_size, entry, option); + if (R_SUCCEEDED(rc)) _capsuProcessImageOutput(&out, width, height, attr, userdata, userdata_maxsize, userdata_size); + return rc; +} + +Result capsuLoadAlbumScreenShotThumbnailImage(s32 *width, s32 *height, CapsScreenShotAttributeForApplication *attr, void* userdata, size_t userdata_maxsize, u32 *userdata_size, void* image, size_t image_size, void* workbuf, size_t workbuf_size, const CapsApplicationAlbumFileEntry *entry, const CapsScreenShotDecodeOption *option) { + Result rc=0; + CapsLoadAlbumScreenShotImageOutputForApplication out={0}; + + rc = _capsuLoadAlbumScreenShotImageByAruid(120, &out, image, image_size, workbuf, workbuf_size, entry, option); + if (R_SUCCEEDED(rc)) _capsuProcessImageOutput(&out, width, height, attr, userdata, userdata_maxsize, userdata_size); + return rc; +} + +Result capsuPrecheckToCreateContents(CapsContentType type, u64 unk) { + return _capsuPrecheckToCreateContentsByAruid(type, unk); +} + +Result capsuOpenAlbumMovieStream(u64 *stream, const CapsApplicationAlbumFileEntry *entry) { + Result rc=0; + + if (!serviceIsActive(&g_capsuAccessor)) rc =_capsuOpenAccessorSessionForApplication(&g_capsuAccessor, entry); + + if (R_SUCCEEDED(rc)) rc = _capsuOpenAlbumMovieReadStream(stream, entry); + + return rc; +} + +Result capsuCloseAlbumMovieStream(u64 stream) { + if (!serviceIsActive(&g_capsuAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsuCmdInU64NoOut(&g_capsuAccessor, stream, 2002); +} + +Result capsuGetAlbumMovieStreamSize(u64 stream, u64 *size) { + if (!serviceIsActive(&g_capsuAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsuGetAlbumMovieReadStreamMovieDataSize(stream, size); +} + +Result capsuReadAlbumMovieStream(u64 stream, s64 offset, void* buffer, size_t size, u64 *actual_size) { + if (!serviceIsActive(&g_capsuAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsuReadMovieDataFromAlbumMovieReadStream(stream, offset, buffer, size, actual_size); +} + +Result capsuGetAlbumMovieStreamBrokenReason(u64 stream) { + if (!serviceIsActive(&g_capsuAccessor)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _capsuCmdInU64NoOut(&g_capsuAccessor, stream, 2005); +} + diff --git a/nx/source/services/csrng.c b/nx/source/services/csrng.c index ac1220d7..fe0cfde6 100644 --- a/nx/source/services/csrng.c +++ b/nx/source/services/csrng.c @@ -1,28 +1,17 @@ -// Copyright 2018 SciresM -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/csrng.h" -#include "services/sm.h" -#include "services/spl.h" static Service g_csrngSrv; -static u64 g_csrngRefCnt; -Result csrngInitialize(void) { - atomicIncrement64(&g_csrngRefCnt); - - if (serviceIsActive(&g_csrngSrv)) - return 0; - +NX_GENERATE_SERVICE_GUARD(csrng); + +Result _csrngInitialize(void) { return smGetService(&g_csrngSrv, "csrng"); } -void csrngExit(void) { - if (atomicDecrement64(&g_csrngRefCnt) == 0) - serviceClose(&g_csrngSrv); +void _csrngCleanup(void) { + serviceClose(&g_csrngSrv); } Service* csrngGetServiceSession(void) { @@ -30,34 +19,8 @@ Service* csrngGetServiceSession(void) { } Result csrngGetRandomBytes(void *out, size_t out_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, out, out_size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_csrngSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(&g_csrngSrv, 0, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out, out_size } }, + ); } diff --git a/nx/source/services/fatal.c b/nx/source/services/fatal.c index ac66b063..e4d8ccc7 100644 --- a/nx/source/services/fatal.c +++ b/nx/source/services/fatal.c @@ -1,9 +1,10 @@ // Copyright 2017 plutoo +#define NX_SERVICE_ASSUME_NON_DOMAIN #include "types.h" #include "result.h" -#include "kernel/ipc.h" #include "kernel/detect.h" #include "kernel/svc.h" +#include "sf/service.h" #include "services/fatal.h" #include "services/sm.h" @@ -17,42 +18,30 @@ static void _fatalImpl(u32 cmd_id, Result err, FatalType type, FatalContext *ctx svcBreak(0x80000000, err, 0); } - if (!smHasInitialized()) { - rc = smInitialize(); + Handle session; + rc = smInitialize(); + if (R_SUCCEEDED(rc)) { + rc = smGetServiceOriginal(&session, smEncodeName("fatal:u")); + smExit(); } if (R_SUCCEEDED(rc)) { - Handle srv; - rc = smGetServiceOriginal(&srv, smEncodeName("fatal:u")); + const struct { + u32 result; + u32 type; + u64 pid_placeholder; + } in = { err, type }; - if (R_SUCCEEDED(rc)) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - if (ctx != NULL) { - ipcAddSendBuffer(&c, ctx, sizeof(*ctx), BufferType_Normal); - } - - struct { - u64 magic; - u64 cmd_id; - u32 result; - u32 type; - u64 pid_placeholder; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->result = err; - raw->type = type; - raw->pid_placeholder = 0; // Overwritten by fatal with PID descriptor. - - ipcDispatch(srv); - } + Service s; + serviceCreate(&s, session); + serviceDispatchIn(&s, cmd_id, in, + .buffer_attrs = { ctx ? (SfBufferAttr_In | SfBufferAttr_HipcMapAlias) : 0U }, + .buffers = { { ctx, sizeof(*ctx) } }, + .in_send_pid = true, + ); + serviceClose(&s); } - + switch (type) { case FatalType_ErrorReport: break; @@ -72,7 +61,7 @@ void NORETURN fatalSimple(Result err) { } void fatalWithType(Result err, FatalType type) { - _fatalImpl(1, err, type, NULL); + _fatalImpl(1, err, type, NULL); } void fatalWithContext(Result err, FatalType type, FatalContext *ctx) { diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index c384efd8..8136398a 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -1,22 +1,114 @@ // Copyright 2017 plutoo #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" +#include "kernel/mutex.h" +#include "kernel/condvar.h" #include "runtime/hosversion.h" #include "services/fs.h" -#include "services/sm.h" +#include "services/acc.h" + +#define FS_MAX_SESSIONS 8 + +__attribute__((weak)) u32 __nx_fs_num_sessions = 3; static Service g_fsSrv; -static u64 g_refCnt; -Result fsInitialize(void) +static Handle g_fsSessions[FS_MAX_SESSIONS]; +static u32 g_fsSessionFreeMask; +static Mutex g_fsSessionMutex; +static CondVar g_fsSessionCondVar; +static bool g_fsSessionWaiting; + +static __thread u32 g_fsPriority = FsPriority_Normal; + +static int _fsGetSessionSlot(void) { - atomicIncrement64(&g_refCnt); + mutexLock(&g_fsSessionMutex); + int slot; + for (;;) { + slot = __builtin_ffs(g_fsSessionFreeMask)-1; + if (slot >= 0) break; + g_fsSessionWaiting = true; + condvarWait(&g_fsSessionCondVar, &g_fsSessionMutex); + } + g_fsSessionFreeMask &= ~(1U << slot); + mutexUnlock(&g_fsSessionMutex); + return slot; +} - if (serviceIsActive(&g_fsSrv)) - return 0; +static void _fsPutSessionSlot(int slot) +{ + mutexLock(&g_fsSessionMutex); + g_fsSessionFreeMask |= 1U << slot; + if (g_fsSessionWaiting) { + g_fsSessionWaiting = false; + condvarWakeOne(&g_fsSessionCondVar); + } + mutexUnlock(&g_fsSessionMutex); +} + +NX_INLINE bool _fsObjectIsChild(Service* s) +{ + return s->session == g_fsSrv.session; +} + +static void _fsObjectClose(Service* s) +{ + if (!_fsObjectIsChild(s)) { + serviceClose(s); + } + else { + int slot = _fsGetSessionSlot(); + uint32_t object_id = serviceGetObjectId(s); + serviceAssumeDomain(s); + cmifMakeCloseRequest(armGetTls(), object_id); + svcSendSyncRequest(g_fsSessions[slot]); + _fsPutSessionSlot(slot); + } +} + +NX_INLINE Result _fsObjectDispatchImpl( + Service* s, u32 request_id, + const void* in_data, u32 in_data_size, + void* out_data, u32 out_data_size, + SfDispatchParams disp +) { + int slot = -1; + if (_fsObjectIsChild(s)) { + slot = _fsGetSessionSlot(); + if (slot < 0) __builtin_unreachable(); + disp.target_session = g_fsSessions[slot]; + serviceAssumeDomain(s); + } + + disp.context = g_fsPriority; + Result rc = serviceDispatchImpl(s, request_id, in_data, in_data_size, out_data, out_data_size, disp); + + if (slot >= 0) { + _fsPutSessionSlot(slot); + } + + return rc; +} + +#define _fsObjectDispatch(_s,_rid,...) \ + _fsObjectDispatchImpl((_s),(_rid),NULL,0,NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define _fsObjectDispatchIn(_s,_rid,_in,...) \ + _fsObjectDispatchImpl((_s),(_rid),&(_in),sizeof(_in),NULL,0,(SfDispatchParams){ __VA_ARGS__ }) + +#define _fsObjectDispatchOut(_s,_rid,_out,...) \ + _fsObjectDispatchImpl((_s),(_rid),NULL,0,&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +#define _fsObjectDispatchInOut(_s,_rid,_in,_out,...) \ + _fsObjectDispatchImpl((_s),(_rid),&(_in),sizeof(_in),&(_out),sizeof(_out),(SfDispatchParams){ __VA_ARGS__ }) + +NX_GENERATE_SERVICE_GUARD(fs); + +Result _fsInitialize(void) +{ + if (__nx_fs_num_sessions < 1 || __nx_fs_num_sessions > FS_MAX_SESSIONS) + return MAKERESULT(Module_Libnx, LibnxError_BadInput); Result rc = smGetService(&g_fsSrv, "fsp-srv"); @@ -25,595 +117,193 @@ Result fsInitialize(void) } if (R_SUCCEEDED(rc)) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); + u64 pid_placeholder = 0; + serviceAssumeDomain(&g_fsSrv); + rc = serviceDispatchIn(&g_fsSrv, 1, pid_placeholder, .in_send_pid = true); + } - struct { - u64 magic; - u64 cmd_id; - u64 unk; - } *raw; + if (R_SUCCEEDED(rc)) { + g_fsSessionFreeMask = (1U << __nx_fs_num_sessions) - 1U; + g_fsSessions[0] = g_fsSrv.session; + } - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->unk = 0; - - rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } + for (u32 i = 1; R_SUCCEEDED(rc) && i < __nx_fs_num_sessions; i ++) { + rc = cmifCloneCurrentObject(g_fsSessions[0], &g_fsSessions[i]); } return rc; } -void fsExit(void) +void _fsCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) - serviceClose(&g_fsSrv); + // Close extra sessions + g_fsSessions[0] = INVALID_HANDLE; + for (u32 i = 1; i < __nx_fs_num_sessions; i ++) { + if (g_fsSessions[i] != INVALID_HANDLE) { + cmifMakeCloseRequest(armGetTls(), 0); + svcSendSyncRequest(g_fsSessions[i]); + g_fsSessions[i] = INVALID_HANDLE; + } + } + + // We can't assume g_fsSrv is a domain here because serviceConvertToDomain might have failed + serviceClose(&g_fsSrv); } Service* fsGetServiceSession(void) { return &g_fsSrv; } +void fsSetPriority(FsPriority prio) +{ + if (hosversionAtLeast(5,0,0)) + g_fsPriority = prio; +} + +//----------------------------------------------------------------------------- +// IFileSystemProxy +//----------------------------------------------------------------------------- + Result fsOpenBisStorage(FsStorage* out, FsBisStorageId partitionId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 PartitionId; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - raw->PartitionId = partitionId; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 12, partitionId, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenBisFileSystem(FsFileSystem* out, FsBisStorageId partitionId, const char* string) { - IpcCommand c; - ipcInitialize(&c); - char tmpstr[FS_MAX_PATH] = {0}; strncpy(tmpstr, string, sizeof(tmpstr)-1); - ipcAddSendStatic(&c, tmpstr, sizeof(tmpstr), 0); - struct { - u64 magic; - u64 cmd_id; - u32 PartitionId; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->PartitionId = partitionId; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 11, partitionId, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { tmpstr, sizeof(tmpstr) } }, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsCreateSaveDataFileSystemBySystemSaveDataId(const FsSave* save, const FsSaveCreate* create) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { FsSave save; FsSaveCreate create; - } PACKED *raw; + } in = { *save, *create }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - memcpy(&raw->save, save, sizeof(FsSave)); - memcpy(&raw->create, create, sizeof(FsSaveCreate)); - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 23, in); } Result fsDeleteSaveDataFileSystemBySaveDataSpaceId(FsSaveDataSpaceId saveDataSpaceId, u64 saveID) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u8 saveDataSpaceId; u64 saveID; - } *raw; + } in = { (u8)saveDataSpaceId, saveID }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 25; - raw->saveDataSpaceId = saveDataSpaceId; - raw->saveID = saveID; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 25, in); } Result fsMountSdcard(FsFileSystem* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatch(&g_fsSrv, 18, + .out_num_objects = 1, + .out_objects = &out->s, + ); } -Result fsMountSaveData(FsFileSystem* out, u8 inval, FsSave *save) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 inval;//Actually u8. +Result fsMountSaveData(FsFileSystem* out, u8 inval, const FsSave *save) { + const struct { + u8 inval; FsSave save; - } PACKED *raw; + } in = { inval, *save }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 51; - raw->inval = (u64)inval; - memcpy(&raw->save, save, sizeof(FsSave)); - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 51, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); } -Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, FsSave *save) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 inval;//Actually u8. +Result fsMountSystemSaveData(FsFileSystem* out, u8 inval, const FsSave *save) { + const struct { + u8 inval; FsSave save; - } PACKED *raw; + } in = { inval, *save }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 52; - raw->inval = (u64)inval; - memcpy(&raw->save, save, sizeof(FsSave)); - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 52, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); } -Result fsOpenSaveDataIterator(FsSaveDataIterator* out, s32 saveDataSpaceId) { - IpcCommand c; - ipcInitialize(&c); +static Result _fsOpenSaveDataInfoReader(FsSaveDataIterator* out) { + return _fsObjectDispatch(&g_fsSrv, 60, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; +static Result _fsOpenSaveDataInfoReaderBySaveDataSpaceId(FsSaveDataIterator* out, FsSaveDataSpaceId saveDataSpaceId) { + u8 in = (u8)saveDataSpaceId; + return _fsObjectDispatchIn(&g_fsSrv, 61, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); - struct { - u64 magic; - u64 cmd_id; - u8 saveDataSpaceId; - } *raw2; +} +Result fsOpenSaveDataIterator(FsSaveDataIterator* out, FsSaveDataSpaceId saveDataSpaceId) { if (saveDataSpaceId == FsSaveDataSpaceId_All) { - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 60; + return _fsOpenSaveDataInfoReader(out); + } else { + return _fsOpenSaveDataInfoReaderBySaveDataSpaceId(out, saveDataSpaceId); } - else { - raw2 = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw2)); - - raw2->magic = SFCI_MAGIC; - raw2->cmd_id = 61; - raw2->saveDataSpaceId = saveDataSpaceId; - } - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; } Result fsOpenContentStorageFileSystem(FsFileSystem* out, FsContentStorageId content_storage_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 content_storage_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 110; - raw->content_storage_id = content_storage_id; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 110, content_storage_id, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenCustomStorageFileSystem(FsFileSystem* out, FsCustomStorageId custom_storage_id) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 custom_storage_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 130; - raw->custom_storage_id = custom_storage_id; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 130, custom_storage_id, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenDataStorageByCurrentProcess(FsStorage* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 200; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatch(&g_fsSrv, 200, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenDataStorageByDataId(FsStorage* out, u64 dataId, FsStorageId storageId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 storage_id; + const struct { + FsStorageId storage_id; u64 data_id; - } *raw; + } in = { storageId, dataId }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 202; - raw->storage_id = storageId; - raw->data_id = dataId; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 202, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenDeviceOperator(FsDeviceOperator* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 400; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatch(&g_fsSrv, 400, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsOpenSdCardDetectionEventNotifier(FsEventNotifier* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 500; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatch(&g_fsSrv, 500, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id) { @@ -621,117 +311,42 @@ Result fsGetRightsIdByPath(const char* path, FsRightsId* out_rights_id) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); char send_path[FS_MAX_PATH] = {0}; - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 609; - strncpy(send_path, path, FS_MAX_PATH-1); - Result rc = serviceIpcDispatch(&g_fsSrv); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - FsRightsId rights_id; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_rights_id) *out_rights_id = resp->rights_id; - } - } - - return rc; + return _fsObjectDispatchOut(&g_fsSrv, 609, *out_rights_id, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { send_path, sizeof(send_path) } }, + ); } Result fsGetRightsIdAndKeyGenerationByPath(const char* path, u8* out_key_generation, FsRightsId* out_rights_id) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - + char send_path[FS_MAX_PATH] = {0}; - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); + strncpy(send_path, path, FS_MAX_PATH-1); struct { - u64 magic; - u64 cmd_id; - } *raw; + u8 key_generation; + u8 padding[0x7]; + FsRightsId rights_id; + } out; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 610; - - strncpy(send_path, path, FS_MAX_PATH-1); - Result rc = serviceIpcDispatch(&g_fsSrv); + Result rc = _fsObjectDispatchOut(&g_fsSrv, 610, out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { send_path, sizeof(send_path) } }, + ); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 key_generation; - u8 padding[0x7]; - FsRightsId rights_id; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_key_generation) *out_key_generation = resp->key_generation; - if (out_rights_id) *out_rights_id = resp->rights_id; - } + if (out_key_generation) *out_key_generation = out.key_generation; + if (out_rights_id) *out_rights_id = out.rights_id; } return rc; } Result fsDisableAutoSaveDataCreation(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1003; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatch(&g_fsSrv, 1003); } Result fsIsExFatSupported(bool* out) @@ -741,316 +356,84 @@ Result fsIsExFatSupported(bool* out) return 0; } - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 27; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 exfat; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->exfat; - } - } - - return rc; + return _fsObjectDispatchOut(&g_fsSrv, 27, *out); } Result fsOpenGameCardFileSystem(FsFileSystem* out, const FsGameCardHandle* handle, FsGameCardPartiton partition) { - IpcCommand c; - ipcInitialize(&c); + const struct { + FsGameCardHandle handle; + FsGameCardPartiton partition; + } in = { *handle, partition }; - struct { - u64 magic; - u64 cmd_id; - u32 handle; - u32 partition; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 31; - raw->handle = handle->value; - raw->partition = partition; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 31, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsReadSaveDataFileSystemExtraDataBySaveDataSpaceId(void* buf, size_t len, FsSaveDataSpaceId saveDataSpaceId, u64 saveID) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, len, BufferType_Normal); - struct { - u64 magic; - u64 cmd_id; - u64 saveDataSpaceId; + const struct { + u8 saveDataSpaceId; u64 saveID; - } *raw; + } in = { (u8)saveDataSpaceId, saveID }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 57; - raw->saveDataSpaceId = saveDataSpaceId; - raw->saveID = saveID; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 57, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, len } }, + ); } Result fsReadSaveDataFileSystemExtraData(void* buf, size_t len, u64 saveID) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, len, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u64 saveID; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 58; - raw->saveID = saveID; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 58, saveID, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, len } }, + ); } Result fsWriteSaveDataFileSystemExtraData(const void* buf, size_t len, FsSaveDataSpaceId saveDataSpaceId, u64 saveID) { if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, buf, len, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u64 saveDataSpaceId; + const struct { + u8 saveDataSpaceId; u64 saveID; - } *raw; + } in = { (u8)saveDataSpaceId, saveID }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 59; - raw->saveDataSpaceId = saveDataSpaceId; - raw->saveID = saveID; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 59, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { buf, len } }, + ); } Result fsExtendSaveDataFileSystem(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, s64 dataSize, s64 journalSize) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 saveDataSpaceId; + const struct { + u8 saveDataSpaceId; u64 saveID; s64 dataSize; s64 journalSize; - } *raw; + } in = { (u8)saveDataSpaceId, saveID, dataSize, journalSize }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 32; - raw->saveDataSpaceId = saveDataSpaceId; - raw->saveID = saveID; - raw->dataSize = dataSize; - raw->saveID = saveID; - raw->journalSize = journalSize; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 32, in); } Result fsSetGlobalAccessLogMode(u32 mode) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 mode; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1004; - raw->mode = mode; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 1004, mode); } Result fsGetGlobalAccessLogMode(u32* out_mode) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1005; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 mode; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_mode = resp->mode; - } - } - - return rc; + return _fsObjectDispatchOut(&g_fsSrv, 1005, *out_mode); } // Wrapper(s) for fsCreateSaveDataFileSystemBySystemSaveDataId. -Result fsCreate_SystemSaveDataWithOwner(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, u128 userID, u64 ownerId, u64 size, u64 journalSize, u32 flags) { +Result fsCreate_SystemSaveDataWithOwner(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, AccountUid *userID, u64 ownerId, u64 size, u64 journalSize, u32 flags) { FsSave save = { - .userID = userID, + .userID = *userID, .saveID = saveID, }; FsSaveCreate create = { @@ -1070,12 +453,12 @@ Result fsCreate_SystemSaveData(FsSaveDataSpaceId saveDataSpaceId, u64 saveID, u6 } // Wrapper(s) for fsMountSaveData. -Result fsMount_SaveData(FsFileSystem* out, u64 titleID, u128 userID) { +Result fsMount_SaveData(FsFileSystem* out, u64 titleID, AccountUid *userID) { FsSave save; memset(&save, 0, sizeof(save)); save.titleID = titleID; - save.userID = userID; + save.userID = *userID; save.saveDataType = FsSaveDataType_SaveData; return fsMountSaveData(out, FsSaveDataSpaceId_NandUser, &save); @@ -1095,63 +478,37 @@ Result fsOpenFileSystem(FsFileSystem* out, FsFileSystemType fsType, const char* return fsOpenFileSystemWithId(out, 0, fsType, contentPath); } +static Result _fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath) { + const struct { + FsFileSystemType fsType; + u64 titleId; + } in = { fsType, titleId }; + + return _fsObjectDispatchIn(&g_fsSrv, 8, in, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { contentPath, FS_MAX_PATH } }, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} + +static Result _fsOpenFileSystem(FsFileSystem* out, FsFileSystemType fsType, const char* contentPath) { + return _fsObjectDispatchIn(&g_fsSrv, 0, fsType, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { contentPath, FS_MAX_PATH } }, + .out_num_objects = 1, + .out_objects = &out->s, + ); +} + Result fsOpenFileSystemWithId(FsFileSystem* out, u64 titleId, FsFileSystemType fsType, const char* contentPath) { char sendStr[FS_MAX_PATH] = {0}; strncpy(sendStr, contentPath, sizeof(sendStr)-1); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, sendStr, sizeof(sendStr), 0); - - if (hosversionAtLeast(2,0,0)) { - struct { - u64 magic; - u64 cmd_id; - u32 fsType; - u64 titleId; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - raw->fsType = fsType; - raw->titleId = titleId; - } - else { - struct { - u64 magic; - u64 cmd_id; - u32 fsType; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->fsType = fsType; - } - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + if (hosversionAtLeast(2,0,0)) + return _fsOpenFileSystemWithId(out, titleId, fsType, sendStr); + else + return _fsOpenFileSystem(out, fsType, sendStr); } Result fsOpenFileSystemWithPatch(FsFileSystem* out, u64 titleId, FsFileSystemType fsType) { @@ -1159,583 +516,135 @@ Result fsOpenFileSystemWithPatch(FsFileSystem* out, u64 titleId, FsFileSystemTyp return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 fsType; + const struct { + FsFileSystemType fsType; u64 titleId; - } *raw; + } in = { fsType, titleId }; - raw = serviceIpcPrepareHeader(&g_fsSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - raw->fsType = fsType; - raw->titleId = titleId; - - Result rc = serviceIpcDispatch(&g_fsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsSrv, &r, 0); - } - } - - return rc; + return _fsObjectDispatchIn(&g_fsSrv, 7, in, + .out_num_objects = 1, + .out_objects = &out->s, + ); } -// IFileSystem impl -Result fsFsCreateFile(FsFileSystem* fs, const char* path, size_t size, int flags) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); +//----------------------------------------------------------------------------- +// IFileSystem +//----------------------------------------------------------------------------- - struct { - u64 magic; - u64 cmd_id; - u32 flags; +Result fsFsCreateFile(FsFileSystem* fs, const char* path, u64 size, u32 option) { + const struct { + u32 option; u64 size; - } *raw; + } in = { option, size }; - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); + return _fsObjectDispatchIn(&fs->s, 0, in, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + ); +} - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->flags = flags; - raw->size = size; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _fsFsCmdWithInPath(FsFileSystem* fs, const char* path, u32 cmd_id) { + return _fsObjectDispatch(&fs->s, cmd_id, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + ); } Result fsFsDeleteFile(FsFileSystem* fs, const char* path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithInPath(fs, path, 1); } Result fsFsCreateDirectory(FsFileSystem* fs, const char* path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithInPath(fs, path, 2); } Result fsFsDeleteDirectory(FsFileSystem* fs, const char* path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithInPath(fs, path, 3); } Result fsFsDeleteDirectoryRecursively(FsFileSystem* fs, const char* path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); + return _fsFsCmdWithInPath(fs, path, 4); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _fsFsCmdWithTwoInPaths(FsFileSystem* fs, const char* cur_path, const char* new_path, u32 cmd_id) { + return _fsObjectDispatch(&fs->s, cmd_id, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { cur_path, FS_MAX_PATH }, + { new_path, FS_MAX_PATH }, + }, + ); } Result fsFsRenameFile(FsFileSystem* fs, const char* cur_path, const char* new_path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, cur_path, FS_MAX_PATH, 0); - ipcAddSendStatic(&c, new_path, FS_MAX_PATH, 1); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithTwoInPaths(fs, cur_path, new_path, 5); } Result fsFsRenameDirectory(FsFileSystem* fs, const char* cur_path, const char* new_path) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, cur_path, FS_MAX_PATH, 0); - ipcAddSendStatic(&c, new_path, FS_MAX_PATH, 1); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithTwoInPaths(fs, cur_path, new_path, 6); } -Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsEntryType* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 type; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->type; - } - } - - return rc; +Result fsFsGetEntryType(FsFileSystem* fs, const char* path, FsDirEntryType* out) { + return _fsObjectDispatchOut(&fs->s, 7, *out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + ); } -Result fsFsOpenFile(FsFileSystem* fs, const char* path, int flags, FsFile* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - u32 flags; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - raw->flags = flags; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &fs->s, &r, 0); - } - } - - return rc; +static Result _fsFsOpenCommon(FsFileSystem* fs, const char* path, u32 flags, Service* out, u32 cmd_id) { + return _fsObjectDispatchIn(&fs->s, cmd_id, flags, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + .out_num_objects = 1, + .out_objects = out, + ); } -Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, int flags, FsDir* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); +Result fsFsOpenFile(FsFileSystem* fs, const char* path, u32 mode, FsFile* out) { + return _fsFsOpenCommon(fs, path, mode, &out->s, 8); +} - struct { - u64 magic; - u64 cmd_id; - u32 flags; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 9; - raw->flags = flags; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &fs->s, &r, 0); - } - } - - return rc; +Result fsFsOpenDirectory(FsFileSystem* fs, const char* path, u32 mode, FsDir* out) { + return _fsFsOpenCommon(fs, path, mode, &out->s, 9); } Result fsFsCommit(FsFileSystem* fs) { - IpcCommand c; - ipcInitialize(&c); + return _fsObjectDispatch(&fs->s, 10); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _fsFsCmdWithInPathAndOutU64(FsFileSystem* fs, const char* path, u64* out, u32 cmd_id) { + return _fsObjectDispatchOut(&fs->s, cmd_id, *out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + ); } Result fsFsGetFreeSpace(FsFileSystem* fs, const char* path, u64* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 space; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->space; - } - } - - return rc; + return _fsFsCmdWithInPathAndOutU64(fs, path, out, 11); } Result fsFsGetTotalSpace(FsFileSystem* fs, const char* path, u64* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 space; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->space; - } - } - - return rc; + return _fsFsCmdWithInPathAndOutU64(fs, path, out, 12); } Result fsFsCleanDirectoryRecursively(FsFileSystem* fs, const char* path) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsFsCmdWithInPath(fs, path, 13); } Result fsFsGetFileTimeStampRaw(FsFileSystem* fs, const char* path, FsTimeStampRaw *out) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - char send_path[FS_MAX_PATH] = {0}; - strncpy(send_path, path, sizeof(send_path)-1); - - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_path, sizeof(send_path), 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 14; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - FsTimeStampRaw out; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + return _fsObjectDispatchOut(&fs->s, 14, *out, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_In }, + .buffers = { { path, FS_MAX_PATH } }, + ); } Result fsFsQueryEntry(FsFileSystem* fs, void *out, size_t out_size, const void *in, size_t in_size, const char* path, FsFileSystemQueryType query_type) { @@ -1745,40 +654,18 @@ Result fsFsQueryEntry(FsFileSystem* fs, void *out, size_t out_size, const void * char send_path[FS_MAX_PATH] = {0}; strncpy(send_path, path, sizeof(send_path)-1); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_path, sizeof(send_path), 0); - ipcAddSendBuffer(&c, in, in_size, BufferType_Type1); - ipcAddRecvBuffer(&c, out, out_size, BufferType_Type1); - - struct { - u64 magic; - u64 cmd_id; - u32 query_type; - } *raw; - - raw = serviceIpcPrepareHeader(&fs->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - raw->query_type = query_type; - - Result rc = serviceIpcDispatch(&fs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&fs->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&fs->s, 15, query_type, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In | SfBufferAttr_HipcMapTransferAllowsNonSecure, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, + }, + .buffers = { + { send_path, sizeof(send_path) }, + { in, in_size }, + { out, out_size }, + }, + ); } Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path) { @@ -1786,750 +673,199 @@ Result fsFsSetArchiveBit(FsFileSystem* fs, const char *path) { } void fsFsClose(FsFileSystem* fs) { - serviceClose(&fs->s); + _fsObjectClose(&fs->s); } -// IFile implementation -Result fsFileRead(FsFile* f, u64 off, void* buf, size_t len, u32 option, size_t* out) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, len, 1); +//----------------------------------------------------------------------------- +// IFile +//----------------------------------------------------------------------------- - struct { - u64 magic; - u64 cmd_id; +Result fsFileRead(FsFile* f, u64 off, void* buf, u64 read_size, u32 option, u64* bytes_read) { + const struct { u32 option; u64 offset; u64 read_size; - } *raw; + } in = { option, off, read_size }; - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->option = option; - raw->offset = off; - raw->read_size = len; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 bytes_read; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->bytes_read; - } - } - - return rc; + return _fsObjectDispatchInOut(&f->s, 0, in, *bytes_read, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure }, + .buffers = { { buf, read_size } }, + ); } -Result fsFileWrite(FsFile* f, u64 off, const void* buf, size_t len, u32 option) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, buf, len, 1); - - struct { - u64 magic; - u64 cmd_id; +Result fsFileWrite(FsFile* f, u64 off, const void* buf, u64 write_size, u32 option) { + const struct { u32 option; u64 offset; u64 write_size; - } *raw; + } in = { option, off, write_size }; - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->option = option; - raw->offset = off; - raw->write_size = len; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&f->s, 1, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In | SfBufferAttr_HipcMapTransferAllowsNonSecure }, + .buffers = { { buf, write_size } }, + ); } Result fsFileFlush(FsFile* f) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatch(&f->s, 2); } Result fsFileSetSize(FsFile* f, u64 sz) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 size; - } *raw; - - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->size = sz; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&f->s, 3, sz); } Result fsFileGetSize(FsFile* f, u64* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 size; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->size; - } - - return rc; + return _fsObjectDispatchOut(&f->s, 4, *out); } -Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out) { +Result fsFileOperateRange(FsFile* f, FsOperationId op_id, u64 off, u64 len, FsRangeInfo* out) { if (hosversionBefore(4,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 op_id; u64 off; u64 len; - } *raw; - - raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->op_id = op_id; - raw->off = off; - raw->len = len; - - Result rc = serviceIpcDispatch(&f->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - FsRangeInfo range_info; - } *resp; - - serviceIpcParse(&f->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->range_info; - } - - return rc; + } in = { op_id, off, len }; + return _fsObjectDispatchInOut(&f->s, 5, in, *out); } void fsFileClose(FsFile* f) { - serviceClose(&f->s); + _fsObjectClose(&f->s); } // IDirectory implementation void fsDirClose(FsDir* d) { - serviceClose(&d->s); + _fsObjectClose(&d->s); } -Result fsDirRead(FsDir* d, u64 inval, size_t* total_entries, size_t max_entries, FsDirectoryEntry *buf) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, sizeof(FsDirectoryEntry)*max_entries, 0); - - struct { - u64 magic; - u64 cmd_id; - u64 inval; - } *raw; - - raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->inval = inval; - - Result rc = serviceIpcDispatch(&d->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 total_entries; - } *resp; - - serviceIpcParse(&d->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (total_entries) *total_entries = resp->total_entries; - } - } - - return rc; +Result fsDirRead(FsDir* d, u64 inval, u64* total_entries, size_t max_entries, FsDirectoryEntry *buf) { + return _fsObjectDispatchInOut(&d->s, 0, inval, *total_entries, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, sizeof(FsDirectoryEntry)*max_entries } }, + ); } Result fsDirGetEntryCount(FsDir* d, u64* count) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(&d->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 count; - } *resp; - - serviceIpcParse(&d->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && count) *count = resp->count; - } - - return rc; + return _fsObjectDispatchOut(&d->s, 1, *count); } -// IStorage implementation -Result fsStorageRead(FsStorage* s, u64 off, void* buf, size_t len) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, len, 1); +//----------------------------------------------------------------------------- +// IStorage +//----------------------------------------------------------------------------- - struct { - u64 magic; - u64 cmd_id; +Result fsStorageRead(FsStorage* s, u64 off, void* buf, u64 read_size) { + const struct { u64 offset; u64 read_size; - } *raw; + } in = { off, read_size }; - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->offset = off; - raw->read_size = len; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&s->s, 0, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure }, + .buffers = { { buf, read_size } }, + ); } -Result fsStorageWrite(FsStorage* s, u64 off, const void* buf, size_t len) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, buf, len, 1); - - struct { - u64 magic; - u64 cmd_id; +Result fsStorageWrite(FsStorage* s, u64 off, const void* buf, u64 write_size) { + const struct { u64 offset; u64 write_size; - } *raw; + } in = { off, write_size }; - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->offset = off; - raw->write_size = len; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&s->s, 1, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In | SfBufferAttr_HipcMapTransferAllowsNonSecure }, + .buffers = { { buf, write_size } }, + ); } Result fsStorageFlush(FsStorage* s) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatch(&s->s, 2); } Result fsStorageSetSize(FsStorage* s, u64 sz) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 size; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->size = sz; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _fsObjectDispatchIn(&s->s, 3, sz); } Result fsStorageGetSize(FsStorage* s, u64* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 size; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->size; - } - - return rc; + return _fsObjectDispatchOut(&s->s, 4, *out); } -Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, size_t len, FsRangeInfo* out) { +Result fsStorageOperateRange(FsStorage* s, FsOperationId op_id, u64 off, u64 len, FsRangeInfo* out) { if (hosversionBefore(4,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 op_id; u64 off; u64 len; - } *raw; + } in = { op_id, off, len }; - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->op_id = op_id; - raw->off = off; - raw->len = len; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - FsRangeInfo range_info; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && out) *out = resp->range_info; - } - - return rc; + return _fsObjectDispatchInOut(&s->s, 5, in, *out); } void fsStorageClose(FsStorage* s) { - serviceClose(&s->s); + _fsObjectClose(&s->s); } +//----------------------------------------------------------------------------- // ISaveDataInfoReader -Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, size_t* total_entries) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buf, sizeof(FsSaveDataInfo)*max_entries, 0); +//----------------------------------------------------------------------------- - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 total_entries; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (total_entries) *total_entries = resp->total_entries; - } - } - - return rc; +Result fsSaveDataIteratorRead(FsSaveDataIterator *s, FsSaveDataInfo* buf, size_t max_entries, u64* total_entries) { + return _fsObjectDispatchOut(&s->s, 0, *total_entries, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buf, sizeof(FsSaveDataInfo)*max_entries } }, + ); } void fsSaveDataIteratorClose(FsSaveDataIterator* s) { - serviceClose(&s->s); + _fsObjectClose(&s->s); } +//----------------------------------------------------------------------------- // IEventNotifier -Result fsEventNotifierGetEventHandle(FsEventNotifier* e, Handle* out) { - IpcCommand c; - ipcInitialize(&c); +//----------------------------------------------------------------------------- - struct { - u64 magic; - u64 cmd_id; - } *raw; +Result fsEventNotifierGetEventHandle(FsEventNotifier* e, Event* out, bool autoclear) { + Handle event = INVALID_HANDLE; + Result rc = _fsObjectDispatch(&e->s, 0, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); - raw = serviceIpcPrepareHeader(&e->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&e->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&e->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = r.Handles[0]; - } - } + if (R_SUCCEEDED(rc)) + eventLoadRemote(out, event, autoclear); return rc; } void fsEventNotifierClose(FsEventNotifier* e) { - serviceClose(&e->s); + _fsObjectClose(&e->s); } +//----------------------------------------------------------------------------- // IDeviceOperator -static Result _fsDeviceOperatorCheckInserted(FsDeviceOperator* d, u32 cmd_id, bool* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&d->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 is_inserted; - } *resp; - - serviceIpcParse(&d->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->is_inserted != 0; - } - } - - return rc; -} +//----------------------------------------------------------------------------- Result fsDeviceOperatorIsSdCardInserted(FsDeviceOperator* d, bool* out) { - return _fsDeviceOperatorCheckInserted(d, 0, out); + return _fsObjectDispatchOut(&d->s, 0, *out); } Result fsDeviceOperatorIsGameCardInserted(FsDeviceOperator* d, bool* out) { - return _fsDeviceOperatorCheckInserted(d, 200, out); + return _fsObjectDispatchOut(&d->s, 200, *out); } Result fsDeviceOperatorGetGameCardHandle(FsDeviceOperator* d, FsGameCardHandle* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 202; - - Result rc = serviceIpcDispatch(&d->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 handle; - } *resp; - - serviceIpcParse(&d->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - out->value = resp->handle; - } - } - - return rc; + return _fsObjectDispatchOut(&d->s, 202, *out); } Result fsDeviceOperatorGetGameCardAttribute(FsDeviceOperator* d, const FsGameCardHandle* handle, u8 *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 handle; - } *raw; - - raw = serviceIpcPrepareHeader(&d->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 205; - raw->handle = handle->value; - - Result rc = serviceIpcDispatch(&d->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 attr; - } *resp; - - serviceIpcParse(&d->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->attr; - } - } - - return rc; + return _fsObjectDispatchInOut(&d->s, 205, *handle, *out); } void fsDeviceOperatorClose(FsDeviceOperator* d) { - serviceClose(&d->s); + _fsObjectClose(&d->s); } diff --git a/nx/source/services/fsldr.c b/nx/source/services/fsldr.c index 8d9fa85c..62336071 100644 --- a/nx/source/services/fsldr.c +++ b/nx/source/services/fsldr.c @@ -1,42 +1,32 @@ // Copyright 2018 SciresM #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/fs.h" -#include "services/sm.h" #include "services/fsldr.h" static Service g_fsldrSrv; -static u64 g_fsldrRefCnt; -Result fsldrSetCurrentProcess(void); +NX_GENERATE_SERVICE_GUARD(fsldr); -Result fsldrInitialize(void) { - atomicIncrement64(&g_fsldrRefCnt); - - if (serviceIsActive(&g_fsldrSrv)) - return 0; +NX_INLINE Result _fsldrSetCurrentProcess(void); +Result _fsldrInitialize(void) { Result rc = smGetService(&g_fsldrSrv, "fsp-ldr"); - + if (R_SUCCEEDED(rc)) { rc = serviceConvertToDomain(&g_fsldrSrv); } if (R_SUCCEEDED(rc) && hosversionAtLeast(4,0,0)) { - rc = fsldrSetCurrentProcess(); + rc = _fsldrSetCurrentProcess(); } return rc; - } -void fsldrExit(void) { - if (atomicDecrement64(&g_fsldrRefCnt) == 0) - serviceClose(&g_fsldrSrv); +void _fsldrCleanup(void) { + serviceClose(&g_fsldrSrv); } Service* fsldrGetServiceSession(void) { @@ -44,115 +34,25 @@ Service* fsldrGetServiceSession(void) { } Result fsldrOpenCodeFileSystem(u64 tid, const char *path, FsFileSystem* out) { - char send_path[FS_MAX_PATH+1] = {0}; - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); - - struct { - u64 magic; - u64 cmd_id; - u64 tid; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->tid = tid; - + char send_path[FS_MAX_PATH + 1]; strncpy(send_path, path, FS_MAX_PATH); - Result rc = serviceIpcDispatch(&g_fsldrSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreateSubservice(&out->s, &g_fsldrSrv, &r, 0); - } - } - - return rc; + return serviceDispatchIn(&g_fsldrSrv, 0, tid, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { send_path, FS_MAX_PATH }, + }, + .out_num_objects = 1, + .out_objects = &out->s, + ); } Result fsldrIsArchivedProgram(u64 pid, bool *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_fsldrSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 is_archived; - } *resp; - - serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->is_archived != 0; - } - } - - return rc; + return serviceDispatchInOut(&g_fsldrSrv, 1, pid, *out); } -Result fsldrSetCurrentProcess(void) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 unk; - } *raw; - - raw = serviceIpcPrepareHeader(&g_fsldrSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->unk = 0; - - Result rc = serviceIpcDispatch(&g_fsldrSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_fsldrSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result _fsldrSetCurrentProcess(void) { + u64 pid_placeholder = 0; + return serviceDispatchIn(&g_fsldrSrv, 2, pid_placeholder, .in_send_pid = true); } - diff --git a/nx/source/services/grc.c b/nx/source/services/grc.c index d788e225..3454a333 100644 --- a/nx/source/services/grc.c +++ b/nx/source/services/grc.c @@ -7,7 +7,10 @@ #include "kernel/tmem.h" #include "services/sm.h" #include "services/grc.h" +#include "services/caps.h" #include "services/applet.h" +#include "display/native_window.h" +#include "audio/audio.h" #include "runtime/hosversion.h" static void _grcGameMovieTrimmerClose(GrcGameMovieTrimmer *t); @@ -44,6 +47,114 @@ static Result _grcCmdNoIO(Service* srv, u64 cmd_id) { return rc; } +static Result _grcCmdInU64(Service* srv, u64 inval, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 inval; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +static Result _grcCmdInU64Out32(Service* srv, u64 inval, u32 *out, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 inval; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) *out = resp->out; + } + + return rc; +} + +static Result _grcCmdNoInOut64(Service* srv, u64 *out, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 out; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) { + *out = resp->out; + } + } + + return rc; +} + static Result _grcGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool autoclear) { IpcCommand c; ipcInitialize(&c); @@ -80,6 +191,80 @@ static Result _grcGetEvent(Service* srv, Event* out_event, u64 cmd_id, bool auto return rc; } +static Result _grcCmdInU64OutEvent(Service* srv, u64 inval, Event* out_event, u64 cmd_id, bool autoclear) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 inval; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->inval = inval; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + eventLoadRemote(out_event, r.Handles[0], autoclear); + } + } + + return rc; +} + +static Result _grcGetSession(Service* srv, Service* srv_out, u64 cmd_id) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + + Result rc = serviceIpcDispatch(srv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(srv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc)) { + serviceCreateSubservice(srv_out, srv, &r, 0); + } + } + + return rc; +} + static Result _grcCreateGameMovieTrimmer(GrcGameMovieTrimmer *t, size_t size) { Result rc=0; Result retryrc = MAKERESULT(212, 4); @@ -260,6 +445,314 @@ Result grcTrimGameMovie(GrcGameMovieId *dst_movieid, const GrcGameMovieId *src_m return rc; } +// IMovieMaker + +void grcCreateOffscreenRecordingParameter(GrcOffscreenRecordingParameter *param) { + memset(param, 0, sizeof(*param)); + param->unk_x10 = 0x103; + + param->video_bitrate = 8000000; + param->video_width = 1280; + param->video_height = 720; + param->video_framerate = 30; + param->video_keyFrameInterval = 30; + + param->audio_bitrate = hosversionAtLeast(6,0,0) ? 128000 : 1536000; + param->audio_samplerate = 48000; + param->audio_channel_count = 2; + param->audio_sample_format = PcmFormat_Int16; + + param->video_imageOrientation = AlbumImageOrientation_Unknown0; +} + +Result grcCreateMovieMaker(GrcMovieMaker *m, size_t size) { + Result rc=0; + Result retryrc = MAKERESULT(212, 4); + s32 binder_id=0; + + memset(m, 0, sizeof(*m)); + + rc = tmemCreate(&m->tmem, size, Perm_None); + if (R_SUCCEEDED(rc)) { + rc = appletCreateMovieMaker(&m->a, &m->tmem); + + while(rc == retryrc) { + svcSleepThread(100000000); + rc = appletCreateMovieMaker(&m->a, &m->tmem); + } + } + + if (R_SUCCEEDED(rc)) rc = _grcGetSession(&m->a, &m->s, 0); // GetGrcMovieMaker + + if (R_SUCCEEDED(rc) && hosversionAtLeast(7,0,0)) rc = _grcCmdInU64(&m->s, capsGetShimLibraryVersion(), 9); // SetAlbumShimLibraryVersion + + if (R_SUCCEEDED(rc)) rc = _grcCmdNoInOut64(&m->a, &m->layer_handle, 1); // GetLayerHandle + + + if (R_SUCCEEDED(rc)) rc = _grcGetSession(&m->s, &m->video_proxy, 2); // CreateVideoProxy + + if (R_SUCCEEDED(rc)) rc = _grcCmdInU64Out32(&m->s, m->layer_handle, (u32*)&binder_id, 10); // OpenOffscreenLayer + if (R_SUCCEEDED(rc)) m->layer_open = true; + + if (R_SUCCEEDED(rc)) rc = nwindowCreate(&m->win, &m->video_proxy, binder_id, false); + if (R_SUCCEEDED(rc)) rc = nwindowSetDimensions(&m->win, 1280, 720); + + if (R_SUCCEEDED(rc)) rc = _grcCmdInU64OutEvent(&m->s, m->layer_handle, &m->recording_event, 50, false); // GetOffscreenLayerRecordingFinishReadyEvent + if (R_SUCCEEDED(rc)) rc = _grcCmdInU64OutEvent(&m->s, m->layer_handle, &m->audio_event, 52, false); // GetOffscreenLayerAudioEncodeReadyEvent + + if (R_FAILED(rc)) grcMovieMakerClose(m); + + return rc; +} + +void grcMovieMakerClose(GrcMovieMaker *m) { + grcMovieMakerAbort(m); + + eventClose(&m->audio_event); + eventClose(&m->recording_event); + + nwindowClose(&m->win); + if (m->layer_open) { + _grcCmdInU64(&m->s, m->layer_handle, 11); // CloseOffscreenLayer + m->layer_open = false; + } + + serviceClose(&m->video_proxy); + serviceClose(&m->s); + serviceClose(&m->a); + tmemClose(&m->tmem); +} + +Result grcMovieMakerStart(GrcMovieMaker *m, const GrcOffscreenRecordingParameter *param) { + if (!serviceIsActive(&m->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 layer_handle; + GrcOffscreenRecordingParameter param; + } *raw; + + raw = serviceIpcPrepareHeader(&m->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 24; + raw->layer_handle = m->layer_handle; + memcpy(&raw->param, param, sizeof(GrcOffscreenRecordingParameter)); + + Result rc = serviceIpcDispatch(&m->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&m->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + if (R_SUCCEEDED(rc)) m->started_flag = true; + + return rc; +} + +Result grcMovieMakerAbort(GrcMovieMaker *m) { + Result rc=0; + + if (!serviceIsActive(&m->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (!m->started_flag) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + rc = _grcCmdInU64(&m->s, m->layer_handle, 21); // AbortOffscreenRecording + if (R_SUCCEEDED(rc)) m->started_flag = false; + return rc; +} + +static Result _grcMovieMakerCompleteOffscreenRecordingFinishEx0(GrcMovieMaker *m, s32 width, s32 height, const void* userdata, size_t userdata_size, const void* thumbnail, size_t thumbnail_size) { + IpcCommand c; + ipcInitialize(&c); + + ipcAddSendBuffer(&c, userdata, userdata_size, BufferType_Normal); + ipcAddSendBuffer(&c, thumbnail, thumbnail_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + s32 width; + s32 height; + u64 layer_handle; + } *raw; + + raw = serviceIpcPrepareHeader(&m->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 25; + raw->width = width; + raw->height = height; + raw->layer_handle = m->layer_handle; + + Result rc = serviceIpcDispatch(&m->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + CapsApplicationAlbumEntry entry; + } *resp; + + serviceIpcParse(&m->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +static Result _grcMovieMakerCompleteOffscreenRecordingFinishEx1(GrcMovieMaker *m, s32 width, s32 height, const void* userdata, size_t userdata_size, const void* thumbnail, size_t thumbnail_size, CapsApplicationAlbumEntry *entry) { + if (hosversionBefore(7,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + IpcCommand c; + ipcInitialize(&c); + + ipcAddSendBuffer(&c, userdata, userdata_size, BufferType_Normal); + ipcAddSendBuffer(&c, thumbnail, thumbnail_size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + s32 width; + s32 height; + u64 layer_handle; + } *raw; + + raw = serviceIpcPrepareHeader(&m->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 26; + raw->width = width; + raw->height = height; + raw->layer_handle = m->layer_handle; + + Result rc = serviceIpcDispatch(&m->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + CapsApplicationAlbumEntry entry; + } *resp; + + serviceIpcParse(&m->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && entry) *entry = resp->entry; + } + + return rc; +} + +Result grcMovieMakerFinish(GrcMovieMaker *m, s32 width, s32 height, const void* userdata, size_t userdata_size, const void* thumbnail, size_t thumbnail_size, CapsApplicationAlbumEntry *entry) { + Result rc=0; + + if (!serviceIsActive(&m->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(7,0,0) && entry) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + rc = _grcCmdInU64(&m->s, m->layer_handle, 22); // RequestOffscreenRecordingFinishReady + + if (R_SUCCEEDED(rc)) rc = eventWait(&m->recording_event, U64_MAX); + + if (hosversionAtLeast(7,0,0)) + rc = _grcMovieMakerCompleteOffscreenRecordingFinishEx1(m, width, height, userdata, userdata_size, thumbnail, thumbnail_size, entry); + else + rc = _grcMovieMakerCompleteOffscreenRecordingFinishEx0(m, width, height, userdata, userdata_size, thumbnail, thumbnail_size); + + if (R_FAILED(rc)) grcMovieMakerAbort(m); + return rc; +} + +Result grcMovieMakerGetError(GrcMovieMaker *m) { + if (!serviceIsActive(&m->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _grcCmdInU64(&m->s, m->layer_handle, 30); // GetOffscreenLayerError +} + +static Result _grcMovieMakerEncodeOffscreenLayerAudioSample(GrcMovieMaker *m, const void* buffer, size_t size, u64 *out_size) { + IpcCommand c; + ipcInitialize(&c); + + ipcAddSendBuffer(&c, buffer, size, BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + u64 layer_handle; + } *raw; + + raw = serviceIpcPrepareHeader(&m->s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 41; + raw->layer_handle = m->layer_handle; + + Result rc = serviceIpcDispatch(&m->s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 out_size; + } *resp; + + serviceIpcParse(&m->s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out_size) *out_size = resp->out_size; + } + + return rc; +} + +Result grcMovieMakerEncodeAudioSample(GrcMovieMaker *m, const void* buffer, size_t size) { + Result rc=0; + u64 out_size=0; + u8 *bufptr = (u8*)buffer; + + if (!serviceIsActive(&m->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + for (u64 pos=0; size!=0; pos+=out_size, size-=out_size) { + rc = eventWait(&m->audio_event, U64_MAX); + if (R_FAILED(rc)) break; + + rc = _grcMovieMakerEncodeOffscreenLayerAudioSample(m, &bufptr[pos], size, &out_size); + if (R_FAILED(rc)) break; + if (out_size > size) out_size = size; + } + + return rc; +} + // grc:d static Service g_grcdSrv; diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 6c88b4d1..25f4581a 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -97,7 +97,7 @@ Result hidInitialize(void) rc = _hidActivateNpad(); if (R_SUCCEEDED(rc)) - rc = hidSetSupportedNpadStyleSet(TYPE_PROCONTROLLER | TYPE_HANDHELD | TYPE_JOYCON_PAIR | TYPE_JOYCON_LEFT | TYPE_JOYCON_RIGHT); + rc = hidSetSupportedNpadStyleSet(TYPE_PROCONTROLLER | TYPE_HANDHELD | TYPE_JOYCON_PAIR | TYPE_JOYCON_LEFT | TYPE_JOYCON_RIGHT | TYPE_SYSTEM_EXT | TYPE_SYSTEM); if (R_SUCCEEDED(rc)) rc = hidSetSupportedNpadIdType(idbuf, 9); @@ -1032,11 +1032,11 @@ Result hidSetNpadJoyHoldType(HidJoyHoldType type) { } Result hidSetNpadJoyAssignmentModeSingleByDefault(HidControllerID id) { - return _hidCmdWithInputU32(122, id); + return _hidCmdWithInputU32(122, hidControllerIDToOfficial(id)); } Result hidSetNpadJoyAssignmentModeDual(HidControllerID id) { - return _hidCmdWithInputU32(124, id); + return _hidCmdWithInputU32(124, hidControllerIDToOfficial(id)); } Result hidMergeSingleJoyAsDualJoy(HidControllerID id0, HidControllerID id1) { @@ -1063,8 +1063,8 @@ Result hidMergeSingleJoyAsDualJoy(HidControllerID id0, HidControllerID id1) { raw->magic = SFCI_MAGIC; raw->cmd_id = 125; - raw->id0 = id0; - raw->id1 = id1; + raw->id0 = hidControllerIDToOfficial(id0); + raw->id1 = hidControllerIDToOfficial(id1); raw->AppletResourceUserId = AppletResourceUserId; rc = serviceIpcDispatch(&g_hidSrv); @@ -1739,3 +1739,44 @@ Result hidResetSevenSixAxisSensorTimestamp(void) { return _hidCmdWithNoInput(310); } +Result hidGetNpadInterfaceType(HidControllerID id, u8 *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc; + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u32 id; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 405; + raw->id = hidControllerIDToOfficial(id); + + rc = serviceIpcDispatch(&g_hidSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + u8 out; + } *resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) *out = resp->out; + } + + return rc; +} + diff --git a/nx/source/services/hiddbg.c b/nx/source/services/hiddbg.c index 925db2d4..7d2a84bd 100644 --- a/nx/source/services/hiddbg.c +++ b/nx/source/services/hiddbg.c @@ -11,11 +11,35 @@ static Service g_hiddbgSrv; static u64 g_hiddbgRefCnt; -static size_t g_hiddbgPtrbufsize; static bool g_hiddbgHdlsInitialized; static TransferMemory g_hiddbgHdlsTmem; +static const u32 g_hiddbgDeviceTypeInternalTable[] = { + BIT(20), // DeviceType 0 Invalid + BIT(0*4+2), // DeviceType 1 JoyRight + BIT(0*4+1), // DeviceType 2 JoyLeft + BIT(1*4+0), // DeviceType 3 FullKey + BIT(1*4+1), // DeviceType 4 JoyLeft + BIT(1*4+2), // DeviceType 5 JoyRight + BIT(8), // DeviceType 6 FullKey + BIT(11), // DeviceType 7 LarkLeft (HVC) + BIT(12), // DeviceType 8 LarkRight (HVC) + BIT(13), // DeviceType 9 LarkLeft (NES) + BIT(14), // DeviceType 10 LarkRight (NES) + BIT(15), // DeviceType 11 Invalid + BIT(16), // DeviceType 12 Palma (Invalid for DeviceTypeInternal) + BIT(9), // DeviceType 13 FullKey + BIT(20), // DeviceType 14 Invalid + BIT(10), // DeviceType 15 FullKey + BIT(18), // DeviceType 16 Invalid + BIT(19), // DeviceType 17 Invalid + BIT(20), // DeviceType 18 Invalid + BIT(21), // DeviceType 19 ::HidDeviceTypeBits_System with HidControllerType |= TYPE_PROCONTROLLER. + BIT(22), // DeviceType 20 ::HidDeviceTypeBits_System with HidControllerType |= TYPE_JOYCON_PAIR. + BIT(23), // DeviceType 21 ::HidDeviceType System with HidControllerType |= TYPE_JOYCON_PAIR. +}; + Result hiddbgInitialize(void) { atomicIncrement64(&g_hiddbgRefCnt); @@ -24,8 +48,6 @@ Result hiddbgInitialize(void) { Result rc = smGetService(&g_hiddbgSrv, "hid:dbg"); - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_hiddbgSrv.handle, &g_hiddbgPtrbufsize); - if (R_FAILED(rc)) hiddbgExit(); return rc; @@ -292,8 +314,55 @@ Result hiddbgReadSerialFlash(u32 offset, void* buffer, size_t size, u64 UniquePa return rc; } +Result hiddbgGetUniquePadDeviceTypeSetInternal(u64 UniquePadId, u32 *out) { + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + Result rc; + + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + u64 UniquePadId; + } *raw; + + raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 234; + raw->UniquePadId = UniquePadId; + + rc = serviceIpcDispatch(&g_hiddbgSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out; + } *resp; + + serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out) { //Pre-9.0.0 output is an u32, with [9.0.0+] it's an u8. + if (hosversionBefore(9,0,0)) + *out = resp->out; + else + *out = resp->out & 0xFF; + } + } + + return rc; +} + Result hiddbgGetAbstractedPadHandles(u64 *AbstractedPadHandles, s32 count, s32 *total_entries) { - if (hosversionBefore(5,0,0)) + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; @@ -326,6 +395,8 @@ Result hiddbgGetAbstractedPadHandles(u64 *AbstractedPadHandles, s32 count, s32 * serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); resp = r.Raw; + rc = resp->result; + if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries; } @@ -333,7 +404,7 @@ Result hiddbgGetAbstractedPadHandles(u64 *AbstractedPadHandles, s32 count, s32 * } Result hiddbgGetAbstractedPadState(u64 AbstractedPadHandle, HiddbgAbstractedPadState *state) { - if (hosversionBefore(5,0,0)) + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; @@ -366,6 +437,8 @@ Result hiddbgGetAbstractedPadState(u64 AbstractedPadHandle, HiddbgAbstractedPadS serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); resp = r.Raw; + rc = resp->result; + if (R_SUCCEEDED(rc) && state) memcpy(state, &resp->state, sizeof(*state)); } @@ -373,7 +446,7 @@ Result hiddbgGetAbstractedPadState(u64 AbstractedPadHandle, HiddbgAbstractedPadS } Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedPadState *states, s32 count, s32 *total_entries) { - if (hosversionBefore(5,0,0)) + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; @@ -387,7 +460,7 @@ Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedP } *raw; ipcAddRecvStatic(&c, AbstractedPadHandles, sizeof(u64)*count, 0); - ipcAddRecvSmart(&c, g_hiddbgPtrbufsize, states, sizeof(HiddbgAbstractedPadState)*count, 0); + ipcAddRecvSmart(&c, g_hiddbgSrv.pointer_buffer_size, states, sizeof(HiddbgAbstractedPadState)*count, 0); raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw)); @@ -407,6 +480,8 @@ Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedP serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); resp = r.Raw; + rc = resp->result; + if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries; } @@ -414,7 +489,7 @@ Result hiddbgGetAbstractedPadsState(u64 *AbstractedPadHandles, HiddbgAbstractedP } Result hiddbgSetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId, const HiddbgAbstractedPadState *state) { - if (hosversionBefore(5,0,0)) + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; @@ -448,13 +523,15 @@ Result hiddbgSetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId, const Hiddbg serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); resp = r.Raw; + + rc = resp->result; } return rc; } Result hiddbgUnsetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId) { - if (hosversionBefore(5,0,0)) + if (hosversionBefore(5,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); Result rc; @@ -485,6 +562,8 @@ Result hiddbgUnsetAutoPilotVirtualPadState(s8 AbstractedVirtualPadId) { serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); resp = r.Raw; + + rc = resp->result; } return rc; @@ -497,6 +576,84 @@ Result hiddbgUnsetAllAutoPilotVirtualPadState(void) { return _hiddbgCmdNoIO(323); } +static u32 _hiddbgConvertDeviceTypeToDeviceTypeInternal(u8 deviceType) { + if (deviceType >= sizeof(g_hiddbgDeviceTypeInternalTable)/sizeof(u32)) return g_hiddbgDeviceTypeInternalTable[0]; + return g_hiddbgDeviceTypeInternalTable[deviceType]; +} + +static u8 _hiddbgConvertDeviceTypeInternalToDeviceType(u32 deviceType) { + for (u32 i=0; ideviceTypeInternal = _hiddbgConvertDeviceTypeToDeviceTypeInternal(in->deviceType); + out->singleColorBody = in->singleColorBody; + out->singleColorButtons = in->singleColorButtons; + out->npadInterfaceType = in->npadInterfaceType; +} + +static void _hiddbgConvertHdlsDeviceInfoFromV7(HiddbgHdlsDeviceInfo *out, const HiddbgHdlsDeviceInfoV7 *in) { + memset(out, 0, sizeof(*out)); + + out->deviceType = _hiddbgConvertDeviceTypeInternalToDeviceType(in->deviceTypeInternal); + out->npadInterfaceType = in->npadInterfaceType; + out->singleColorBody = in->singleColorBody; + out->singleColorButtons = in->singleColorButtons; + //Leave out color*Grip at zero since V7 doesn't have those. +} + +static void _hiddbgConverHiddbgHdlsStateToV7(HiddbgHdlsStateV7 *out, const HiddbgHdlsState *in) { + memset(out, 0, sizeof(*out)); + + out->powerConnected = (in->flags & BIT(0)) != 0; + out->flags = (in->flags & BIT(1)) != 0; + out->batteryCharge = in->batteryCharge; + out->buttons = in->buttons; + memcpy(out->joysticks, in->joysticks, sizeof(in->joysticks)); + out->unk_x20 = in->unk_x20; +} + +static void _hiddbgConverHiddbgHdlsStateFromV7(HiddbgHdlsState *out, const HiddbgHdlsStateV7 *in) { + memset(out, 0, sizeof(*out)); + + out->batteryCharge = in->batteryCharge; + out->flags = (in->powerConnected & 1) | ((in->flags & 1)<<1); + out->buttons = in->buttons; + memcpy(out->joysticks, in->joysticks, sizeof(in->joysticks)); + out->unk_x20 = in->unk_x20; +} + +static void _hiddbgConvertHdlsStateListToV7(HiddbgHdlsStateListV7 *out, const HiddbgHdlsStateList *in) { + s32 count; + memset(out, 0, sizeof(*out)); + out->total_entries = in->total_entries; + count = out->total_entries > 0x10 ? 0x10 : out->total_entries; + + for (s32 i=0; ientries[i].HdlsHandle = in->entries[i].HdlsHandle; + _hiddbgConvertHdlsDeviceInfoToV7(&out->entries[i].device, &in->entries[i].device); + _hiddbgConverHiddbgHdlsStateToV7(&out->entries[i].state, &in->entries[i].state); + } +} + +static void _hiddbgConvertHdlsStateListFromV7(HiddbgHdlsStateList *out, const HiddbgHdlsStateListV7 *in) { + s32 count; + memset(out, 0, sizeof(*out)); + out->total_entries = in->total_entries; + count = out->total_entries > 0x10 ? 0x10 : out->total_entries; + + for (s32 i=0; ientries[i].HdlsHandle = in->entries[i].HdlsHandle; + _hiddbgConvertHdlsDeviceInfoFromV7(&out->entries[i].device, &in->entries[i].device); + _hiddbgConverHiddbgHdlsStateFromV7(&out->entries[i].state, &in->entries[i].state); + } +} + static Result _hiddbgAttachHdlsWorkBuffer(TransferMemory *tmem) { IpcCommand c; ipcInitialize(&c); @@ -594,7 +751,15 @@ Result hiddbgDumpHdlsStates(HiddbgHdlsStateList *state) { rc = _hiddbgCmdNoIO(327); if (R_FAILED(rc)) return rc; - if (state) memcpy(state, g_hiddbgHdlsTmem.src_addr, sizeof(*state)); + if (state) { + if (hosversionBefore(9,0,0)) { + HiddbgHdlsStateListV7 statev7; + memcpy(&statev7, g_hiddbgHdlsTmem.src_addr, sizeof(statev7)); + _hiddbgConvertHdlsStateListFromV7(state, &statev7); + } + else + memcpy(state, g_hiddbgHdlsTmem.src_addr, sizeof(*state)); + } return rc; } @@ -622,10 +787,54 @@ Result hiddbgApplyHdlsStateList(const HiddbgHdlsStateList *state) { if (state==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); - memcpy(g_hiddbgHdlsTmem.src_addr, state, sizeof(*state)); + if (hosversionBefore(9,0,0)) { + HiddbgHdlsStateListV7 statev7; + _hiddbgConvertHdlsStateListToV7(&statev7, state); + memcpy(g_hiddbgHdlsTmem.src_addr, &statev7, sizeof(statev7)); + } + else + memcpy(g_hiddbgHdlsTmem.src_addr, state, sizeof(*state)); + return _hiddbgCmdNoIO(329); } +static Result _hiddbgAttachHdlsVirtualDeviceV7(u64 *HdlsHandle, const HiddbgHdlsDeviceInfoV7 *info) { + IpcCommand c; + ipcInitialize(&c); + + struct { + u64 magic; + u64 cmd_id; + HiddbgHdlsDeviceInfoV7 info; + } *raw; + + raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 330; + raw->info = *info; + + Result rc = serviceIpcDispatch(&g_hiddbgSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u64 handle; + } *resp; + + serviceIpcParse(&g_hiddbgSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && HdlsHandle) *HdlsHandle = resp->handle; + } + + return rc; +} + static Result _hiddbgAttachHdlsVirtualDevice(u64 *HdlsHandle, const HiddbgHdlsDeviceInfo *info) { IpcCommand c; ipcInitialize(&c); @@ -670,7 +879,13 @@ Result hiddbgAttachHdlsVirtualDevice(u64 *HdlsHandle, const HiddbgHdlsDeviceInfo if (!g_hiddbgHdlsInitialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - return _hiddbgAttachHdlsVirtualDevice(HdlsHandle, info); + if (hosversionBefore(9,0,0)) { + HiddbgHdlsDeviceInfoV7 infov7; + _hiddbgConvertHdlsDeviceInfoToV7(&infov7, info); + return _hiddbgAttachHdlsVirtualDeviceV7(HdlsHandle, &infov7); + } + else + return _hiddbgAttachHdlsVirtualDevice(HdlsHandle, info); } Result hiddbgDetachHdlsVirtualDevice(u64 HdlsHandle) { @@ -690,16 +905,30 @@ static Result _hiddbgSetHdlsState(u64 HdlsHandle, const HiddbgHdlsState *state) struct { u64 magic; u64 cmd_id; - HiddbgHdlsState state; - u64 handle; + union { + struct { + HiddbgHdlsStateV7 state; + u64 handle; + } v7; // [7.0.0-8.1.0] + struct { + u64 handle; + HiddbgHdlsState state; + } v9; // [9.0.0+] + }; } *raw; raw = serviceIpcPrepareHeader(&g_hiddbgSrv, &c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 332; - memcpy(&raw->state, state, sizeof(*state)); - raw->handle = HdlsHandle; + if (hosversionBefore(9,0,0)) { + _hiddbgConverHiddbgHdlsStateToV7(&raw->v7.state, state); + raw->v7.handle = HdlsHandle; + } + else { + raw->v9.handle = HdlsHandle; + memcpy(&raw->v9.state, state, sizeof(*state)); + } Result rc = serviceIpcDispatch(&g_hiddbgSrv); diff --git a/nx/source/services/i2c.c b/nx/source/services/i2c.c index 75dae96d..3f667f4b 100644 --- a/nx/source/services/i2c.c +++ b/nx/source/services/i2c.c @@ -6,20 +6,17 @@ #include "services/sm.h" static Service g_i2cSrv; -static size_t g_i2cSrvPtrBufSize; static u64 g_refCnt; Result i2cInitialize(void) { Result rc = 0; - + atomicIncrement64(&g_refCnt); if (serviceIsActive(&g_i2cSrv)) return 0; rc = smGetService(&g_i2cSrv, "i2c"); - - if (R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(g_i2cSrv.handle, &g_i2cSrvPtrBufSize); if (R_FAILED(rc)) i2cExit(); @@ -28,7 +25,6 @@ Result i2cInitialize(void) { void i2cExit(void) { if (atomicDecrement64(&g_refCnt) == 0) { - g_i2cSrvPtrBufSize = 0; serviceClose(&g_i2cSrv); } } @@ -78,7 +74,7 @@ Result i2cOpenSession(I2cSession *out, I2cDevice dev) { Result i2csessionSendAuto(I2cSession *s, const void *buf, size_t size, I2cTransactionOption option) { IpcCommand c; ipcInitialize(&c); - ipcAddSendSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); + ipcAddSendSmart(&c, s->s.pointer_buffer_size, buf, size, 0); struct { u64 magic; @@ -113,7 +109,7 @@ Result i2csessionSendAuto(I2cSession *s, const void *buf, size_t size, I2cTransa Result i2csessionReceiveAuto(I2cSession *s, void *buf, size_t size, I2cTransactionOption option) { IpcCommand c; ipcInitialize(&c); - ipcAddRecvSmart(&c, g_i2cSrvPtrBufSize, buf, size, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, buf, size, 0); struct { u64 magic; @@ -149,7 +145,7 @@ Result i2csessionExecuteCommandList(I2cSession *s, void *dst, size_t dst_size, c IpcCommand c; ipcInitialize(&c); ipcAddSendStatic(&c, cmd_list, cmd_list_size, 0); - ipcAddRecvSmart(&c, g_i2cSrvPtrBufSize, dst, dst_size, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, dst, dst_size, 0); struct { u64 magic; diff --git a/nx/source/services/lr.c b/nx/source/services/lr.c index 6d26185e..a287689a 100644 --- a/nx/source/services/lr.c +++ b/nx/source/services/lr.c @@ -7,17 +7,18 @@ #include "services/lr.h" #include "services/fs.h" #include "services/sm.h" +#include "runtime/hosversion.h" static Service g_managerSrv; static u64 g_managerRefCnt; Result lrInitialize(void) { atomicIncrement64(&g_managerRefCnt); - + if (serviceIsActive(&g_managerSrv)) { return 0; } - + return smGetService(&g_managerSrv, "lr"); } @@ -34,19 +35,19 @@ Service* lrGetServiceSession(void) { Result lrOpenLocationResolver(FsStorageId storage, LrLocationResolver* out) { IpcCommand c; ipcInitialize(&c); - + struct { u64 magic; u64 cmd_id; u32 storage_id; // Actually u8 } *raw; - + raw = ipcPrepareHeader(&c, sizeof(*raw)); - + raw->magic = SFCI_MAGIC; raw->cmd_id = 0; raw->storage_id = (u32)storage; - + Result rc = serviceIpcDispatch(&g_managerSrv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -63,24 +64,24 @@ Result lrOpenLocationResolver(FsStorageId storage, LrLocationResolver* out) { serviceCreate(&out->s, r.Handles[0]); } } - + return rc; } Result lrOpenRegisteredLocationResolver(LrRegisteredLocationResolver* out) { IpcCommand c; ipcInitialize(&c); - + struct { u64 magic; u64 cmd_id; } *raw; - + raw = ipcPrepareHeader(&c, sizeof(*raw)); - + raw->magic = SFCI_MAGIC; raw->cmd_id = 1; - + Result rc = serviceIpcDispatch(&g_managerSrv); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -97,11 +98,11 @@ Result lrOpenRegisteredLocationResolver(LrRegisteredLocationResolver* out) { serviceCreate(&out->s, r.Handles[0]); } } - + return rc; } -/* +/* All the LocationResolver/RegisteredLocationResolver "Resolve" commands have a common API. This is a helper function to perform the work for those funcs, given a command ID. */ @@ -110,18 +111,18 @@ static Result _lrResolvePath(Service* s, u64 cmd_id, u64 tid, char *out) { IpcCommand c; ipcInitialize(&c); ipcAddRecvStatic(&c, out_path, FS_MAX_PATH, 0); - + struct { u64 magic; u64 cmd_id; u64 tid; } *raw; - + raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = cmd_id; raw->tid = tid; - + Result rc = serviceIpcDispatch(s); if (R_SUCCEEDED(rc)) { @@ -139,11 +140,11 @@ static Result _lrResolvePath(Service* s, u64 cmd_id, u64 tid, char *out) { strncpy(out, out_path, FS_MAX_PATH); } } - + return rc; } -/* +/* All the LocationResolver/RegisteredLocationResolver "Redirect" commands have a common API. This is a helper function to perform the work for those funcs, given a command ID. */ @@ -152,18 +153,18 @@ static Result _lrRedirectPath(Service* s, u64 cmd_id, u64 tid, const char *path) IpcCommand c; ipcInitialize(&c); ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); - + struct { u64 magic; u64 cmd_id; u64 tid; } *raw; - + raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = cmd_id; raw->tid = tid; - + strncpy(send_path, path, FS_MAX_PATH); Result rc = serviceIpcDispatch(s); @@ -178,10 +179,55 @@ static Result _lrRedirectPath(Service* s, u64 cmd_id, u64 tid, const char *path) rc = resp->result; } - + return rc; } +/* + In 9.0.0, "RedirectApplication" commands began taking in a second tid argument. + This is a helper function to perform the work for those funcs, given a command ID. +*/ +static Result _lrRedirectApplicationPath(Service* s, u64 cmd_id, u64 tid, u64 tid2, const char *path) { + // On < 9.0.0, call the original redirection helper. + if (hosversionBefore(9,0,0)) { + return _lrRedirectPath(s, cmd_id, tid, path); + } + + char send_path[FS_MAX_PATH+1] = {0}; + IpcCommand c; + ipcInitialize(&c); + ipcAddSendStatic(&c, send_path, FS_MAX_PATH, 0); + + struct { + u64 magic; + u64 cmd_id; + u64 tid; + u64 tid2; + } *raw; + + raw = ipcPrepareHeader(&c, sizeof(*raw)); + raw->magic = SFCI_MAGIC; + raw->cmd_id = cmd_id; + raw->tid = tid; + raw->tid2 = tid2; + + strncpy(send_path, path, FS_MAX_PATH); + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + ipcParse(&r); + + struct { + u64 magic; + u64 result; + } *resp = r.Raw; + + rc = resp->result; + } + + return rc; +} Result lrLrResolveProgramPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, 0, tid, out); @@ -203,36 +249,36 @@ Result lrLrResolveDataPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, 4, tid, out); } -Result lrLrRedirectApplicationControlPath(LrLocationResolver* lr, u64 tid, const char *path) { - return _lrRedirectPath(&lr->s, 5, tid, path); +Result lrLrRedirectApplicationControlPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { + return _lrRedirectApplicationPath(&lr->s, 5, tid, tid2, path); } -Result lrLrRedirectApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, const char *path) { - return _lrRedirectPath(&lr->s, 6, tid, path); +Result lrLrRedirectApplicationHtmlDocumentPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { + return _lrRedirectApplicationPath(&lr->s, 6, tid, tid2, path); } -Result lrLrResolveLegalInformationPath(LrLocationResolver* lr, u64 tid, char *out) { +Result lrLrResolveApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, char *out) { return _lrResolvePath(&lr->s, 7, tid, out); } -Result lrLrRedirectLegalInformationPath(LrLocationResolver* lr, u64 tid, const char *path) { - return _lrRedirectPath(&lr->s, 8, tid, path); +Result lrLrRedirectApplicationLegalInformationPath(LrLocationResolver* lr, u64 tid, u64 tid2, const char *path) { + return _lrRedirectApplicationPath(&lr->s, 8, tid, tid2, path); } Result lrLrRefresh(LrLocationResolver* lr) { IpcCommand c; ipcInitialize(&c); - + struct { u64 magic; u64 cmd_id; } *raw; - + raw = ipcPrepareHeader(&c, sizeof(*raw)); - + raw->magic = SFCI_MAGIC; raw->cmd_id = 9; - + Result rc = serviceIpcDispatch(&lr->s); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -245,7 +291,7 @@ Result lrLrRefresh(LrLocationResolver* lr) { rc = resp->result; } - + return rc; } diff --git a/nx/source/services/ncm.c b/nx/source/services/ncm.c index 217c1ebb..4c18b354 100644 --- a/nx/source/services/ncm.c +++ b/nx/source/services/ncm.c @@ -1,1029 +1,484 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include +#include "service_guard.h" +#include "runtime/hosversion.h" #include "services/ncm.h" -#include "arm/atomics.h" static Service g_ncmSrv; -static u64 g_ncmRefCnt; -Result ncmInitialize(void) { - atomicIncrement64(&g_ncmRefCnt); - - if (serviceIsActive(&g_ncmSrv)) - return 0; +NX_GENERATE_SERVICE_GUARD(ncm); +Result _ncmInitialize(void) { return smGetService(&g_ncmSrv, "ncm"); } -void ncmExit(void) { - if (atomicDecrement64(&g_ncmRefCnt) == 0) { - serviceClose(&g_ncmSrv); - } +void _ncmCleanup(void) { + serviceClose(&g_ncmSrv); } Service* ncmGetServiceSession(void) { return &g_ncmSrv; } -Result ncmOpenContentStorage(FsStorageId storage, NcmContentStorage* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - raw->storage_id = (u32)storage; - - Result rc = serviceIpcDispatch(&g_ncmSrv); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(&out->s, r.Handles[0]); - } - } - - return rc; +static Result _ncmGetInterfaceInU8(Service* srv_out, u32 cmd_id, u8 inval) { + return serviceDispatchIn(&g_ncmSrv, cmd_id, inval, + .out_num_objects = 1, + .out_objects = srv_out, + ); } -Result ncmOpenContentMetaDatabase(FsStorageId storage, NcmContentMetaDatabase* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 storage_id; // Actually u8 - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->storage_id = (u32)storage; - - Result rc = serviceIpcDispatch(&g_ncmSrv); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(&out->s, r.Handles[0]); - } - } - - return rc; +static Result _ncmCmdNoIo(Service* srv, u32 cmd_id) { + return serviceDispatch(srv, cmd_id); } -Result ncmContentStorageGeneratePlaceHolderId(NcmContentStorage* cs, NcmNcaId* outputId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&cs->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - NcmNcaId outputId; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(outputId, &resp->outputId, sizeof(NcmNcaId)); - } - } - - return rc; +static Result _ncmCmdNoInOutU64(Service* srv, u32 cmd_id, u64* outval) { + return serviceDispatchOut(srv, cmd_id, *outval); } -Result ncmContentStorageCreatePlaceHolder(NcmContentStorage* cs, const NcmNcaId* registeredId, const NcmNcaId* placeholderId, u64 size) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId registeredId; - NcmNcaId placeholderId; +static Result _ncmCmdOutNcaId(Service* srv, u32 cmd_id, NcmNcaId* outval) { + return serviceDispatchOut(srv, cmd_id, *outval); +} + +static Result _ncmCmdInU8(Service* srv, u32 cmd_id, u8 inval) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _ncmCmdInNcaId(Service* srv, u32 cmd_id, const NcmNcaId* inval) { + return serviceDispatchIn(srv, cmd_id, *inval); +} + +static Result _ncmCmdInNcaIdOutU64(Service* srv, u32 cmd_id, const NcmNcaId* inval, u64* outval) { + return serviceDispatchInOut(srv, cmd_id, *inval, *outval); +} + +Result ncmCreateContentStorage(FsStorageId storage_id) { + return _ncmCmdInU8(&g_ncmSrv, 0, storage_id); +} + +Result ncmCreateContentMetaDatabase(FsStorageId storage_id) { + return _ncmCmdInU8(&g_ncmSrv, 1, storage_id); +} + +Result ncmVerifyContentStorage(FsStorageId storage_id) { + return _ncmCmdInU8(&g_ncmSrv, 2, storage_id); +} + +Result ncmVerifyContentMetaDatabase(FsStorageId storage_id) { + return _ncmCmdInU8(&g_ncmSrv, 3, storage_id); +} + +Result ncmOpenContentStorage(NcmContentStorage* out_content_storage, FsStorageId storage_id) { + return _ncmGetInterfaceInU8(&out_content_storage->s, 4, storage_id); +} + +Result ncmOpenContentMetaDatabase(NcmContentMetaDatabase* out_content_meta_database, FsStorageId storage_id) { + return _ncmGetInterfaceInU8(&out_content_meta_database->s, 5, storage_id); +} + +Result ncmCloseContentStorageForcibly(FsStorageId storage_id) { + if (hosversionAtLeast(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 6, storage_id); +} + +Result ncmCloseContentMetaDatabaseForcibly(FsStorageId storage_id) { + if (hosversionAtLeast(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 7, storage_id); +} + +Result ncmCleanupContentMetaDatabase(FsStorageId storage_id) { + return _ncmCmdInU8(&g_ncmSrv, 8, storage_id); +} + +Result ncmActivateContentStorage(FsStorageId storage_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 9, storage_id); +} + +Result ncmInactivateContentStorage(FsStorageId storage_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 10, storage_id); +} + +Result ncmActivateContentMetaDatabase(FsStorageId storage_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 11, storage_id); +} + +Result ncmInactivateContentMetaDatabase(FsStorageId storage_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInU8(&g_ncmSrv, 12, storage_id); +} + +Result ncmInvalidateRightsIdCache(void) { + if (hosversionBefore(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdNoIo(&g_ncmSrv, 13); +} + +void ncmContentStorageClose(NcmContentStorage* cs) { + serviceClose(&cs->s); +} + +Result ncmContentStorageGeneratePlaceHolderId(NcmContentStorage* cs, NcmNcaId* out_id) { + return _ncmCmdOutNcaId(&cs->s, 0, out_id); +} + +Result ncmContentStorageCreatePlaceHolder(NcmContentStorage* cs, const NcmNcaId* content_id, const NcmNcaId* placeholder_id, u64 size) { + const struct { + NcmNcaId content_id; + NcmNcaId placeholder_id; u64 size; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - memcpy(&raw->registeredId, registeredId, sizeof(NcmNcaId)); - memcpy(&raw->placeholderId, placeholderId, sizeof(NcmNcaId)); - raw->size = size; - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *content_id, *placeholder_id, size }; + return serviceDispatchIn(&cs->s, 1, in); } -Result ncmContentStorageDeletePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholderId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId placeholderId; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - memcpy(&raw->placeholderId, placeholderId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result ncmContentStorageDeletePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id) { + return _ncmCmdInNcaId(&cs->s, 2, placeholder_id); } -Result ncmContentStorageWritePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholderId, u64 offset, const void* srcData, size_t srcDataSize) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, srcData, srcDataSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId placeholderId; +Result ncmContentStorageHasPlaceHolder(NcmContentStorage* cs, bool* out, const NcmNcaId* placeholder_id) { + return serviceDispatchInOut(&cs->s, 3, *placeholder_id, *out); +} + +Result ncmContentStorageWritePlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id, u64 offset, const void* data, size_t data_size) { + const struct { + NcmNcaId placeholder_id; u64 offset; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - memcpy(&raw->placeholderId, placeholderId, sizeof(NcmNcaId)); - raw->offset = offset; - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *placeholder_id, offset }; + return serviceDispatchIn(&cs->s, 4, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { data, data_size } }, + ); } -Result ncmContentStorageRegister(NcmContentStorage* cs, const NcmNcaId* registeredId, const NcmNcaId* placeholderId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId registeredId; - NcmNcaId placeholderId; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - memcpy(&raw->registeredId, registeredId, sizeof(NcmNcaId)); - memcpy(&raw->placeholderId, placeholderId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result ncmContentStorageRegister(NcmContentStorage* cs, const NcmNcaId* content_id, const NcmNcaId* placeholder_id) { + const struct { + NcmNcaId content_id; + NcmNcaId placeholder_id; + } in = { *content_id, *placeholder_id }; + return serviceDispatchIn(&cs->s, 5, in); } -Result ncmContentStorageDelete(NcmContentStorage* cs, const NcmNcaId* registeredId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId registeredId; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - memcpy(&raw->registeredId, registeredId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result ncmContentStorageDelete(NcmContentStorage* cs, const NcmNcaId* content_id) { + return _ncmCmdInNcaId(&cs->s, 6, content_id); } -Result ncmContentStorageHas(NcmContentStorage* cs, const NcmNcaId* ncaId, bool* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - bool out; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->out; - } - } - - return rc; +Result ncmContentStorageHas(NcmContentStorage* cs, bool* out, const NcmNcaId* content_id) { + return serviceDispatchInOut(&cs->s, 7, *content_id, *out); } -Result ncmContentStorageGetPath(NcmContentStorage* cs, const NcmNcaId* ncaId, char* out, size_t outSize) { - char out_path[FS_MAX_PATH-1] = {0}; - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvStatic(&c, out_path, FS_MAX_PATH-1, 0); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (outSize > FS_MAX_PATH-1) outSize = FS_MAX_PATH-1; - strncpy(out, out_path, outSize); - } - } - - return rc; +Result ncmContentStorageGetPath(NcmContentStorage* cs, char* out_path, size_t out_size, const NcmNcaId* content_id) { + return serviceDispatchIn(&cs->s, 8, *content_id, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { out_path, out_size } }, + ); } -Result ncmContentStorageGetPlaceHolderPath(NcmContentStorage* cs, const NcmNcaId* ncaId, char* out, size_t outSize) { - char out_path[FS_MAX_PATH-1] = {0}; - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvStatic(&c, out_path, FS_MAX_PATH-1, 0); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 9; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (outSize > FS_MAX_PATH-1) outSize = FS_MAX_PATH-1; - strncpy(out, out_path, outSize); - } - } - - return rc; +Result ncmContentStorageGetPlaceHolderPath(NcmContentStorage* cs, const char* out_path, size_t out_size, const NcmNcaId* placeholder_id) { + return serviceDispatchIn(&cs->s, 9, *placeholder_id, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { out_path, out_size } }, + ); } Result ncmContentStorageCleanupAllPlaceHolder(NcmContentStorage* cs) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _ncmCmdNoIo(&cs->s, 10); } -Result ncmContentStorageGetSize(NcmContentStorage* cs, const NcmNcaId* ncaId, u64* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 14; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); +Result ncmContentStorageListPlaceHolder(NcmContentStorage* cs, NcmNcaId* out_ids, size_t out_ids_size, u32* out_count) { + return serviceDispatchOut(&cs->s, 11, *out_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_ids, out_ids_size } }, + ); +} - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); +Result ncmContentStorageGetContentCount(NcmContentStorage* cs, u32* out_count) { + return serviceDispatchOut(&cs->s, 12, *out_count); +} - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; +Result ncmContentStorageListContentId(NcmContentStorage* cs, NcmNcaId* out_ids, size_t out_ids_size, u32* out_count, u32 start_offset) { + return serviceDispatchInOut(&cs->s, 13, start_offset, *out_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_ids, out_ids_size } }, + ); +} - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->size; - } - } - - return rc; +Result ncmContentStorageGetSizeFromContentId(NcmContentStorage* cs, u64* out_size, const NcmNcaId* content_id) { + return _ncmCmdInNcaIdOutU64(&cs->s, 14, content_id, out_size); } Result ncmContentStorageDisableForcibly(NcmContentStorage* cs) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - - Result rc = serviceIpcDispatch(&cs->s); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _ncmCmdNoIo(&cs->s, 15); } -Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, const NcmNcaId* ncaId, u64 offset, void* outBuf, size_t bufSize) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, outBuf, bufSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; +Result ncmContentStorageRevertToPlaceHolder(NcmContentStorage* cs, const NcmNcaId* placeholder_id, const NcmNcaId* old_content_id, const NcmNcaId* new_content_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + NcmNcaId old_content_id; + NcmNcaId new_content_id; + NcmNcaId placeholder_id; + } in = { *old_content_id, *new_content_id, *placeholder_id }; + return serviceDispatchIn(&cs->s, 16, in); +} + +Result ncmContentStorageSetPlaceHolderSize(NcmContentStorage* cs, const NcmNcaId* placeholder_id, u64 size) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + NcmNcaId placeholder_id; + u64 size; + } in = { *placeholder_id, size }; + return serviceDispatchIn(&cs->s, 17, in); +} + +Result ncmContentStorageReadContentIdFile(NcmContentStorage* cs, void* out_data, size_t out_data_size, const NcmNcaId* content_id, u64 offset) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + NcmNcaId content_id; u64 offset; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - raw->offset = offset; - - Result rc = serviceIpcDispatch(&cs->s); + } in = { *content_id, offset }; + return serviceDispatchIn(&cs->s, 18, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_data, out_data_size } }, + ); +} +Result ncmContentStorageGetRightsIdFromPlaceHolderId(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* placeholder_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + struct { + FsRightsId rights_id; + u32 key_generation; + } out; + Result rc = serviceDispatchInOut(&cs->s, 19, *placeholder_id, out); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (out_rights_id) *out_rights_id = out.rights_id; + if (out_key_generation) *out_key_generation = out.key_generation; } - return rc; } -Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, const NcmNcaId* ncaId, FsRightsId* rightsIdOut, u32* keyGenerationOut) { - IpcCommand c; - ipcInitialize(&c); - +Result ncmContentStorageGetRightsIdFromContentId(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* content_id) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); struct { - u64 magic; - u64 cmd_id; - NcmNcaId nca_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 20; - memcpy(&raw->nca_id, ncaId, sizeof(NcmNcaId)); - - Result rc = serviceIpcDispatch(&cs->s); + FsRightsId rights_id; + u32 key_generation; + } out; + Result rc = serviceDispatchInOut(&cs->s, 20, *content_id, out); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - FsRightsId rights_id; - u32 key_generation; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (rightsIdOut) memcpy(rightsIdOut, &resp->rights_id, sizeof(FsRightsId)); - if (keyGenerationOut) *keyGenerationOut = resp->key_generation; - } + if (out_rights_id) *out_rights_id = out.rights_id; + if (out_key_generation) *out_key_generation = out.key_generation; } - return rc; } -Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 inDataSize, const NcmContentMetaRecordsHeader* srcRecordsData) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, srcRecordsData, inDataSize, BufferType_Normal); +Result ncmContentStorageWriteContentForDebug(NcmContentStorage* cs, const NcmNcaId* content_id, u64 offset, const void* data, size_t data_size) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + NcmNcaId content_id; + u64 offset; + } in = { *content_id, offset }; + return serviceDispatchIn(&cs->s, 21, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { data, data_size } }, + ); +} +Result ncmContentStorageGetFreeSpaceSize(NcmContentStorage* cs, u64* out_size) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdNoInOutU64(&cs->s, 22, out_size); +} + +Result ncmContentStorageGetTotalSpaceSize(NcmContentStorage* cs, u64* out_size) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdNoInOutU64(&cs->s, 23, out_size); +} + +Result ncmContentStorageFlushPlaceHolder(NcmContentStorage* cs) { + if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdNoIo(&cs->s, 24); +} + +Result ncmContentStorageGetSizeFromPlaceHolderId(NcmContentStorage* cs, u64* out_size, const NcmNcaId* placeholder_id) { + if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdInNcaIdOutU64(&cs->s, 25, placeholder_id, out_size); +} + +Result ncmContentStorageRepairInvalidFileAttribute(NcmContentStorage* cs) { + if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return _ncmCmdNoIo(&cs->s, 26); +} + +Result ncmContentStorageGetRightsIdFromPlaceHolderIdWithCache(NcmContentStorage* cs, FsRightsId* out_rights_id, u32* out_key_generation, const NcmNcaId* placeholder_id, const NcmNcaId* cache_content_id) { + if (hosversionBefore(8,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + NcmNcaId cache_content_id; + NcmNcaId placeholder_id; + } in = { *cache_content_id, *placeholder_id }; struct { - u64 magic; - u64 cmd_id; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); + FsRightsId rights_id; + u32 key_generation; + } out; + Result rc = serviceDispatchInOut(&cs->s, 27, in, out); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (out_rights_id) *out_rights_id = out.rights_id; + if (out_key_generation) *out_key_generation = out.key_generation; } - return rc; } -Result ncmContentMetaDatabaseGet(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u64 outDataSize, NcmContentMetaRecordsHeader* outRecordsData, u64* sizeRead) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, outRecordsData, outDataSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size_read; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (sizeRead) *sizeRead = resp->size_read; - } - } - - return rc; +void ncmContentMetaDatabaseClose(NcmContentMetaDatabase* db) { + serviceClose(&db->s); } -Result ncmContentMetaDatabaseRemove(NcmContentMetaDatabase* db, const NcmMetaRecord *record) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result ncmContentMetaDatabaseSet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, const void* data, u64 data_size) { + return serviceDispatchIn(&db->s, 0, *key, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { data, data_size } }, + ); } -Result ncmContentMetaDatabaseGetContentIdByType(NcmContentMetaDatabase* db, NcmContentType contentType, const NcmMetaRecord* record, NcmNcaId* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 content_type; - u32 padding; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->content_type = contentType; - raw->padding = 0; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - NcmNcaId nca_id; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - memcpy(out, &resp->nca_id, sizeof(NcmNcaId)); - } - } - - return rc; +Result ncmContentMetaDatabaseGet(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u64* out_size, void* out_data, u64 out_data_size) { + return serviceDispatchInOut(&db->s, 1, *key, *out_size, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_data, out_data_size } }, + ); } -Result ncmContentMetaDatabaseListContentInfo(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u32 index, NcmContentRecord* contentRecordsOut, size_t contentRecordsBufSize, u32* numEntriesRead) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, contentRecordsOut, contentRecordsBufSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u32 index; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - raw->index = index; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 entries_read; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (numEntriesRead) *numEntriesRead = resp->entries_read; - } - } - - return rc; +Result ncmContentMetaDatabaseRemove(NcmContentMetaDatabase* db, const NcmContentMetaKey *key) { + return serviceDispatchIn(&db->s, 2, *key); } -Result ncmContentMetaDatabaseList(NcmContentMetaDatabase* db, u32 titleType, u64 titleIdExact, u64 titleIdLow, u64 titleIdHigh, NcmMetaRecord* metaRecordsOut, size_t metaRecordsBufSize, u32* numEntriesWritten, u32* numEntriesTotal) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, metaRecordsOut, metaRecordsBufSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u32 titleType; - u64 titleIdExact; - u64 titleIdLow; - u64 titleIdHigh; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->titleType = titleType; - raw->titleIdExact = titleIdExact; - raw->titleIdLow = titleIdLow; - raw->titleIdHigh = titleIdHigh; - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 numEntriesTotal; - u32 numEntriesWritten; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (numEntriesTotal) - *numEntriesTotal = resp->numEntriesTotal; - if (numEntriesWritten) - *numEntriesWritten = resp->numEntriesWritten; - } - } - - return rc; +Result ncmContentMetaDatabaseGetContentIdByType(NcmContentMetaDatabase* db, NcmNcaId* out_content_id, const NcmContentMetaKey* key, NcmContentType type) { + const struct { + u8 type; + u8 padding[7]; + NcmContentMetaKey key; + } in = { type, {0}, *key }; + return serviceDispatchInOut(&db->s, 3, in, *out_content_id); } -Result ncmContentMetaDatabaseGetLatestContentMetaKey(NcmContentMetaDatabase* db, u64 titleId, NcmMetaRecord* out) { - IpcCommand c; - ipcInitialize(&c); - +Result ncmContentMetaDatabaseListContentInfo(NcmContentMetaDatabase* db, u32* out_entries_written, NcmContentInfo* out_info, size_t out_info_size, const NcmContentMetaKey* key, u32 start_index) { + const struct { + u32 start_index; + NcmContentMetaKey key; + } in = { start_index, *key }; + return serviceDispatchInOut(&db->s, 4, in, *out_entries_written, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_info, out_info_size } }, + ); +} +Result ncmContentMetaDatabaseList(NcmContentMetaDatabase* db, u32* out_entries_total, u32* out_entries_written, NcmContentMetaKey* out_keys, size_t out_keys_size, NcmContentMetaType meta_type, u64 application_title_id, u64 title_id_min, u64 title_id_max, NcmContentInstallType install_type) { + const struct { + u8 meta_type; + u8 install_type; + u16 padding; + u64 application_title_id; + u64 title_id_min; + u64 title_id_max; + } in = { meta_type, install_type, 0, application_title_id, title_id_min, title_id_max }; struct { - u64 magic; - u64 cmd_id; - u64 title_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - raw->title_id = titleId; - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - NcmMetaRecord record; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - memcpy(out, &resp->record, sizeof(NcmMetaRecord)); - } - } - - return rc; + u32 out_entries_total; + u32 out_entries_written; + } out; + return serviceDispatchInOut(&db->s, 5, in, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_keys, out_keys_size } }, + ); } -Result ncmContentMetaDatabaseListApplication(NcmContentMetaDatabase* db, u8 filter, NcmApplicationContentMetaKey* outBuf, size_t outBufSize, u32* numEntriesWritten, u32* numEntriesTotal) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, outBuf, outBufSize, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u8 filter; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - raw->filter = filter; - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 total_entries; - u32 entries_written; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (numEntriesTotal) *numEntriesTotal = resp->total_entries; - if (numEntriesWritten) *numEntriesWritten = resp->entries_written; - } - } - - return rc; +Result ncmContentMetaDatabaseGetLatestContentMetaKey(NcmContentMetaDatabase* db, NcmContentMetaKey* out_key, u64 title_id) { + return serviceDispatchInOut(&db->s, 6, title_id, *out_key); } -Result ncmContentMetaDatabaseHas(NcmContentMetaDatabase* db, const NcmMetaRecord* record, bool* out) { - IpcCommand c; - ipcInitialize(&c); - +Result ncmContentMetaDatabaseListApplication(NcmContentMetaDatabase* db, u32* out_entries_total, u32* out_entries_written, NcmApplicationContentMetaKey* out_keys, size_t out_keys_size, NcmContentMetaType meta_type) { struct { - u64 magic; - u64 cmd_id; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); + u32 out_entries_total; + u32 out_entries_written; + } out; + return serviceDispatchInOut(&db->s, 7, meta_type, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_keys, out_keys_size } }, + ); +} - struct { - u64 magic; - u64 result; - bool out; - } *resp = r.Raw; +Result ncmContentMetaDatabaseHas(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* key) { + return serviceDispatchInOut(&db->s, 8, *key, *out); +} - rc = resp->result; +Result ncmContentMetaDatabaseHasAll(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* keys, size_t keys_size) { + return serviceDispatchOut(&db->s, 9, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { keys, keys_size } }, + ); +} - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->out; - } - } - - return rc; +Result ncmContentMetaDatabaseGetSize(NcmContentMetaDatabase* db, u64* out_size, const NcmContentMetaKey* key) { + return serviceDispatchInOut(&db->s, 10, *key, *out_size); +} + +Result ncmContentMetaDatabaseGetRequiredSystemVersion(NcmContentMetaDatabase* db, u64* out_version, const NcmContentMetaKey* key) { + return serviceDispatchInOut(&db->s, 11, *key, *out_version); +} + +Result ncmContentMetaDatabaseGetPatchId(NcmContentMetaDatabase* db, u64* out_patch_id, const NcmContentMetaKey* key) { + return serviceDispatchInOut(&db->s, 12, *key, *out_patch_id); } Result ncmContentMetaDatabaseDisableForcibly(NcmContentMetaDatabase* db) { - IpcCommand c; - ipcInitialize(&c); + return _ncmCmdNoIo(&db->s, 13); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result ncmContentMetaDatabaseLookupOrphanContent(NcmContentMetaDatabase* db, bool* out_orphaned, size_t out_orphaned_size, const NcmNcaId* content_ids, size_t content_ids_size) { + return serviceDispatch(&db->s, 14, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + }, + .buffers = { + { out_orphaned, out_orphaned_size }, + { content_ids, content_ids_size }, + }, + ); } Result ncmContentMetaDatabaseCommit(NcmContentMetaDatabase* db) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _ncmCmdNoIo(&db->s, 15); } -Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmMetaRecord* record, u8* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - NcmMetaRecord meta_record; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - memcpy(&raw->meta_record, record, sizeof(NcmMetaRecord)); - - Result rc = serviceIpcDispatch(&db->s); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 out; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->out; - } - } - - return rc; +Result ncmContentMetaDatabaseHasContent(NcmContentMetaDatabase* db, bool* out, const NcmContentMetaKey* key, const NcmNcaId* content_id) { + const struct { + NcmNcaId content_id; + NcmContentMetaKey key; + } in = { *content_id, *key }; + return serviceDispatchInOut(&db->s, 16, in, *out); +} + +Result ncmContentMetaDatabaseListContentMetaInfo(NcmContentMetaDatabase* db, u32* out_entries_written, void* out_meta_info, size_t out_meta_info_size, const NcmContentMetaKey* key, u32 start_index) { + const struct { + u32 start_index; + u32 padding; + NcmContentMetaKey key; + } in = { start_index, 0, *key }; + return serviceDispatchInOut(&db->s, 17, in, *out_entries_written, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { out_meta_info, out_meta_info_size } }, + ); +} + +Result ncmContentMetaDatabaseGetAttributes(NcmContentMetaDatabase* db, const NcmContentMetaKey* key, u8* out) { + return serviceDispatchInOut(&db->s, 18, *key, *out); +} + +Result ncmContentMetaDatabaseGetRequiredApplicationVersion(NcmContentMetaDatabase* db, u64* out_version, const NcmContentMetaKey* key) { + if (hosversionBefore(2,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatchInOut(&db->s, 19, *key, *out_version); +} + +Result ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(NcmContentMetaDatabase* db, NcmNcaId* out_content_id, const NcmContentMetaKey* key, NcmContentType type, u8 id_offset) { + if (hosversionBefore(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + const struct { + u8 type; + u8 id_offset; + u8 padding[6]; + NcmContentMetaKey key; + } in = { type, id_offset, {0}, *key }; + return serviceDispatchInOut(&db->s, 20, in, *out_content_id); } diff --git a/nx/source/services/nifm.c b/nx/source/services/nifm.c index 031aa211..762cb56f 100644 --- a/nx/source/services/nifm.c +++ b/nx/source/services/nifm.c @@ -1,33 +1,22 @@ -/** - * @file nifm.c - * @brief Network interface service IPC wrapper. - * @author shadowninja108, shibboleet - * @copyright libnx Authors - */ - +#include "service_guard.h" #include "services/nifm.h" -#include "arm/atomics.h" #include "runtime/hosversion.h" static NifmServiceType g_nifmServiceType = NifmServiceType_NotInitialized; static Service g_nifmSrv; static Service g_nifmIGS; -static u64 g_refCnt; -static Result _nifmCreateGeneralService(Service* out, u64 in); -static Result _nifmCreateGeneralServiceOld(Service* out); +static Result _nifmCreateGeneralService(Service* srv_out); +static Result _nifmCreateGeneralServiceOld(Service* srv_out); + +NX_GENERATE_SERVICE_GUARD(nifm); void nifmSetServiceType(NifmServiceType serviceType) { g_nifmServiceType = serviceType; } -Result nifmInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_nifmSrv)) - return 0; - +Result _nifmInitialize(void) { Result rc = 0; switch (g_nifmServiceType) { case NifmServiceType_NotInitialized: @@ -47,393 +36,125 @@ Result nifmInitialize(void) { if (R_SUCCEEDED(rc)) { if (hosversionAtLeast(3,0,0)) - rc = _nifmCreateGeneralService(&g_nifmIGS, 0); // What does this parameter do? + rc = _nifmCreateGeneralService(&g_nifmIGS); else rc = _nifmCreateGeneralServiceOld(&g_nifmIGS); } - if (R_FAILED(rc)) - nifmExit(); - return rc; } -void nifmExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_nifmIGS); - serviceClose(&g_nifmSrv); - g_nifmServiceType = NifmServiceType_NotInitialized; - } +void _nifmCleanup(void) { + serviceClose(&g_nifmIGS); + serviceClose(&g_nifmSrv); + g_nifmServiceType = NifmServiceType_NotInitialized; +} + +Service* nifmGetServiceSession_StaticService(void) { + return &g_nifmSrv; +} + +Service* nifmGetServiceSession_GeneralService(void) { + return &g_nifmIGS; +} + +static Result _nifmCmdNoIO(Service* srv, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id); +} + +static Result _nifmCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _nifmCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _nifmCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _nifmCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) { + u8 tmp=0; + Result rc = _nifmCmdNoInOutU8(srv, &tmp, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmp!=0; + return rc; +} + +static Result _nifmCmdInU8NoOut(Service* srv, u8 inval, u64 cmd_id) { + serviceAssumeDomain(srv); + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _nifmCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) { + return _nifmCmdInU8NoOut(srv, inval!=0, cmd_id); +} + +static Result _nifmCreateGeneralServiceOld(Service* srv_out) { + return _nifmCmdGetSession(&g_nifmSrv, srv_out, 4); +} + +static Result _nifmCreateGeneralService(Service* srv_out) { + u64 reserved=0; + serviceAssumeDomain(&g_nifmSrv); + return serviceDispatchIn(&g_nifmSrv, 5, reserved, + .in_send_pid = true, + .out_num_objects = 1, + .out_objects = srv_out, + ); } Result nifmGetCurrentIpAddress(u32* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u32 out; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - *out = resp->out; - } - - return rc; -} - -Result nifmIsWirelessCommunicationEnabled(bool* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 17; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u8 out; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) - *out = resp->out != 0; - } - - return rc; + return _nifmCmdNoInOutU32(&g_nifmIGS, out, 12); } Result nifmSetWirelessCommunicationEnabled(bool enable) { if (g_nifmServiceType < NifmServiceType_System) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); + return _nifmCmdInBoolNoOut(&g_nifmIGS, enable, 16); +} +Result nifmIsWirelessCommunicationEnabled(bool* out) { + return _nifmCmdNoInOutBool(&g_nifmIGS, out, 17); +} + +Result nifmGetInternetConnectionStatus(NifmInternetConnectionType* connectionType, u32* wifiStrength, NifmInternetConnectionStatus* connectionStatus) { struct { - u64 magic; - u64 cmd_id; - u8 value; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 16; - raw->value = enable!= 0; - - Result rc = serviceIpcDispatch(&g_nifmIGS); + u8 out1; + u8 out2; + u8 out3; + } out; + serviceAssumeDomain(&g_nifmIGS); + Result rc = serviceDispatchOut(&g_nifmIGS, 18, out); if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; + if (connectionType) *connectionType = out.out1; + if (wifiStrength) *wifiStrength = out.out2; + if (connectionStatus) *connectionStatus = out.out3; } - return rc; } Result nifmIsEthernetCommunicationEnabled(bool* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 20; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u8 out; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) - *out = resp->out != 0; - } - - return rc; + return _nifmCmdNoInOutBool(&g_nifmIGS, out, 20); } Result nifmIsAnyForegroundRequestAccepted(bool* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 22; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u8 out; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) - *out = resp->out != 0; - } - - return rc; + return _nifmCmdNoInOutBool(&g_nifmIGS, out, 22); } Result nifmPutToSleep(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _nifmCmdNoIO(&g_nifmIGS, 23); } Result nifmWakeUp(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 24; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -Result nifmGetInternetConnectionStatus(NifmInternetConnectionType* connectionType, u32* wifiStrength, NifmInternetConnectionStatus* connectionStatus) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nifmIGS, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - - Result rc = serviceIpcDispatch(&g_nifmIGS); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u8 out1; - u8 out2; - u8 out3; - } PACKED *resp; - - serviceIpcParse(&g_nifmIGS, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (connectionType) - *connectionType = resp->out1; - - if (wifiStrength) - *wifiStrength = resp->out2; - - if (connectionStatus) - *connectionStatus = resp->out3; - } - } - - return rc; -} - -static Result _nifmCreateGeneralService(Service* out, u64 in) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 param; - } PACKED *raw; - - raw = serviceIpcPrepareHeader(&g_nifmSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->param = in; - - Result rc = serviceIpcDispatch(&g_nifmSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nifmSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - serviceCreateSubservice(out, &g_nifmSrv, &r, 0); - } - - return rc; -} - -static Result _nifmCreateGeneralServiceOld(Service* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } PACKED *raw; - - raw = serviceIpcPrepareHeader(&g_nifmSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&g_nifmSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nifmSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - serviceCreateSubservice(out, &g_nifmSrv, &r, 0); - } - - return rc; + return _nifmCmdNoIO(&g_nifmIGS, 24); } diff --git a/nx/source/services/ns.c b/nx/source/services/ns.c index 6fcbc492..10a18ed2 100644 --- a/nx/source/services/ns.c +++ b/nx/source/services/ns.c @@ -1,847 +1,670 @@ -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include "service_guard.h" #include "runtime/hosversion.h" -#include "services/sm.h" #include "services/ns.h" +#include "services/fs.h" +#include "services/ncm.h" +#include "services/async.h" +#include "kernel/tmem.h" -static Service g_nsAppManSrv, g_nsGetterSrv, g_nsvmSrv, g_nsdevSrv; -static u64 g_nsRefCnt, g_nsvmRefCnt, g_nsdevRefCnt; +static Service g_nsAppManSrv, g_nsGetterSrv; +static Service g_nsvmSrv; +static Service g_nsdevSrv; +static Service g_nssuSrv; -static Result _nsGetInterface(Service* srv_out, u64 cmd_id); +static Result _nsGetSession(Service* srv, Service* srv_out, u32 cmd_id); -Result nsInitialize(void) +// ns + +NX_GENERATE_SERVICE_GUARD(ns); + +Result _nsInitialize(void) { Result rc=0; - atomicIncrement64(&g_nsRefCnt); - - if (serviceIsActive(&g_nsGetterSrv) || serviceIsActive(&g_nsAppManSrv)) - return 0; - if(hosversionBefore(3,0,0)) return smGetService(&g_nsAppManSrv, "ns:am"); rc = smGetService(&g_nsGetterSrv, "ns:am2");//TODO: Support the other services?(Only useful when ns:am2 isn't accessible) if (R_FAILED(rc)) return rc; - rc = _nsGetInterface(&g_nsAppManSrv, 7996); + rc = _nsGetSession(&g_nsGetterSrv, &g_nsAppManSrv, 7996); if (R_FAILED(rc)) serviceClose(&g_nsGetterSrv); return rc; } -void nsExit(void) +void _nsCleanup(void) { - if (atomicDecrement64(&g_nsRefCnt) == 0) { - serviceClose(&g_nsAppManSrv); - if(hosversionBefore(3,0,0)) return; + serviceClose(&g_nsAppManSrv); + if(hosversionBefore(3,0,0)) return; - serviceClose(&g_nsGetterSrv); - } + serviceClose(&g_nsGetterSrv); } -Result nsdevInitialize(void) { - atomicIncrement64(&g_nsdevRefCnt); - - if (serviceIsActive(&g_nsdevSrv)) - return 0; - - return smGetService(&g_nsdevSrv, "ns:dev"); +Service* nsGetServiceSession_GetterInterface(void) { + return &g_nsGetterSrv; } -void nsdevExit(void) { - if (atomicDecrement64(&g_nsdevRefCnt) == 0) - serviceClose(&g_nsdevSrv); +Service* nsGetServiceSession_ApplicationManagerInterface(void) { + return &g_nsAppManSrv; } -static Result _nsGetInterface(Service* srv_out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); +static Result _nsGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; +static Result _nsCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) { + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(srv, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_nsGetterSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(srv_out, r.Handles[0]); - } - } + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, autoclear); return rc; } -Result nsListApplicationRecord(NsApplicationRecord* buffer, size_t size, size_t entry_offset, size_t* out_entrycount) -{ - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buffer, size, 0); +static Result _nsCmdInHandle64NoOut(Service* srv, Handle handle, u64 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval, + .in_num_handles = 1, + .in_handles = { handle }, + ); +} - struct { - u64 magic; - u64 cmd_id; - u32 entry_offset; - } *raw; +static Result _nsCmdInTmemNoOut(Service* srv, TransferMemory *tmem, u32 cmd_id) { + return _nsCmdInHandle64NoOut(srv, tmem->handle, tmem->size, cmd_id); +} - raw = ipcPrepareHeader(&c, sizeof(*raw)); +static Result _nsCmdNoIO(Service* srv, u32 cmd_id) { + return serviceDispatch(srv, cmd_id); +} - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->entry_offset = entry_offset; +static Result _nsCmdInBool(Service* srv, bool inval, u32 cmd_id) { + u8 in = inval!=0; - Result rc = serviceIpcDispatch(&g_nsAppManSrv); + return serviceDispatchIn(srv, cmd_id, in); +} - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); +static Result _nsCmdInU64(Service* srv, u64 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} - struct { - u64 magic; - u64 result; - u32 entry_count; - } *resp = r.Raw; +static Result _nsCmdInU64OutU64(Service* srv, u64 inval, u64 *out, u32 cmd_id) { + return serviceDispatchInOut(srv, cmd_id, inval, *out); +} - rc = resp->result; +static Result _nsCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} - if (R_SUCCEEDED(rc) && out_entrycount) *out_entrycount = resp->entry_count; - } +static Result _nsCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) { + u8 tmpout=0; + Result rc = _nsCmdNoInOutU8(srv, &tmpout, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmpout!=0; + return rc; +} + +static Result _nsCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _nsCmdNoInOutSystemUpdateProgress(Service* srv, NsSystemUpdateProgress *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _nsCmdRequestSendReceiveSystemUpdate(Service* srv, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info, u32 cmd_id) { + const struct { + u16 inval0; + u32 inval1; + } in = { inval0, inval1 }; + + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(srv, cmd_id, in, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { info, sizeof(*info) } }, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); return rc; } -Result nsListApplicationContentMetaStatus(u64 titleID, u32 index, NsApplicationContentMetaStatus* buffer, size_t size, size_t* out_entrycount) -{ - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buffer, size, 0); +static Result _nsCmdNoInOutAsyncValue(Service* srv, AsyncValue *a, u32 cmd_id) { + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); - struct { - u64 magic; - u64 cmd_id; - u32 index; + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + +static Result _nsCmdNoInOutAsyncResult(Service* srv, AsyncResult *a, u32 cmd_id) { + memset(a, 0, sizeof(*a)); + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = &a->s, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + + if (R_SUCCEEDED(rc)) + eventLoadRemote(&a->event, event, false); + + return rc; +} + +Result nsListApplicationRecord(NsApplicationRecord* records, s32 count, s32 entry_offset, s32* out_entrycount) { + return serviceDispatchInOut(&g_nsAppManSrv, 0, entry_offset, *out_entrycount, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { records, count*sizeof(NsApplicationRecord) } }, + ); +} + +Result nsListApplicationContentMetaStatus(u64 titleID, s32 index, NsApplicationContentMetaStatus* list, s32 count, s32* out_entrycount) { + const struct { + s32 index; u64 titleID; - } *raw; + } in = { index, titleID }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 601; - raw->index = index; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_nsAppManSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 entry_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out_entrycount) *out_entrycount = resp->entry_count; - } - - return rc; + return serviceDispatchInOut(&g_nsAppManSrv, 601, in, *out_entrycount, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { list, count*sizeof(NsApplicationContentMetaStatus) } }, + ); } -Result nsGetApplicationControlData(u8 flag, u64 titleID, NsApplicationControlData* buffer, size_t size, size_t* actual_size) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buffer, size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 flag; +Result nsGetApplicationControlData(NsApplicationControlSource source, u64 titleID, NsApplicationControlData* buffer, size_t size, u64* actual_size) { + const struct { + u8 source; u64 titleID; - } *raw; + } in = { source, titleID }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 400; - raw->flag = flag; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_nsAppManSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 actual_size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && actual_size) *actual_size = resp->actual_size; - } + u32 tmp=0; + Result rc = serviceDispatchInOut(&g_nsAppManSrv, 400, in, tmp, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { buffer, size } }, + ); + if (R_SUCCEEDED(rc) && actual_size) *actual_size = tmp; return rc; } -Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 47; - raw->storage_id = storage_id; - - Result rc = serviceIpcDispatch(&g_nsAppManSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && size) *size = resp->size; - } - - return rc; +Result nsGetTotalSpaceSize(FsStorageId storage_id, u64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 47); } -Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 48; - raw->storage_id = storage_id; - - Result rc = serviceIpcDispatch(&g_nsAppManSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && size) *size = resp->size; - } - - return rc; +Result nsGetFreeSpaceSize(FsStorageId storage_id, u64 *size) { + return _nsCmdInU64OutU64(&g_nsAppManSrv, storage_id, size, 48); } -Result nsvmInitialize(void) +// ns:vm + +NX_GENERATE_SERVICE_GUARD(nsvm); + +Result _nsvmInitialize(void) { if (hosversionBefore(3,0,0)) return 0; - atomicIncrement64(&g_nsvmRefCnt); - - if (serviceIsActive(&g_nsvmSrv)) - return 0; - return smGetService(&g_nsvmSrv, "ns:vm"); } -void nsvmExit(void) +void _nsvmCleanup(void) { if (hosversionBefore(3,0,0)) return; - if (atomicDecrement64(&g_nsvmRefCnt) == 0) { - serviceClose(&g_nsvmSrv); - } + serviceClose(&g_nsvmSrv); +} + +Service* nsvmGetServiceSession(void) { + return &g_nsvmSrv; } Result nsvmNeedsUpdateVulnerability(bool *out) { - IpcCommand c; - ipcInitialize(&c); + Service *srv = &g_nsAppManSrv; + if (hosversionAtLeast(3,0,0)) srv = &g_nsvmSrv; - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1200; - - Result rc; - - if (hosversionAtLeast(3,0,0)) - rc = serviceIpcDispatch(&g_nsvmSrv); - else - rc = serviceIpcDispatch(&g_nsAppManSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 out; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; + return _nsCmdNoInOutBool(srv, out, 1200); } -Result nsvmGetSafeSystemVersion(u16 *out) -{ - if (hosversionBefore(3,0,0)) +Result nsvmGetSafeSystemVersion(NcmContentMetaKey *out) { + if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); + return serviceDispatchOut(&g_nsvmSrv, 1202, *out); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; +// ns:dev - raw = ipcPrepareHeader(&c, sizeof(*raw)); +NX_GENERATE_SERVICE_GUARD(nsdev); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1202; +Result _nsdevInitialize(void) { + return smGetService(&g_nsdevSrv, "ns:dev"); +} - Result rc = serviceIpcDispatch(&g_nsvmSrv); +void _nsdevCleanup(void) { + serviceClose(&g_nsdevSrv); +} - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u16 out; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->out; - } - - return rc; +Service* nsdevGetServiceSession(void) { + return &g_nsdevSrv; } Result nsdevLaunchProgram(u64* out_pid, const NsLaunchProperties* properties, u32 flags) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 flags; - u32 pad; NsLaunchProperties properties; - } *raw; + } in = { flags, *properties}; - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->flags = flags; - raw->pad = 0; - raw->properties = *properties; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 pid; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_pid) *out_pid = resp->pid; - } - } - - return rc; + return serviceDispatchInOut(&g_nsdevSrv, 0, in, *out_pid); } Result nsdevTerminateProcess(u64 pid) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _nsCmdInU64(&g_nsdevSrv, pid, 1); } Result nsdevTerminateProgram(u64 tid) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 tid; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->tid = tid; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _nsCmdInU64(&g_nsdevSrv, tid, 2); } -Result nsdevGetShellEvent(Event* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - eventLoadRemote(out, r.Handles[0], true); - } - } - - return rc; +Result nsdevGetShellEvent(Event* out_event) { + return _nsCmdGetEvent(&g_nsdevSrv, out_event, true, 4); } Result nsdevGetShellEventInfo(NsShellEventInfo* out) { - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; + u32 event; + u64 process_id; + } tmpout; - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 event; - u32 pad; - u64 process_id; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) { - out->event = (NsShellEvent)resp->event; - out->process_id = resp->process_id; - } - } + Result rc = serviceDispatchOut(&g_nsdevSrv, 5, tmpout); + if (R_SUCCEEDED(rc) && out) { + out->event = (NsShellEvent)tmpout.event; + out->process_id = tmpout.process_id; } - return rc; } Result nsdevTerminateApplication(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _nsCmdNoIO(&g_nsdevSrv, 6); } Result nsdevPrepareLaunchProgramFromHost(NsLaunchProperties* out, const char* path, size_t path_len) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, path, path_len, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - NsLaunchProperties properties; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->properties; - } - } - - return rc; + return serviceDispatchOut(&g_nsdevSrv, 7, *out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { path, path_len } }, + ); } -Result nsdevLaunchApplication(u64* out_pid, u64 app_title_id, u32 flags) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result nsdevLaunchApplicationForDevelop(u64* out_pid, u64 app_title_id, u32 flags) { + const struct { u32 flags; - u32 pad; u64 app_title_id; - } *raw; + } in = { .flags = flags, .app_title_id = app_title_id}; - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - raw->flags = flags; - raw->pad = 0; - raw->app_title_id = app_title_id; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 pid; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_pid) *out_pid = resp->pid; - } - } - - return rc; + return serviceDispatchInOut(&g_nsdevSrv, 8, in, *out_pid); } -Result nsdevLaunchApplicationWithStorageId(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result nsdevLaunchApplicationWithStorageIdForDevelop(u64* out_pid, u64 app_title_id, u32 flags, u8 app_storage_id, u8 patch_storage_id) { + const struct { u8 app_storage_id; u8 patch_storage_id; - u16 pad; u32 flags; u64 app_title_id; - } *raw; + } in = { .app_storage_id = app_storage_id, .patch_storage_id = patch_storage_id, .flags = flags, .app_title_id = app_title_id}; - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 9; - raw->app_storage_id = app_storage_id; - raw->patch_storage_id = patch_storage_id; - raw->pad = 0; - raw->flags = flags; - raw->app_title_id = app_title_id; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 pid; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_pid) *out_pid = resp->pid; - } - } - - return rc; + return serviceDispatchInOut(&g_nsdevSrv, 9, in, *out_pid); } Result nsdevIsSystemMemoryResourceLimitBoosted(bool* out) { + if (hosversionBefore(6,0,0) || hosversionAtLeast(9,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutBool(&g_nsdevSrv, out, 10); +} + +Result nsdevGetRunningApplicationProcessIdForDevelop(u64* out_pid) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - IpcCommand c; - ipcInitialize(&c); + return _nsCmdNoInOutU64(&g_nsdevSrv, out_pid, 11); +} - struct { - u64 magic; - u64 cmd_id; - } *raw; +Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActiveForDevelop(bool can_be_active) { + if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); + return _nsCmdInBool(&g_nsdevSrv, can_be_active, 12); +} - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; +// ns:su - Result rc = serviceIpcDispatch(&g_nsdevSrv); +NX_GENERATE_SERVICE_GUARD(nssu); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u8 boosted; - } *resp; +Result _nssuInitialize(void) { + return smGetService(&g_nssuSrv, "ns:su"); +} - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; +void _nssuCleanup(void) { + serviceClose(&g_nssuSrv); +} - rc = resp->result; +Service* nssuGetServiceSession(void) { + return &g_nssuSrv; +} - if (R_SUCCEEDED(rc)) { - if (out) *out = resp->boosted != 0; - } - } +Result nssuGetBackgroundNetworkUpdateState(NsBackgroundNetworkUpdateState *out) { + u8 tmpout=0; + Result rc = _nsCmdNoInOutU8(&g_nssuSrv, &tmpout, 0); + if (R_SUCCEEDED(rc)) *out = tmpout; + return rc; +} + +Result nssuOpenSystemUpdateControl(NsSystemUpdateControl *c) { + return _nsGetSession(&g_nssuSrv, &c->s, 1); +} + +Result nssuNotifyExFatDriverRequired(void) { + return _nsCmdNoIO(&g_nssuSrv, 2); +} + +Result nssuClearExFatDriverStatusForDebug(void) { + return _nsCmdNoIO(&g_nssuSrv, 3); +} + +Result nssuRequestBackgroundNetworkUpdate(void) { + return _nsCmdNoIO(&g_nssuSrv, 4); +} + +Result nssuNotifyBackgroundNetworkUpdate(const NcmContentMetaKey *key) { + return serviceDispatchIn(&g_nssuSrv, 5, *key); +} + +Result nssuNotifyExFatDriverDownloadedForDebug(void) { + return _nsCmdNoIO(&g_nssuSrv, 6); +} + +Result nssuGetSystemUpdateNotificationEventForContentDelivery(Event* out_event) { + return _nsCmdGetEvent(&g_nssuSrv, out_event, false, 9); +} + +Result nssuNotifySystemUpdateForContentDelivery(void) { + return _nsCmdNoIO(&g_nssuSrv, 10); +} + +Result nssuPrepareShutdown(void) { + if (hosversionBefore(3,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nssuSrv, 11); +} + +Result nssuDestroySystemUpdateTask(void) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&g_nssuSrv, 16); +} + +Result nssuRequestSendSystemUpdate(AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdRequestSendReceiveSystemUpdate(&g_nssuSrv, a, inval0, inval1, info, 17); +} + +Result nssuGetSendSystemUpdateProgress(NsSystemUpdateProgress *out) { + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutSystemUpdateProgress(&g_nssuSrv, out, 18); +} + +// ISystemUpdateControl + +void nssuControlClose(NsSystemUpdateControl *c) { + serviceClose(&c->s); + tmemClose(&c->tmem); +} + +static Result _nssuControlGetEulaDataSize(NsSystemUpdateControl *c, u32 cmd_id, const char* path, u64 *filesize) { + NsEulaDataPath datapath; + + memset(&datapath, 0, sizeof(datapath)); + strncpy(datapath.path, path, sizeof(datapath.path)-1); + + return serviceDispatchOut(&c->s, cmd_id, *filesize, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { &datapath, sizeof(datapath) } }, + ); +} + +static Result _nssuControlGetEulaData(NsSystemUpdateControl *c, u32 cmd_id, const char* path, void* buffer, size_t size, u64 *filesize) { + NsEulaDataPath datapath; + + memset(&datapath, 0, sizeof(datapath)); + strncpy(datapath.path, path, sizeof(datapath.path)-1); + + return serviceDispatchOut(&c->s, cmd_id, *filesize, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { &datapath, sizeof(datapath) }, + { buffer, size }, + }, + ); +} + +static Result _nssuControlCmdTmemNoOut(NsSystemUpdateControl *c, void* buffer, size_t size, u32 cmd_id) { + Result rc=0; + + if (buffer==NULL) rc = tmemCreate(&c->tmem, size, Perm_None); + else rc = tmemCreateFromMemory(&c->tmem, buffer, size, Perm_None); + if (R_FAILED(rc)) return rc; + + rc = _nsCmdInTmemNoOut(&c->s, &c->tmem, cmd_id); + if (R_FAILED(rc)) tmemClose(&c->tmem); return rc; } -Result nsdevGetRunningApplicationProcessId(u64* out_pid) { - if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); +Result nssuControlHasDownloaded(NsSystemUpdateControl *c, bool* out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 pid; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_pid) *out_pid = resp->pid; - } - } - - return rc; + return _nsCmdNoInOutBool(&c->s, out, 0); } -Result nsdevSetCurrentApplicationRightsEnvironmentCanBeActive(bool can_be_active) { - if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); +Result nssuControlRequestCheckLatestUpdate(NsSystemUpdateControl *c, AsyncValue *a) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 can_be_active; - } *raw; - - raw = serviceIpcPrepareHeader(&g_nsdevSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - raw->can_be_active = can_be_active ? 1 : 0; - - Result rc = serviceIpcDispatch(&g_nsdevSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_nsdevSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _nsCmdNoInOutAsyncValue(&c->s, a, 1); } + +Result nssuControlRequestDownloadLatestUpdate(NsSystemUpdateControl *c, AsyncResult *a) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoInOutAsyncResult(&c->s, a, 2); +} + +Result nssuControlGetDownloadProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 3); +} + +Result nssuControlApplyDownloadedUpdate(NsSystemUpdateControl *c) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoIO(&c->s, 4); +} + +Result nssuControlRequestPrepareCardUpdate(NsSystemUpdateControl *c, AsyncResult *a) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoInOutAsyncResult(&c->s, a, 5); +} + +Result nssuControlGetPrepareCardUpdateProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 6); +} + +Result nssuControlHasPreparedCardUpdate(NsSystemUpdateControl *c, bool* out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoInOutBool(&c->s, out, 7); +} + +Result nssuControlApplyCardUpdate(NsSystemUpdateControl *c) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nsCmdNoIO(&c->s, 8); +} + +Result nssuControlGetDownloadedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nssuControlGetEulaDataSize(c, 9, path, filesize); +} + +Result nssuControlGetDownloadedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nssuControlGetEulaData(c, 10, path, buffer, size, filesize); +} + +Result nssuControlSetupCardUpdate(NsSystemUpdateControl *c, void* buffer, size_t size) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nssuControlCmdTmemNoOut(c, buffer, size, 11); +} + +Result nssuControlGetPreparedCardUpdateEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nssuControlGetEulaDataSize(c, 12, path, filesize); +} + +Result nssuControlGetPreparedCardUpdateEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return _nssuControlGetEulaData(c, 13, path, buffer, size, filesize); +} + +Result nssuControlSetupCardUpdateViaSystemUpdater(NsSystemUpdateControl *c, void* buffer, size_t size) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nssuControlCmdTmemNoOut(c, buffer, size, 14); +} + +Result nssuControlHasReceived(NsSystemUpdateControl *c, bool* out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutBool(&c->s, out, 15); +} + +Result nssuControlRequestReceiveSystemUpdate(NsSystemUpdateControl *c, AsyncResult *a, u32 inval0, u16 inval1, NsSystemDeliveryInfo *info) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdRequestSendReceiveSystemUpdate(&c->s, a, inval0, inval1, info, 16); +} + +Result nssuControlGetReceiveProgress(NsSystemUpdateControl *c, NsSystemUpdateProgress *out) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutSystemUpdateProgress(&c->s, out, 17); +} + +Result nssuControlApplyReceivedUpdate(NsSystemUpdateControl *c) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&c->s, 18); +} + +Result nssuControlGetReceivedEulaDataSize(NsSystemUpdateControl *c, const char* path, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nssuControlGetEulaDataSize(c, 19, path, filesize); +} + +Result nssuControlGetReceivedEulaData(NsSystemUpdateControl *c, const char* path, void* buffer, size_t size, u64 *filesize) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nssuControlGetEulaData(c, 20, path, buffer, size, filesize); +} + +Result nssuControlSetupToReceiveSystemUpdate(NsSystemUpdateControl *c) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(4,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoIO(&c->s, 21); +} + +Result nssuControlRequestCheckLatestUpdateIncludesRebootlessUpdate(NsSystemUpdateControl *c, AsyncValue *a) { + if (!serviceIsActive(&c->s)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (hosversionBefore(6,0,0)) + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + + return _nsCmdNoInOutAsyncValue(&c->s, a, 22); +} + diff --git a/nx/source/services/nv.c b/nx/source/services/nv.c index fcf5cd09..85c43562 100644 --- a/nx/source/services/nv.c +++ b/nx/source/services/nv.c @@ -1,33 +1,26 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "kernel/tmem.h" #include "services/applet.h" -#include "nvidia/ioctl.h" #include "services/nv.h" -#include "services/sm.h" +#include "nvidia/ioctl.h" __attribute__((weak)) u32 __nx_nv_transfermem_size = 0x800000; static Service g_nvSrv; static Service g_nvSrvClone; -static u64 g_refCnt; static size_t g_nvIpcBufferSize = 0; static TransferMemory g_nvTransfermem; -static Result _nvInitialize(Handle proc, Handle sharedmem, u32 transfermem_size); +static Result _nvCmdInitialize(Handle proc, Handle sharedmem, u32 transfermem_size); static Result _nvSetClientPID(u64 AppletResourceUserId); -Result nvInitialize(void) +NX_GENERATE_SERVICE_GUARD(nv); + +Result _nvInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_nvSrv)) - return 0; - Result rc = 0; u64 AppletResourceUserId = 0; @@ -51,22 +44,17 @@ Result nvInitialize(void) } if (R_SUCCEEDED(rc)) { - g_nvIpcBufferSize = 0; - rc = ipcQueryPointerBufferSize(g_nvSrv.handle, &g_nvIpcBufferSize); + g_nvIpcBufferSize = g_nvSrv.pointer_buffer_size; if (R_SUCCEEDED(rc)) rc = tmemCreate(&g_nvTransfermem, __nx_nv_transfermem_size, Perm_None); if (R_SUCCEEDED(rc)) - rc = _nvInitialize(CUR_PROCESS_HANDLE, g_nvTransfermem.handle, __nx_nv_transfermem_size); + rc = _nvCmdInitialize(CUR_PROCESS_HANDLE, g_nvTransfermem.handle, __nx_nv_transfermem_size); // Clone the session handle - the cloned session is used to execute certain commands in parallel - Handle nv_clone = INVALID_HANDLE; if (R_SUCCEEDED(rc)) - rc = ipcCloneSession(g_nvSrv.handle, 1, &nv_clone); - - if (R_SUCCEEDED(rc)) - serviceCreate(&g_nvSrvClone, nv_clone); + rc = serviceCloneEx(&g_nvSrv, 1, &g_nvSrvClone); if (R_SUCCEEDED(rc)) { @@ -84,120 +72,43 @@ Result nvInitialize(void) return rc; } -void nvExit(void) +void _nvCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_nvSrvClone); - serviceClose(&g_nvSrv); - tmemClose(&g_nvTransfermem); - } + serviceClose(&g_nvSrvClone); + serviceClose(&g_nvSrv); + tmemClose(&g_nvTransfermem); } -static Result _nvInitialize(Handle proc, Handle sharedmem, u32 transfermem_size) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 transfermem_size; - } *raw; - - ipcSendHandleCopy(&c, proc); - ipcSendHandleCopy(&c, sharedmem); - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->transfermem_size = transfermem_size; - - Result rc = serviceIpcDispatch(&g_nvSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _nvCmdInitialize(Handle proc, Handle sharedmem, u32 transfermem_size) +{ + return serviceDispatchIn(&g_nvSrv, 3, transfermem_size, + .in_num_handles = 2, + .in_handles = { proc, sharedmem }, + ); } -static Result _nvSetClientPID(u64 AppletResourceUserId) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 AppletResourceUserId; - } *raw; - - ipcSendPid(&c); - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - raw->AppletResourceUserId = AppletResourceUserId; - - Result rc = serviceIpcDispatch(&g_nvSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _nvSetClientPID(u64 AppletResourceUserId) +{ + return serviceDispatchIn(&g_nvSrv, 8, AppletResourceUserId, .in_send_pid = true); } -Result nvOpen(u32 *fd, const char *devicepath) { - IpcCommand c; - ipcInitialize(&c); - +Result nvOpen(u32 *fd, const char *devicepath) +{ struct { - u64 magic; - u64 cmd_id; - } *raw; + u32 fd; + u32 error; + } out; - ipcAddSendBuffer(&c, devicepath, strlen(devicepath), 0); + Result rc = serviceDispatchOut(&g_nvSrv, 0, out, + .buffer_attrs = { SfBufferAttr_In | SfBufferAttr_HipcMapAlias }, + .buffers = { { devicepath, strlen(devicepath) } }, + ); - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; + if (R_SUCCEEDED(rc)) + rc = nvConvertError(out.error); - Result rc = serviceIpcDispatch(&g_nvSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 fd; - u32 error; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - rc = nvConvertError(resp->error); - - if (R_SUCCEEDED(rc)) - *fd = resp->fd; - } + if (R_SUCCEEDED(rc) && fd) + *fd = out.fd; return rc; } @@ -215,194 +126,120 @@ static inline Service* _nvGetSessionForRequest(u32 request) return &g_nvSrv; } -Result nvIoctl(u32 fd, u32 request, void* argp) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 fd; - u32 request; - } *raw; - +Result nvIoctl(u32 fd, u32 request, void* argp) +{ size_t bufsize = _NV_IOC_SIZE(request); u32 dir = _NV_IOC_DIR(request); - void* buf_send = NULL, *buf_recv = NULL; + void *buf_send = NULL, *buf_recv = NULL; size_t buf_send_size = 0, buf_recv_size = 0; - if(dir & _NV_IOC_WRITE) { + if (dir & _NV_IOC_WRITE) { buf_send = argp; buf_send_size = bufsize; } - if(dir & _NV_IOC_READ) { + if (dir & _NV_IOC_READ) { buf_recv = argp; buf_recv_size = bufsize; } - ipcAddSendSmart(&c, g_nvIpcBufferSize, buf_send, buf_send_size, 0); - ipcAddRecvSmart(&c, g_nvIpcBufferSize, buf_recv, buf_recv_size, 0); + const struct { + u32 fd; + u32 request; + } in = { fd, request }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->fd = fd; - raw->request = request; + u32 error = 0; + Result rc = serviceDispatchInOut(_nvGetSessionForRequest(request), 1, in, error, + .buffer_attrs = { + SfBufferAttr_HipcAutoSelect | SfBufferAttr_In, + SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out, + }, + .buffers = { + { buf_send, buf_send_size }, + { buf_recv, buf_recv_size }, + }, + ); - Result rc = serviceIpcDispatch(_nvGetSessionForRequest(request)); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 error; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - rc = nvConvertError(resp->error); - } + if (R_SUCCEEDED(rc)) + rc = nvConvertError(error); return rc; } -Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 fd; - u32 request; - } *raw; - +Result nvIoctl2(u32 fd, u32 request, void* argp, const void* inbuf, size_t inbuf_size) +{ size_t bufsize = _NV_IOC_SIZE(request); u32 dir = _NV_IOC_DIR(request); - void* buf_send = NULL, *buf_recv = NULL; + void *buf_send = NULL, *buf_recv = NULL; size_t buf_send_size = 0, buf_recv_size = 0; - if(dir & _NV_IOC_WRITE) { + if (dir & _NV_IOC_WRITE) { buf_send = argp; buf_send_size = bufsize; } - if(dir & _NV_IOC_READ) { + if (dir & _NV_IOC_READ) { buf_recv = argp; buf_recv_size = bufsize; } - ipcAddSendSmart(&c, g_nvIpcBufferSize, buf_send, buf_send_size, 0); - ipcAddSendSmart(&c, g_nvIpcBufferSize, inbuf, inbuf_size, 1); - ipcAddRecvSmart(&c, g_nvIpcBufferSize, buf_recv, buf_recv_size, 0); - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->fd = fd; - raw->request = request; - - Result rc = serviceIpcDispatch(_nvGetSessionForRequest(request)); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 error; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - rc = nvConvertError(resp->error); - } - - return rc; -} - -Result nvClose(u32 fd) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 fd; - } *raw; + u32 request; + } in = { fd, request }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->fd = fd; + u32 error = 0; + Result rc = serviceDispatchInOut(_nvGetSessionForRequest(request), 11, in, error, + .buffer_attrs = { + SfBufferAttr_HipcAutoSelect | SfBufferAttr_In, + SfBufferAttr_HipcAutoSelect | SfBufferAttr_In, + SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out, + }, + .buffers = { + { buf_send, buf_send_size }, + { inbuf, inbuf_size }, + { buf_recv, buf_recv_size }, + }, + ); - Result rc = serviceIpcDispatch(&g_nvSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 error; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - rc = nvConvertError(resp->error); - } + if (R_SUCCEEDED(rc)) + rc = nvConvertError(error); return rc; } -Result nvQueryEvent(u32 fd, u32 event_id, Event *event_out) { - IpcCommand c; - ipcInitialize(&c); +Result nvClose(u32 fd) +{ + u32 error = 0; + Result rc = serviceDispatchInOut(&g_nvSrv, 2, fd, error); - struct { - u64 magic; - u64 cmd_id; + if (R_SUCCEEDED(rc)) + rc = nvConvertError(error); + + return rc; +} + +Result nvQueryEvent(u32 fd, u32 event_id, Event *event_out) +{ + const struct { u32 fd; u32 event_id; - } *raw; + } in = { fd, event_id }; - raw = ipcPrepareHeader(&c, sizeof(*raw)); - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - raw->fd = fd; - raw->event_id = event_id; + u32 error = 0; + Handle event; + Result rc = serviceDispatchInOut(&g_nvSrv, 4, in, error, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); - Result rc = serviceIpcDispatch(&g_nvSrv); + if (R_SUCCEEDED(rc)) + rc = nvConvertError(error); - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 error; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - rc = nvConvertError(resp->error); - - if (R_SUCCEEDED(rc)) - eventLoadRemote(event_out, r.Handles[0], true); - } + if (R_SUCCEEDED(rc)) + eventLoadRemote(event_out, event, true); return rc; } diff --git a/nx/source/services/pm.c b/nx/source/services/pm.c index cb72ea36..1d23d2fb 100644 --- a/nx/source/services/pm.c +++ b/nx/source/services/pm.c @@ -1,837 +1,160 @@ // Copyright 2017 plutoo -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/pm.h" -#include "services/sm.h" -static Service g_pmdmntSrv, g_pmshellSrv, g_pminfoSrv, g_pmbmSrv; -static u64 g_pmdmntRefCnt, g_pmshellRefCnt, g_pminfoRefCnt, g_pmbmRefCnt; - -Result pmdmntInitialize(void) -{ - atomicIncrement64(&g_pmdmntRefCnt); - - if (serviceIsActive(&g_pmdmntSrv)) - return 0; - - return smGetService(&g_pmdmntSrv, "pm:dmnt"); +#define PM_GENERATE_SERVICE_INIT(name) \ +static Service g_pm##name##Srv; \ + \ +NX_GENERATE_SERVICE_GUARD(pm##name); \ + \ +Result _pm##name##Initialize(void) { \ + return smGetService(&g_pm##name##Srv, "pm:"#name); \ +} \ + \ +void _pm##name##Cleanup(void) { \ + serviceClose(&g_pm##name##Srv); \ +} \ + \ +Service* pm##name##GetServiceSession(void) { \ + return &g_pm##name##Srv; \ } -void pmdmntExit(void) -{ - if (atomicDecrement64(&g_pmdmntRefCnt) == 0) { - serviceClose(&g_pmdmntSrv); - } -} - -Service* pmdmntGetServiceSession(void) { - return &g_pmdmntSrv; -} - -Result pminfoInitialize(void) -{ - atomicIncrement64(&g_pminfoRefCnt); - - if (serviceIsActive(&g_pminfoSrv)) - return 0; - - return smGetService(&g_pminfoSrv, "pm:info"); -} - -void pminfoExit(void) -{ - if (atomicDecrement64(&g_pminfoRefCnt) == 0) { - serviceClose(&g_pminfoSrv); - } -} - -Service* pminfoGetServiceSession(void) -{ - return &g_pminfoSrv; -} - -Result pmshellInitialize(void) -{ - atomicIncrement64(&g_pmshellRefCnt); - - if (serviceIsActive(&g_pmshellSrv)) - return 0; - - return smGetService(&g_pmshellSrv, "pm:shell"); -} - -void pmshellExit(void) -{ - if (atomicDecrement64(&g_pmshellRefCnt) == 0) { - serviceClose(&g_pmshellSrv); - } -} - -Service* pmshellGetServiceSession(void) -{ - return &g_pmshellSrv; -} - -Result pmbmInitialize(void) -{ - atomicIncrement64(&g_pmbmRefCnt); - - if (serviceIsActive(&g_pmbmSrv)) - return 0; - - return smGetService(&g_pmbmSrv, "pm:bm"); -} - -void pmbmExit(void) -{ - if (atomicDecrement64(&g_pmbmRefCnt) == 0) { - serviceClose(&g_pmbmSrv); - } -} - -Service* pmbmGetServiceSession(void) -{ - return &g_pmbmSrv; -} +PM_GENERATE_SERVICE_INIT(dmnt); +PM_GENERATE_SERVICE_INIT(shell); +PM_GENERATE_SERVICE_INIT(info); +PM_GENERATE_SERVICE_INIT(bm); Result pmdmntGetDebugProcesses(u32* out_count, u64* out_pids, size_t max_pids) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, out_pids, sizeof(*out_pids) * max_pids, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 0 : 1; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 out_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_count) *out_count = resp->out_count; - } - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 0 : 1; + return serviceDispatchOut(&g_pmdmntSrv, cmd_id, *out_count, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { out_pids, max_pids * sizeof(*out_pids) }, + }, + ); } Result pmdmntStartProcess(u64 pid) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 1 : 2; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 1 : 2; + return serviceDispatchIn(&g_pmdmntSrv, cmd_id, pid); } Result pmdmntGetTitlePid(u64* pid_out, u64 title_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 title_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 2 : 3; - raw->title_id = title_id; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 pid; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *pid_out = resp->pid; - } - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 2 : 3; + return serviceDispatchInOut(&g_pmdmntSrv, cmd_id, title_id, *pid_out); } -Result pmdmntEnableDebugForTitleId(Handle* handle_out, u64 title_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 title_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 3 : 4; - raw->title_id = title_id; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; -} - -Result pminfoGetTitleId(u64* title_id_out, u64 pid) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_pminfoSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 title_id; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *title_id_out = resp->title_id; - } - } +Result pmdmntEnableDebugForTitleId(Event* out_event, u64 title_id) { + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 3 : 4; + Handle event = INVALID_HANDLE; + Result rc = serviceDispatchIn(&g_pmdmntSrv, cmd_id, title_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, true); return rc; } Result pmdmntGetApplicationPid(u64* pid_out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 4 : 5; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 pid; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *pid_out = resp->pid; - } - } + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 4 : 5; + return serviceDispatchOut(&g_pmdmntSrv, cmd_id, *pid_out); +} +Result pmdmntEnableDebugForApplication(Event* out_event) { + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 5 : 6; + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(&g_pmdmntSrv, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, true); return rc; } -Result pmdmntEnableDebugForApplication(Handle* handle_out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 5 : 6; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; -} - -Result pmdmntDisableDebug(void) { +Result pmdmntDisableDebug(u32 which) { if (hosversionBefore(6,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - - Result rc = serviceIpcDispatch(&g_pmdmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_pmdmntSrv, 6, which); } Result pmshellLaunchProcess(u32 launch_flags, u64 titleID, u64 storageID, u64 *pid) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 launch_flags; u64 titleID; u64 storageID; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->launch_flags = launch_flags; - raw->titleID = titleID; - raw->storageID = storageID; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 pid; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && pid) *pid = resp->pid; - } - - return rc; + } in = { launch_flags, titleID, storageID }; + return serviceDispatchInOut(&g_pmshellSrv, 0, in, *pid); } Result pmshellTerminateProcessByProcessId(u64 processID) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 processID; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->processID = processID; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_pmshellSrv, 1, processID); } Result pmshellTerminateProcessByTitleId(u64 titleID) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 titleID; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->titleID = titleID; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_pmshellSrv, 2, titleID); } -Result pmshellGetProcessEvent(Event* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - eventLoadRemote(out, r.Handles[0], true); - } - } - +Result pmshellGetProcessEvent(Event* out_event) { + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(&g_pmshellSrv, 3, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, true); return rc; } Result pmshellGetProcessEventInfo(PmProcessEventInfo* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 event; - u32 pad; - u64 process_id; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out) { - out->event = (PmProcessEvent)resp->event; - out->process_id = resp->process_id; - } - } - } - - return rc; + _Static_assert(sizeof(out->event) == sizeof(u32), "PmProcessEvent"); + return serviceDispatchOut(&g_pmshellSrv, 4, *out); } Result pmshellFinalizeDeadProcess(u64 pid) { if (hosversionAtLeast(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_pmshellSrv, 5, pid); } Result pmshellClearProcessExceptionOccurred(u64 pid) { if (hosversionAtLeast(5,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 6; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_pmshellSrv, 6, pid); } Result pmshellNotifyBootFinished(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 5 : 7; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 5 : 7; + return serviceDispatch(&g_pmshellSrv, cmd_id); } Result pmshellGetApplicationPid(u64* pid_out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 6 : 8; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 pid; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *pid_out = resp->pid; - } - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 6 : 8; + return serviceDispatchOut(&g_pmshellSrv, cmd_id, *pid_out); } Result pmshellBoostSystemMemoryResourceLimit(u64 boost_size) { if (hosversionBefore(4,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 boost_size; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(5,0,0) ? 7 : 9; - raw->boost_size = boost_size; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + const u64 cmd_id = hosversionAtLeast(5,0,0) ? 7 : 9; + return serviceDispatchIn(&g_pmshellSrv, cmd_id, boost_size); } Result pmshellBoostSystemThreadResourceLimit(void) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + return serviceDispatch(&g_pmshellSrv, 8); +} - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 8; - - Result rc = serviceIpcDispatch(&g_pmshellSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result pminfoGetTitleId(u64* title_id_out, u64 pid) { + return serviceDispatchInOut(&g_pminfoSrv, 0, pid, *title_id_out); } Result pmbmGetBootMode(PmBootMode *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_pmbmSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 boot_mode; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) { - *out = (PmBootMode)resp->boot_mode; - } - } - - return rc; + _Static_assert(sizeof(*out) == sizeof(u32), "PmBootMode"); + return serviceDispatchOut(&g_pmbmSrv, 0, *out); } Result pmbmSetMaintenanceBoot(void) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(&g_pmbmSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(&g_pmbmSrv, 1); } diff --git a/nx/source/services/psm.c b/nx/source/services/psm.c index cb982ce1..8aecdbe3 100644 --- a/nx/source/services/psm.c +++ b/nx/source/services/psm.c @@ -1,135 +1,80 @@ -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "kernel/event.h" #include "services/psm.h" -#include "services/sm.h" static Service g_psmSrv; -static u64 g_refCnt; -static Result _psmOpenSession(Service* out); +static Result _psmOpenSession(Service* srv_out); static Result _psmBindStateChangeEvent(PsmSession* s, Event* event_out); static Result _psmSetChargerTypeChangeEventEnabled(PsmSession* s, bool flag); static Result _psmSetPowerSupplyChangeEventEnabled(PsmSession* s, bool flag); static Result _psmSetBatteryVoltageStateChangeEventEnabled(PsmSession* s, bool flag); -Result psmInitialize(void) { - Result rc = 0; - - atomicIncrement64(&g_refCnt); +NX_GENERATE_SERVICE_GUARD(psm); - if (serviceIsActive(&g_psmSrv)) - return 0; - - rc = smGetService(&g_psmSrv, "psm"); - - if (R_FAILED(rc)) psmExit(); - - return rc; +Result _psmInitialize(void) { + return smGetService(&g_psmSrv, "psm"); } -void psmExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_psmSrv); - } +void _psmCleanup(void) { + serviceClose(&g_psmSrv); } Service* psmGetServiceSession(void) { return &g_psmSrv; } -static Result _psmGetOutU32(u64 cmd_id, u32 *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_psmSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_psmSrv); - - if(R_SUCCEEDED(rc)) { - IpcParsedCommand r; +static Result _psmCmdNoIO(Service* srv, u32 cmd_id) { + return serviceDispatch(srv, cmd_id); +} - struct { - u64 magic; - u64 result; - u32 out; - } *resp; +static Result _psmCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) { + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(srv, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = &event, + ); - serviceIpcParse(&g_psmSrv, &r, sizeof(*resp)); - resp = r.Raw; + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, autoclear); - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out = resp->out; - } - } - return rc; } +static Result _psmCmdInU8NoOut(Service* srv, u8 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _psmCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) { + return _psmCmdInU8NoOut(srv, inval!=0, cmd_id); +} + +static Result _psmCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + Result psmGetBatteryChargePercentage(u32 *out) { - return _psmGetOutU32(0, out); + return _psmCmdNoInOutU32(&g_psmSrv, out, 0); } Result psmGetChargerType(ChargerType *out) { - return _psmGetOutU32(1, out); + return _psmCmdNoInOutU32(&g_psmSrv, out, 1); } Result psmGetBatteryVoltageState(PsmBatteryVoltageState *out) { u32 state; - Result rc = _psmGetOutU32(12, &state); - if (R_SUCCEEDED(rc)) { - *out = (PsmBatteryVoltageState)state; - } + Result rc = _psmCmdNoInOutU32(&g_psmSrv, &state, 12); + if (R_SUCCEEDED(rc) && out) *out = state; return rc; } -static Result _psmOpenSession(Service* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_psmSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - - Result rc = serviceIpcDispatch(&g_psmSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_psmSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) - serviceCreateSubservice(out, &g_psmSrv, &r, 0); - } - - return rc; +static Result _psmOpenSession(Service* srv_out) { + return serviceDispatch(&g_psmSrv, 7, + .out_num_objects = 1, + .out_objects = srv_out, + ); } Result psmBindStateChangeEvent(PsmSession* s, bool ChargerType, bool PowerSupply, bool BatteryVoltage) { @@ -162,71 +107,12 @@ Result psmWaitStateChangeEvent(PsmSession* s, u64 timeout) { } static Result _psmBindStateChangeEvent(PsmSession* s, Event *event_out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&s->s); - - if(R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - eventLoadRemote(event_out, r.Handles[0], false); - } - } - - return rc; + return _psmCmdGetEvent(&s->s, event_out, false, 0); } Result psmUnbindStateChangeEvent(PsmSession* s) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(&s->s); - - if(R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } + Result rc=0; + if (serviceIsActive(&s->s)) rc = _psmCmdNoIO(&s->s, 1); eventClose(&s->StateChangeEvent); serviceClose(&s->s); @@ -234,49 +120,18 @@ Result psmUnbindStateChangeEvent(PsmSession* s) { return rc; } -static Result _psmSetEventEnabled(PsmSession* s, u64 cmd_id, bool flag) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 flag; - } *raw; - - raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->flag = (flag != 0); - - Result rc = serviceIpcDispatch(&s->s); - - if(R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&s->s, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; +static Result _psmSetEventEnabled(PsmSession* s, bool flag, u32 cmd_id) { + return _psmCmdInBoolNoOut(&s->s, flag, cmd_id); } static Result _psmSetChargerTypeChangeEventEnabled(PsmSession* s, bool flag) { - return _psmSetEventEnabled(s, 2, flag); + return _psmSetEventEnabled(s, flag, 2); } static Result _psmSetPowerSupplyChangeEventEnabled(PsmSession* s, bool flag) { - return _psmSetEventEnabled(s, 3, flag); + return _psmSetEventEnabled(s, flag, 3); } static Result _psmSetBatteryVoltageStateChangeEventEnabled(PsmSession* s, bool flag) { - return _psmSetEventEnabled(s, 4, flag); + return _psmSetEventEnabled(s, flag, 4); } diff --git a/nx/source/services/ro.c b/nx/source/services/ro.c index 79903a11..00e1e646 100644 --- a/nx/source/services/ro.c +++ b/nx/source/services/ro.c @@ -1,86 +1,60 @@ // Copyright 2018 SciresM +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/ro.h" -#include "services/sm.h" static Service g_roSrv, g_ro1Srv, g_dmntSrv; -static u64 g_roRefCnt, g_ro1RefCnt, g_dmntRefCnt; -static Result _rosrvInitialize(Service* srv); -static Result _rosrvLoadNro(Service* srv, u64* out_address, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); -static Result _rosrvUnloadNro(Service* srv, u64 nro_address); -static Result _rosrvLoadNrr(Service* srv, u64 cmd_id, u64 nrr_address, u64 nrr_size); -static Result _rosrvUnloadNrr(Service* srv, u64 nrr_address); +NX_GENERATE_SERVICE_GUARD(ldrRo); +NX_GENERATE_SERVICE_GUARD(ro1); +NX_GENERATE_SERVICE_GUARD(roDmnt); -Result ldrRoInitialize(void) { - atomicIncrement64(&g_roRefCnt); - - if (serviceIsActive(&g_roSrv)) - return 0; +NX_INLINE Result _rosrvInitialize(Service* srv); +NX_INLINE Result _rosrvLoadNro(Service* srv, u64* out_address, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size); +NX_INLINE Result _rosrvUnloadNro(Service* srv, u64 nro_address); +NX_INLINE Result _rosrvLoadNrr(Service* srv, u64 cmd_id, u64 nrr_address, u64 nrr_size); +NX_INLINE Result _rosrvUnloadNrr(Service* srv, u64 nrr_address); +Result _ldrRoInitialize(void) { Result rc = smGetService(&g_roSrv, "ldr:ro"); - - if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc)) rc = _rosrvInitialize(&g_roSrv); - } - return rc; } -void ldrRoExit(void) { - if (atomicDecrement64(&g_roRefCnt) == 0) - serviceClose(&g_roSrv); +void _ldrRoCleanup(void) { + serviceClose(&g_roSrv); } Service* ldrRoGetServiceSession(void) { return &g_roSrv; } -Result ro1Initialize(void) { +Result _ro1Initialize(void) { if (hosversionBefore(7,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - atomicIncrement64(&g_ro1RefCnt); - - if (serviceIsActive(&g_ro1Srv)) - return 0; - Result rc = smGetService(&g_ro1Srv, "ro:1"); - - if (R_SUCCEEDED(rc)) { + if (R_SUCCEEDED(rc)) rc = _rosrvInitialize(&g_ro1Srv); - } - return rc; } -void ro1Exit(void) { - if (atomicDecrement64(&g_ro1RefCnt) == 0) - serviceClose(&g_ro1Srv); +void _ro1Cleanup(void) { + serviceClose(&g_ro1Srv); } Service* ro1GetServiceSession(void) { return &g_ro1Srv; } -Result roDmntInitialize(void) { +Result _roDmntInitialize(void) { if (hosversionBefore(3,0,0)) return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); - - atomicIncrement64(&g_dmntRefCnt); - - if (serviceIsActive(&g_dmntSrv)) - return 0; - return smGetService(&g_dmntSrv, "ro:dmnt"); } -void roDmntExit(void) { - if (atomicDecrement64(&g_dmntRefCnt) == 0) - serviceClose(&g_dmntSrv); +void _roDmntCleanup(void) { + serviceClose(&g_dmntSrv); } Service* roDmntGetServiceSession(void) { @@ -88,198 +62,46 @@ Service* roDmntGetServiceSession(void) { } Result _rosrvInitialize(Service* srv) { - IpcCommand c; - ipcInitialize(&c); - ipcSendHandleCopy(&c, CUR_PROCESS_HANDLE); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(srv, 4, + .in_num_handles = 1, + .in_handles = { CUR_PROCESS_HANDLE }, + ); } Result _rosrvLoadNro(Service* srv, u64* out_address, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; + const struct { + u64 pid_placeholder; u64 nro_address; u64 nro_size; u64 bss_address; u64 bss_size; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->pid = 0; - raw->nro_address = nro_address; - raw->nro_size = nro_size; - raw->bss_address = bss_address; - raw->bss_size = bss_size; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u64 out_address; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - if (out_address) *out_address = resp->out_address; - } - } - - return rc; + } in = { 0, nro_address, nro_size, bss_address, bss_size }; + return serviceDispatchInOut(srv, 0, in, *out_address, .in_send_pid = true); } Result _rosrvUnloadNro(Service* srv, u64 nro_address) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; + const struct { + u64 pid_placeholder; u64 nro_address; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->pid = 0; - raw->nro_address = nro_address; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { 0, nro_address }; + return serviceDispatchIn(srv, 1, in, .in_send_pid = true); } Result _rosrvLoadNrr(Service* srv, u64 cmd_id, u64 nrr_address, u64 nrr_size) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; + const struct { + u64 pid_placeholder; u64 nrr_address; u64 nrr_size; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - raw->pid = 0; - raw->nrr_address = nrr_address; - raw->nrr_size = nrr_size; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { 0, nrr_address, nrr_size }; + return serviceDispatchIn(srv, cmd_id, in, .in_send_pid = true); } Result _rosrvUnloadNrr(Service* srv, u64 nrr_address) { - IpcCommand c; - ipcInitialize(&c); - ipcSendPid(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; + const struct { + u64 pid_placeholder; u64 nrr_address; - } *raw; - - raw = serviceIpcPrepareHeader(srv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->pid = 0; - raw->nrr_address = nrr_address; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(srv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { 0, nrr_address }; + return serviceDispatchIn(srv, 3, in, .in_send_pid = true); } Result ldrRoLoadNro(u64* out_address, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) { @@ -326,41 +148,12 @@ Result ro1LoadNrrEx(u64 nrr_address, u64 nrr_size) { } Result roDmntGetModuleInfos(u64 pid, LoaderModuleInfo *out_module_infos, size_t max_out_modules, u32 *num_out) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, out_module_infos, max_out_modules * sizeof(*out_module_infos), BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u64 pid; - } *raw; - - raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->pid = pid; - - Result rc = serviceIpcDispatch(&g_dmntSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - u32 num_out; - } *resp; - - serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc) && num_out != NULL) { - *num_out = resp->num_out; - } - } - - return rc; + return serviceDispatchInOut(&g_dmntSrv, 0, pid, *num_out, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { out_module_infos, max_out_modules * sizeof(*out_module_infos) }, + }, + ); } diff --git a/nx/source/services/service_guard.h b/nx/source/services/service_guard.h new file mode 100644 index 00000000..4f4620b4 --- /dev/null +++ b/nx/source/services/service_guard.h @@ -0,0 +1,56 @@ +#pragma once +#include "types.h" +#include "result.h" +#include "kernel/mutex.h" +#include "sf/service.h" +#include "services/sm.h" + +typedef struct ServiceGuard { + Mutex mutex; + u32 refCount; +} ServiceGuard; + +NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g) +{ + mutexLock(&g->mutex); + return (g->refCount++) == 0; +} + +NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void)) +{ + if (R_FAILED(rc)) { + cleanupFunc(); + --g->refCount; + } + mutexUnlock(&g->mutex); + return rc; +} + +NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void)) +{ + mutexLock(&g->mutex); + if (g->refCount && (--g->refCount) == 0) + cleanupFunc(); + mutexUnlock(&g->mutex); +} + +#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \ +\ +static ServiceGuard g_##name##Guard; \ +NX_INLINE Result _##name##Initialize _paramdecl; \ +static void _##name##Cleanup(void); \ +\ +Result name##Initialize _paramdecl \ +{ \ + Result rc = 0; \ + if (serviceGuardBeginInit(&g_##name##Guard)) \ + rc = _##name##Initialize _parampass; \ + return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \ +} \ +\ +void name##Exit(void) \ +{ \ + serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \ +} + +#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ()) diff --git a/nx/source/services/set.c b/nx/source/services/set.c index 38381549..720d45b8 100644 --- a/nx/source/services/set.c +++ b/nx/source/services/set.c @@ -1,24 +1,12 @@ -/** - * @file set.h - * @brief Settings services IPC wrapper. - * @author plutoo - * @author yellows8 - * @copyright libnx Authors - */ +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" #include "services/set.h" -#include "services/sm.h" #include "services/applet.h" static Service g_setSrv; static Service g_setsysSrv; -static u64 g_refCnt; -static u64 g_refCntSys; static bool g_setLanguageCodesInitialized; static u64 g_setLanguageCodes[0x40]; @@ -26,50 +14,83 @@ static s32 g_setLanguageCodesTotal; static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode); -Result setInitialize(void) -{ - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_setSrv)) - return 0; +NX_GENERATE_SERVICE_GUARD(set); +Result _setInitialize(void) { g_setLanguageCodesInitialized = 0; return smGetService(&g_setSrv, "set"); } -void setExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_setSrv); - } +void _setCleanup(void) { + serviceClose(&g_setSrv); } Service* setGetServiceSession(void) { return &g_setSrv; } -Result setsysInitialize(void) -{ - atomicIncrement64(&g_refCntSys); - - if (serviceIsActive(&g_setsysSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); +NX_GENERATE_SERVICE_GUARD(setsys); +Result _setsysInitialize(void) { return smGetService(&g_setsysSrv, "set:sys"); } -void setsysExit(void) -{ - if (atomicDecrement64(&g_refCntSys) == 0) { - serviceClose(&g_setsysSrv); - } +void _setsysCleanup(void) { + serviceClose(&g_setsysSrv); } -Service* setsysGetSessionService(void) { +Service* setsysGetServiceSession(void) { return &g_setsysSrv; } +static Result _setCmdGetHandle(Service* srv, Handle* handle_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_handle_attrs = { SfOutHandleAttr_HipcCopy }, + .out_handles = handle_out, + ); +} + +static Result _setCmdGetEvent(Service* srv, Event* out_event, bool autoclear, u32 cmd_id) { + Handle tmp_handle = INVALID_HANDLE; + Result rc = 0; + + rc = _setCmdGetHandle(srv, &tmp_handle, cmd_id); + if (R_SUCCEEDED(rc)) eventLoadRemote(out_event, tmp_handle, autoclear); + return rc; +} + +static Result _setCmdNoInOut64(Service* srv, u64 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _setCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _setCmdNoInOutU8(Service* srv, u8 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _setCmdNoInOutBool(Service* srv, bool *out, u32 cmd_id) { + u8 tmp=0; + Result rc = _setCmdNoInOutU8(srv, &tmp, cmd_id); + if (R_SUCCEEDED(rc) && out) *out = tmp!=0; + return rc; +} + +static Result _setCmdInU8NoOut(Service* srv, u8 inval, u64 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _setCmdInBoolNoOut(Service* srv, bool inval, u32 cmd_id) { + return _setCmdInU8NoOut(srv, inval!=0, cmd_id); +} + +static Result _setCmdInU32NoOut(Service* srv, u32 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + static Result setInitializeLanguageCodesCache(void) { if (g_setLanguageCodesInitialized) return 0; Result rc = 0; @@ -84,7 +105,7 @@ static Result setInitializeLanguageCodesCache(void) { return rc; } -Result setMakeLanguage(u64 LanguageCode, s32 *Language) { +Result setMakeLanguage(u64 LanguageCode, SetLanguage *Language) { Result rc = setInitializeLanguageCodesCache(); if (R_FAILED(rc)) return rc; @@ -100,7 +121,7 @@ Result setMakeLanguage(u64 LanguageCode, s32 *Language) { return rc; } -Result setMakeLanguageCode(s32 Language, u64 *LanguageCode) { +Result setMakeLanguageCode(SetLanguage Language, u64 *LanguageCode) { Result rc = setInitializeLanguageCodesCache(); if (R_FAILED(rc)) return rc; @@ -126,43 +147,10 @@ Result setGetSystemLanguage(u64 *LanguageCode) { } Result setGetLanguageCode(u64 *LanguageCode) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_setSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 LanguageCode; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && LanguageCode) *LanguageCode = resp->LanguageCode; - } - - return rc; + return _setCmdNoInOut64(&g_setSrv, LanguageCode, 0); } Result setGetAvailableLanguageCodes(s32 *total_entries, u64 *LanguageCodes, size_t max_entries) { - IpcCommand c; - ipcInitialize(&c); - Result rc=0; bool new_cmd = hosversionAtLeast(4,0,0); @@ -175,260 +163,38 @@ Result setGetAvailableLanguageCodes(s32 *total_entries, u64 *LanguageCodes, size if (max_entries > (size_t)tmptotal) max_entries = (size_t)tmptotal; } - size_t bufsize = max_entries*sizeof(u64); - - if (!new_cmd) { - ipcAddRecvStatic(&c, LanguageCodes, bufsize, 0); - } - else { - ipcAddRecvBuffer(&c, LanguageCodes, bufsize, 0); - } - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = new_cmd ? 5 : 1; - - rc = serviceIpcDispatch(&g_setSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - s32 total_entries; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_entries) *total_entries = resp->total_entries; - } - - return rc; + return serviceDispatchOut(&g_setSrv, new_cmd ? 5 : 1, *total_entries, + .buffer_attrs = { (new_cmd ? SfBufferAttr_HipcMapAlias : SfBufferAttr_HipcPointer) | SfBufferAttr_Out }, + .buffers = { { LanguageCodes, max_entries*sizeof(u64) } }, + ); } static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - s32 Language; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->Language = Language; - - Result rc = serviceIpcDispatch(&g_setSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 LanguageCode; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && LanguageCode) *LanguageCode = resp->LanguageCode; - } - - return rc; + return serviceDispatchInOut(&g_setSrv, 2, Language, *LanguageCode); } Result setGetAvailableLanguageCodeCount(s32 *total) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = hosversionAtLeast(4,0,0) ? 6 : 3; - - Result rc = serviceIpcDispatch(&g_setSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - s32 total; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total) { - *total = resp->total; - if (*total < 0) *total = 0; - } - } - + Result rc = _setCmdNoInOutU32(&g_setSrv, (u32*)total, hosversionAtLeast(4,0,0) ? 6 : 3); + if (R_SUCCEEDED(rc) && total && *total < 0) *total = 0; return rc; } Result setGetRegionCode(SetRegion *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&g_setSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - s32 RegionCode; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && out) *out = resp->RegionCode; - } - + s32 code=0; + Result rc = _setCmdNoInOutU32(&g_setSrv, (u32*)&code, 4); + if (R_SUCCEEDED(rc) && out) *out = code; return rc; } -Result setsysGetColorSetId(ColorSetId *out) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 color_set; - } *resp = r.Raw; - - *out = resp->color_set; - rc = resp->result; - } - +Result setsysGetColorSetId(ColorSetId *out) { + u32 color_set=0; + Result rc = _setCmdNoInOutU32(&g_setsysSrv, &color_set, 23); + if (R_SUCCEEDED(rc) && out) *out = color_set; return rc; } -Result setsysSetColorSetId(ColorSetId id) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - s32 id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 24; - raw->id = id; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size) { - char send_name[SET_MAX_NAME_SIZE]; - char send_item_key[SET_MAX_NAME_SIZE]; - - memset(send_name, 0, SET_MAX_NAME_SIZE); - memset(send_item_key, 0, SET_MAX_NAME_SIZE); - strncpy(send_name, name, SET_MAX_NAME_SIZE-1); - strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1); - - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_name, SET_MAX_NAME_SIZE, 0); - ipcAddSendStatic(&c, send_item_key, SET_MAX_NAME_SIZE, 0); - ipcAddRecvBuffer(&c, value_out, value_out_size, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 38; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +Result setsysSetColorSetId(ColorSetId id) { + return _setCmdInU32NoOut(&g_setsysSrv, id, 24); } Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u64 *size_out) { @@ -439,178 +205,66 @@ Result setsysGetSettingsItemValueSize(const char *name, const char *item_key, u6 memset(send_item_key, 0, SET_MAX_NAME_SIZE); strncpy(send_name, name, SET_MAX_NAME_SIZE-1); strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1); + + return serviceDispatchOut(&g_setsysSrv, 37, *size_out, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { send_name, SET_MAX_NAME_SIZE }, + { send_item_key, SET_MAX_NAME_SIZE }, + }, + ); +} + +Result setsysGetSettingsItemValue(const char *name, const char *item_key, void *value_out, size_t value_out_size, u64 *size_out) { + char send_name[SET_MAX_NAME_SIZE]; + char send_item_key[SET_MAX_NAME_SIZE]; - IpcCommand c; - ipcInitialize(&c); - ipcAddSendStatic(&c, send_name, SET_MAX_NAME_SIZE, 0); - ipcAddSendStatic(&c, send_item_key, SET_MAX_NAME_SIZE, 0); + memset(send_name, 0, SET_MAX_NAME_SIZE); + memset(send_item_key, 0, SET_MAX_NAME_SIZE); + strncpy(send_name, name, SET_MAX_NAME_SIZE-1); + strncpy(send_item_key, item_key, SET_MAX_NAME_SIZE-1); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 37; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && size_out) *size_out = resp->size; - } - - return rc; + return serviceDispatchOut(&g_setsysSrv, 38, *size_out, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out, + }, + .buffers = { + { send_name, SET_MAX_NAME_SIZE }, + { send_item_key, SET_MAX_NAME_SIZE }, + { value_out, value_out_size }, + }, + ); } Result setsysGetSerialNumber(char *serial) { - IpcCommand c; - ipcInitialize(&c); + char out[0x18]={0}; - if (serial) memset(serial, 0, 0x19); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 68; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - char serial[0x18]; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && serial) - memcpy(serial, resp->serial, 0x18); + Result rc = serviceDispatchOut(&g_setsysSrv, 68, out); + if (R_SUCCEEDED(rc) && serial) { + memcpy(serial, out, 0x18); + serial[0x18]=0; } - return rc; } Result setsysGetFlag(SetSysFlag flag, bool *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = flag; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 flag; - } *resp = r.Raw; - - *out = resp->flag; - rc = resp->result; - } - - return rc; + return _setCmdNoInOutBool(&g_setsysSrv, out, flag); } Result setsysSetFlag(SetSysFlag flag, bool enable) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 flag; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = flag + 1; - raw->flag = enable; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 flag; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _setCmdInBoolNoOut(&g_setsysSrv, enable, flag + 1); } static Result _setsysGetFirmwareVersionImpl(SetSysFirmwareVersion *out, u32 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvStatic(&c, out, sizeof(*out), 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_setsysSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - struct { - u64 magic; - u64 result; - } *resp; - - serviceIpcParse(&g_setsysSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - } - - return rc; - + return serviceDispatch(&g_setsysSrv, cmd_id, + .buffer_attrs = { SfBufferAttr_FixedSize | SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { out, sizeof(*out) } }, + ); } Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out) { @@ -622,143 +276,35 @@ Result setsysGetFirmwareVersion(SetSysFirmwareVersion *out) { } } -Result setsysBindFatalDirtyFlagEvent(Event *out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 93; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - eventLoadRemote(out, r.Handles[0], false); - } - } - - return rc; +Result setsysBindFatalDirtyFlagEvent(Event *out_event) { + return _setCmdGetEvent(&g_setsysSrv, out_event, false, 93); } Result setsysGetFatalDirtyFlags(u64 *flags_0, u64 *flags_1) { - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 94; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 flags_0; - u64 flags_1; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *flags_0 = resp->flags_0; - *flags_1 = resp->flags_1; - } - } + u64 flags_0; + u64 flags_1; + } out; + Result rc = serviceDispatchOut(&g_setsysSrv, 94, out); + if (R_SUCCEEDED(rc) && flags_0) *flags_0 = out.flags_0; + if (R_SUCCEEDED(rc) && flags_1) *flags_1 = out.flags_1; return rc; } Result setsysGetDeviceNickname(char* nickname) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvBuffer(&c, nickname, SET_MAX_NICKNAME_SIZE, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 77; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(&g_setsysSrv, 77, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { nickname, SET_MAX_NICKNAME_SIZE } }, + ); } Result setsysSetDeviceNickname(const char* nickname) { char send_nickname[SET_MAX_NICKNAME_SIZE] = {0}; strncpy(send_nickname, nickname, SET_MAX_NICKNAME_SIZE-1); - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, send_nickname, SET_MAX_NICKNAME_SIZE, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 78; - - Result rc = serviceIpcDispatch(&g_setsysSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(&g_setsysSrv, 78, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { send_nickname, SET_MAX_NICKNAME_SIZE } }, + ); } diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index 445b1658..19b05da6 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -1,13 +1,9 @@ // Copyright 2017 plutoo -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/fatal.h" -#include "services/sm.h" static Service g_smSrv; -static u64 g_refCnt; #define MAX_OVERRIDES 32 @@ -33,28 +29,17 @@ void smAddOverrideHandle(u64 name, Handle handle) Handle smGetServiceOverride(u64 name) { - size_t i; - - for (i=0; imagic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->zero = 0; - - rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - } + rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true); } - if (R_FAILED(rc)) - smExit(); - return rc; } -void smExit(void) +void _smCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) - { - serviceClose(&g_smSrv); - } + serviceClose(&g_smSrv); } Service *smGetServiceSession(void) @@ -120,43 +73,21 @@ Service *smGetServiceSession(void) return &g_smSrv; } -u64 smEncodeName(const char* name) -{ - u64 name_encoded = 0; - size_t i; - - for (i=0; i<8; i++) - { - if (name[i] == '\0') - break; - - name_encoded |= ((u64) name[i]) << (8*i); - } - - return name_encoded; -} - Result smGetService(Service* service_out, const char* name) { u64 name_encoded = smEncodeName(name); Handle handle = smGetServiceOverride(name_encoded); - Result rc; + bool own_handle = false; + Result rc = 0; - if (handle != INVALID_HANDLE) - { - service_out->type = ServiceType_Override; - service_out->handle = handle; - rc = 0; - } - else - { + if (handle == INVALID_HANDLE) { + own_handle = true; rc = smGetServiceOriginal(&handle, name_encoded); + } - if (R_SUCCEEDED(rc)) - { - service_out->type = ServiceType_Normal; - service_out->handle = handle; - } + if (R_SUCCEEDED(rc)) { + serviceCreate(service_out, handle); + service_out->own_handle = own_handle; } return rc; @@ -164,117 +95,35 @@ Result smGetService(Service* service_out, const char* name) Result smGetServiceOriginal(Handle* handle_out, u64 name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u64 service_name; - u64 reserved[2]; - } *raw; + } in = { name }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->service_name = name; - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; + return serviceDispatchIn(&g_smSrv, 1, in, + .out_handle_attrs = { SfOutHandleAttr_HipcMove }, + .out_handles = handle_out, + ); } -Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions) +{ + const struct { u64 service_name; u32 is_light; u32 max_sessions; - } *raw; + } in = { smEncodeName(name), !!is_light, max_sessions }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - raw->service_name = smEncodeName(name); - raw->is_light = !!is_light; - raw->max_sessions = max_sessions; - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *handle_out = r.Handles[0]; - } - } - - return rc; + return serviceDispatchIn(&g_smSrv, 2, in, + .out_handle_attrs = { SfOutHandleAttr_HipcMove }, + .out_handles = handle_out, + ); } -Result smUnregisterService(const char* name) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; +Result smUnregisterService(const char* name) +{ + const struct { u64 service_name; - u64 reserved; - } *raw; + } in = { smEncodeName(name) }; - raw = serviceIpcPrepareHeader(&g_smSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->service_name = smEncodeName(name); - - Result rc = serviceIpcDispatch(&g_smSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - } *resp; - serviceIpcParse(&g_smSrv, &r, sizeof(*resp)); - - resp = r.Raw; - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_smSrv, 3, in); } diff --git a/nx/source/services/spl.c b/nx/source/services/spl.c index b51168e2..5191d4ce 100644 --- a/nx/source/services/spl.c +++ b/nx/source/services/spl.c @@ -1,31 +1,32 @@ // Copyright 2018 SciresM +#define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#include "service_guard.h" #include "runtime/hosversion.h" -#include "services/sm.h" #include "services/spl.h" +#include "crypto/sha256.h" + +/* Structs used in service implementations. */ +typedef struct SplKey { + u8 key[0x10]; +} SplKey; static Service g_splSrv, g_splCryptoSrv, g_splSslSrv, g_splEsSrv, g_splFsSrv, g_splManuSrv; -static u64 g_splRefCnt, g_splCryptoRefCnt, g_splSslRefCnt, g_splEsRefCnt, g_splFsRefCnt, g_splManuRefCnt; /* Helper prototypes for accessing handles. */ -static Service* _splGetGeneralSrv(void); -static Service* _splGetCryptoSrv(void); -static Service* _splGetRsaSrv(void); - -static Service* _splGetEsSrv(void); -static Service* _splGetFsSrv(void); -static Service* _splGetSslSrv(void); -static Service* _splGetManuSrv(void); +NX_INLINE Service* _splGetGeneralSrv(void); +NX_INLINE Service* _splGetCryptoSrv(void); +NX_INLINE Service* _splGetRsaSrv(void); +NX_INLINE Service* _splGetEsSrv(void); +NX_INLINE Service* _splGetFsSrv(void); +NX_INLINE Service* _splGetSslSrv(void); +NX_INLINE Service* _splGetManuSrv(void); Service* _splGetGeneralSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splSrv)) { return &g_splSrv; } else { @@ -37,7 +38,7 @@ Service* _splGetCryptoSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splManuSrv)) { return &g_splManuSrv; } else if (serviceIsActive(&g_splFsSrv)) { @@ -55,14 +56,14 @@ Service* _splGetRsaSrv(void) { if (hosversionBefore(4,0,0)) { return &g_splSrv; } - + if (serviceIsActive(&g_splFsSrv)) { return &g_splFsSrv; } else if (serviceIsActive(&g_splEsSrv)) { return &g_splEsSrv; } else { return &g_splSslSrv; - } + } } Service* _splGetEsSrv(void) { @@ -81,937 +82,342 @@ Service* _splGetManuSrv(void) { return hosversionAtLeast(4,0,0) ? &g_splManuSrv : &g_splSrv; } -/* There are like six services, so these helpers will initialize/exit the relevant services. */ -static Result _splSrvInitialize(Service* srv, u64 *refcnt, const char *name) { - atomicIncrement64(refcnt); - - if (serviceIsActive(srv)) - return 0; - - return smGetService(srv, name); +/* Initialization. */ +NX_GENERATE_SERVICE_GUARD(spl) +NX_GENERATE_SERVICE_GUARD(splCrypto) +NX_GENERATE_SERVICE_GUARD(splSsl) +NX_GENERATE_SERVICE_GUARD(splEs) +NX_GENERATE_SERVICE_GUARD(splFs) +NX_GENERATE_SERVICE_GUARD(splManu) + +static Result _splInitialize(void) { + return smGetService(&g_splSrv, "spl:"); } -static void _splSrvExit(Service* srv, u64 *refcnt) { - if (atomicDecrement64(refcnt) == 0) - serviceClose(srv); -} - -Result splInitialize(void) { - return _splSrvInitialize(&g_splSrv, &g_splRefCnt, "spl:"); -} - -void splExit(void) { - return _splSrvExit(&g_splSrv, &g_splRefCnt); +static void _splCleanup() { + serviceClose(&g_splSrv); } Service* splGetServiceSession(void) { return _splGetGeneralSrv(); } -Result splCryptoInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splCryptoSrv, &g_splCryptoRefCnt, "spl:mig"); - } else { - return splInitialize(); - } -} - -void splCryptoExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splCryptoSrv, &g_splCryptoRefCnt); - } else { - return splExit(); - } -} - -Service* splCryptoGetServiceSession(void) { - return _splGetCryptoSrv(); -} - -Result splSslInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splSslSrv, &g_splSslRefCnt, "spl:ssl"); - } else { - return splInitialize(); - } -} - -void splSslExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splSslSrv, &g_splSslRefCnt); - } else { - return splExit(); - } -} - -Service* splSslGetServiceSession(void) { - return _splGetSslSrv(); -} - -Result splEsInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splEsSrv, &g_splEsRefCnt, "spl:es"); - } else { - return splInitialize(); - } -} - -void splEsExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splEsSrv, &g_splEsRefCnt); - } else { - return splExit(); - } -} - -Service* splEsGetServiceSession(void) { - return _splGetEsSrv(); -} - -Result splFsInitialize(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvInitialize(&g_splFsSrv, &g_splFsRefCnt, "spl:fs"); - } else { - return splInitialize(); - } -} - -void splFsExit(void) { - if (hosversionAtLeast(4,0,0)) { - return _splSrvExit(&g_splFsSrv, &g_splFsRefCnt); - } else { - return splExit(); - } -} - -Service* splFsGetServiceSession(void) { - return _splGetFsSrv(); -} - -Result splManuInitialize(void) { - return _splSrvInitialize(&g_splManuSrv, &g_splManuRefCnt, "spl:manu"); -} - -void splManuExit(void) { - return _splSrvExit(&g_splManuSrv, &g_splManuRefCnt); -} - -Service* splManuGetServiceSession(void) { - return _splGetManuSrv(); +#define NX_GENERATE_SPL_SRV_INIT(name, subsrv) \ +static Result _spl##name##Initialize(void) { \ + if (hosversionAtLeast(4,0,0)) { \ + return smGetService(&g_spl##name##Srv, "spl:"#subsrv); \ + } else { \ + return splInitialize(); \ + } \ +} \ + \ +static void _spl##name##Cleanup() { \ + if (hosversionAtLeast(4,0,0)) { \ + splExit(); \ + } else { \ + serviceClose(&g_spl##name##Srv); \ + } \ +} \ +Service* _spl##name##GetServiceSession() { \ + return _splGet##name##Srv(); \ } +NX_GENERATE_SPL_SRV_INIT(Crypto, mig) +NX_GENERATE_SPL_SRV_INIT(Ssl, ssl) +NX_GENERATE_SPL_SRV_INIT(Es, es) +NX_GENERATE_SPL_SRV_INIT(Fs, fs) +NX_GENERATE_SPL_SRV_INIT(Manu, manu) /* SPL IGeneralService functionality. */ Result splGetConfig(SplConfigItem config_item, u64 *out_config) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 config_item; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - raw->config_item = config_item; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 out; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_config = resp->out; - } - } - - return rc; + } in = { config_item }; + return serviceDispatchInOut(_splGetGeneralSrv(), 0, in, *out_config); } Result splUserExpMod(const void *input, const void *modulus, const void *exp, size_t exp_size, void *dst) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, exp, exp_size, 1); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 2); - ipcAddRecvStatic(&c, dst, SPL_RSA_BUFFER_SIZE, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(_splGetGeneralSrv(), 1, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, SPL_RSA_BUFFER_SIZE }, + { input, SPL_RSA_BUFFER_SIZE }, + { exp, exp_size }, + { modulus, SPL_RSA_BUFFER_SIZE }, + }, + ); } Result splSetConfig(SplConfigItem config_item, u64 value) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; + const struct { u32 config_item; u64 value; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->config_item = config_item; - raw->value = value; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { config_item, value }; + return serviceDispatchIn(_splGetGeneralSrv(), 5, in); } Result splGetRandomBytes(void *out, size_t out_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddRecvStatic(&c, out, out_size, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatch(_splGetGeneralSrv(), 7, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { out, out_size }, + }, + ); } Result splIsDevelopment(bool *out_is_development) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 is_development; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_is_development = resp->is_development != 0; - } - } - - return rc; + return serviceDispatchOut(_splGetGeneralSrv(), 11, *out_is_development); } Result splSetBootReason(u32 value) { if (hosversionBefore(3,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 value; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 24; - raw->value = value; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(_splGetGeneralSrv(), 24, value); } Result splGetBootReason(u32 *out_value) { if (hosversionBefore(3,0,0)) { return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 25; - - Result rc = serviceIpcDispatch(_splGetGeneralSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 value; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_value = resp->value; - } - } - - return rc; + return serviceDispatchOut(_splGetGeneralSrv(), 25, *out_value); } /* SPL ICryptoService functionality. */ -Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) { - IpcCommand c; - ipcInitialize(&c); - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_kek[0x10]; +Result splCryptoGenerateAesKek(const void *wrapped_kek, u32 key_generation, u32 option, void *out_sealed_kek) { + const struct { + SplKey wrapped_kek; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - memcpy(raw->wrapped_kek, wrapped_kek, sizeof(raw->wrapped_kek)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_kek[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_kek, resp->sealed_kek, sizeof(resp->sealed_kek)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_kek), key_generation, option }; + return serviceDispatchInOut(_splGetCryptoSrv(), 2, in, *((SplKey *)out_sealed_kek)); } Result splCryptoLoadAesKey(const void *sealed_kek, const void *wrapped_key, u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), keyslot }; + return serviceDispatchIn(_splGetCryptoSrv(), 3, in); } Result splCryptoGenerateAesKey(const void *sealed_kek, const void *wrapped_key, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key) }; + return serviceDispatchInOut(_splGetCryptoSrv(), 4, in, *((SplKey *)out_sealed_key)); } Result splCryptoDecryptAesKey(const void *wrapped_key, u32 key_generation, u32 option, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_key[0x10]; + const struct { + SplKey wrapped_key; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 14; - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_key), key_generation, option }; + return serviceDispatchInOut(_splGetCryptoSrv(), 14, in, *((SplKey *)out_sealed_key)); } Result splCryptoCryptAesCtr(const void *input, void *output, size_t size, u32 keyslot, const void *ctr) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendBuffer(&c, input, size, BufferType_Type1); - ipcAddRecvBuffer(&c, output, size, BufferType_Type1); - - struct { - u64 magic; - u64 cmd_id; - u8 ctr[0x10]; + const struct { + SplKey ctr; u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 15; - memcpy(raw->ctr, ctr, sizeof(raw->ctr)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + } in = { *((const SplKey *)ctr), keyslot }; + return serviceDispatchIn(_splGetCryptoSrv(), 15, in, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_Out | SfBufferAttr_HipcMapTransferAllowsNonSecure, + SfBufferAttr_HipcMapAlias | SfBufferAttr_In | SfBufferAttr_HipcMapTransferAllowsNonSecure, + }, + .buffers = { + { output, size }, + { input, size }, + }, + ); } Result splCryptoComputeCmac(const void *input, size_t size, u32 keyslot, void *out_cmac) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, size, 0); - - struct { - u64 magic; - u64 cmd_id; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 16; - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 cmac[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_cmac, resp->cmac, sizeof(resp->cmac)); - } - } - - return rc; + return serviceDispatchInOut(_splGetCryptoSrv(), 16, keyslot, *((SplKey *)out_cmac), + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { input, size }, + }, + ); } Result splCryptoLockAesEngine(u32 *out_keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 21; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 keyslot; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - *out_keyslot = resp->keyslot; - } + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatchOut(_splGetCryptoSrv(), 21, *out_keyslot); } Result splCryptoUnlockAesEngine(u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 22; - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatchIn(_splGetCryptoSrv(), 22, keyslot); } -Result splCryptoGetSecurityEngineEvent(Handle *out_event) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 23; - - Result rc = serviceIpcDispatch(_splGetCryptoSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - *out_event = r.Handles[0]; - } +Result splCryptoGetSecurityEngineEvent(Event *out_event) { + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } + Handle event = INVALID_HANDLE; + Result rc = serviceDispatch(_splGetCryptoSrv(), 23); + if (R_SUCCEEDED(rc)) + eventLoadRemote(out_event, event, true); return rc; } /* SPL IRsaService functionality. NOTE: IRsaService is not a real part of inheritance, unlike ICryptoService/IGeneralService. */ Result splRsaDecryptPrivateKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version, void *dst, size_t dst_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, wrapped_rsa_key_size, 0); - ipcAddRecvStatic(&c, dst, dst_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - u32 version; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 13; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->version = version; - - Result rc = serviceIpcDispatch(_splGetRsaSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + u32 version; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), version }; + return serviceDispatchIn(_splGetRsaSrv(), 13, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, dst_size }, + { wrapped_rsa_key, wrapped_rsa_key_size }, + }, + ); } /* Helper function for RSA key importing. */ -static Result _splImportSecureExpModKey(Service* srv, u64 cmd_id, const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, wrapped_rsa_key_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek[0x10]; - u8 wrapped_key[0x10]; - u32 version; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - memcpy(raw->sealed_kek, sealed_kek, sizeof(raw->sealed_kek)); - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->version = version; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +NX_INLINE Result _splImportSecureExpModKey(Service* srv, u64 cmd_id, const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + const struct { + SplKey sealed_kek; + SplKey wrapped_key; + u32 version; + } in = { *((const SplKey *)sealed_kek), *((const SplKey *)wrapped_key), version }; + return serviceDispatchIn(srv, cmd_id, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { wrapped_rsa_key, wrapped_rsa_key_size }, + }, + ); } -static Result _splSecureExpMod(Service* srv, u64 cmd_id, const void *input, const void *modulus, void *dst) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, input, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 1); - ipcAddRecvStatic(&c, dst, SPL_RSA_BUFFER_SIZE, 0); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; +NX_INLINE Result _splSecureExpMod(Service* srv, u64 cmd_id, const void *input, const void *modulus, void *dst) { + return serviceDispatch(srv, cmd_id, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { dst, SPL_RSA_BUFFER_SIZE }, + { input, SPL_RSA_BUFFER_SIZE }, + { modulus, SPL_RSA_BUFFER_SIZE }, + }, + ); } /* SPL ISslService functionality. */ Result splSslLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splImportSecureExpModKey(&g_splSslSrv, 26, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splSslSecureExpMod(const void *input, const void *modulus, void *dst) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splSecureExpMod(&g_splSslSrv, 27, input, modulus, dst); } /* SPL IEsService functionality. */ +NX_INLINE Result _splUnwrapRsaOaepWrappedKey(Service *srv, u64 cmd_id, const void *rsa_wrapped_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_key) { + return serviceDispatchInOut(srv, cmd_id, key_generation, *((SplKey *)out_sealed_key), + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { rsa_wrapped_key, SPL_RSA_BUFFER_SIZE }, + { modulus, SPL_RSA_BUFFER_SIZE }, + { label_hash, label_hash_size }, + }, + ); +} + +NX_INLINE Result _splLoadContentKey(Service *srv, u64 cmd_id, const void *sealed_key, u32 keyslot) { + const struct { + SplKey sealed_key; + u32 keyslot; + } in = { *((const SplKey *)sealed_key), keyslot }; + return serviceDispatchIn(srv, cmd_id, in); +} + Result splEsLoadRsaOaepKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { return _splImportSecureExpModKey(_splGetEsSrv(), 17, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splEsUnwrapRsaOaepWrappedTitlekey(const void *rsa_wrapped_titlekey, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_titlekey) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, rsa_wrapped_titlekey, SPL_RSA_BUFFER_SIZE, 0); - ipcAddSendStatic(&c, modulus, SPL_RSA_BUFFER_SIZE, 1); - ipcAddSendStatic(&c, label_hash, label_hash_size, 2); - - struct { - u64 magic; - u64 cmd_id; - u32 key_generation; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 18; - raw->key_generation = key_generation; - - Result rc = serviceIpcDispatch(_splGetEsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_titlekey[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_titlekey, resp->sealed_titlekey, sizeof(resp->sealed_titlekey)); - } - } - - return rc; + return _splUnwrapRsaOaepWrappedKey(_splGetEsSrv(), 18, rsa_wrapped_titlekey, modulus, label_hash, label_hash_size, key_generation, out_sealed_titlekey); } Result splEsUnwrapAesWrappedTitlekey(const void *aes_wrapped_titlekey, u32 key_generation, void *out_sealed_titlekey) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 aes_wrapped_titlekey[0x10]; - u32 key_generation; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 20; - memcpy(raw->aes_wrapped_titlekey, aes_wrapped_titlekey, sizeof(raw->aes_wrapped_titlekey)); - raw->key_generation = key_generation; - - Result rc = serviceIpcDispatch(_splGetEsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_titlekey[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_titlekey, resp->sealed_titlekey, sizeof(resp->sealed_titlekey)); - } + if (hosversionBefore(2,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + const struct { + SplKey aes_wrapped_titlekey; + u32 key_generation; + } in = { *(const SplKey *)aes_wrapped_titlekey, key_generation }; + return serviceDispatchInOut(_splGetEsSrv(), 20, in, *((SplKey *)out_sealed_titlekey)); } Result splEsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splImportSecureExpModKey(&g_splEsSrv, 28, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); } Result splEsSecureExpMod(const void *input, const void *modulus, void *dst) { + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } return _splSecureExpMod(&g_splEsSrv, 29, input, modulus, dst); } +Result splEsUnwrapElicenseKey(const void *rsa_wrapped_elicense_key, const void *modulus, const void *label_hash, size_t label_hash_size, u32 key_generation, void *out_sealed_elicense_key) { + if (hosversionBefore(6,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return _splUnwrapRsaOaepWrappedKey(&g_splEsSrv, 31, rsa_wrapped_elicense_key, modulus, label_hash, label_hash_size, key_generation, out_sealed_elicense_key); +} + +Result splEsLoadElicenseKey(const void *sealed_elicense_key, u32 keyslot) { + if (hosversionBefore(6,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); + } + return _splLoadContentKey(&g_splEsSrv, 32, sealed_elicense_key, keyslot); +} + /* SPL IFsService functionality. */ Result splFsLoadSecureExpModKey(const void *sealed_kek, const void *wrapped_key, const void *wrapped_rsa_key, size_t wrapped_rsa_key_size, RsaKeyVersion version) { return _splImportSecureExpModKey(_splGetFsSrv(), 9, sealed_kek, wrapped_key, wrapped_rsa_key, wrapped_rsa_key_size, version); @@ -1022,157 +428,52 @@ Result splFsSecureExpMod(const void *input, const void *modulus, void *dst) { } Result splFsGenerateSpecificAesKey(const void *wrapped_key, u32 key_generation, u32 option, void *out_sealed_key) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 wrapped_key[0x10]; + const struct { + SplKey wrapped_key; u32 key_generation; u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - memcpy(raw->wrapped_key, wrapped_key, sizeof(raw->wrapped_key)); - raw->key_generation = key_generation; - raw->option = option; - - Result rc = serviceIpcDispatch(_splGetFsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 sealed_key[0x10]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_sealed_key, resp->sealed_key, sizeof(resp->sealed_key)); - } - } - - return rc; + } in = { *((const SplKey *)wrapped_key), key_generation, option }; + return serviceDispatchInOut(_splGetFsSrv(), 12, in, *((SplKey *)out_sealed_key)); } Result splFsLoadTitlekey(const void *sealed_titlekey, u32 keyslot) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_titlekey[0x10]; - u32 keyslot; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 19; - memcpy(raw->sealed_titlekey, sealed_titlekey, sizeof(raw->sealed_titlekey)); - raw->keyslot = keyslot; - - Result rc = serviceIpcDispatch(_splGetFsSrv()); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _splLoadContentKey(_splGetFsSrv(), 19, sealed_titlekey, keyslot); } Result splFsGetPackage2Hash(void *out_hash) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 31; - - Result rc = serviceIpcDispatch(&g_splFsSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u8 package2_hash[0x20]; - } *resp = r.Raw; - - rc = resp->result; - if (R_SUCCEEDED(rc)) { - memcpy(out_hash, resp->package2_hash, sizeof(resp->package2_hash)); - } + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + return serviceDispatch(&g_splFsSrv, 31, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { out_hash, SHA256_HASH_SIZE }, + }, + ); } /* SPL IManuService funcionality. */ Result splManuEncryptRsaKeyForImport(const void *sealed_kek_pre, const void *wrapped_key_pre, const void *sealed_kek_post, const void *wrapped_kek_post, u32 option, const void *wrapped_rsa_key, void *out_wrapped_rsa_key, size_t rsa_key_size) { - IpcCommand c; - ipcInitialize(&c); - - ipcAddSendStatic(&c, wrapped_rsa_key, rsa_key_size, 0); - ipcAddRecvStatic(&c, out_wrapped_rsa_key, rsa_key_size, 0); - - struct { - u64 magic; - u64 cmd_id; - u8 sealed_kek_pre[0x10]; - u8 wrapped_key_pre[0x10]; - u8 sealed_kek_post[0x10]; - u8 wrapped_kek_post[0x10]; - u32 option; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 30; - memcpy(raw->sealed_kek_pre, sealed_kek_pre, sizeof(raw->sealed_kek_pre)); - memcpy(raw->wrapped_key_pre, wrapped_key_pre, sizeof(raw->wrapped_key_pre)); - memcpy(raw->sealed_kek_post, sealed_kek_post, sizeof(raw->sealed_kek_post)); - memcpy(raw->wrapped_kek_post, wrapped_kek_post, sizeof(raw->wrapped_kek_post)); - raw->option = option; - - Result rc = serviceIpcDispatch(&g_splManuSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; + if (hosversionBefore(5,0,0)) { + return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer); } - - return rc; + const struct { + SplKey sealed_kek_pre; + SplKey wrapped_key_pre; + SplKey sealed_kek_post; + SplKey wrapped_kek_post; + u32 option; + } in = { *((const SplKey *)sealed_kek_pre), *((const SplKey *)wrapped_key_pre), *((const SplKey *)sealed_kek_post), *((const SplKey *)wrapped_kek_post), option }; + return serviceDispatchIn(&g_splManuSrv, 30, in, + .buffer_attrs = { + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + SfBufferAttr_HipcPointer | SfBufferAttr_In, + }, + .buffers = { + { out_wrapped_rsa_key, rsa_key_size }, + { wrapped_rsa_key, rsa_key_size }, + }, + ); } diff --git a/nx/source/services/time.c b/nx/source/services/time.c index 4e18c4d3..b1acdc31 100644 --- a/nx/source/services/time.c +++ b/nx/source/services/time.c @@ -1,28 +1,19 @@ -#include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "kernel/ipc.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/time.h" -#include "services/sm.h" static Service g_timeSrv; static Service g_timeUserSystemClock; static Service g_timeNetworkSystemClock; static Service g_timeTimeZoneService; static Service g_timeLocalSystemClock; -static u64 g_refCnt; -static Result _timeGetSession(Service* srv_out, u64 cmd_id); +static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id); -Result timeInitialize(void) -{ - atomicIncrement64(&g_refCnt); +NX_GENERATE_SERVICE_GUARD(time); - if (serviceIsActive(&g_timeSrv)) - return 0; - - Result rc; +Result _timeInitialize(void) { + Result rc=0; rc = smGetService(&g_timeSrv, "time:s"); if (R_FAILED(rc)) @@ -31,75 +22,33 @@ Result timeInitialize(void) if (R_FAILED(rc)) return rc; - rc = _timeGetSession(&g_timeUserSystemClock, 0); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeUserSystemClock, 0); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeNetworkSystemClock, 1); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeNetworkSystemClock, 1); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeTimeZoneService, 3); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeTimeZoneService, 3); if (R_SUCCEEDED(rc)) - rc = _timeGetSession(&g_timeLocalSystemClock, 4); - - if (R_FAILED(rc)) - timeExit(); + rc = _timeCmdGetSession(&g_timeSrv, &g_timeLocalSystemClock, 4); return rc; } -void timeExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) - { - serviceClose(&g_timeLocalSystemClock); - serviceClose(&g_timeTimeZoneService); - serviceClose(&g_timeNetworkSystemClock); - serviceClose(&g_timeUserSystemClock); - serviceClose(&g_timeSrv); - } +void _timeCleanup(void) { + serviceClose(&g_timeLocalSystemClock); + serviceClose(&g_timeTimeZoneService); + serviceClose(&g_timeNetworkSystemClock); + serviceClose(&g_timeUserSystemClock); + serviceClose(&g_timeSrv); } Service* timeGetServiceSession(void) { return &g_timeSrv; } -static Result _timeGetSession(Service* srv_out, u64 cmd_id) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = cmd_id; - - Result rc = serviceIpcDispatch(&g_timeSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) { - serviceCreate(srv_out, r.Handles[0]); - } - } - - return rc; -} - -static Service* _timeGetClockSession(TimeType type) { +Service* timeGetServiceSession_SystemClock(TimeType type) { if (type==TimeType_UserSystemClock) { return &g_timeUserSystemClock; } @@ -114,403 +63,143 @@ static Service* _timeGetClockSession(TimeType type) { } } +Service* timeGetServiceSession_TimeZoneService(void) { + return &g_timeTimeZoneService; +} + +static Result _timeCmdGetSession(Service* srv, Service* srv_out, u32 cmd_id) { + return serviceDispatch(srv, cmd_id, + .out_num_objects = 1, + .out_objects = srv_out, + ); +} + +static Result _timeCmdInU64NoOut(Service* srv, u64 inval, u32 cmd_id) { + return serviceDispatchIn(srv, cmd_id, inval); +} + +static Result _timeCmdNoInOutU64(Service* srv, u64 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + +static Result _appletCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + Result timeGetCurrentTime(TimeType type, u64 *timestamp) { - Service *srv = _timeGetClockSession(type); + Service *srv = timeGetServiceSession_SystemClock(type); if (srv==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 timestamp; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp) *timestamp = resp->timestamp; - } - - return rc; + return _timeCmdNoInOutU64(srv, timestamp, 0); } Result timeSetCurrentTime(TimeType type, u64 timestamp) { - Service *srv = _timeGetClockSession(type); + Service *srv = timeGetServiceSession_SystemClock(type); if (srv==NULL) return MAKERESULT(Module_Libnx, LibnxError_BadInput); - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(srv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return _timeCmdInU64NoOut(srv, timestamp, 1); } Result timeGetDeviceLocationName(TimeLocationName *name) { - IpcCommand c; - ipcInitialize(&c); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 0; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeLocationName name; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && name) memcpy(name, &resp->name, sizeof(TimeLocationName)); - } - - return rc; + return serviceDispatchOut(&g_timeTimeZoneService, 0, *name); } Result timeSetDeviceLocationName(const TimeLocationName *name) { - IpcCommand c; - ipcInitialize(&c); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - TimeLocationName name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 1; - memcpy(&raw->name, name, sizeof(TimeLocationName)); - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_timeTimeZoneService, 1, *name); } -Result timeGetTotalLocationNameCount(u32 *total_location_name_count) { - IpcCommand c; - ipcInitialize(&c); +Result timeGetTotalLocationNameCount(s32 *total_location_name_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 2; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 total_location_name_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && total_location_name_count) *total_location_name_count = resp->total_location_name_count; - } - - return rc; + return _appletCmdNoInOutU32(&g_timeTimeZoneService, (u32*)total_location_name_count, 2); } -Result timeLoadLocationNameList(u32 index, TimeLocationName *location_name_array, size_t location_name_size, u32 *location_name_count) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, location_name_array, location_name_size, BufferType_Normal); +Result timeLoadLocationNameList(s32 index, TimeLocationName *location_name_array, s32 location_name_max, s32 *location_name_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - u32 index; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 3; - raw->index = index; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 location_name_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && location_name_count) *location_name_count = resp->location_name_count; - } - - return rc; + return serviceDispatchInOut(&g_timeTimeZoneService, 3, index, *location_name_count, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { location_name_array, sizeof(TimeLocationName)*location_name_max } }, + ); } Result timeLoadTimeZoneRule(const TimeLocationName *name, TimeZoneRule *rule) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - TimeLocationName name; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - memcpy(&raw->name, name, sizeof(TimeLocationName)); - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; + return serviceDispatchIn(&g_timeTimeZoneService, 4, *name, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out }, + .buffers = { { rule, sizeof(TimeZoneRule) } }, + ); } Result timeToCalendarTime(const TimeZoneRule *rule, u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 100; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeCalendarTime caltime; - TimeCalendarAdditionalInfo info; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && caltime) memcpy(caltime, &resp->caltime, sizeof(TimeCalendarTime)); - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(TimeCalendarAdditionalInfo)); - } + TimeCalendarTime caltime; + TimeCalendarAdditionalInfo info; + } out; + Result rc = serviceDispatchInOut(&g_timeTimeZoneService, 100, timestamp, out, + .buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In }, + .buffers = { { rule, sizeof(TimeZoneRule) } }, + ); + if (R_SUCCEEDED(rc) && caltime) *caltime = out.caltime; + if (R_SUCCEEDED(rc) && info) *info = out.info; return rc; } Result timeToCalendarTimeWithMyRule(u64 timestamp, TimeCalendarTime *caltime, TimeCalendarAdditionalInfo *info) { - IpcCommand c; - ipcInitialize(&c); + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); struct { - u64 magic; - u64 cmd_id; - u64 timestamp; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 101; - raw->timestamp = timestamp; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - TimeCalendarTime caltime; - TimeCalendarAdditionalInfo info; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && caltime) memcpy(caltime, &resp->caltime, sizeof(TimeCalendarTime)); - if (R_SUCCEEDED(rc) && info) memcpy(info, &resp->info, sizeof(TimeCalendarAdditionalInfo)); - } - - return rc; -} - -Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_size, u32 *timestamp_count) { - IpcCommand c; - ipcInitialize(&c); - ipcAddSendBuffer(&c, rule, sizeof(TimeZoneRule), BufferType_Normal); - ipcAddRecvStatic(&c, timestamp_list, timestamp_list_size, 0); - - struct { - u64 magic; - u64 cmd_id; TimeCalendarTime caltime; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 201; - raw->caltime = *caltime; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 timestamp_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp_count) *timestamp_count = resp->timestamp_count; - } + TimeCalendarAdditionalInfo info; + } out; + Result rc = serviceDispatchInOut(&g_timeTimeZoneService, 101, timestamp, out); + if (R_SUCCEEDED(rc) && caltime) *caltime = out.caltime; + if (R_SUCCEEDED(rc) && info) *info = out.info; return rc; } -Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, size_t timestamp_list_size, u32 *timestamp_count) { - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvStatic(&c, timestamp_list, timestamp_list_size, 0); +Result timeToPosixTime(const TimeZoneRule *rule, const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - struct { - u64 magic; - u64 cmd_id; - TimeCalendarTime caltime; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 202; - raw->caltime = *caltime; - - Result rc = serviceIpcDispatch(&g_timeTimeZoneService); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u32 timestamp_count; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc) && timestamp_count) *timestamp_count = resp->timestamp_count; - } - - return rc; + return serviceDispatchInOut(&g_timeTimeZoneService, 201, *caltime, *timestamp_count, + .buffer_attrs = { + SfBufferAttr_HipcMapAlias | SfBufferAttr_In, + SfBufferAttr_HipcPointer | SfBufferAttr_Out, + }, + .buffers = { + { rule, sizeof(TimeZoneRule) }, + { timestamp_list, sizeof(u64)*timestamp_list_count }, + }, + ); +} + +Result timeToPosixTimeWithMyRule(const TimeCalendarTime *caltime, u64 *timestamp_list, s32 timestamp_list_count, s32 *timestamp_count) { + if (!serviceIsActive(&g_timeTimeZoneService)) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + + return serviceDispatchInOut(&g_timeTimeZoneService, 202, *caltime, *timestamp_count, + .buffer_attrs = { SfBufferAttr_HipcPointer | SfBufferAttr_Out }, + .buffers = { { timestamp_list, sizeof(u64)*timestamp_list_count } }, + ); } diff --git a/nx/source/services/ts.c b/nx/source/services/ts.c new file mode 100644 index 00000000..6852233b --- /dev/null +++ b/nx/source/services/ts.c @@ -0,0 +1,48 @@ +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include +#include "service_guard.h" +#include "runtime/hosversion.h" +#include "services/ts.h" + +static Service g_tsSrv; + +NX_GENERATE_SERVICE_GUARD(ts); + +Result _tsInitialize(void) { + return smGetService(&g_tsSrv, "ts"); +} + +void _tsCleanup(void) { + serviceClose(&g_tsSrv); +} + +Service* tsGetServiceSession(void) { + return &g_tsSrv; +} + +static Result _tsCmdInU8Out32(u8 inval, u32 *out, u64 cmd_id) { + return serviceDispatchInOut(&g_tsSrv, cmd_id, inval, *out); +} + +Result tsGetTemperatureRange(TsLocation location, s32 *min_temperature, s32 *max_temperature) { + u8 tmp_location = location; + + struct { + s32 min_temperature; + s32 max_temperature; + } out; + + Result rc = serviceDispatchInOut(&g_tsSrv, 0, tmp_location, out); + if (R_SUCCEEDED(rc) && min_temperature) *min_temperature = out.min_temperature; + if (R_SUCCEEDED(rc) && max_temperature) *max_temperature = out.max_temperature; + return rc; +} + +Result tsGetTemperature(TsLocation location, s32 *temperature) { + return _tsCmdInU8Out32(location, (u32*)temperature, 1); +} + +Result tsGetTemperatureMilliC(TsLocation location, s32 *temperature) { + return _tsCmdInU8Out32(location, (u32*)temperature, 3); +} + diff --git a/nx/source/services/usbhs.c b/nx/source/services/usbhs.c index 09630586..650ee5df 100644 --- a/nx/source/services/usbhs.c +++ b/nx/source/services/usbhs.c @@ -725,8 +725,6 @@ Result usbHsIfOpenUsbEp(UsbHsClientIfSession* s, UsbHsClientEpSession* ep, u16 m if (R_SUCCEEDED(rc)) rc = _usbHsGetEvent(&ep->s, &ep->eventXfer, 2); } - if (hosversionAtLeast(3,0,0) && R_SUCCEEDED(rc)) rc = ipcQueryPointerBufferSize(ep->s.handle, &ep->ptrbufsize); - if (R_FAILED(rc)) { serviceClose(&ep->s); eventClose(&ep->eventXfer); @@ -854,7 +852,7 @@ static Result _usbHsEpGetXferReport(UsbHsClientEpSession* s, UsbHsXferReport* re ipcAddRecvBuffer(&c, reports, sizeof(UsbHsXferReport) * max_reports, BufferType_Normal); } else { - ipcAddRecvSmart(&c, s->ptrbufsize, reports, sizeof(UsbHsXferReport) * max_reports, 0); + ipcAddRecvSmart(&c, s->s.pointer_buffer_size, reports, sizeof(UsbHsXferReport) * max_reports, 0); } raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw)); diff --git a/nx/source/services/wlaninf.c b/nx/source/services/wlaninf.c index 1eb0d854..49a984ad 100644 --- a/nx/source/services/wlaninf.c +++ b/nx/source/services/wlaninf.c @@ -1,111 +1,34 @@ -/** - * @file wlaninf.c - * @brief WLAN InfraManager service IPC wrapper. - * @author natinusala - * @copyright libnx Authors - */ - -#include "types.h" -#include "result.h" -#include "services/sm.h" +#define NX_SERVICE_ASSUME_NON_DOMAIN +#include "service_guard.h" #include "services/wlaninf.h" -#include "arm/atomics.h" static Service g_wlaninfSrv; -static u64 g_refCnt; -Result wlaninfInitialize(void) { - Result rc; +NX_GENERATE_SERVICE_GUARD(wlaninf); - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_wlaninfSrv)) - return 0; - - rc = smGetService(&g_wlaninfSrv, "wlan:inf"); - - if (R_FAILED(rc)) - wlaninfExit(); - - return rc; +Result _wlaninfInitialize(void) { + return smGetService(&g_wlaninfSrv, "wlan:inf"); } -void wlaninfExit(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_wlaninfSrv); - } +void _wlaninfCleanup(void) { + serviceClose(&g_wlaninfSrv); } Service* wlaninfGetServiceSession(void) { return &g_wlaninfSrv; } +static Result _wlaninfCmdNoInOutU32(Service* srv, u32 *out, u32 cmd_id) { + return serviceDispatchOut(srv, cmd_id, *out); +} + Result wlaninfGetState(WlanInfState* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_wlaninfSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 10; - - Result rc = serviceIpcDispatch(&g_wlaninfSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - u32 out; - } *resp; - - serviceIpcParse(&g_wlaninfSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - *out = resp->out; - } - + u32 tmp=0; + Result rc = _wlaninfCmdNoInOutU32(&g_wlaninfSrv, &tmp, 10); + if (R_SUCCEEDED(rc) && out) *out = tmp; return rc; } Result wlaninfGetRSSI(s32* out) { - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = serviceIpcPrepareHeader(&g_wlaninfSrv, &c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - - Result rc = serviceIpcDispatch(&g_wlaninfSrv); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - - struct { - u64 magic; - u64 result; - s32 out; - } *resp; - - serviceIpcParse(&g_wlaninfSrv, &r, sizeof(*resp)); - resp = r.Raw; - - rc = resp->result; - *out = resp->out; - } - - return rc; + return _wlaninfCmdNoInOutU32(&g_wlaninfSrv, (u32*)out, 12); }