/** * @file sm.h * @brief Service manager (sm) IPC wrapper. * @author plutoo * @author yellows8 * @copyright libnx Authors */ #pragma once #include "../types.h" #include "../kernel/svc.h" #include "../kernel/ipc.h" #include "../sf/service.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" /** * @brief Closes a domain object by ID. * @param[in] s Service object, necessarily a domain or domain subservice. * @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->session, object_id); } /** * @brief Dispatches an IPC request to a service. * @param[in] s Service object. * @return Result code. */ DEPRECATED static inline Result serviceIpcDispatch(Service* s) { return ipcDispatch(s->session); } /** * @brief Creates a subservice object from a parent service. * @param[out] s Service object. * @param[in] parent Parent service, possibly a domain or domain subservice. * @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]); } else { return serviceCreate(s, r->Handles[i]); } } /** * @brief Sends a service object with the specified cmd. This only supports domains. * @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 Prepares the header of an IPC command structure for a service. * @param s Service to prepare message header for * @param cmd IPC command structure. * @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)); } else { return ipcPrepareHeader(cmd, sizeof_raw); } } /** * @brief Parse an IPC command response into an IPC parsed command structure for a service. * @param s Service to prepare message header for * @param r IPC parsed command structure to fill in. * @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); } else { return ipcParse(r); } } #pragma GCC diagnostic pop /** * @brief Initializes SM. * @return Result code. * @note This function is already called in the default application startup code (before main() is called). */ Result smInitialize(void); /** * @brief Uninitializes SM. * @return Result code. * @note This function is already handled in the default application exit code (after main() returns). */ void smExit(void); /** * @brief Requests a service from SM. * @param[out] service_out Service structure which will be filled in. * @param[in] name Name of the service to request. * @return Result code. */ Result smGetService(Service* service_out, const char* name); /** * @brief Requests a service from SM, as an IPC session handle directly * @param[out] handle_out Variable containing IPC session handle. * @param[in] name Name of the service to request. * @return Result code. */ Result smGetServiceOriginal(Handle* handle_out, u64 name); /** * @brief Retrieves an overriden service in the homebrew environment. * @param[in] name Name of the service to request (as 64-bit integer). * @return IPC session handle. */ Handle smGetServiceOverride(u64 name); /** * @brief Creates and registers a new service within SM. * @param[out] handle_out Variable containing IPC port handle. * @param[in] name Name of the service. * @param[in] is_light "Is light" * @param[in] max_sessions Maximum number of concurrent sessions that the service will accept. * @return Result code. */ Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions); /** * @brief Unregisters a previously registered service in SM. * @param[in] name Name of the service. * @return Result code. */ Result smUnregisterService(const char* name); /** * @brief Gets the Service session used to communicate with SM. * @return Pointer to service session used to communicate with SM. */ Service *smGetServiceSession(void); /** * @brief Encodes a service name as a 64-bit integer. * @param[in] name Name of the service. * @return Encoded 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. * @param[in] name Name of the service (as 64-bit integer). * @param[in] handle IPC session handle. */ void smAddOverrideHandle(u64 name, Handle handle);