87b4c0c272b5369b24a833f5cb1f9d7ac9942c91
[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 "hal-api-conf.h"
29
30 #include "common.h"
31
32 static enum hal_abi_version _platform_abi_version = HAL_ABI_VERSION_END;
33
34 static json_object *_json_file_object = NULL;
35
36 static GHashTable *_module_hash = NULL;
37
38 static int _usage_count = 0;
39
40 static enum hal_abi_version __convert_abi_version_str_to_enum(const char *abi_version) {
41         int version;
42         for (version = HAL_ABI_VERSION_UNKNOWN + 1; version < HAL_ABI_VERSION_END; version++){
43                 if (g_strcmp0(abi_version, hal_abi_version_str[version]) == 0)
44                         return (enum hal_abi_version)version;
45         }
46
47         return HAL_ABI_VERSION_UNKNOWN;
48 }
49
50 static const char *__convert_module_to_string(enum hal_module module)
51 {
52         return hal_module_string[module];
53 }
54
55 static enum hal_group __convert_group_str_to_enum(const char * group)
56 {
57         enum hal_group group_idx;
58
59         for (group_idx = HAL_GROUP_UNKNOWN + 1; group_idx < HAL_GROUP_END; group_idx++) {
60                 if (g_strcmp0(group, hal_group_string[group_idx]) == 0)
61                         return group_idx;
62         }
63
64         return HAL_GROUP_UNKNOWN;
65 }
66
67 static enum hal_license __convert_license_str_to_enum(const char *license)
68 {
69         if (g_strcmp0(license, "APACHE_2_0") == 0)
70                 return HAL_LICENSE_APACHE_2_0;
71
72         if (g_strcmp0(license, "FLORA") == 0)
73                 return HAL_LICENSE_FLORA;
74
75         if (g_strcmp0(license, "MIT") == 0)
76                 return HAL_LICENSE_MIT;
77
78         return HAL_LICENSE_UNKNOWN;
79 }
80
81 __attribute__ ((visibility("default")))
82 void _destroy_module_info(gpointer data)
83 {
84 #define SAFE_FREE_AND_NULL(x) \
85 do { \
86         if (x) { \
87                 free(x); \
88                 x = NULL; \
89         } \
90 } while (0);
91
92         struct __hal_module_info *info = (struct __hal_module_info *)data;
93
94         if (info) {
95                 SAFE_FREE_AND_NULL(info->module_name);
96                 SAFE_FREE_AND_NULL(info->library_name);
97                 SAFE_FREE_AND_NULL(info->library_name_64bit);
98                 SAFE_FREE_AND_NULL(info->symbol_name);
99                 SAFE_FREE_AND_NULL(info->abi_versions);
100                 SAFE_FREE_AND_NULL(info);
101         }
102 }
103
104 static const char * __get_json_object_string(json_object *object, const char *key)
105 {
106         json_object *temp_object = NULL;
107
108         json_object_object_get_ex(object, key, &temp_object);
109         return json_object_get_string(temp_object);
110 }
111
112 static struct __hal_module_info *__create_hal_module_info(enum hal_module module, json_object *object)
113 {
114         struct __hal_module_info *info;
115         GList *abi_list = NULL;
116         GList *iter_list = NULL;
117         int list_index = 0;
118         json_object *abi_versions_array;
119         json_object *tmp_object;
120         const char *tmp;
121
122         info = (struct __hal_module_info *)calloc(1, sizeof(struct __hal_module_info));
123         if (info == NULL) {
124                 _E("Out of Memory\n");
125                 return NULL;
126         }
127
128         info->module = module;
129         info->module_name = g_strdup(__convert_module_to_string(module));
130
131         tmp = __get_json_object_string(object, "group");
132         info->group = __convert_group_str_to_enum(tmp);
133
134         tmp = __get_json_object_string(object, "license");
135         info->license = __convert_license_str_to_enum(tmp);
136
137         info->library_name = g_strdup(__get_json_object_string(object, "library_name"));
138         info->library_name_64bit = g_strdup(__get_json_object_string(object, "library_name_64bit"));
139         info->symbol_name = g_strdup(__get_json_object_string(object, "symbol_name"));
140
141         if (info->library_name && info->library_name_64bit && info->symbol_name)
142                 info->hal_api = true;
143
144         json_object_object_get_ex(object, "abi_versions", &abi_versions_array);
145         if (json_object_get_type(abi_versions_array) != json_type_array)
146                 return info;
147
148         info->num_abi_versions = json_object_array_length(abi_versions_array);
149         if (info->num_abi_versions > 0) {
150                 info->abi_versions = (struct hal_abi_version_match*)calloc(info->num_abi_versions,
151                                 sizeof(struct hal_abi_version_match));
152                 if (info->abi_versions == NULL) {
153                         _E("Out of Memory\n");
154                         _destroy_module_info(info);
155                         return NULL;
156                 }
157
158                 for (int i = 0; i < info->num_abi_versions; i++) {
159                         json_object *abi_object = json_object_array_get_idx(abi_versions_array, i);
160
161                         tmp = __get_json_object_string(abi_object, "platform_abi_version");
162                         info->abi_versions[list_index].platform_abi_version =
163                                 __convert_abi_version_str_to_enum(tmp);
164
165                         tmp = __get_json_object_string(abi_object, "backend_min_abi_version");
166                         info->abi_versions[list_index].backend_min_abi_version =
167                                 __convert_abi_version_str_to_enum(tmp);
168                         list_index++;
169                 }
170         }
171
172         return info;
173 }
174
175 static struct __hal_module_info* _get_module_info(enum hal_module module)
176 {
177         struct __hal_module_info *info = NULL;
178         json_object *module_array_object = NULL;
179         const char *group_name = NULL;
180         const char *module_name = NULL;
181         int i;
182
183         if (!_json_file_object || !_module_hash)
184                 return NULL;
185
186         info = (struct __hal_module_info*)g_hash_table_lookup(_module_hash, GINT_TO_POINTER(module));
187         if (info != NULL)
188                 return info;
189
190         json_object_object_get_ex(_json_file_object, "MODULE_INFO", &module_array_object);
191         module_name = __convert_module_to_string(module);
192
193         for (i = 0; i < json_object_array_length(module_array_object); i++) {
194                 json_object *temp_object = json_object_array_get_idx(module_array_object, i);
195                 const char *value = __get_json_object_string(temp_object, "module");
196                 if (g_strcmp0(value, module_name) == 0) {
197                         info = __create_hal_module_info(module, temp_object);
198                         if (info == NULL)
199                                 _E("Failed to create hal module info\n");
200                         else
201                                 g_hash_table_insert(_module_hash, GINT_TO_POINTER(module), info);
202                         break;
203                 }
204         }
205
206         return info;
207 }
208
209 static struct __hal_module_info* _get_module_info_with_library_name(enum hal_module module,
210                                                                 const char *library_name)
211 {
212         struct __hal_module_info *info = NULL, *new_info = NULL;
213         json_object *module_array_object = NULL;
214         const char *group_name = NULL;
215         const char *module_name = NULL;
216         int ret;
217
218         if (!_json_file_object || !_module_hash | !library_name)
219                 return NULL;
220
221         if (!g_str_has_prefix(library_name, "libhal-backend-")) {
222                 _E("Invalid library name(%s) of HAL module(%d)\n",
223                                 library_name, module);
224                 return NULL;
225         }
226
227         /* Find module info with the passed library name */
228         info = (struct __hal_module_info*)g_hash_table_lookup(_module_hash,
229                                                 (gpointer)library_name);
230         if (info)
231                 return info;
232
233         /* Create new module info with the passed library name */
234         info = _get_module_info(module);
235         if (info == NULL) {
236                 _E("Failed to get HAL module(%d) information\n", module);
237                 return NULL;
238         }
239
240         new_info = (struct __hal_module_info *)calloc(1,
241                                         sizeof(struct __hal_module_info));
242         if (new_info == NULL) {
243                 _E("Failed to allocate the memory\n");
244                 return NULL;
245         }
246
247         new_info->usage_count = 0;
248         new_info->group = info->group;
249         new_info->module = info->module;
250         new_info->license = info->license;
251         new_info->module_name = g_strdup(info->module_name);
252 #if defined(__aarch64__)
253         new_info->library_name_64bit = g_strdup_printf("/hal/lib64/%s", library_name);
254 #else
255         new_info->library_name = g_strdup_printf("/hal/lib/%s", library_name);
256 #endif
257         new_info->symbol_name = g_strdup(info->symbol_name);
258         new_info->num_abi_versions = info->num_abi_versions;
259         new_info->abi_versions = info->abi_versions;
260         new_info->hal_api = info->hal_api;
261         new_info->hal_backend_extension = true;
262
263         g_hash_table_insert(_module_hash, (gpointer)library_name, new_info);
264
265         return new_info;
266 }
267
268 __attribute__ ((visibility("default")))
269 struct __hal_module_info* _hal_api_conf_get_module_info(enum hal_module module,
270                                                         const char *library_name)
271 {
272         struct __hal_module_info *info = NULL;
273         json_object *module_array_object = NULL;
274         const char *group_name = NULL;
275         const char *module_name = NULL;
276         const char *key = NULL;
277         int i;
278
279         if (!_json_file_object || !_module_hash)
280                 return NULL;
281
282         if (!library_name)
283                 return _get_module_info(module);
284         else
285                 return _get_module_info_with_library_name(module, library_name);
286 }
287
288
289 enum hal_abi_version _hal_api_conf_get_platform_abi_version(void)
290 {
291         const char *abi_version = NULL;
292         bool ret_initialized;
293         json_object *platform_obj = NULL;
294
295         if (_platform_abi_version != HAL_ABI_VERSION_END)
296                 return _platform_abi_version;
297
298         if (!_json_file_object || !_module_hash)
299                 return HAL_ABI_VERSION_UNKNOWN;
300
301         abi_version = __get_json_object_string(_json_file_object, "PLATFORM_ABI_VERSION");
302         _platform_abi_version = __convert_abi_version_str_to_enum(abi_version);
303
304         return _platform_abi_version;
305 }
306
307 __attribute__ ((visibility("default")))
308 int _hal_api_conf_init(void)
309 {
310         if (_usage_count++ > 0)
311                 return 0;
312
313         _json_file_object = json_object_from_file(HAL_CONFIGURATION_PATH);
314         if (_json_file_object == NULL) {
315                 _E("Failed to parsing json configuration file : %s\n", json_util_get_last_err());
316                 goto err;
317         }
318
319         _module_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _destroy_module_info);
320
321         return 0;
322
323 err:
324         _usage_count--;
325
326         if (_module_hash) {
327                 g_hash_table_remove_all(_module_hash);
328                 g_hash_table_unref(_module_hash);
329         }
330
331         return -EINVAL;
332 }
333
334 __attribute__ ((visibility("default")))
335 void _hal_api_conf_exit(void)
336 {
337         _usage_count--;
338         if (_usage_count != 0)
339                 return;
340
341         if (_json_file_object) {
342                 json_object_put(_json_file_object);
343                 _json_file_object = NULL;
344         }
345
346         if (_module_hash) {
347                 g_hash_table_remove_all(_module_hash);
348                 g_hash_table_unref(_module_hash);
349         }
350 }