halapi: Add new backend_module_name information
[platform/hal/api/common.git] / src / hal-api-conf.c
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdlib.h>
18
19 #include <gio/gio.h>
20 #include <glib-object.h>
21
22 #include <json-c/json.h>
23 #include <json-c/arraylist.h>
24
25 #include "hal-common.h"
26 #include "hal-common-interface.h"
27
28 #include "common.h"
29 #include "hal-api-conf.h"
30 #include "hal-api-list.h"
31
32 #ifdef HAL_API_CONF_JSON
33 static enum hal_abi_version _platform_abi_version = HAL_ABI_VERSION_END;
34
35 static json_object *_json_file_object = NULL;
36 #endif
37
38 static GHashTable *_module_hash = NULL;
39
40 static int _usage_count = 0;
41
42 __attribute__ ((visibility("default")))
43 void _destroy_module_info(gpointer data)
44 {
45 #define SAFE_FREE_AND_NULL(x) \
46 do { \
47         if (x) { \
48                 free(x); \
49                 x = NULL; \
50         } \
51 } while (0);
52
53         struct __hal_module_info *info = (struct __hal_module_info *)data;
54
55         if (info) {
56                 SAFE_FREE_AND_NULL(info->module_name);
57                 SAFE_FREE_AND_NULL(info->backend_module_name);
58                 SAFE_FREE_AND_NULL(info->library_name);
59                 SAFE_FREE_AND_NULL(info->library_name_64bit);
60                 SAFE_FREE_AND_NULL(info->symbol_name);
61                 SAFE_FREE_AND_NULL(info->abi_versions);
62                 SAFE_FREE_AND_NULL(info);
63         }
64 }
65
66 #ifdef HAL_API_CONF_JSON
67 static enum hal_abi_version __convert_abi_version_str_to_enum(const char *abi_version) {
68         int version;
69         for (version = HAL_ABI_VERSION_UNKNOWN + 1; version < HAL_ABI_VERSION_END; version++){
70                 if (g_strcmp0(abi_version, hal_abi_version_str[version]) == 0)
71                         return (enum hal_abi_version)version;
72         }
73
74         return HAL_ABI_VERSION_UNKNOWN;
75 }
76
77 static const char *__convert_module_to_string(enum hal_module module)
78 {
79         return hal_module_string[module];
80 }
81
82 static enum hal_group __convert_group_str_to_enum(const char * group)
83 {
84         enum hal_group group_idx;
85
86         for (group_idx = HAL_GROUP_UNKNOWN + 1; group_idx < HAL_GROUP_END; group_idx++) {
87                 if (g_strcmp0(group, hal_group_string[group_idx]) == 0)
88                         return group_idx;
89         }
90
91         return HAL_GROUP_UNKNOWN;
92 }
93
94 static enum hal_license __convert_license_str_to_enum(const char *license)
95 {
96         if (g_strcmp0(license, "APACHE_2_0") == 0)
97                 return HAL_LICENSE_APACHE_2_0;
98
99         if (g_strcmp0(license, "FLORA") == 0)
100                 return HAL_LICENSE_FLORA;
101
102         if (g_strcmp0(license, "MIT") == 0)
103                 return HAL_LICENSE_MIT;
104
105         return HAL_LICENSE_UNKNOWN;
106 }
107
108 static const char * __get_json_object_string(json_object *object, const char *key)
109 {
110         json_object *temp_object = NULL;
111
112         json_object_object_get_ex(object, key, &temp_object);
113         return json_object_get_string(temp_object);
114 }
115
116 static struct __hal_module_info *__create_hal_module_info(enum hal_module module, json_object *object)
117 {
118         struct __hal_module_info *info;
119         GList *abi_list = NULL;
120         GList *iter_list = NULL;
121         int list_index = 0;
122         json_object *abi_versions_array;
123         json_object *tmp_object;
124         const char *tmp;
125
126         info = (struct __hal_module_info *)calloc(1, sizeof(struct __hal_module_info));
127         if (info == NULL) {
128                 _E("Out of Memory\n");
129                 return NULL;
130         }
131
132         info->module = module;
133         info->module_name = g_strdup(__convert_module_to_string(module));
134         info->backend_module_name = g_strdup(__convert_module_to_string(backend_module));
135
136         tmp = __get_json_object_string(object, "group");
137         info->group = __convert_group_str_to_enum(tmp);
138
139         tmp = __get_json_object_string(object, "license");
140         info->license = __convert_license_str_to_enum(tmp);
141
142         info->library_name = g_strdup(__get_json_object_string(object, "library_name"));
143         info->library_name_64bit = g_strdup(__get_json_object_string(object, "library_name_64bit"));
144         info->symbol_name = g_strdup(__get_json_object_string(object, "symbol_name"));
145
146         if (info->library_name && info->library_name_64bit && info->symbol_name)
147                 info->hal_api = true;
148
149         json_object_object_get_ex(object, "abi_versions", &abi_versions_array);
150         if (json_object_get_type(abi_versions_array) != json_type_array)
151                 return info;
152
153         info->num_abi_versions = json_object_array_length(abi_versions_array);
154         if (info->num_abi_versions > 0) {
155                 info->abi_versions = (struct hal_abi_version_match*)calloc(info->num_abi_versions,
156                                 sizeof(struct hal_abi_version_match));
157                 if (info->abi_versions == NULL) {
158                         _E("Out of Memory\n");
159                         _destroy_module_info(info);
160                         return NULL;
161                 }
162
163                 for (int i = 0; i < info->num_abi_versions; i++) {
164                         json_object *abi_object = json_object_array_get_idx(abi_versions_array, i);
165
166                         tmp = __get_json_object_string(abi_object, "platform_abi_version");
167                         info->abi_versions[list_index].platform_abi_version =
168                                 __convert_abi_version_str_to_enum(tmp);
169
170                         tmp = __get_json_object_string(abi_object, "backend_min_abi_version");
171                         info->abi_versions[list_index].backend_min_abi_version =
172                                 __convert_abi_version_str_to_enum(tmp);
173                         list_index++;
174                 }
175         }
176
177         return info;
178 }
179
180 static struct __hal_module_info* _get_module_info(enum hal_module module)
181 {
182         struct __hal_module_info *info = NULL;
183         json_object *module_array_object = NULL;
184         const char *group_name = NULL;
185         const char *module_name = NULL;
186         int i;
187
188         if (!_json_file_object || !_module_hash)
189                 return NULL;
190
191         info = (struct __hal_module_info*)g_hash_table_lookup(_module_hash, GINT_TO_POINTER(module));
192         if (info != NULL)
193                 return info;
194
195         json_object_object_get_ex(_json_file_object, "MODULE_INFO", &module_array_object);
196         module_name = __convert_module_to_string(module);
197
198         for (i = 0; i < json_object_array_length(module_array_object); i++) {
199                 json_object *temp_object = json_object_array_get_idx(module_array_object, i);
200                 const char *value = __get_json_object_string(temp_object, "module");
201                 if (g_strcmp0(value, module_name) == 0) {
202                         info = __create_hal_module_info(module, temp_object);
203                         if (info == NULL)
204                                 _E("Failed to create hal module info\n");
205                         else
206                                 g_hash_table_insert(_module_hash, GINT_TO_POINTER(module), info);
207                         break;
208                 }
209         }
210
211         return info;
212 }
213 #else
214 static struct __hal_module_info* _get_module_info(enum hal_module module)
215 {
216         return &g_hal_module_info[module];
217 }
218 #endif
219
220 static struct __hal_module_info* _get_module_info_with_library_name(enum hal_module module,
221                                                                 const char *library_name)
222 {
223         struct __hal_module_info *info = NULL, *new_info = NULL, *tmp_info = NULL;
224         json_object *module_array_object = NULL;
225         const char *group_name = NULL;
226         const char *module_name = NULL;
227         char *library_name_prefix = NULL;
228         int ret;
229
230 #ifdef HAL_API_CONF_JSON
231         if (!_json_file_object)
232                 return NULL;
233 #endif
234
235         if (!_module_hash | !library_name)
236                 return NULL;
237
238         tmp_info = _get_module_info(module);
239         if (tmp_info == NULL) {
240                 _E("Failed to get HAL module(%d) information\n", module);
241                 return NULL;
242         }
243
244         if (tmp_info->backend_module_name == NULL) {
245                 _E("Don't support HAL backend of HAL module(%s)\n",
246                                 tmp_info->module_name);
247                 return NULL;
248         }
249         library_name_prefix = g_strdup_printf("libhal-backend-%s",
250                                 tmp_info->backend_module_name);
251         if (!library_name_prefix) {
252                 _E("Failed to allocate library_name_prefix of HAL module(%s)\n",
253                                 tmp_info->module_name);
254                 return NULL;
255         }
256
257         if (!g_str_has_prefix(library_name, library_name_prefix)) {
258                 _E("Invalid library name(%s) of HAL module(%s)\n",
259                                 library_name, tmp_info->module_name);
260                 goto out;
261         }
262
263         /* Find module info with the passed library name */
264         info = (struct __hal_module_info*)g_hash_table_lookup(_module_hash,
265                                                 (gpointer)library_name);
266         if (info) {
267                 g_free(library_name_prefix);
268                 return info;
269         }
270
271         /* Create new module info with the passed library name */
272         info = tmp_info;
273
274         new_info = (struct __hal_module_info *)calloc(1,
275                                         sizeof(struct __hal_module_info));
276         if (new_info == NULL) {
277                 _E("Failed to allocate the memory\n");
278                 goto out;
279         }
280
281         new_info->usage_count = 0;
282         new_info->group = info->group;
283         new_info->module = info->module;
284         new_info->license = info->license;
285         new_info->module_name = g_strdup(info->module_name);
286 #if defined(__aarch64__)
287         new_info->library_name_64bit = g_strdup_printf("/hal/lib64/%s", library_name);
288 #else
289         new_info->library_name = g_strdup_printf("/hal/lib/%s", library_name);
290 #endif
291         new_info->symbol_name = g_strdup(info->symbol_name);
292         new_info->num_abi_versions = info->num_abi_versions;
293         new_info->abi_versions = info->abi_versions;
294         new_info->hal_api = info->hal_api;
295         new_info->hal_backend_extension = true;
296
297         g_hash_table_insert(_module_hash, (gpointer)library_name, new_info);
298
299 out:
300         g_free(library_name_prefix);
301
302         return new_info;
303 }
304
305 __attribute__ ((visibility("default")))
306 struct __hal_module_info* _hal_api_conf_get_module_info(enum hal_module module,
307                                                         const char *library_name)
308 {
309 #ifdef HAL_API_CONF_JSON
310         if (!_json_file_object)
311                 return NULL;
312 #endif
313
314         if (!_module_hash)
315                 return NULL;
316
317         if (!library_name)
318                 return _get_module_info(module);
319         else
320                 return _get_module_info_with_library_name(module, library_name);
321 }
322
323
324 enum hal_abi_version _hal_api_conf_get_platform_abi_version(void)
325 {
326 #ifdef HAL_API_CONF_JSON
327         const char *abi_version = NULL;
328         bool ret_initialized;
329         json_object *platform_obj = NULL;
330
331         if (_platform_abi_version != HAL_ABI_VERSION_END)
332                 return _platform_abi_version;
333
334         if (!_json_file_object || !_module_hash)
335                 return HAL_ABI_VERSION_UNKNOWN;
336
337         abi_version = __get_json_object_string(_json_file_object, "PLATFORM_ABI_VERSION");
338         _platform_abi_version = __convert_abi_version_str_to_enum(abi_version);
339
340         return _platform_abi_version;
341 #else
342         return g_platform_curr_abi_version;
343 #endif
344 }
345
346 __attribute__ ((visibility("default")))
347 int _hal_api_conf_init(void)
348 {
349         if (_usage_count++ > 0)
350                 return 0;
351
352 #ifdef HAL_API_CONF_JSON
353         _json_file_object = json_object_from_file(HAL_CONFIGURATION_PATH);
354         if (_json_file_object == NULL) {
355                 _E("Failed to parsing json configuration file : %s\n", json_util_get_last_err());
356                 goto err;
357         }
358 #endif
359
360         _module_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _destroy_module_info);
361
362         return 0;
363
364 #ifdef HAL_API_CONF_JSON
365 err:
366         _usage_count--;
367
368         if (_module_hash) {
369                 g_hash_table_remove_all(_module_hash);
370                 g_hash_table_unref(_module_hash);
371         }
372
373         return -EINVAL;
374 #endif
375 }
376
377 __attribute__ ((visibility("default")))
378 void _hal_api_conf_exit(void)
379 {
380         _usage_count--;
381         if (_usage_count != 0)
382                 return;
383
384 #ifdef HAL_API_CONF_JSON
385         if (_json_file_object) {
386                 json_object_put(_json_file_object);
387                 _json_file_object = NULL;
388         }
389 #endif
390
391         if (_module_hash) {
392                 g_hash_table_remove_all(_module_hash);
393                 g_hash_table_unref(_module_hash);
394         }
395 }