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);
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);
449 strncpy(vendor, info->backend->vendor, len);
452 _E("%s: Failed to get backend data\n", info->module_name);
459 _hal_api_conf_exit();
461 G_UNLOCK(hal_common_lock);
466 int hal_common_get_backend(enum hal_module module, void **data)
468 return __get_backend(module, data, NULL);
472 int hal_common_put_backend(enum hal_module module, void *data)
474 return __put_backend(module, data, NULL);
478 int hal_common_get_backend_with_library_name(enum hal_module module,
479 void **data, const char *library_name)
481 return __get_backend(module, data, library_name);
485 int hal_common_put_backend_with_library_name(enum hal_module module,
486 void *data, const char *library_name)
488 return __put_backend(module, data, library_name);
492 int hal_common_check_backend_abi_version(enum hal_module module,
493 enum hal_abi_version abi_version)
495 struct __hal_module_info *info = NULL;
499 /* Check parameter whether is valid or not */
500 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
501 _E("Invalid paramer of HAL module(%d)\n", module);
505 if (abi_version <= HAL_ABI_VERSION_UNKNOWN
506 || abi_version >= HAL_ABI_VERSION_END) {
507 _E("Invalid paramer of HAL ABI version(%d) for HAL module(%d)\n",
508 abi_version, module);
512 if (_hal_api_conf_init())
515 info = _hal_api_conf_get_module_info(module, NULL);
517 _E("Failed to get HAL module(%d) information\n", module);
522 /* Check abi_version whether is supported or not */
523 if (!info->hal_api) {
524 _E("%s: Doesn't support HAL API\n", info->module_name);
529 if (!info->num_abi_versions
530 || !info->abi_versions) {
531 _E("%s: Doesn't have the ABI version information\n",
537 g_platform_curr_abi_version = _hal_api_conf_get_platform_abi_version();
539 if (g_platform_curr_abi_version <= HAL_ABI_VERSION_UNKNOWN
540 || g_platform_curr_abi_version >= HAL_ABI_VERSION_END) {
541 _E("Invalid paramer of current HAL ABI version(%d)(%d)\n",
542 g_platform_curr_abi_version, module);
547 for (i = 0; i < info->num_abi_versions; i++) {
548 struct hal_abi_version_match *data
549 = &info->abi_versions[i];
551 if (g_platform_curr_abi_version != data->platform_abi_version)
554 if (data->backend_min_abi_version <= HAL_ABI_VERSION_UNKNOWN ||
555 data->backend_min_abi_version >= HAL_ABI_VERSION_END) {
556 _E("%s: abi_versions[%d].backend_min_abi_version(%d) is invalid\n",
557 info->module_name, i, data->backend_min_abi_version);
562 if (abi_version <= data->platform_abi_version
563 && abi_version >= data->backend_min_abi_version) {
568 _E("%s: \'%s\' doesn't support \'%s\'\n",
570 hal_abi_version_str[g_platform_curr_abi_version],
571 hal_abi_version_str[abi_version]);
572 _E("%s: Must use ABI versions from \'%s\' to \'%s\'\n",
574 hal_abi_version_str[data->backend_min_abi_version],
575 hal_abi_version_str[data->platform_abi_version]);
580 _hal_api_conf_exit();
585 unsigned int hal_common_get_backend_abi_version(enum hal_module module)
587 unsigned int abi_version;
590 ret = __get_backend_data(module, &abi_version, NULL, 0, NULL, 0);
592 return HAL_ABI_VERSION_UNKNOWN;
598 int hal_common_get_backend_name(enum hal_module module, char *name, int size)
600 return __get_backend_data(module, NULL, name, size, NULL, 0);
604 int hal_common_get_backend_vendor(enum hal_module module, char *vendor, int size)
606 return __get_backend_data(module, NULL, NULL, 0, vendor, size);
610 static int __get_backend_library_data(enum hal_module module,
615 struct __hal_module_info *info = NULL;
618 char *backend_module_name = NULL;
619 int count, i, ret, len;
620 #if defined(__aarch64__) || defined(__x86_64__)
621 const char hal_backend_path[] = "/hal/lib64";
623 const char hal_backend_path[] = "/hal/lib";
626 /* Check parameter whether is valid or not */
627 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
628 _E("Invalid parameter of HAL module (%d)\n", module);
632 if (_hal_api_conf_init())
635 info = _hal_api_conf_get_module_info(module, NULL);
637 _E("Failed to get HAL module(%d) information\n", module);
642 if (info->backend_module_name == NULL) {
643 _E("Don't support HAL backend of HAL module(%s)\n",
648 backend_module_name = g_strdup_printf("libhal-backend-%s",
649 info->backend_module_name);
650 if (!backend_module_name) {
651 _E("Failed to allocate the backend_module_name of HAL module(%s)\n",
657 /* Find HAL backend libraries */
658 dir = opendir(hal_backend_path);
660 _E("Failed to find HAL backend path(%s) for HAL module(%s)\n",
661 hal_backend_path, info->module_name);
663 goto err_free_backend_module_name;
667 while ((de = readdir(dir)) != NULL) {
668 if (!g_str_has_prefix(de->d_name, backend_module_name))
673 else if (lib_count > 0) {
674 len = strlen(de->d_name) + 1;
676 if (len > lib_name_size)
679 strncpy(lib_names[count++], de->d_name, len);
683 if (lib_count > 0 && count != lib_count) {
685 goto err_mismatch_count;
689 _hal_api_conf_exit();
690 g_free(backend_module_name);
695 for (i = count - 1; i >= 0; i--)
696 memset(lib_names[i], 0, strlen(lib_names[i]));
699 err_free_backend_module_name:
700 g_free(backend_module_name);
702 _hal_api_conf_exit();
707 int hal_common_get_backend_count(enum hal_module module)
709 return __get_backend_library_data(module, NULL, 0, 0);
713 int hal_common_get_backend_library_names(enum hal_module module,
714 char **library_names,
716 int library_name_size)
718 int ret = __get_backend_library_data(module, library_names,
719 library_count, library_name_size);
720 return (ret < 0) ? ret : 0;