9be72fae30fe3640cf72c9779da48548bb6d5568
[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
27 #ifndef EXPORT
28 #define EXPORT __attribute__ ((visibility("default")))
29 #endif
30
31 EXPORT
32 const char *hal_common_get_backend_library_name(enum hal_module module)
33 {
34         char *library_name;
35
36         /* Check parameter whether is valid or not */
37         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
38                 _E("Invalid parameter of HAL module (%d)\n", module);
39                 return NULL;
40         }
41
42 #if defined(__aarch64__)
43         library_name = hal_module_info[module].library_name_64bit;
44 #else
45         library_name = hal_module_info[module].library_name;
46 #endif
47
48         if (!library_name) {
49                 _E("%s backend library name is NULL\n",
50                                 hal_module_info[module].module_name);
51                 return NULL;
52         }
53         return library_name;
54 }
55
56 EXPORT
57 const char *hal_common_get_backend_symbol_name(enum hal_module module)
58 {
59         /* Check parameter whether is valid or not */
60         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
61                 _E("Invalid paramer of HAL module (%d)\n", module);
62                 return NULL;
63         }
64
65         if (!hal_module_info[module].symbol_name) {
66                 _E("%s backend library name is NULL\n",
67                                 hal_module_info[module].module_name);
68                 return NULL;
69         }
70
71         return hal_module_info[module].symbol_name;
72 }
73
74 EXPORT
75 int hal_common_get_backend(enum hal_module module, void **data)
76 {
77         void *handle = NULL;
78         hal_backend *backend;
79         const char *library_name, *symbol_name;
80         int ret = 0;
81
82         /* Load module */
83         library_name = hal_common_get_backend_library_name(HAL_MODULE_FOO);
84         if (!library_name) {
85                 _E("Failed to get backend library name of %s\n",
86                                 hal_module_info[module].module_name);
87                 return TIZEN_ERROR_INVALID_PARAMETER;
88         }
89
90         handle = dlopen(library_name, RTLD_LAZY);
91         if (!handle) {
92                 _E("Failed to load shared library (%s)\n", dlerror());
93                 return TIZEN_ERROR_INVALID_PARAMETER;
94         }
95
96         symbol_name = hal_common_get_backend_symbol_name(HAL_MODULE_FOO);
97         if (!symbol_name) {
98                 _E("Failed to get backend symbol name of %s\n",
99                                 hal_module_info[module].module_name);
100                 ret = TIZEN_ERROR_INVALID_PARAMETER;
101                 goto err;
102         }
103
104         backend = dlsym(handle, symbol_name);
105         if (!backend) {
106                 _E("Failed to find backend data (%s)\n", dlerror());
107                 ret = TIZEN_ERROR_INVALID_PARAMETER;
108                 goto err;
109         }
110
111         /* Print backend module and vendor name */
112
113         /* Check HAL ABI Version */
114         ret = hal_common_check_backend_abi_version(HAL_MODULE_FOO,
115                                            backend->abi_version);
116         if (ret < 0) {
117                 _E("Failed to check ABI version of %s\n",
118                                 hal_module_info[module].module_name);
119                 ret = TIZEN_ERROR_INVALID_PARAMETER;
120                 goto err;
121         }
122
123         /* Get the backend module data */
124         if (!backend->init) {
125                 _E("hal_backend->init() is NULL for %s\n",
126                                 hal_module_info[module].module_name);
127                 ret = TIZEN_ERROR_INVALID_PARAMETER;
128                 goto err;
129         }
130
131         ret = backend->init(data);
132         if (ret < 0) {
133                 _E("Failed to initialize backend: name(%s)/vendor(%s)\n",
134                                         backend->name, backend->vendor);
135                 ret = TIZEN_ERROR_INVALID_PARAMETER;
136                 goto err;
137         }
138
139         hal_module_info[module].library_backend = backend;
140         hal_module_info[module].library_handle = handle;
141
142         _I("Get HAL backend: name(%s)/vendor(%s)\n",
143                         backend->name, backend->vendor);
144
145         return TIZEN_ERROR_NONE;
146 err:
147         dlclose(handle);
148         return ret;
149 }
150
151 EXPORT
152 int hal_common_put_backend(enum hal_module module, void *data)
153 {
154         hal_backend *backend = NULL;
155         void *handle = NULL;
156         int ret;
157
158         /* Check parameter whether is valid or not */
159         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
160                 _E("Invalid parameter of HAL module (%d)\n", module);
161                 return TIZEN_ERROR_INVALID_PARAMETER;
162         }
163
164         backend = hal_module_info[module].library_backend;
165         handle = hal_module_info[module].library_handle;
166
167         if (backend && backend->exit) {
168                 ret = backend->exit(data);
169                 if (ret < 0) {
170                         _E("Failed to exit backend: name(%s)/vendor(%s)\n",
171                                                 backend->name, backend->vendor);
172                         return TIZEN_ERROR_INVALID_PARAMETER;
173                 }
174         }
175
176         if (handle)
177                 dlclose(handle);
178
179         _I("Put HAL backend: name(%s)/vendor(%s)\n",
180                         backend->name, backend->vendor);
181
182         return TIZEN_ERROR_NONE;
183 }
184
185 EXPORT
186 int hal_common_check_backend_abi_version(enum hal_module module,
187                                 enum hal_abi_version abi_version)
188 {
189         int i;
190
191         /* Check parameter whether is valid or not */
192         if (module <= HAL_MODULE_UNKNOWN || module >= HAL_MODULE_END) {
193                 _E("Invalid paramer of HAL module (%d)\n", module);
194                 return TIZEN_ERROR_INVALID_PARAMETER;
195         }
196
197         if (abi_version <= HAL_ABI_VERSION_UNKNOWN
198                         || abi_version >= HAL_ABI_VERSION_END) {
199                 _E("Invalid paramer of HAL ABI version (%d)\n", abi_version);
200                 return TIZEN_ERROR_INVALID_PARAMETER;
201         }
202
203         /* Check abi_version whether is supported or not */
204         if (!hal_module_info[module].hal_api) {
205                 _E("HAL module(%d) doesn't support HAL API\n", module);
206                 return TIZEN_ERROR_INVALID_PARAMETER;
207         }
208
209         if (!hal_module_info[module].num_abi_versions
210                         || !hal_module_info[module].abi_versions) {
211                 _E("HAL module(%d) doesn't have the ABI version information\n",
212                                                 module);
213                 return TIZEN_ERROR_INVALID_PARAMETER;
214         }
215
216         for (i = 0; i < hal_module_info[module].num_abi_versions; i++) {
217                 struct hal_abi_version_match *data
218                                 = &hal_module_info[module].abi_versions[i];
219
220                 if (g_curr_hal_abi_version != data->curr_version)
221                         continue;
222
223                 if (abi_version <= data->curr_version
224                                 && abi_version >= data->compat_version)
225                         return TIZEN_ERROR_NONE;
226         }
227
228         return TIZEN_ERROR_INVALID_PARAMETER;
229 }