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.
28 #include <glib-object.h>
31 #include "hal-api-conf.h"
33 extern char *program_invocation_name;
36 #define EXPORT __attribute__ ((visibility("default")))
39 static enum hal_abi_version g_platform_curr_abi_version;
40 G_LOCK_DEFINE_STATIC(hal_common_lock);
43 int hal_common_get_backend_library_name(enum hal_module module, char *name, int size)
45 const char *library_name = NULL;
46 struct __hal_module_info *info = NULL;
50 /* Check parameter whether is valid or not */
51 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
52 _E("Invalid parameter of HAL module (%d)\n", module);
56 if (_hal_api_conf_init())
59 info = _hal_api_conf_get_module_info(module, NULL);
61 _E("Failed to get HAL module(%d) information\n", module);
66 library_name = get_backend_library_name(info);
68 _E("%s backend library name is NULL\n", info->module_name);
73 len_library_name = strlen(library_name);
74 if (!name || (len_library_name + 1 > size)) {
79 strncpy(name, library_name, len_library_name);
80 name[len_library_name] = '\0';
90 int hal_common_get_backend_symbol_name(enum hal_module module, char *name, int size)
92 struct __hal_module_info *info = NULL;
93 char *symbol_name = NULL;
97 /* Check parameter whether is valid or not */
98 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
99 _E("Invalid paramer of HAL module (%d)\n", module);
103 if (_hal_api_conf_init())
106 info = _hal_api_conf_get_module_info(module, NULL);
108 _E("Failed to get HAL module(%d) information\n", module);
112 symbol_name = info->symbol_name;
114 _E("%s backend symbol name is NULL\n", info->module_name);
119 len_symbol_name = strlen(symbol_name);
120 if (!name || (len_symbol_name + 1 > size)) {
125 strncpy(name, symbol_name, len_symbol_name);
126 name[len_symbol_name] = '\0';
130 _hal_api_conf_exit();
135 static int __open_backend(struct __hal_module_info *info)
137 const char *backend_library_name = NULL;
140 if (info->backend && info->handle)
143 backend_library_name = get_backend_library_name(info);
144 if (!backend_library_name) {
145 _E("%s: Failed to get backend library name\n",
151 if (!info->symbol_name) {
152 _E("%s: Failed to get backend symbol name\n",
158 info->handle = dlopen(backend_library_name, RTLD_LAZY);
160 _E("%s: Failed to load backend library (%s)\n",
161 info->module_name, dlerror());
166 info->backend = dlsym(info->handle, info->symbol_name);
167 if (!info->backend) {
168 _E("%s: Failed to find backend data (%s)\n",
169 info->module_name, dlerror());
174 _I("%s: Open HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
175 info->module_name, info->backend->name, info->backend->vendor,
176 backend_library_name, info->usage_count,
177 program_invocation_name);
182 dlclose(info->handle);
184 info->backend = NULL;
190 static void __close_backend(struct __hal_module_info *info)
192 if (!info->backend || !info->handle)
195 _I("%s: Close HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
196 info->module_name, info->backend->name, info->backend->vendor,
197 get_backend_library_name(info), info->usage_count,
198 program_invocation_name);
201 dlclose(info->handle);
203 info->backend = NULL;
207 static int __init_backend(struct __hal_module_info *info, void **data,
208 const char *library_name)
212 if (!info->handle || !info->backend) {
213 _I("%s: Has not yet dlopend backend\n", info->module_name);
217 if (!info->backend->init) {
218 _E("%s: hal_backend->init() is NULL\n", info->module_name);
222 /* Check HAL ABI Version */
223 ret = hal_common_check_backend_abi_version(info->module,
224 info->backend->abi_version);
226 _E("%s: Failed to check ABI version\n", info->module_name);
230 /* Initialize backend */
231 ret = info->backend->init(data);
233 _E("%s: Failed to initialize backend: name(%s)/vendor(%s)\n",
234 info->module_name, info->backend->name,
235 info->backend->vendor);
242 static int __exit_backend(struct __hal_module_info *info, void *data,
243 const char *library_name)
247 if (!info->handle || !info->backend) {
248 _I("%s: Has not yet dlopend backend\n", info->module_name);
253 if (info->backend->exit) {
254 ret = info->backend->exit(data);
256 _E("%s: Failed to exit backend: name(%s)/vendor(%s)\n",
257 info->module_name, info->backend->name,
258 info->backend->vendor);
266 static int __get_backend(enum hal_module module, void **data,
267 const char *library_name)
269 struct __hal_module_info *info = NULL;
272 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
273 _E("Invalid parameter of HAL module (%d)\n", module);
277 G_LOCK(hal_common_lock);
278 if (_hal_api_conf_init()) {
283 info = _hal_api_conf_get_module_info(module, library_name);
286 _E("Failed to get HAL module(%d) information\n", module);
288 _E("Failed to get HAL module(%d) information (%s)\n",
289 module, library_name);
294 ret = __open_backend(info);
296 _E("%s: Failed to get the backend library by dlopen\n",
302 ret = __init_backend(info, data, NULL);
304 _E("%s: Failed to initialize the backend library\n",
312 _I("%s: Get HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
313 info->module_name, info->backend->name, info->backend->vendor,
314 get_backend_library_name(info), info->usage_count,
315 program_invocation_name);
317 G_UNLOCK(hal_common_lock);
321 _hal_api_conf_exit();
322 __close_backend(info);
324 G_UNLOCK(hal_common_lock);
328 static int __put_backend(enum hal_module module, void *data,
329 const char *library_name)
331 struct __hal_module_info *info = NULL;
334 /* Check parameter whether is valid or not */
335 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
336 _E("Invalid parameter of HAL module (%d)\n", module);
340 G_LOCK(hal_common_lock);
342 info = _hal_api_conf_get_module_info(module, library_name);
344 _E("Failed to get HAL module(%d) information\n", module);
349 if (!info->handle || !info->backend) {
350 _I("%s: Has not yet dlopend backend\n", info->module_name);
355 if (!info->usage_count) {
356 _I("%s: Already fully put for HAL module\n", info->module_name);
361 ret = __exit_backend(info, data, NULL);
363 _E("%s: Failed to exit the backend library\n",
371 _I("%s: Put HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
372 info->module_name, info->backend->name, info->backend->vendor,
373 get_backend_library_name(info), info->usage_count,
374 program_invocation_name);
376 if (info->usage_count > 0) {
381 __close_backend(info);
382 _hal_api_conf_exit();
387 G_UNLOCK(hal_common_lock);
391 static int __get_backend_data(enum hal_module module, unsigned int *abi_version,
392 char *name, int name_size, char *vendor, int vendor_size)
394 struct __hal_module_info *info = NULL;
397 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
398 _E("Invalid parameter of HAL module (%d)\n", module);
402 G_LOCK(hal_common_lock);
404 if (_hal_api_conf_init()) {
405 ret = HAL_ABI_VERSION_UNKNOWN;
409 info = _hal_api_conf_get_module_info(module, NULL);
411 _E("Failed to get HAL module(%d) information\n", module);
412 ret = HAL_ABI_VERSION_UNKNOWN;
416 ret = __open_backend(info);
418 _E("%s: Failed to get the backend library by dlopen\n",
424 /* Return abi_verion of hal_backend structure */
425 if (!name_size && !vendor_size) {
426 *abi_version = info->backend->abi_version;
428 /* Return name of hal_backend structure */
429 } else if (info->backend->name && name_size && !vendor_size) {
430 len = strlen(info->backend->name);
432 if (!info->backend->name || (len + 1 > name_size)) {
433 _E("%s: Invalid size of name[] array\n", info->module_name);
438 strncpy(name, info->backend->name, len);
441 /* Return vendor of hal_backend structure */
442 } else if (info->backend->vendor && !name_size && vendor_size) {
443 len = strlen(info->backend->vendor);
445 if (!info->backend->vendor || (len + 1 > vendor_size)) {
446 _E("%s: Invalid size of vendor[] array\n", info->module_name);
451 strncpy(vendor, info->backend->vendor, len);
454 _E("%s: Failed to get backend data\n", info->module_name);
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;