4 * Copyright (c) 2020 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
29 #include <glib-object.h>
32 #include "hal-api-conf.h"
34 extern char *program_invocation_name;
37 #define EXPORT __attribute__ ((visibility("default")))
40 static enum hal_abi_version g_platform_curr_abi_version;
41 G_LOCK_DEFINE_STATIC(hal_common_lock);
44 int hal_common_get_backend_library_name(enum hal_module module, char *name, int size)
46 const char *library_name = NULL;
47 struct __hal_module_info *info = NULL;
51 /* Check parameter whether is valid or not */
52 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
53 _E("Invalid parameter of HAL module (%d)\n", module);
57 if (_hal_api_conf_init())
60 info = _hal_api_conf_get_module_info(module, NULL);
62 _E("Failed to get HAL module(%d) information\n", module);
67 library_name = get_backend_library_name(info);
69 _E("%s backend library name is NULL\n", info->module_name);
74 len_library_name = strlen(library_name);
75 if (!name || (len_library_name + 1 > size)) {
80 strncpy(name, library_name, len_library_name);
81 name[len_library_name] = '\0';
91 int hal_common_get_backend_symbol_name(enum hal_module module, char *name, int size)
93 struct __hal_module_info *info = NULL;
94 char *symbol_name = NULL;
98 /* Check parameter whether is valid or not */
99 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
100 _E("Invalid paramer of HAL module (%d)\n", module);
104 if (_hal_api_conf_init())
107 info = _hal_api_conf_get_module_info(module, NULL);
109 _E("Failed to get HAL module(%d) information\n", module);
113 symbol_name = info->symbol_name;
115 _E("%s backend symbol name is NULL\n", info->module_name);
120 len_symbol_name = strlen(symbol_name);
121 if (!name || (len_symbol_name + 1 > size)) {
126 strncpy(name, symbol_name, len_symbol_name);
127 name[len_symbol_name] = '\0';
131 _hal_api_conf_exit();
136 static int __open_backend(struct __hal_module_info *info)
138 const char *backend_library_name = NULL;
141 if (info->backend && info->handle)
144 backend_library_name = get_backend_library_name(info);
145 if (!backend_library_name) {
146 _E("%s: Failed to get backend library name\n",
150 } else if (access(backend_library_name, F_OK) == -1) {
151 _I("%s: There is no backend library\n",
157 if (!info->symbol_name) {
158 _E("%s: Failed to get backend symbol name\n",
164 info->handle = dlopen(backend_library_name, RTLD_LAZY);
166 _E("%s: Failed to load backend library (%s)\n",
167 info->module_name, dlerror());
172 info->backend = dlsym(info->handle, info->symbol_name);
173 if (!info->backend) {
174 _E("%s: Failed to find backend data (%s)\n",
175 info->module_name, dlerror());
180 _I("%s: Open HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
181 info->module_name, info->backend->name, info->backend->vendor,
182 backend_library_name, info->usage_count,
183 program_invocation_name);
188 dlclose(info->handle);
190 info->backend = NULL;
196 static void __close_backend(struct __hal_module_info *info)
198 if (!info->backend || !info->handle)
201 _I("%s: Close HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
202 info->module_name, info->backend->name, info->backend->vendor,
203 get_backend_library_name(info), info->usage_count,
204 program_invocation_name);
207 dlclose(info->handle);
209 info->backend = NULL;
213 static int __init_backend(struct __hal_module_info *info, void **data,
214 const char *library_name)
218 if (!info->handle || !info->backend) {
219 _I("%s: Has not yet dlopend backend\n", info->module_name);
223 if (!info->backend->init) {
224 _E("%s: hal_backend->init() is NULL\n", info->module_name);
228 /* Check HAL ABI Version */
229 ret = hal_common_check_backend_abi_version(info->module,
230 info->backend->abi_version);
232 _E("%s: Failed to check ABI version\n", info->module_name);
236 /* Initialize backend */
237 ret = info->backend->init(data);
239 _E("%s: Failed to initialize backend: name(%s)/vendor(%s)\n",
240 info->module_name, info->backend->name,
241 info->backend->vendor);
248 static int __exit_backend(struct __hal_module_info *info, void *data,
249 const char *library_name)
253 if (!info->handle || !info->backend) {
254 _I("%s: Has not yet dlopend backend\n", info->module_name);
259 if (info->backend->exit) {
260 ret = info->backend->exit(data);
262 _E("%s: Failed to exit backend: name(%s)/vendor(%s)\n",
263 info->module_name, info->backend->name,
264 info->backend->vendor);
272 static int __get_backend(enum hal_module module, void **data,
273 const char *library_name)
275 struct __hal_module_info *info = NULL;
278 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
279 _E("Invalid parameter of HAL module (%d)\n", module);
283 G_LOCK(hal_common_lock);
284 if (_hal_api_conf_init()) {
289 info = _hal_api_conf_get_module_info(module, library_name);
292 _E("Failed to get HAL module(%d) information\n", module);
294 _E("Failed to get HAL module(%d) information (%s)\n",
295 module, library_name);
300 ret = __open_backend(info);
304 ret = __init_backend(info, data, NULL);
306 _E("%s: Failed to initialize the backend library\n",
314 _I("%s: Get HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
315 info->module_name, info->backend->name, info->backend->vendor,
316 get_backend_library_name(info), info->usage_count,
317 program_invocation_name);
319 G_UNLOCK(hal_common_lock);
323 __close_backend(info);
324 _hal_api_conf_exit();
326 G_UNLOCK(hal_common_lock);
330 static int __put_backend(enum hal_module module, void *data,
331 const char *library_name)
333 struct __hal_module_info *info = NULL;
336 /* Check parameter whether is valid or not */
337 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
338 _E("Invalid parameter of HAL module (%d)\n", module);
342 G_LOCK(hal_common_lock);
344 info = _hal_api_conf_get_module_info(module, library_name);
346 _E("Failed to get HAL module(%d) information\n", module);
351 if (!info->handle || !info->backend) {
352 _I("%s: Has not yet dlopend backend\n", info->module_name);
357 if (!info->usage_count) {
358 _I("%s: Already fully put for HAL module\n", info->module_name);
363 ret = __exit_backend(info, data, NULL);
365 _E("%s: Failed to exit the backend library\n",
373 _I("%s: Put HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
374 info->module_name, info->backend->name, info->backend->vendor,
375 get_backend_library_name(info), info->usage_count,
376 program_invocation_name);
378 if (info->usage_count > 0) {
383 __close_backend(info);
384 _hal_api_conf_exit();
389 G_UNLOCK(hal_common_lock);
393 static int __get_backend_data(enum hal_module module, unsigned int *abi_version,
394 char *name, int name_size, char *vendor, int vendor_size)
396 struct __hal_module_info *info = NULL;
399 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
400 _E("Invalid parameter of HAL module (%d)\n", module);
404 G_LOCK(hal_common_lock);
406 if (_hal_api_conf_init()) {
407 ret = HAL_ABI_VERSION_UNKNOWN;
411 info = _hal_api_conf_get_module_info(module, NULL);
413 _E("Failed to get HAL module(%d) information\n", module);
414 ret = HAL_ABI_VERSION_UNKNOWN;
418 ret = __open_backend(info);
422 /* Return abi_verion of hal_backend structure */
423 if (!name_size && !vendor_size) {
424 *abi_version = info->backend->abi_version;
426 /* Return name of hal_backend structure */
427 } else if (info->backend->name && name_size && !vendor_size) {
428 len = strlen(info->backend->name);
430 if (!info->backend->name || (len + 1 > name_size)) {
431 _E("%s: Invalid size of name[] array\n", info->module_name);
433 goto err_close_backend;
436 strncpy(name, info->backend->name, len);
439 /* Return vendor of hal_backend structure */
440 } else if (info->backend->vendor && !name_size && vendor_size) {
441 len = strlen(info->backend->vendor);
443 if (!info->backend->vendor || (len + 1 > vendor_size)) {
444 _E("%s: Invalid size of vendor[] array\n", info->module_name);
446 goto err_close_backend;
449 strncpy(vendor, info->backend->vendor, len);
452 _E("%s: Failed to get backend data\n", info->module_name);
454 goto err_close_backend;
459 __close_backend(info);
461 _hal_api_conf_exit();
463 G_UNLOCK(hal_common_lock);
468 int hal_common_get_backend(enum hal_module module, void **data)
470 return __get_backend(module, data, NULL);
474 int hal_common_put_backend(enum hal_module module, void *data)
476 return __put_backend(module, data, NULL);
480 int hal_common_get_backend_with_library_name(enum hal_module module,
481 void **data, const char *library_name)
483 return __get_backend(module, data, library_name);
487 int hal_common_put_backend_with_library_name(enum hal_module module,
488 void *data, const char *library_name)
490 return __put_backend(module, data, library_name);
494 int hal_common_check_backend_abi_version(enum hal_module module,
495 enum hal_abi_version abi_version)
497 struct __hal_module_info *info = NULL;
501 /* Check parameter whether is valid or not */
502 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
503 _E("Invalid paramer of HAL module(%d)\n", module);
507 if (abi_version <= HAL_ABI_VERSION_UNKNOWN
508 || abi_version >= HAL_ABI_VERSION_END) {
509 _E("Invalid paramer of HAL ABI version(%d) for HAL module(%d)\n",
510 abi_version, module);
514 if (_hal_api_conf_init())
517 info = _hal_api_conf_get_module_info(module, NULL);
519 _E("Failed to get HAL module(%d) information\n", module);
524 /* Check abi_version whether is supported or not */
525 if (!info->hal_api) {
526 _E("%s: Doesn't support HAL API\n", info->module_name);
531 if (!info->num_abi_versions
532 || !info->abi_versions) {
533 _E("%s: Doesn't have the ABI version information\n",
539 g_platform_curr_abi_version = _hal_api_conf_get_platform_abi_version();
541 if (g_platform_curr_abi_version <= HAL_ABI_VERSION_UNKNOWN
542 || g_platform_curr_abi_version >= HAL_ABI_VERSION_END) {
543 _E("Invalid paramer of current HAL ABI version(%d)(%d)\n",
544 g_platform_curr_abi_version, module);
549 for (i = 0; i < info->num_abi_versions; i++) {
550 struct hal_abi_version_match *data
551 = &info->abi_versions[i];
553 if (g_platform_curr_abi_version != data->platform_abi_version)
556 if (data->backend_min_abi_version <= HAL_ABI_VERSION_UNKNOWN ||
557 data->backend_min_abi_version >= HAL_ABI_VERSION_END) {
558 _E("%s: abi_versions[%d].backend_min_abi_version(%d) is invalid\n",
559 info->module_name, i, data->backend_min_abi_version);
564 if (abi_version <= data->platform_abi_version
565 && abi_version >= data->backend_min_abi_version) {
570 _E("%s: \'%s\' doesn't support \'%s\'\n",
572 hal_abi_version_str[g_platform_curr_abi_version],
573 hal_abi_version_str[abi_version]);
574 _E("%s: Must use ABI versions from \'%s\' to \'%s\'\n",
576 hal_abi_version_str[data->backend_min_abi_version],
577 hal_abi_version_str[data->platform_abi_version]);
582 _hal_api_conf_exit();
587 unsigned int hal_common_get_backend_abi_version(enum hal_module module)
589 unsigned int abi_version;
592 ret = __get_backend_data(module, &abi_version, NULL, 0, NULL, 0);
594 return HAL_ABI_VERSION_UNKNOWN;
600 int hal_common_get_backend_name(enum hal_module module, char *name, int size)
602 return __get_backend_data(module, NULL, name, size, NULL, 0);
606 int hal_common_get_backend_vendor(enum hal_module module, char *vendor, int size)
608 return __get_backend_data(module, NULL, NULL, 0, vendor, size);
612 static int __get_backend_library_data(enum hal_module module,
617 struct __hal_module_info *info = NULL;
620 char *backend_module_name = NULL;
621 int count, i, ret, len;
622 #if defined(__aarch64__) || defined(__x86_64__)
623 const char hal_backend_path[] = "/hal/lib64";
625 const char hal_backend_path[] = "/hal/lib";
628 /* Check parameter whether is valid or not */
629 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
630 _E("Invalid parameter of HAL module (%d)\n", module);
634 if (_hal_api_conf_init())
637 info = _hal_api_conf_get_module_info(module, NULL);
639 _E("Failed to get HAL module(%d) information\n", module);
644 if (info->backend_module_name == NULL) {
645 _E("Don't support HAL backend of HAL module(%s)\n",
650 backend_module_name = g_strdup_printf("libhal-backend-%s",
651 info->backend_module_name);
652 if (!backend_module_name) {
653 _E("Failed to allocate the backend_module_name of HAL module(%s)\n",
659 /* Find HAL backend libraries */
660 dir = opendir(hal_backend_path);
662 _E("Failed to find HAL backend path(%s) for HAL module(%s)\n",
663 hal_backend_path, info->module_name);
665 goto err_free_backend_module_name;
669 while ((de = readdir(dir)) != NULL) {
670 if (!g_str_has_prefix(de->d_name, backend_module_name))
675 else if (lib_count > 0) {
676 len = strlen(de->d_name) + 1;
678 if (len > lib_name_size)
681 strncpy(lib_names[count++], de->d_name, len);
685 if (lib_count > 0 && count != lib_count) {
687 goto err_mismatch_count;
691 _hal_api_conf_exit();
692 g_free(backend_module_name);
697 for (i = count - 1; i >= 0; i--)
698 memset(lib_names[i], 0, strlen(lib_names[i]));
701 err_free_backend_module_name:
702 g_free(backend_module_name);
704 _hal_api_conf_exit();
709 int hal_common_get_backend_count(enum hal_module module)
711 return __get_backend_library_data(module, NULL, 0, 0);
715 int hal_common_get_backend_library_names(enum hal_module module,
716 char **library_names,
718 int library_name_size)
720 int ret = __get_backend_library_data(module, library_names,
721 library_count, library_name_size);
722 return (ret < 0) ? ret : 0;