libnx
sm.h
Go to the documentation of this file.
1 /**
2  * @file sm.h
3  * @brief Service manager (sm) IPC wrapper.
4  * @author plutoo
5  * @author yellows8
6  * @copyright libnx Authors
7  */
8 #pragma once
9 #include "../types.h"
10 #include "../kernel/svc.h"
11 #include "../kernel/ipc.h"
12 
13 /// Service type.
14 typedef enum {
15  ServiceType_Uninitialized, ///< Uninitialized service.
16  ServiceType_Normal, ///< Normal service.
17  ServiceType_Domain, ///< Domain.
18  ServiceType_DomainSubservice, ///< Domain subservice;
19  ServiceType_Override ///< Service overriden in the homebrew environment.
20 } ServiceType;
21 
22 /// Service object structure.
23 typedef struct {
24  Handle handle;
25  u32 object_id;
26  ServiceType type;
27 } Service;
28 
29 /**
30  * @brief Returns whether a service is overriden in the homebrew environment.
31  * @param[in] s Service object.
32  * @return true if overriden.
33  */
34 static inline bool serviceIsOverride(Service* s) {
35  return s->type == ServiceType_Override;
36 }
37 
38 /**
39  * @brief Returns whether a service has been initialized.
40  * @param[in] s Service object.
41  * @return true if initialized.
42  */
43 static inline bool serviceIsActive(Service* s) {
44  return s->type != ServiceType_Uninitialized;
45 }
46 
47 /**
48  * @brief Returns whether a service is a domain.
49  * @param[in] s Service object.
50  * @return true if a domain.
51  */
52 static inline bool serviceIsDomain(Service* s) {
53  return s->type == ServiceType_Domain;
54 }
55 
56 /**
57  * @brief Returns whether a service is a domain subservice.
58  * @param[in] s Service object.
59  * @return true if a domain subservice.
60  */
61 static inline bool serviceIsDomainSubservice(Service* s) {
62  return s->type == ServiceType_DomainSubservice;
63 }
64 
65 /**
66  * @brief For a domain/domain subservice, return the associated object ID.
67  * @param[in] s Service object, necessarily a domain or domain subservice.
68  * @return The object ID.
69  */
70 static inline u32 serviceGetObjectId(Service* s) {
71  return s->object_id;
72 }
73 
74 /**
75  * @brief Closes a domain object by ID.
76  * @param[in] s Service object, necessarily a domain or domain subservice.
77  * @param object_id ID of the object to close.
78  * @return Result code.
79  */
80 static inline Result serviceCloseObjectById(Service* s, u32 object_id) {
81  return ipcCloseObjectById(s->handle, object_id);
82 }
83 
84 /**
85  * @brief Dispatches an IPC request to a service.
86  * @param[in] s Service object.
87  * @return Result code.
88  */
89 static inline Result serviceIpcDispatch(Service* s) {
90  return ipcDispatch(s->handle);
91 }
92 
93 /**
94  * @brief Creates a service object from an IPC session handle.
95  * @param[out] s Service object.
96  * @param[in] h IPC session handle.
97  */
98 static inline void serviceCreate(Service* s, Handle h) {
99  s->handle = h;
100  s->type = ServiceType_Normal;
101  s->object_id = IPC_INVALID_OBJECT_ID;
102 }
103 
104 /**
105  * @brief Creates a domain subservice object from a parent service.
106  * @param[out] s Service object.
107  * @param[in] parent Parent service, necessarily a domain or domain subservice.
108  * @param[in] object_id Object ID for this subservice.
109  */
110 static inline void serviceCreateDomainSubservice(Service* s, Service* parent, u32 object_id) {
111  s->handle = parent->handle;
113  s->object_id = object_id;
114 }
115 
116 /**
117  * @brief Converts a regular service to a domain.
118  * @param[in] s Service object.
119  * @return Result code.
120  */
122  Result rc = ipcConvertSessionToDomain(s->handle, &s->object_id);
123  if(R_SUCCEEDED(rc))
124  s->type = ServiceType_Domain;
125  return rc;
126 }
127 
128 /**
129  * @brief Closes a service.
130  * @param[in] s Service object.
131  */
132 static inline void serviceClose(Service* s) {
133  switch (s->type) {
134 
135  case ServiceType_Normal:
136  case ServiceType_Domain:
137  ipcCloseSession(s->handle);
138  svcCloseHandle(s->handle);
139  break;
140 
142  serviceCloseObjectById(s, s->object_id);
143  break;
144 
146  // Don't close because we don't own the overridden handle.
147  break;
148 
150  break;
151  }
152 
153  s->type = ServiceType_Uninitialized;
154 }
155 
156 /**
157  * @brief Initializes SM.
158  * @return Result code.
159  * @note This function is already called in the default application startup code (before main() is called).
160  */
161 Result smInitialize(void);
162 
163 /**
164  * @brief Uninitializes SM.
165  * @return Result code.
166  * @note This function is already handled in the default application exit code (after main() returns).
167  */
168 void smExit(void);
169 
170 /**
171  * @brief Requests a service from SM.
172  * @param[out] service_out Service structure which will be filled in.
173  * @param[in] name Name of the service to request.
174  * @return Result code.
175  */
176 Result smGetService(Service* service_out, const char* name);
177 
178 /**
179  * @brief Requests a service from SM, as an IPC session handle directly
180  * @param[out] handle_out Variable containing IPC session handle.
181  * @param[in] name Name of the service to request.
182  * @return Result code.
183  */
184 Result smGetServiceOriginal(Handle* handle_out, u64 name);
185 
186 /**
187  * @brief Retrieves an overriden service in the homebrew environment.
188  * @param[in] name Name of the service to request (as 64-bit integer).
189  * @return IPC session handle.
190  */
192 
193 /**
194  * @brief Creates and registers a new service within SM.
195  * @param[out] handle_out Variable containing IPC port handle.
196  * @param[in] name Name of the service.
197  * @param[in] is_light "Is light"
198  * @param[in] max_sessions Maximum number of concurrent sessions that the service will accept.
199  * @return Result code.
200  */
201 Result smRegisterService(Handle* handle_out, const char* name, bool is_light, int max_sessions);
202 
203 /**
204  * @brief Unregisters a previously registered service in SM.
205  * @param[in] name Name of the service.
206  * @return Result code.
207  */
208 Result smUnregisterService(const char* name);
209 
210 /**
211  * @brief Check whether SM is initialized.
212  * @return true if initialized.
213  */
214 bool smHasInitialized(void);
215 
216 /**
217  * @brief Encodes a service name as a 64-bit integer.
218  * @param[in] name Name of the service.
219  * @return Encoded name.
220  */
221 u64 smEncodeName(const char* name);
222 
223 /**
224  * @brief Overrides a service with a custom IPC service handle.
225  * @param[in] name Name of the service (as 64-bit integer).
226  * @param[in] handle IPC session handle.
227  */
228 void smAddOverrideHandle(u64 name, Handle handle);
static bool serviceIsDomainSubservice(Service *s)
Returns whether a service is a domain subservice.
Definition: sm.h:61
static bool serviceIsOverride(Service *s)
Returns whether a service is overriden in the homebrew environment.
Definition: sm.h:34
Normal service.
Definition: sm.h:16
Domain.
Definition: sm.h:17
void smAddOverrideHandle(u64 name, Handle handle)
Overrides a service with a custom IPC service handle.
static bool serviceIsActive(Service *s)
Returns whether a service has been initialized.
Definition: sm.h:43
static Result serviceConvertToDomain(Service *s)
Converts a regular service to a domain.
Definition: sm.h:121
static Result ipcCloseObjectById(Handle session, u32 object_id)
Closes a domain object by ID.
Definition: ipc.h:634
u32 Handle
Kernel object handle.
Definition: types.h:45
static void serviceClose(Service *s)
Closes a service.
Definition: sm.h:132
Service object structure.
Definition: sm.h:23
u32 Result
Function error code result type.
Definition: types.h:46
Result smUnregisterService(const char *name)
Unregisters a previously registered service in SM.
static Result ipcCloseSession(Handle session)
Closes the IPC session with proper clean up.
Definition: ipc.h:515
Domain subservice;.
Definition: sm.h:18
uint64_t u64
64-bit unsigned integer.
Definition: types.h:24
#define IPC_INVALID_OBJECT_ID
IPC invalid object ID.
Definition: ipc.h:18
uint32_t u32
32-bit unsigned integer.
Definition: types.h:23
static void serviceCreate(Service *s, Handle h)
Creates a service object from an IPC session handle.
Definition: sm.h:98
void smExit(void)
Uninitializes SM.
Uninitialized service.
Definition: sm.h:15
static Result ipcDispatch(Handle session)
Dispatches an IPC request.
Definition: ipc.h:331
Result smInitialize(void)
Initializes SM.
ServiceType
Service type.
Definition: sm.h:14
Service overriden in the homebrew environment.
Definition: sm.h:19
Result smGetService(Service *service_out, const char *name)
Requests a service from SM.
static void serviceCreateDomainSubservice(Service *s, Service *parent, u32 object_id)
Creates a domain subservice object from a parent service.
Definition: sm.h:110
u64 smEncodeName(const char *name)
Encodes a service name as a 64-bit integer.
static Result serviceCloseObjectById(Service *s, u32 object_id)
Closes a domain object by ID.
Definition: sm.h:80
#define R_SUCCEEDED(res)
Checks whether a result code indicates success.
Definition: result.h:10
Result smGetServiceOriginal(Handle *handle_out, u64 name)
Requests a service from SM, as an IPC session handle directly.
static Result serviceIpcDispatch(Service *s)
Dispatches an IPC request to a service.
Definition: sm.h:89
Handle smGetServiceOverride(u64 name)
Retrieves an overriden service in the homebrew environment.
Result smRegisterService(Handle *handle_out, const char *name, bool is_light, int max_sessions)
Creates and registers a new service within SM.
Result svcCloseHandle(Handle handle)
Closes a handle, decrementing the reference count of the corresponding kernel object.
static u32 serviceGetObjectId(Service *s)
For a domain/domain subservice, return the associated object ID.
Definition: sm.h:70
bool smHasInitialized(void)
Check whether SM is initialized.
static Result ipcConvertSessionToDomain(Handle session, u32 *object_id_out)
Converts an IPC session handle into a domain.
Definition: ipc.h:531
static bool serviceIsDomain(Service *s)
Returns whether a service is a domain.
Definition: sm.h:52