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 #define HAL_BACKEND_SYMBOL_NAME 1
41 #define HAL_BACKEND_MODULE_NAME 2
43 static enum hal_abi_version g_platform_curr_abi_version;
44 G_LOCK_DEFINE_STATIC(hal_common_lock);
47 int hal_common_get_backend_library_name(enum hal_module module, char *name, int size)
49 const char *library_name = NULL;
50 struct __hal_module_info *info = NULL;
54 /* Check parameter whether is valid or not */
55 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
56 _E("Invalid parameter of HAL module (%d)\n", module);
60 if (_hal_api_conf_init())
63 info = _hal_api_conf_get_module_info(module, NULL);
65 _E("Failed to get HAL module(%d) information\n", module);
70 library_name = get_backend_library_name(info);
72 _E("%s backend library name is NULL\n", info->module_name);
77 len_library_name = strlen(library_name);
78 if (!name || (len_library_name + 1 > size) || len_library_name == 0) {
83 strncpy(name, library_name, len_library_name);
84 name[len_library_name] = '\0';
93 static int __hal_common_get_backend_name(enum hal_module module, char *name, int size, int name_type)
95 struct __hal_module_info *info = NULL;
100 /* Check parameter whether is valid or not */
101 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
102 _E("Invalid paramer of HAL module (%d)\n", module);
106 if (_hal_api_conf_init())
109 info = _hal_api_conf_get_module_info(module, NULL);
111 _E("Failed to get HAL module(%d) information\n", module);
117 case HAL_BACKEND_SYMBOL_NAME:
118 str = info->symbol_name;
120 case HAL_BACKEND_MODULE_NAME:
121 str = info->module_name;
128 _I("%s backend name is NULL\n", info->module_name);
133 len_str = strlen(str);
134 if (!str || (len_str + 1 > size) || len_str == 0) {
139 strncpy(name, str, len_str);
140 name[len_str] = '\0';
144 _hal_api_conf_exit();
150 int hal_common_get_backend_symbol_name(enum hal_module module, char *name, int size)
152 return __hal_common_get_backend_name(module, name, size, HAL_BACKEND_SYMBOL_NAME);
156 int hal_common_get_backend_module_name(enum hal_module module, char *name, int size)
158 return __hal_common_get_backend_name(module, name, size, HAL_BACKEND_MODULE_NAME);
161 static int __open_backend(struct __hal_module_info *info)
163 const char *backend_library_name = NULL;
166 if (info->backend && info->handle)
169 backend_library_name = get_backend_library_name(info);
170 if (!backend_library_name) {
171 _E("%s: Failed to get backend library name\n",
175 } else if (access(backend_library_name, F_OK) == -1) {
176 _I("%s: There is no backend library\n",
182 if (!info->symbol_name) {
183 _E("%s: Failed to get backend symbol name\n",
189 info->handle = dlopen(backend_library_name, RTLD_LAZY);
191 _E("%s: Failed to load backend library (%s)\n",
192 info->module_name, dlerror());
197 info->backend = dlsym(info->handle, info->symbol_name);
198 if (!info->backend) {
199 _E("%s: Failed to find backend data (%s)\n",
200 info->module_name, dlerror());
205 _I("%s: Open HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
206 info->module_name, info->backend->name, info->backend->vendor,
207 backend_library_name, info->usage_count,
208 program_invocation_name);
213 dlclose(info->handle);
215 info->backend = NULL;
221 static void __close_backend(struct __hal_module_info *info)
223 if (!info->backend || !info->handle)
226 _I("%s: Close HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
227 info->module_name, info->backend->name, info->backend->vendor,
228 get_backend_library_name(info), info->usage_count,
229 program_invocation_name);
232 dlclose(info->handle);
234 info->backend = NULL;
238 static int __init_backend(struct __hal_module_info *info, void **data,
239 const char *library_name)
243 if (!info->handle || !info->backend) {
244 _I("%s: Has not yet dlopend backend\n", info->module_name);
248 if (!info->backend->init) {
249 _E("%s: hal_backend->init() is NULL\n", info->module_name);
253 /* Check HAL ABI Version */
254 ret = hal_common_check_backend_abi_version(info->module,
255 info->backend->abi_version);
257 _E("%s: Failed to check ABI version\n", info->module_name);
261 /* Initialize backend */
262 ret = info->backend->init(data);
264 _E("%s: Failed to initialize backend: name(%s)/vendor(%s)\n",
265 info->module_name, info->backend->name,
266 info->backend->vendor);
273 static int __exit_backend(struct __hal_module_info *info, void *data,
274 const char *library_name)
278 if (!info->handle || !info->backend) {
279 _I("%s: Has not yet dlopend backend\n", info->module_name);
284 if (info->backend->exit) {
285 ret = info->backend->exit(data);
287 _E("%s: Failed to exit backend: name(%s)/vendor(%s)\n",
288 info->module_name, info->backend->name,
289 info->backend->vendor);
297 static int __get_backend(enum hal_module module, void **data,
298 const char *library_name)
300 struct __hal_module_info *info = NULL;
303 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
304 _E("Invalid parameter of HAL module (%d)\n", module);
308 G_LOCK(hal_common_lock);
309 if (_hal_api_conf_init()) {
314 info = _hal_api_conf_get_module_info(module, library_name);
317 _E("Failed to get HAL module(%d) information\n", module);
319 _E("Failed to get HAL module(%d) information (%s)\n",
320 module, library_name);
325 ret = __open_backend(info);
329 ret = __init_backend(info, data, NULL);
331 _E("%s: Failed to initialize the backend library\n",
339 _I("%s: Get HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
340 info->module_name, info->backend->name, info->backend->vendor,
341 get_backend_library_name(info), info->usage_count,
342 program_invocation_name);
344 G_UNLOCK(hal_common_lock);
348 __close_backend(info);
349 _hal_api_conf_exit();
351 G_UNLOCK(hal_common_lock);
355 static int __put_backend(enum hal_module module, void *data,
356 const char *library_name)
358 struct __hal_module_info *info = NULL;
361 /* Check parameter whether is valid or not */
362 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
363 _E("Invalid parameter of HAL module (%d)\n", module);
367 G_LOCK(hal_common_lock);
369 info = _hal_api_conf_get_module_info(module, library_name);
371 _E("Failed to get HAL module(%d) information\n", module);
376 if (!info->handle || !info->backend) {
377 _I("%s: Has not yet dlopend backend\n", info->module_name);
382 if (!info->usage_count) {
383 _I("%s: Already fully put for HAL module\n", info->module_name);
388 ret = __exit_backend(info, data, NULL);
390 _E("%s: Failed to exit the backend library\n",
398 _I("%s: Put HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
399 info->module_name, info->backend->name, info->backend->vendor,
400 get_backend_library_name(info), info->usage_count,
401 program_invocation_name);
403 if (info->usage_count > 0) {
408 __close_backend(info);
409 _hal_api_conf_exit();
414 G_UNLOCK(hal_common_lock);
418 static int __get_backend_data(enum hal_module module, unsigned int *abi_version,
419 char *name, int name_size, char *vendor, int vendor_size)
421 struct __hal_module_info *info = NULL;
424 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
425 _E("Invalid parameter of HAL module (%d)\n", module);
429 G_LOCK(hal_common_lock);
431 if (_hal_api_conf_init()) {
432 ret = HAL_ABI_VERSION_UNKNOWN;
436 info = _hal_api_conf_get_module_info(module, NULL);
438 _E("Failed to get HAL module(%d) information\n", module);
439 ret = HAL_ABI_VERSION_UNKNOWN;
443 ret = __open_backend(info);
447 /* Return abi_verion of hal_backend structure */
448 if (!name_size && !vendor_size) {
449 *abi_version = info->backend->abi_version;
451 /* Return name of hal_backend structure */
452 } else if (info->backend->name && name_size && !vendor_size) {
453 len = strlen(info->backend->name);
455 if (!info->backend->name || (len + 1 > name_size)) {
456 _E("%s: Invalid size of name[] array\n", info->module_name);
458 goto err_close_backend;
461 strncpy(name, info->backend->name, len);
464 /* Return vendor of hal_backend structure */
465 } else if (info->backend->vendor && !name_size && vendor_size) {
466 len = strlen(info->backend->vendor);
468 if (!info->backend->vendor || (len + 1 > vendor_size)) {
469 _E("%s: Invalid size of vendor[] array\n", info->module_name);
471 goto err_close_backend;
474 strncpy(vendor, info->backend->vendor, len);
477 _E("%s: Failed to get backend data\n", info->module_name);
479 goto err_close_backend;
484 __close_backend(info);
486 _hal_api_conf_exit();
488 G_UNLOCK(hal_common_lock);
493 int hal_common_get_backend(enum hal_module module, void **data)
495 return __get_backend(module, data, NULL);
499 int hal_common_put_backend(enum hal_module module, void *data)
501 return __put_backend(module, data, NULL);
505 int hal_common_get_backend_with_library_name(enum hal_module module,
506 void **data, const char *library_name)
508 return __get_backend(module, data, library_name);
512 int hal_common_put_backend_with_library_name(enum hal_module module,
513 void *data, const char *library_name)
515 return __put_backend(module, data, library_name);
519 int hal_common_check_backend_abi_version(enum hal_module module,
520 enum hal_abi_version abi_version)
522 struct __hal_module_info *info = NULL;
526 /* Check parameter whether is valid or not */
527 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
528 _E("Invalid paramer of HAL module(%d)\n", module);
532 if (abi_version <= HAL_ABI_VERSION_UNKNOWN
533 || abi_version >= HAL_ABI_VERSION_END) {
534 _E("Invalid paramer of HAL ABI version(%d) for HAL module(%d)\n",
535 abi_version, module);
539 if (_hal_api_conf_init())
542 info = _hal_api_conf_get_module_info(module, NULL);
544 _E("Failed to get HAL module(%d) information\n", module);
549 /* Check abi_version whether is supported or not */
550 if (!info->hal_api) {
551 _E("%s: Doesn't support HAL API\n", info->module_name);
556 if (!info->num_abi_versions
557 || !info->abi_versions) {
558 _E("%s: Doesn't have the ABI version information\n",
564 g_platform_curr_abi_version = _hal_api_conf_get_platform_abi_version();
566 if (g_platform_curr_abi_version <= HAL_ABI_VERSION_UNKNOWN
567 || g_platform_curr_abi_version >= HAL_ABI_VERSION_END) {
568 _E("Invalid paramer of current HAL ABI version(%d)(%d)\n",
569 g_platform_curr_abi_version, module);
574 for (i = 0; i < info->num_abi_versions; i++) {
575 struct hal_abi_version_match *data
576 = &info->abi_versions[i];
578 if (g_platform_curr_abi_version != data->platform_abi_version)
581 if (data->backend_min_abi_version <= HAL_ABI_VERSION_UNKNOWN ||
582 data->backend_min_abi_version >= HAL_ABI_VERSION_END) {
583 _E("%s: abi_versions[%d].backend_min_abi_version(%d) is invalid\n",
584 info->module_name, i, data->backend_min_abi_version);
589 if (abi_version <= data->platform_abi_version
590 && abi_version >= data->backend_min_abi_version) {
595 _E("%s: \'%s\' doesn't support \'%s\'\n",
597 hal_abi_version_str[g_platform_curr_abi_version],
598 hal_abi_version_str[abi_version]);
599 _E("%s: Must use ABI versions from \'%s\' to \'%s\'\n",
601 hal_abi_version_str[data->backend_min_abi_version],
602 hal_abi_version_str[data->platform_abi_version]);
607 _hal_api_conf_exit();
612 unsigned int hal_common_get_backend_abi_version(enum hal_module module)
614 unsigned int abi_version;
617 ret = __get_backend_data(module, &abi_version, NULL, 0, NULL, 0);
619 return HAL_ABI_VERSION_UNKNOWN;
625 int hal_common_get_backend_name(enum hal_module module, char *name, int size)
627 return __get_backend_data(module, NULL, name, size, NULL, 0);
631 int hal_common_get_backend_vendor(enum hal_module module, char *vendor, int size)
633 return __get_backend_data(module, NULL, NULL, 0, vendor, size);
637 static int __get_backend_library_data(enum hal_module module,
642 struct __hal_module_info *info = NULL;
645 char *backend_module_name = NULL;
646 int count, i, ret, len;
647 #if defined(__aarch64__) || defined(__x86_64__)
648 const char hal_backend_path[] = "/hal/lib64";
650 const char hal_backend_path[] = "/hal/lib";
653 /* Check parameter whether is valid or not */
654 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
655 _E("Invalid parameter of HAL module (%d)\n", module);
659 if (_hal_api_conf_init())
662 info = _hal_api_conf_get_module_info(module, NULL);
664 _E("Failed to get HAL module(%d) information\n", module);
669 if (info->backend_module_name == NULL) {
670 _E("Don't support HAL backend of HAL module(%s)\n",
675 backend_module_name = g_strdup_printf("libhal-backend-%s",
676 info->backend_module_name);
677 if (!backend_module_name) {
678 _E("Failed to allocate the backend_module_name of HAL module(%s)\n",
684 /* Find HAL backend libraries */
685 dir = opendir(hal_backend_path);
687 _E("Failed to find HAL backend path(%s) for HAL module(%s)\n",
688 hal_backend_path, info->module_name);
690 goto err_free_backend_module_name;
694 while ((de = readdir(dir)) != NULL) {
695 if (!g_str_has_prefix(de->d_name, backend_module_name))
700 else if (lib_count > 0) {
701 len = strlen(de->d_name) + 1;
703 if (len > lib_name_size)
706 strncpy(lib_names[count++], de->d_name, len);
710 if (lib_count > 0 && count != lib_count) {
712 goto err_mismatch_count;
716 _hal_api_conf_exit();
717 g_free(backend_module_name);
722 for (i = count - 1; i >= 0; i--)
723 memset(lib_names[i], 0, strlen(lib_names[i]));
726 err_free_backend_module_name:
727 g_free(backend_module_name);
729 _hal_api_conf_exit();
734 int hal_common_get_backend_count(enum hal_module module)
736 return __get_backend_library_data(module, NULL, 0, 0);
740 int hal_common_get_backend_library_names(enum hal_module module,
741 char **library_names,
743 int library_name_size)
745 int ret = __get_backend_library_data(module, library_names,
746 library_count, library_name_size);
747 return (ret < 0) ? ret : 0;