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);
54 return TIZEN_ERROR_INVALID_PARAMETER;
57 if (_hal_api_conf_init())
58 return TIZEN_ERROR_UNKNOWN;
60 info = _hal_api_conf_get_module_info(module, NULL);
62 _E("Failed to get HAL module(%d) information\n", module);
63 ret = TIZEN_ERROR_UNKNOWN;
67 library_name = get_backend_library_name(info);
69 _E("%s backend library name is NULL\n", info->module_name);
70 ret = TIZEN_ERROR_NONE;
74 len_library_name = strlen(library_name);
75 if (!name || (len_library_name + 1 > size)) {
76 ret = TIZEN_ERROR_UNKNOWN;
80 strncpy(name, library_name, len_library_name);
81 name[len_library_name] = '\0';
83 ret = TIZEN_ERROR_NONE;
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);
101 return TIZEN_ERROR_INVALID_PARAMETER;
104 if (_hal_api_conf_init())
105 return TIZEN_ERROR_UNKNOWN;
107 info = _hal_api_conf_get_module_info(module, NULL);
109 _E("Failed to get HAL module(%d) information\n", module);
110 ret = TIZEN_ERROR_UNKNOWN;
113 symbol_name = info->symbol_name;
115 _E("%s backend symbol name is NULL\n", info->module_name);
116 ret = TIZEN_ERROR_NONE;
120 len_symbol_name = strlen(symbol_name);
121 if (!name || (len_symbol_name + 1 > size)) {
122 ret = TIZEN_ERROR_UNKNOWN;
126 strncpy(name, symbol_name, len_symbol_name);
127 name[len_symbol_name] = '\0';
129 ret = TIZEN_ERROR_NONE;
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",
148 ret = TIZEN_ERROR_INVALID_PARAMETER;
152 if (!info->symbol_name) {
153 _E("%s: Failed to get backend symbol name\n",
155 ret = TIZEN_ERROR_INVALID_PARAMETER;
159 info->handle = dlopen(backend_library_name, RTLD_LAZY);
161 _E("%s: Failed to load backend library (%s)\n",
162 info->module_name, dlerror());
163 ret = TIZEN_ERROR_INVALID_PARAMETER;
167 info->backend = dlsym(info->handle, info->symbol_name);
168 if (!info->backend) {
169 _E("%s: Failed to find backend data (%s)\n",
170 info->module_name, dlerror());
171 ret = TIZEN_ERROR_INVALID_PARAMETER;
175 _I("%s: Open HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
176 info->module_name, info->backend->name, info->backend->vendor,
177 backend_library_name, info->usage_count,
178 program_invocation_name);
183 dlclose(info->handle);
185 info->backend = NULL;
191 static void __close_backend(struct __hal_module_info *info)
193 if (!info->backend || !info->handle)
196 _I("%s: Close HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
197 info->module_name, info->backend->name, info->backend->vendor,
198 get_backend_library_name(info), info->usage_count,
199 program_invocation_name);
202 dlclose(info->handle);
204 info->backend = NULL;
208 static int __init_backend(struct __hal_module_info *info, void **data,
209 const char *library_name)
213 if (!info->handle || !info->backend) {
214 _I("%s: Has not yet dlopend backend\n", info->module_name);
215 return TIZEN_ERROR_NONE;
218 if (!info->backend->init) {
219 _E("%s: hal_backend->init() is NULL\n", info->module_name);
220 return TIZEN_ERROR_INVALID_PARAMETER;
223 /* Check HAL ABI Version */
224 ret = hal_common_check_backend_abi_version(info->module,
225 info->backend->abi_version);
227 _E("%s: Failed to check ABI version\n", info->module_name);
228 return TIZEN_ERROR_INVALID_PARAMETER;
231 /* Initialize backend */
232 ret = info->backend->init(data);
234 _E("%s: Failed to initialize backend: name(%s)/vendor(%s)\n",
235 info->module_name, info->backend->name,
236 info->backend->vendor);
237 return TIZEN_ERROR_INVALID_PARAMETER;
240 return TIZEN_ERROR_NONE;
243 static int __exit_backend(struct __hal_module_info *info, void *data,
244 const char *library_name)
248 if (!info->handle || !info->backend) {
249 _I("%s: Has not yet dlopend backend\n", info->module_name);
250 return TIZEN_ERROR_NONE;
254 if (info->backend->exit) {
255 ret = info->backend->exit(data);
257 _E("%s: Failed to exit backend: name(%s)/vendor(%s)\n",
258 info->module_name, info->backend->name,
259 info->backend->vendor);
260 return TIZEN_ERROR_INVALID_PARAMETER;
267 static int __get_backend(enum hal_module module, void **data,
268 const char *library_name)
270 struct __hal_module_info *info = NULL;
273 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
274 _E("Invalid parameter of HAL module (%d)\n", module);
275 return TIZEN_ERROR_INVALID_PARAMETER;
278 G_LOCK(hal_common_lock);
279 if (_hal_api_conf_init()) {
280 ret = TIZEN_ERROR_UNKNOWN;
284 info = _hal_api_conf_get_module_info(module, library_name);
287 _E("Failed to get HAL module(%d) information\n", module);
289 _E("Failed to get HAL module(%d) information (%s)\n",
290 module, library_name);
291 ret = TIZEN_ERROR_UNKNOWN;
295 ret = __open_backend(info);
297 _E("%s: Failed to get the backend library by dlopen\n",
299 ret = TIZEN_ERROR_INVALID_PARAMETER;
303 ret = __init_backend(info, data, NULL);
305 _E("%s: Failed to initialize the backend library\n",
307 ret = TIZEN_ERROR_INVALID_PARAMETER;
313 _I("%s: Get HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
314 info->module_name, info->backend->name, info->backend->vendor,
315 get_backend_library_name(info), info->usage_count,
316 program_invocation_name);
318 G_UNLOCK(hal_common_lock);
319 return TIZEN_ERROR_NONE;
322 _hal_api_conf_exit();
323 __close_backend(info);
325 G_UNLOCK(hal_common_lock);
329 static int __put_backend(enum hal_module module, void *data,
330 const char *library_name)
332 struct __hal_module_info *info = NULL;
335 /* Check parameter whether is valid or not */
336 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
337 _E("Invalid parameter of HAL module (%d)\n", module);
338 return TIZEN_ERROR_INVALID_PARAMETER;
341 G_LOCK(hal_common_lock);
343 info = _hal_api_conf_get_module_info(module, library_name);
345 _E("Failed to get HAL module(%d) information\n", module);
346 ret = TIZEN_ERROR_UNKNOWN;
350 if (!info->handle || !info->backend) {
351 _I("%s: Has not yet dlopend backend\n", info->module_name);
352 ret = TIZEN_ERROR_NONE;
356 if (!info->usage_count) {
357 _I("%s: Already fully put for HAL module\n", info->module_name);
358 ret = TIZEN_ERROR_NONE;
362 ret = __exit_backend(info, data, NULL);
364 _E("%s: Failed to exit the backend library\n",
366 ret = TIZEN_ERROR_INVALID_PARAMETER;
372 _I("%s: Put HAL backend: name(%s)/vendor(%s)/library(%s)/count(%d) by %s\n",
373 info->module_name, info->backend->name, info->backend->vendor,
374 get_backend_library_name(info), info->usage_count,
375 program_invocation_name);
377 if (info->usage_count > 0) {
378 ret = TIZEN_ERROR_NONE;
382 __close_backend(info);
383 _hal_api_conf_exit();
385 ret = TIZEN_ERROR_NONE;
388 G_UNLOCK(hal_common_lock);
392 static int __get_backend_data(enum hal_module module, unsigned int *abi_version,
393 char *name, int name_size, char *vendor, int vendor_size)
395 struct __hal_module_info *info = NULL;
398 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
399 _E("Invalid parameter of HAL module (%d)\n", module);
403 G_LOCK(hal_common_lock);
405 if (_hal_api_conf_init()) {
406 ret = HAL_ABI_VERSION_UNKNOWN;
410 info = _hal_api_conf_get_module_info(module, NULL);
412 _E("Failed to get HAL module(%d) information\n", module);
413 ret = HAL_ABI_VERSION_UNKNOWN;
417 ret = __open_backend(info);
419 _E("%s: Failed to get the backend library by dlopen\n",
421 ret = TIZEN_ERROR_INVALID_PARAMETER;
425 /* Return abi_verion of hal_backend structure */
426 if (!name_size && !vendor_size) {
427 *abi_version = info->backend->abi_version;
429 /* Return name of hal_backend structure */
430 } else if (info->backend->name && name_size && !vendor_size) {
431 len = strlen(info->backend->name);
433 if (!info->backend->name || (len + 1 > name_size)) {
434 _E("%s: Invalid size of name[] array\n", info->module_name);
435 ret = TIZEN_ERROR_INVALID_PARAMETER;
439 strncpy(name, info->backend->name, len);
442 /* Return vendor of hal_backend structure */
443 } else if (info->backend->vendor && !name_size && vendor_size) {
444 len = strlen(info->backend->vendor);
446 if (!info->backend->vendor || (len + 1 > vendor_size)) {
447 _E("%s: Invalid size of vendor[] array\n", info->module_name);
448 ret = TIZEN_ERROR_INVALID_PARAMETER;
452 strncpy(vendor, info->backend->vendor, len);
455 _E("%s: Failed to get backend data\n", info->module_name);
456 ret = TIZEN_ERROR_INVALID_PARAMETER;
459 ret = TIZEN_ERROR_NONE;
462 _hal_api_conf_exit();
464 G_UNLOCK(hal_common_lock);
469 int hal_common_get_backend(enum hal_module module, void **data)
471 return __get_backend(module, data, NULL);
475 int hal_common_put_backend(enum hal_module module, void *data)
477 return __put_backend(module, data, NULL);
481 int hal_common_get_backend_with_library_name(enum hal_module module,
482 void **data, const char *library_name)
484 return __get_backend(module, data, library_name);
488 int hal_common_put_backend_with_library_name(enum hal_module module,
489 void *data, const char *library_name)
491 return __put_backend(module, data, library_name);
495 int hal_common_check_backend_abi_version(enum hal_module module,
496 enum hal_abi_version abi_version)
498 struct __hal_module_info *info = NULL;
502 /* Check parameter whether is valid or not */
503 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
504 _E("Invalid paramer of HAL module(%d)\n", module);
505 return TIZEN_ERROR_INVALID_PARAMETER;
508 if (abi_version <= HAL_ABI_VERSION_UNKNOWN
509 || abi_version >= HAL_ABI_VERSION_END) {
510 _E("Invalid paramer of HAL ABI version(%d) for HAL module(%d)\n",
511 abi_version, module);
512 return TIZEN_ERROR_INVALID_PARAMETER;
515 if (_hal_api_conf_init())
516 return TIZEN_ERROR_UNKNOWN;
518 info = _hal_api_conf_get_module_info(module, NULL);
520 _E("Failed to get HAL module(%d) information\n", module);
521 ret = TIZEN_ERROR_UNKNOWN;
525 /* Check abi_version whether is supported or not */
526 if (!info->hal_api) {
527 _E("%s: Doesn't support HAL API\n", info->module_name);
528 ret = TIZEN_ERROR_INVALID_PARAMETER;
532 if (!info->num_abi_versions
533 || !info->abi_versions) {
534 _E("%s: Doesn't have the ABI version information\n",
536 ret = TIZEN_ERROR_INVALID_PARAMETER;
540 g_platform_curr_abi_version = _hal_api_conf_get_platform_abi_version();
541 for (i = 0; i < info->num_abi_versions; i++) {
542 struct hal_abi_version_match *data
543 = &info->abi_versions[i];
545 if (g_platform_curr_abi_version != data->platform_abi_version)
548 if (data->backend_min_abi_version <= HAL_ABI_VERSION_UNKNOWN ||
549 data->backend_min_abi_version >= HAL_ABI_VERSION_END) {
550 _E("%s: abi_versions[%d].backend_min_abi_version(%d) is invalid\n",
551 info->module_name, i, data->backend_min_abi_version);
552 ret = TIZEN_ERROR_INVALID_PARAMETER;
556 if (abi_version <= data->platform_abi_version
557 && abi_version >= data->backend_min_abi_version) {
558 ret = TIZEN_ERROR_NONE;
562 _E("%s: \'%s\' doesn't support \'%s\'\n",
564 hal_abi_version_str[g_platform_curr_abi_version],
565 hal_abi_version_str[abi_version]);
566 _E("%s: Must use ABI versions from \'%s\' to \'%s\'\n",
568 hal_abi_version_str[data->backend_min_abi_version],
569 hal_abi_version_str[data->platform_abi_version]);
571 ret = TIZEN_ERROR_INVALID_PARAMETER;
574 _hal_api_conf_exit();
579 unsigned int hal_common_get_backend_abi_version(enum hal_module module)
581 unsigned int abi_version;
584 ret = __get_backend_data(module, &abi_version, NULL, 0, NULL, 0);
586 return HAL_ABI_VERSION_UNKNOWN;
592 int hal_common_get_backend_name(enum hal_module module, char *name, int size)
594 return __get_backend_data(module, NULL, name, size, NULL, 0);
598 int hal_common_get_backend_vendor(enum hal_module module, char *vendor, int size)
600 return __get_backend_data(module, NULL, NULL, 0, vendor, size);
604 static int __get_backend_library_data(enum hal_module module,
609 struct __hal_module_info *info = NULL;
612 const char *backend_module_name = NULL;
613 int count, i, ret, len;
614 #if defined(__aarch64__)
615 const char hal_backend_path[] = "/hal/lib64";
617 const char hal_backend_path[] = "/hal/lib";
620 /* Check parameter whether is valid or not */
621 if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
622 _E("Invalid parameter of HAL module (%d)\n", module);
623 return TIZEN_ERROR_INVALID_PARAMETER;
626 if (_hal_api_conf_init())
627 return TIZEN_ERROR_UNKNOWN;
629 info = _hal_api_conf_get_module_info(module, NULL);
631 _E("Failed to get HAL module(%d) information\n", module);
632 ret = TIZEN_ERROR_INVALID_PARAMETER;
636 if (info->backend_module_name == NULL) {
637 _E("Don't support HAL backend of HAL module(%s)\n",
639 ret = TIZEN_ERROR_INVALID_PARAMETER;
642 backend_module_name = g_strdup_printf("libhal-backend-%s",
643 info->backend_module_name);
644 if (!backend_module_name) {
645 _E("Failed to allocate the backend_module_name of HAL module(%s)\n",
647 ret = TIZEN_ERROR_UNKNOWN;
651 /* Find HAL backend libraries */
652 dir = opendir(hal_backend_path);
654 _E("Failed to find HAL backend path(%s) for HAL module(%s)\n",
655 hal_backend_path, info->module_name);
656 ret = TIZEN_ERROR_UNKNOWN;
657 goto err_free_backend_module_name;
661 while ((de = readdir(dir)) != NULL) {
662 if (!g_str_has_prefix(de->d_name, backend_module_name))
667 else if (lib_count > 0) {
668 len = strlen(de->d_name) + 1;
670 if (len > lib_name_size)
673 strncpy(lib_names[count++], de->d_name, len);
677 if (lib_count > 0 && count != lib_count) {
678 ret = TIZEN_ERROR_INVALID_PARAMETER;
679 goto err_mismatch_count;
683 _hal_api_conf_exit();
684 g_free(backend_module_name);
689 for (i = count - 1; i >= 0; i--)
690 memset(lib_names[i], 0, strlen(lib_names[i]));
693 err_free_backend_module_name:
694 g_free(backend_module_name);
696 _hal_api_conf_exit();
701 int hal_common_get_backend_count(enum hal_module module)
703 return __get_backend_library_data(module, NULL, 0, 0);
707 int hal_common_get_backend_library_names(enum hal_module module,
708 char **library_names,
710 int library_name_size)
712 int ret = __get_backend_library_data(module, library_names,
713 library_count, library_name_size);
714 return (ret < 0) ? ret : 0;