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