halapi: Update error log for providing the more correct debugging info
[platform/hal/api/common.git] / src / hal-api-common.c
1 /*
2  * HAL Common API
3  *
4  * Copyright (c) 2020 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19 #include <stdio.h>
20 #include <stdint.h>
21 #include <stdbool.h>
22 #include <dlfcn.h>
23 #include <dlog.h>
24
25 #include "common.h"
26 #include "hal-api-conf.h"
27
28 #ifndef EXPORT
29 #define EXPORT __attribute__ ((visibility("default")))
30 #endif
31
32 static enum hal_abi_version g_platform_curr_abi_version;
33
34 EXPORT
35 const char *hal_common_get_backend_library_name(enum hal_module module)
36 {
37         char *library_name;
38         struct __hal_module_info *info = NULL;
39
40         /* Check parameter whether is valid or not */
41         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
42                 _E("Invalid parameter of HAL module (%d)\n", module);
43                 return NULL;
44         }
45
46         info = _hal_api_conf_get_module_info(module);
47         if (info == NULL) {
48                 _E("Failed to get HAL module(%d) information\n", module);
49                 return NULL;
50         }
51
52 #if defined(__aarch64__)
53         library_name = info->library_name_64bit;
54 #else
55         library_name = info->library_name;
56 #endif
57
58         if (!library_name) {
59                 _E("%s backend library name is NULL\n", info->module_name);
60                 return NULL;
61         }
62         return library_name;
63 }
64
65 EXPORT
66 const char *hal_common_get_backend_symbol_name(enum hal_module module)
67 {
68         struct __hal_module_info *info = NULL;
69
70         /* Check parameter whether is valid or not */
71         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
72                 _E("Invalid paramer of HAL module (%d)\n", module);
73                 return NULL;
74         }
75
76         info = _hal_api_conf_get_module_info(module);
77         if (info == NULL) {
78                 _E("Failed to get HAL module(%d) information\n", module);
79                 return NULL;
80         }
81
82         if (!info->symbol_name) {
83                 _E("%s backend library name is NULL\n", info->module_name);
84                 return NULL;
85         }
86
87         return info->symbol_name;
88 }
89
90 EXPORT
91 int hal_common_get_backend(enum hal_module module, void **data)
92 {
93         struct __hal_module_info *info = NULL;
94         void *handle = NULL;
95         hal_backend *backend;
96         const char *library_name, *symbol_name;
97         int ret = 0;
98
99         info = _hal_api_conf_get_module_info(module);
100         if (info == NULL) {
101                 _E("Failed to get HAL module(%d) information\n", module);
102                 ret = TIZEN_ERROR_UNKNOWN;
103                 goto err;
104         }
105
106         /* Load module */
107         library_name = hal_common_get_backend_library_name(module);
108         if (!library_name) {
109                 _E("%s: Failed to get backend library name\n",
110                                 info->module_name);
111                 return TIZEN_ERROR_INVALID_PARAMETER;
112         }
113
114         handle = dlopen(library_name, RTLD_LAZY);
115         if (!handle) {
116                 _E("%s: Failed to load shared library (%s)\n",
117                                 info->module_name, dlerror());
118                 return TIZEN_ERROR_INVALID_PARAMETER;
119         }
120
121         symbol_name = hal_common_get_backend_symbol_name(module);
122         if (!symbol_name) {
123                 _E("%s: Failed to get backend symbol name\n",
124                                 info->module_name);
125                 ret = TIZEN_ERROR_INVALID_PARAMETER;
126                 goto err;
127         }
128
129         backend = dlsym(handle, symbol_name);
130         if (!backend) {
131                 _E("%s: Failed to find backend data (%s)\n",
132                                 info->module_name, dlerror());
133                 ret = TIZEN_ERROR_INVALID_PARAMETER;
134                 goto err;
135         }
136
137         /* Check HAL ABI Version */
138         ret = hal_common_check_backend_abi_version(module, backend->abi_version);
139         if (ret < 0) {
140                 _E("%s: Failed to check ABI version\n",
141                                 info->module_name);
142                 ret = TIZEN_ERROR_INVALID_PARAMETER;
143                 goto err;
144         }
145
146         /* Get the backend module data */
147         if (!backend->init) {
148                 _E("%s: hal_backend->init() is NULL\n",
149                                 info->module_name);
150                 ret = TIZEN_ERROR_INVALID_PARAMETER;
151                 goto err;
152         }
153
154         ret = backend->init(data);
155         if (ret < 0) {
156                 _E("%s: Failed to initialize backend: name(%s)/vendor(%s)\n",
157                                 info->module_name, backend->name, backend->vendor);
158                 ret = TIZEN_ERROR_INVALID_PARAMETER;
159                 goto err;
160         }
161
162         info->library_backend = backend;
163         info->library_handle = handle;
164
165         _I("%s: Get HAL backend: name(%s)/vendor(%s)\n",
166                         info->module_name, backend->name, backend->vendor);
167
168         return TIZEN_ERROR_NONE;
169 err:
170         dlclose(handle);
171         return ret;
172 }
173
174 EXPORT
175 int hal_common_put_backend(enum hal_module module, void *data)
176 {
177         struct __hal_module_info *info = NULL;
178         hal_backend *backend = NULL;
179         void *handle = NULL;
180         int ret;
181
182         /* Check parameter whether is valid or not */
183         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
184                 _E("Invalid parameter of HAL module (%d)\n", module);
185                 return TIZEN_ERROR_INVALID_PARAMETER;
186         }
187
188         info = _hal_api_conf_get_module_info(module);
189         if (info == NULL) {
190                 _E("Failed to get HAL module(%d) information\n", module);
191                 return TIZEN_ERROR_UNKNOWN;
192         }
193
194         backend = info->library_backend;
195         handle = info->library_handle;
196
197         if (!backend) {
198                 _I("%s: Already fully put for HAL module\n", info->module_name);
199                 return TIZEN_ERROR_NONE;
200         }
201
202         if (backend->exit) {
203                 ret = backend->exit(data);
204                 if (ret < 0) {
205                         _E("%s: Failed to exit backend: name(%s)/vendor(%s)\n",
206                                 info->module_name, backend->name, backend->vendor);
207                         return TIZEN_ERROR_INVALID_PARAMETER;
208                 }
209         }
210
211         _I("%s: Put HAL backend: name(%s)/vendor(%s)\n",
212                         info->module_name, backend->name, backend->vendor);
213
214         if (handle)
215                 dlclose(handle);
216
217         info->library_backend = NULL;
218         info->library_handle = NULL;
219
220         return TIZEN_ERROR_NONE;
221 }
222
223 EXPORT
224 int hal_common_check_backend_abi_version(enum hal_module module,
225                                 enum hal_abi_version abi_version)
226 {
227         struct __hal_module_info *info = NULL;
228         int i;
229
230         /* Check parameter whether is valid or not */
231         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
232                 _E("Invalid paramer of HAL module(%d)\n", module);
233                 return TIZEN_ERROR_INVALID_PARAMETER;
234         }
235
236         if (abi_version <= HAL_ABI_VERSION_UNKNOWN
237                         || abi_version >= HAL_ABI_VERSION_END) {
238                 _E("Invalid paramer of HAL ABI version(%d) for HAL module(%d)\n",
239                                 abi_version, module);
240                 return TIZEN_ERROR_INVALID_PARAMETER;
241         }
242
243         info = _hal_api_conf_get_module_info(module);
244         if (info == NULL) {
245                 _E("Failed to get HAL module(%d) information\n", module);
246                 return TIZEN_ERROR_UNKNOWN;
247         }
248
249         /* Check abi_version whether is supported or not */
250         if (!info->hal_api) {
251                 _E("%s: Doesn't support HAL API\n", info->module_name);
252                 return TIZEN_ERROR_INVALID_PARAMETER;
253         }
254
255         if (!info->num_abi_versions
256                         || !info->abi_versions) {
257                 _E("%s: Doesn't have the ABI version information\n",
258                                                 info->module_name);
259                 return TIZEN_ERROR_INVALID_PARAMETER;
260         }
261
262         g_platform_curr_abi_version = _hal_api_conf_get_platform_abi_version();
263         for (i = 0; i < info->num_abi_versions; i++) {
264                 struct hal_abi_version_match *data
265                                 = &info->abi_versions[i];
266
267                 if (g_platform_curr_abi_version != data->platform_abi_version)
268                         continue;
269
270                 if (data->backend_min_abi_version <= HAL_ABI_VERSION_UNKNOWN ||
271                         data->backend_min_abi_version >= HAL_ABI_VERSION_END) {
272                         _E("%s: abi_versions[%d].backend_min_abi_version(%d) is invalid\n",
273                                 info->module_name, i, data->backend_min_abi_version);
274                         return TIZEN_ERROR_INVALID_PARAMETER;
275                 }
276
277                 if (abi_version <= data->platform_abi_version
278                                 && abi_version >= data->backend_min_abi_version)
279                         return TIZEN_ERROR_NONE;
280
281                 _E("%s: \'%s\' doesn't support \'%s\'\n",
282                                 info->module_name,
283                                 hal_abi_version_str[g_platform_curr_abi_version],
284                                 hal_abi_version_str[abi_version]);
285                 _E("%s: Must use ABI versions from \'%s\' to \'%s\'\n",
286                                 info->module_name,
287                                 hal_abi_version_str[data->backend_min_abi_version],
288                                 hal_abi_version_str[data->platform_abi_version]);
289         }
290
291         return TIZEN_ERROR_INVALID_PARAMETER;
292 }