Line data Source code
1 : /* SPDX-License-Identifier: Apache-2.0 */
2 : /**
3 : * Copyright (C) 2024 Samsung Electronics Co., Ltd. All Rights Reserved.
4 : *
5 : * @file nnstreamer-edge-custom-impl.c
6 : * @date 14 Aug 2024
7 : * @brief Internal interface to support communication using custom library.
8 : * @see https://github.com/nnstreamer/nnstreamer
9 : * @author Gichan Jang <gichan2.jang@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : */
12 :
13 : #include <dlfcn.h>
14 :
15 : #include "nnstreamer-edge-custom-impl.h"
16 : #include "nnstreamer-edge-log.h"
17 : #include "nnstreamer-edge-util.h"
18 :
19 : /**
20 : * @brief Internal data structure for edge custom connection.
21 : */
22 : typedef struct
23 : {
24 : void *dl_handle;
25 : nns_edge_custom_s *instance;
26 : void *priv;
27 : } custom_connection_s;
28 :
29 : typedef const nns_edge_custom_s *custom_get_instance (void);
30 :
31 : /**
32 : * @brief Internal function to load custom library.
33 : */
34 : static int
35 7 : _load_custom_library (custom_connection_s * custom, const char *lib_path)
36 : {
37 : void *handle;
38 : nns_edge_custom_s *custom_h;
39 7 : int ret = NNS_EDGE_ERROR_UNKNOWN;
40 :
41 7 : handle = dlopen (lib_path, RTLD_LAZY);
42 7 : if (NULL == handle) {
43 0 : nns_edge_loge ("Failed to open custom library: %s", dlerror ());
44 0 : goto error;
45 : }
46 :
47 7 : custom_get_instance *get_instance =
48 7 : (custom_get_instance *) dlsym (handle, "nns_edge_custom_get_instance");
49 7 : if (!get_instance) {
50 0 : nns_edge_loge ("Failed to find nns_edge_custom_get_instance: %s",
51 : dlerror ());
52 0 : goto error;
53 : }
54 :
55 7 : custom_h = (nns_edge_custom_s *) get_instance ();
56 7 : if (!custom_h) {
57 0 : nns_edge_loge ("Failed to get custom instance from library.");
58 0 : goto error;
59 : }
60 :
61 7 : custom->dl_handle = handle;
62 7 : custom->instance = custom_h;
63 7 : ret = NNS_EDGE_ERROR_NONE;
64 :
65 7 : error:
66 7 : if (NNS_EDGE_ERROR_NONE != ret) {
67 0 : if (handle)
68 0 : dlclose (handle);
69 : }
70 :
71 7 : return ret;
72 : }
73 :
74 : /**
75 : * @brief Internal function to load custom connection from library.
76 : */
77 : int
78 10 : nns_edge_custom_load (const char *lib_path,
79 : nns_edge_custom_connection_h * handle)
80 : {
81 : custom_connection_s *custom;
82 : nns_edge_custom_s *custom_h;
83 : int ret;
84 :
85 10 : if (!STR_IS_VALID (lib_path))
86 2 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
87 :
88 8 : if (!handle)
89 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
90 :
91 7 : custom = (custom_connection_s *) calloc (1, sizeof (custom_connection_s));
92 7 : if (!custom) {
93 0 : nns_edge_loge ("Failed to allocate memory for edge custom connection.");
94 0 : return NNS_EDGE_ERROR_OUT_OF_MEMORY;
95 : }
96 :
97 7 : ret = _load_custom_library (custom, lib_path);
98 7 : if (NNS_EDGE_ERROR_NONE != ret) {
99 0 : nns_edge_loge
100 : ("Failed to load custom library. Please check the library path or permission.");
101 0 : goto error;
102 : }
103 :
104 7 : custom_h = custom->instance;
105 :
106 7 : ret = custom_h->nns_edge_custom_create (&custom->priv);
107 7 : if (NNS_EDGE_ERROR_NONE != ret) {
108 0 : nns_edge_loge ("Failed to create custom connection handle.");
109 : }
110 :
111 7 : error:
112 7 : if (NNS_EDGE_ERROR_NONE == ret) {
113 7 : *handle = custom;
114 : } else {
115 0 : nns_edge_custom_release (custom);
116 : }
117 :
118 7 : return ret;
119 : }
120 :
121 : /**
122 : * @brief Internal function to release custom connection.
123 : */
124 : int
125 8 : nns_edge_custom_release (nns_edge_custom_connection_h handle)
126 : {
127 8 : custom_connection_s *custom = (custom_connection_s *) handle;
128 : nns_edge_custom_s *custom_h;
129 : int ret;
130 :
131 8 : if (!custom || !custom->instance)
132 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
133 :
134 7 : custom_h = custom->instance;
135 :
136 7 : ret = custom_h->nns_edge_custom_close (custom->priv);
137 7 : if (NNS_EDGE_ERROR_NONE != ret) {
138 0 : nns_edge_loge ("Failed to stop custom connection.");
139 : }
140 :
141 7 : if (custom->dl_handle) {
142 7 : dlclose (custom->dl_handle);
143 : }
144 :
145 7 : custom->dl_handle = NULL;
146 7 : custom->instance = NULL;
147 7 : custom->priv = NULL;
148 :
149 7 : free (custom);
150 7 : return ret;
151 : }
152 :
153 : /**
154 : * @brief Internal function to start custom connection.
155 : */
156 : int
157 2 : nns_edge_custom_start (nns_edge_custom_connection_h handle)
158 : {
159 2 : custom_connection_s *custom = (custom_connection_s *) handle;
160 : nns_edge_custom_s *custom_h;
161 : int ret;
162 :
163 2 : if (!custom || !custom->instance)
164 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
165 :
166 1 : custom_h = custom->instance;
167 :
168 1 : ret = custom_h->nns_edge_custom_start (custom->priv);
169 1 : if (NNS_EDGE_ERROR_NONE != ret) {
170 0 : nns_edge_loge ("Failed to start custom connection.");
171 : }
172 :
173 1 : return ret;
174 : }
175 :
176 : /**
177 : * @brief Internal function to stop custom connection.
178 : */
179 : int
180 2 : nns_edge_custom_stop (nns_edge_custom_connection_h handle)
181 : {
182 2 : custom_connection_s *custom = (custom_connection_s *) handle;
183 : nns_edge_custom_s *custom_h;
184 : int ret;
185 :
186 2 : if (!custom || !custom->instance)
187 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
188 :
189 1 : custom_h = custom->instance;
190 :
191 1 : ret = custom_h->nns_edge_custom_stop (custom->priv);
192 1 : if (NNS_EDGE_ERROR_NONE != ret) {
193 0 : nns_edge_loge ("Failed to stop custom connection.");
194 : }
195 :
196 1 : return ret;
197 : }
198 :
199 : /**
200 : * @brief Internal function to set the event callback of custom connection.
201 : */
202 : int
203 2 : nns_edge_custom_set_event_callback (nns_edge_custom_connection_h handle,
204 : nns_edge_event_cb cb, void *user_data)
205 : {
206 2 : custom_connection_s *custom = (custom_connection_s *) handle;
207 : nns_edge_custom_s *custom_h;
208 : int ret;
209 :
210 2 : if (!custom || !custom->instance)
211 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
212 :
213 1 : custom_h = custom->instance;
214 :
215 1 : ret = custom_h->nns_edge_custom_set_event_cb (custom->priv, cb, user_data);
216 1 : if (NNS_EDGE_ERROR_NONE != ret) {
217 0 : nns_edge_loge ("Failed to set event callback to custom connection.");
218 : }
219 :
220 1 : return ret;
221 : }
222 :
223 : /**
224 : * @brief Internal function to start discovery devices of custom connection.
225 : */
226 : int
227 2 : nns_edge_custom_start_discovery (nns_edge_custom_connection_h handle)
228 : {
229 2 : custom_connection_s *custom = (custom_connection_s *) handle;
230 : nns_edge_custom_s *custom_h;
231 : int ret;
232 :
233 2 : if (!custom || !custom->instance)
234 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
235 :
236 1 : custom_h = custom->instance;
237 :
238 1 : ret = custom_h->nns_edge_custom_start_discovery (custom->priv);
239 1 : if (NNS_EDGE_ERROR_NONE != ret) {
240 0 : nns_edge_loge ("Failed to start discovery devices of custom connection.");
241 : }
242 :
243 1 : return ret;
244 : }
245 :
246 : /**
247 : * @brief Internal function to stop discovery devices of custom connection.
248 : */
249 : int
250 2 : nns_edge_custom_stop_discovery (nns_edge_custom_connection_h handle)
251 : {
252 2 : custom_connection_s *custom = (custom_connection_s *) handle;
253 : nns_edge_custom_s *custom_h;
254 : int ret;
255 :
256 2 : if (!custom || !custom->instance)
257 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
258 :
259 1 : custom_h = custom->instance;
260 :
261 1 : ret = custom_h->nns_edge_custom_stop_discovery (custom->priv);
262 1 : if (NNS_EDGE_ERROR_NONE != ret) {
263 0 : nns_edge_loge ("Failed to stop discovery devices of custom connection.");
264 : }
265 :
266 1 : return ret;
267 : }
268 :
269 : /**
270 : * @brief Internal function to connect custom connection.
271 : */
272 : int
273 3 : nns_edge_custom_connect (nns_edge_custom_connection_h handle)
274 : {
275 3 : custom_connection_s *custom = (custom_connection_s *) handle;
276 : nns_edge_custom_s *custom_h;
277 : int ret;
278 :
279 3 : if (!custom || !custom->instance)
280 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
281 :
282 2 : custom_h = custom->instance;
283 :
284 2 : ret = custom_h->nns_edge_custom_connect (custom->priv);
285 2 : if (NNS_EDGE_ERROR_NONE != ret) {
286 0 : nns_edge_loge ("Failed to connect custom connection.");
287 : }
288 :
289 2 : return ret;
290 : }
291 :
292 : /**
293 : * @brief Internal function to disconnect custom connection.
294 : */
295 : int
296 2 : nns_edge_custom_disconnect (nns_edge_custom_connection_h handle)
297 : {
298 2 : custom_connection_s *custom = (custom_connection_s *) handle;
299 : nns_edge_custom_s *custom_h;
300 : int ret;
301 :
302 2 : if (!custom || !custom->instance)
303 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
304 :
305 1 : custom_h = custom->instance;
306 :
307 1 : ret = custom_h->nns_edge_custom_disconnect (custom->priv);
308 1 : if (NNS_EDGE_ERROR_NONE != ret) {
309 0 : nns_edge_loge ("Failed to disconnect custom connection.");
310 : }
311 :
312 1 : return ret;
313 : }
314 :
315 : /**
316 : * @brief Internal function to check custom connection.
317 : */
318 : int
319 8 : nns_edge_custom_is_connected (nns_edge_custom_connection_h handle)
320 : {
321 8 : custom_connection_s *custom = (custom_connection_s *) handle;
322 : nns_edge_custom_s *custom_h;
323 :
324 8 : if (!custom || !custom->instance)
325 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
326 :
327 7 : custom_h = custom->instance;
328 :
329 7 : return custom_h->nns_edge_custom_is_connected (custom->priv);
330 : }
331 :
332 : /**
333 : * @brief Internal function to send data to custom connection.
334 : */
335 : int
336 3 : nns_edge_custom_send_data (nns_edge_custom_connection_h handle,
337 : nns_edge_data_h data_h)
338 : {
339 3 : custom_connection_s *custom = (custom_connection_s *) handle;
340 : nns_edge_custom_s *custom_h;
341 : int ret;
342 :
343 3 : if (!custom || !custom->instance)
344 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
345 :
346 2 : ret = nns_edge_data_is_valid (data_h);
347 2 : if (NNS_EDGE_ERROR_NONE != ret)
348 1 : return ret;
349 :
350 1 : custom_h = custom->instance;
351 :
352 1 : ret = custom_h->nns_edge_custom_send_data (custom->priv, data_h);
353 1 : if (NNS_EDGE_ERROR_NONE != ret) {
354 0 : nns_edge_loge ("Failed to send data to custom connection.");
355 : }
356 :
357 1 : return ret;
358 : }
359 :
360 : /**
361 : * @brief Internal function to set information to custom connection.
362 : */
363 : int
364 6 : nns_edge_custom_set_info (nns_edge_custom_connection_h handle, const char *key,
365 : const char *value)
366 : {
367 6 : custom_connection_s *custom = (custom_connection_s *) handle;
368 : nns_edge_custom_s *custom_h;
369 6 : int ret = NNS_EDGE_ERROR_NOT_SUPPORTED;
370 :
371 6 : if (!custom || !custom->instance)
372 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
373 :
374 5 : if (!STR_IS_VALID (key) || !STR_IS_VALID (value))
375 4 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
376 :
377 1 : custom_h = custom->instance;
378 :
379 1 : if (custom_h->nns_edge_custom_set_info) {
380 1 : ret = custom_h->nns_edge_custom_set_info (custom->priv, key, value);
381 1 : if (NNS_EDGE_ERROR_NONE != ret) {
382 0 : nns_edge_loge ("Failed to set information to custom connection.");
383 : }
384 : }
385 :
386 1 : return ret;
387 : }
388 :
389 : /**
390 : * @brief Internal function to get information from custom connection.
391 : */
392 : int
393 5 : nns_edge_custom_get_info (nns_edge_custom_connection_h handle, const char *key,
394 : char **value)
395 : {
396 5 : custom_connection_s *custom = (custom_connection_s *) handle;
397 : nns_edge_custom_s *custom_h;
398 5 : int ret = NNS_EDGE_ERROR_NOT_SUPPORTED;
399 :
400 5 : if (!custom || !custom->instance)
401 1 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
402 :
403 4 : if (!STR_IS_VALID (key) || !value)
404 3 : return NNS_EDGE_ERROR_INVALID_PARAMETER;
405 :
406 1 : custom_h = custom->instance;
407 :
408 1 : if (custom_h->nns_edge_custom_get_info) {
409 1 : ret = custom_h->nns_edge_custom_get_info (custom->priv, key, value);
410 1 : if (NNS_EDGE_ERROR_NONE != ret) {
411 0 : nns_edge_loge ("Failed to get information from custom connection.");
412 : }
413 : }
414 :
415 1 : return ret;
416 : }
|