Fix: Memory Leak in HAL layer.
[platform/core/connectivity/bluetooth-frwk.git] / bt-oal / oal-manager.c
1 /*
2  * Open Adaptation Layer (OAL)
3  *
4  * Copyright (c) 2012-2013 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
20 #include <stdio.h>
21 #include <dlog.h>
22 #include <string.h>
23 #include <vconf.h>
24 #include <sys/prctl.h>
25 #include <unistd.h>
26 #include <dlfcn.h>
27
28 #include <bluetooth.h>
29
30 #include "oal-internal.h"
31 #include "oal-event.h"
32 #include <oal-hardware.h>
33
34 #define BT_HAL_LIB_NAME                 "libbluetooth.default.so"
35
36 #ifdef ARCH64
37 #define HAL_LIBRARY_PATH                "/usr/lib64"
38 #else
39 #define HAL_LIBRARY_PATH                "/usr/lib"
40 #endif
41
42 #define LIB_PATH_SIZE                   50
43 #define LIB_NAME_SIZE                   50
44
45 static const hw_module_t* module = NULL;
46 static const bt_interface_t *blued_api = NULL;
47 static bluetooth_device_t* bt_device = NULL;
48
49 static gboolean unload_libs(gpointer data);
50 static bluetooth_device_t* load_hal_lib(void);
51 static const bt_interface_t * get_stack_interface(bluetooth_device_t* bt_device);
52 static int load(const char *libname, const struct hw_module_t **module);
53 static int unload(const struct hw_module_t *module);
54
55 oal_status_t oal_mgr_init_internal(void)
56 {
57         bt_device = load_hal_lib();
58
59         if (bt_device == NULL) {
60                 BT_ERR("HAL Library loading failed");
61                 return OAL_STATUS_INTERNAL_ERROR;
62         }
63
64         blued_api = get_stack_interface(bt_device);
65
66         if (blued_api == NULL) {
67                 BT_ERR("Stack Interface failed");
68                 return OAL_STATUS_INTERNAL_ERROR;
69         }
70
71         device_mgr_init(blued_api);
72
73         return adapter_mgr_init(blued_api);
74 }
75
76 oal_status_t oal_bt_init(oal_event_callback cb)
77 {
78         API_TRACE("Version: %s", OAL_VERSION_STR);
79         _bt_event_dispatcher_init(cb);
80         return OAL_STATUS_PENDING;
81 }
82
83 void oal_bt_deinit(void)
84 {
85         BT_INFO("+");
86         if (blued_api) {
87                 blued_api->cleanup();
88                 blued_api = NULL;
89         }
90         _bt_event_dispatcher_deinit();
91         sleep(1);
92         unload_libs(NULL);
93         BT_INFO("-");
94 }
95
96 void oal_mgr_cleanup(void)
97 {
98         /*TODO Unsupported */
99 }
100
101 void oal_mgr_stack_reload(void)
102 {
103         /*TODO Unsupported */
104 }
105
106 gboolean oal_lib_init(gpointer data)
107 {
108         oal_status_t ret;
109         BT_INFO("Going to check Chip Attachment...");
110
111         if (hw_is_module_ready() == OAL_STATUS_SUCCESS) {
112                 if (hw_get_chip_type() == BT_CHIP_TYPE_UNKNOWN) {
113                         BT_DBG("Chip Type Unknown, starting timer...");
114                 } else {
115                         ret = oal_mgr_init_internal();
116                         if (OAL_STATUS_SUCCESS == ret)
117                                 send_event(OAL_EVENT_OAL_INITIALISED_SUCCESS, NULL, 0);
118                         else
119                                 send_event(OAL_EVENT_OAL_INITIALISED_FAILED, NULL, 0);
120                 }
121         } else {
122                 BT_DBG("Chip Not Yet Ready, try again...");
123                 return FALSE;
124         }
125         return TRUE;
126 }
127
128 static gboolean unload_libs(gpointer data)
129 {
130         bt_device->common.close((hw_device_t*)bt_device);
131         unload((hw_module_t const*)module);
132         module = NULL;
133         return FALSE;
134 }
135
136 static bluetooth_device_t* load_hal_lib(void)
137 {
138         int err = 0;
139         hw_device_t* device;
140
141         BT_DBG("Loading HAL lib");
142         if (module == NULL) {
143                 switch (hw_get_chip_type()) {
144                 case BT_CHIP_TYPE_PLATFORM:
145                         BT_INFO("Tizen Platform BT chip: Tizen Platform HAL library will be loaded");
146                         err = load(BT_HAL_LIB_NAME, (const hw_module_t **)&module);
147                         break;
148                 default:
149                         BT_WARN("Chip type Unknown, So no Library Load");
150                         err = -EINVAL;
151                         break;
152                 }
153         } else
154                 BT_WARN("Lib already loaded");
155
156         if (err == 0) {
157                 err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
158                 if (err == 0) {
159                         bt_device = (bluetooth_device_t *)device;
160                         BT_INFO("HAL Library loaded successfullly");
161                 }
162         }
163
164         if (err != 0)
165                 BT_INFO("%d", err);
166         return bt_device;
167 }
168
169 static const bt_interface_t * get_stack_interface(bluetooth_device_t* bt_device)
170 {
171         const bt_interface_t *blued_api = NULL;
172         /* Get the Bluetooth interface */
173         blued_api = bt_device->get_bluetooth_interface();
174
175         return blued_api;
176 }
177
178 static int load(const char *libname, const struct hw_module_t **module)
179 {
180         int status = -ENOENT;
181         char libpath[LIB_PATH_SIZE];
182         void *handle;
183         struct hw_module_t *hmi;
184
185         OAL_CHECK_PARAMETER(libname, return);
186
187         snprintf(libpath, sizeof(libpath), "%s/%s", HAL_LIBRARY_PATH, libname);
188         BT_INFO("Loading Library: %s", libpath);
189
190         /*
191          * load the symbols resolving undefined symbols before
192          * dlopen returns. Since RTLD_GLOBAL is not or'd in with
193          * RTLD_NOW the external symbols will not be global
194          */
195
196         prctl(666, "[bt-service] Load Lib S", strlen("[bt-service] Load Lib S"));
197
198         handle = dlopen(libpath, RTLD_NOW);
199         if (handle == NULL) {
200                 char const *err_str = dlerror();
201                 BT_ERR("load: module=%s\n%s", libpath, err_str ? err_str : "unknown");
202                 status = -EINVAL;
203                 goto done;
204         }
205
206         prctl(666, "[bt-service] Load Lib E", strlen("[bt-service] Load Lib E"));
207
208         /* Get the address of the struct hal_module_info. */
209         const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
210         hmi = (struct hw_module_t *)dlsym(handle, sym);
211         if (hmi == NULL) {
212                 BT_ERR("load: couldn't find symbol %s", sym);
213                 status = -EINVAL;
214                 goto done;
215         }
216
217         /* Check that the id matches */
218         if (strcmp(BT_HARDWARE_MODULE_ID, hmi->id) != 0) {
219                 BT_ERR("load: id=%s != hmi->id=%s", BT_HARDWARE_MODULE_ID, hmi->id);
220                 status = -EINVAL;
221                 goto done;
222         }
223
224         hmi->dso = handle;
225         status = 0;
226
227 done:
228         if (status != 0) {
229                 hmi = NULL;
230                 if (handle != NULL) {
231                         dlclose(handle);
232                         handle = NULL;
233                 }
234         } else {
235                 BT_DBG("loaded HAL id=%s libpath=%s hmi=%p handle=%p",
236                                 BT_HARDWARE_MODULE_ID, libpath, hmi, handle);
237         }
238         *module = hmi;
239         return status;
240 }
241
242 static int unload(const struct hw_module_t *module)
243 {
244         int ret = 1;
245
246         if (module)
247                 ret = dlclose(module->dso);
248
249         if (ret != 0)
250                 BT_ERR("dlclose failed:%d", ret);
251         BT_WARN("Issues with dl: %s\n", dlerror());
252         return ret;
253 }
254
255 void oal_set_debug_mode(gboolean mode)
256 {
257         /*TODO Unsupported */
258 }
259
260 gboolean oal_get_debug_mode(void)
261 {
262         /*TODO Unsupported */
263         return FALSE;
264 }
265
266 const char *oal_get_stack_name(void)
267 {
268         return module ? module->name : NULL;
269 }