Initial code for libbt-oal
[platform/core/connectivity/bluetooth-frwk.git] / oal-hdp.c
1 /*
2  * Open Adaptation Layer (OAL)
3  *
4  * Copyright (c) 2014-2015 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
24 #include <bluetooth.h>
25 #include <bt_hl.h>
26
27 #include "oal-event.h"
28 #include "oal-internal.h"
29 #include "oal-common.h"
30 #include "oal-manager.h"
31 #include "oal-utils.h"
32 #include "oal-hdp.h"
33
34 #define CHECK_OAL_HDP_ENABLED() \
35         do { \
36                 if (hdp_api == NULL) { \
37                         BT_ERR("HDP Not Enabled"); \
38                         return -1; \
39                 } \
40         } while (0)
41
42 typedef struct {
43         int app_id;
44         int role;
45         int data_type;
46         int channel_type;
47 } oal_hdp_app_data_t;
48
49 static void hdp_app_reg_state_cb(int app_id, bthl_app_reg_state_t state);
50 static void hdp_channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
51                 int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd);
52
53 static bthl_callbacks_t sBluetoothHdpCallbacks = {
54         sizeof(sBluetoothHdpCallbacks),
55         hdp_app_reg_state_cb,
56         hdp_channel_state_cb,
57 };
58
59 static const bthl_interface_t *hdp_api;
60 static GSList *app_list;
61
62 static oal_hdp_app_data_t *__get_hdp_app_data(int app_id)
63 {
64         GSList *l;
65
66         for (l = app_list; l != NULL; l = g_slist_next(l)) {
67                 oal_hdp_app_data_t *app = l->data;
68
69                 if (app && (app->app_id == app_id))
70                         return app;
71         }
72
73         return NULL;
74 }
75
76 static void __free_hdp_app_data(int app_id)
77 {
78         oal_hdp_app_data_t *app = __get_hdp_app_data(app_id);
79
80         if (!app) {
81                 BT_ERR("No app found with id: %d", app_id);
82                 return;
83         }
84
85         app_list = g_slist_remove(app_list, app);
86         g_free(app);
87 }
88
89 static void hdp_app_reg_state_cb(int app_id, bthl_app_reg_state_t state)
90 {
91         event_hdp_app_reg_t *event_data = g_new0(event_hdp_app_reg_t, 1);
92         oal_event_t event;
93
94         BT_DBG("app_id: %d, state: %d", app_id, state);
95
96         switch (state) {
97         case BTHL_APP_REG_STATE_REG_SUCCESS:
98                 event = OAL_EVENT_HDP_APP_REGISTERED;
99                 event_data->status = OAL_STATUS_SUCCESS;
100                 break;
101         case BTHL_APP_REG_STATE_REG_FAILED:
102                 event = OAL_EVENT_HDP_APP_REGISTERED;
103                 event_data->status = OAL_STATUS_INTERNAL_ERROR;
104                 __free_hdp_app_data(app_id);
105                 break;
106         case BTHL_APP_REG_STATE_DEREG_SUCCESS:
107                 event = OAL_EVENT_HDP_APP_UNREGISTERED;
108                 event_data->status = OAL_STATUS_SUCCESS;
109                 __free_hdp_app_data(app_id);
110                 break;
111         case BTHL_APP_REG_STATE_DEREG_FAILED:
112                 event = OAL_EVENT_HDP_APP_UNREGISTERED;
113                 event_data->status = OAL_STATUS_INTERNAL_ERROR;
114                 break;
115         default:
116                 BT_ERR("Unknown state:%d received", state);
117                 return;
118         }
119
120         event_data->app_id = app_id;
121         send_event(event, event_data, sizeof(event_hdp_app_reg_t));
122 }
123
124 static void hdp_channel_state_cb(int app_id, bt_bdaddr_t *bd_addr,
125                 int mdep_cfg_index, int channel_id, bthl_channel_state_t state, int fd)
126 {
127         event_hdp_channel_conn_t *event_data;
128         oal_event_t event;
129         oal_hdp_app_data_t *app;
130
131         BT_DBG("app_id: %d, channel_id:%d, state:%d, fd:%d", app_id, channel_id, state, fd);
132
133         app = __get_hdp_app_data(app_id);
134         if (!app) {
135                 BT_ERR("No app found with app_id: %d", app_id);
136                 return;
137         }
138
139         switch (state) {
140         case BTHL_CONN_STATE_CONNECTING:
141                 BT_DBG("BTHL_CONN_STATE_CONNECTING");
142                 return;
143         case BTHL_CONN_STATE_DISCONNECTING:
144                 BT_DBG("BTHL_CONN_STATE_DISCONNECTING");
145                 return;
146         case BTHL_CONN_STATE_CONNECTED:
147                 BT_DBG("BTHL_CONN_STATE_CONNECTED");
148                 event = OAL_EVENT_HDP_CHANNEL_CONNECTED;
149                 break;
150         case BTHL_CONN_STATE_DISCONNECTED:
151                 BT_DBG("BTHL_CONN_STATE_DISCONNECTED");
152                 event = OAL_EVENT_HDP_CHANNEL_DESTROYED;
153                 break;
154         case BTHL_CONN_STATE_DESTROYED:
155                 BT_DBG("BTHL_CONN_STATE_DESTROYED");
156                 event = OAL_EVENT_HDP_CHANNEL_DESTROYED;
157                 break;
158         default:
159                 BT_ERR("Unknown stat: %d", state);
160                 return;
161         }
162
163         event_data = g_new0(event_hdp_channel_conn_t, 1);
164         event_data->fd = fd;
165         event_data->app_id = app_id;
166         event_data->channel_id = channel_id;
167         event_data->ch_type = app->channel_type;
168         memcpy(event_data->address.addr, bd_addr->address, BT_ADDRESS_BYTES_NUM);
169
170         send_event_bda_trace(event, event_data,
171                 sizeof(event_hdp_channel_conn_t), (bt_address_t*)bd_addr);
172 }
173
174 oal_status_t hdp_init(void)
175 {
176         const bt_interface_t *blued_api;
177         int ret;
178
179         API_TRACE();
180
181         if (hdp_api != NULL) {
182                 BT_WARN("HID Interface is already initialized...");
183                 return OAL_STATUS_ALREADY_DONE;
184         }
185
186         blued_api = adapter_get_stack_interface();
187         if (blued_api == NULL) {
188                 BT_ERR("Stack is not initialized");
189                 return OAL_STATUS_NOT_READY;
190         }
191
192         hdp_api = (const bthl_interface_t *)blued_api->get_profile_interface(BT_PROFILE_HEALTH_ID);
193         if (hdp_api == NULL) {
194                 BT_ERR("HDP interface failed");
195                 return OAL_STATUS_INTERNAL_ERROR;
196         }
197
198         if ((ret = hdp_api->init(&sBluetoothHdpCallbacks)) != BT_STATUS_SUCCESS) {
199                 BT_ERR("HDP Init failed: %s", status2string(ret));
200                 hdp_api->cleanup();
201                 hdp_api = NULL;
202                 return convert_to_oal_status(ret);
203         }
204
205         return OAL_STATUS_SUCCESS;
206 }
207
208 oal_status_t hdp_cleanup(void)
209 {
210         GSList *l = app_list;
211
212         API_TRACE();
213
214         CHECK_OAL_HDP_ENABLED();
215
216         BT_DBG("+");
217
218         hdp_api->cleanup();
219         hdp_api = NULL;
220
221         for (l = app_list; NULL != l;) {
222                 oal_hdp_app_data_t *app = l->data;
223                 l = l->next;
224                 if (app)
225                         __free_hdp_app_data(app->app_id);
226         }
227
228         if (app_list)
229                 g_free(app_list);
230
231         BT_DBG("-");
232         return OAL_STATUS_SUCCESS;
233 }
234
235 int hdp_register_application(oal_hdp_role_t role,
236                 oal_channel_type_t channel_type, const char *name, int data_type)
237 {
238         int ret;
239         int app_id = -1;
240         bthl_mdep_role_t mdep_role;
241         bthl_channel_type_t ch_type;
242         bthl_reg_param_t *reg_param;
243         oal_hdp_app_data_t *app_data;
244
245         API_TRACE();
246
247         CHECK_OAL_HDP_ENABLED();
248
249         switch (role) {
250         case OAL_HDP_ROLE_SOURCE:
251                 mdep_role = BTHL_MDEP_ROLE_SOURCE;
252                 break;
253         case OAL_HDP_ROLE_SINK:
254                 mdep_role = BTHL_MDEP_ROLE_SINK;
255                 break;
256         default:
257                 BT_ERR("Unknown role:%d", role);
258                 return -1;
259         }
260
261         switch (channel_type) {
262         case OAL_CHANNEL_TYPE_RELIABLE:
263                 ch_type = BTHL_CHANNEL_TYPE_RELIABLE;
264                 break;
265         case OAL_CHANNEL_TYPE_STREAMING:
266                 ch_type = BTHL_CHANNEL_TYPE_STREAMING;
267                 break;
268         case OAL_CHANNEL_TYPE_ANY:
269                 ch_type = BTHL_CHANNEL_TYPE_ANY;
270                 break;
271         default:
272                 BT_ERR("Unknown channel_type:%d", channel_type);
273                 return -1;
274         }
275
276         reg_param = g_new0(bthl_reg_param_t, 1);
277         reg_param->application_name = name;
278         reg_param->number_of_mdeps = 1;
279         reg_param->mdep_cfg = g_new0(bthl_mdep_cfg_t, 1);
280         reg_param->mdep_cfg->mdep_role = mdep_role;
281         reg_param->mdep_cfg->data_type = data_type;
282         reg_param->mdep_cfg->channel_type = ch_type;
283
284         ret = hdp_api->register_application(reg_param, &app_id);
285         g_free(reg_param->mdep_cfg);
286         g_free(reg_param);
287
288         if (ret != BT_STATUS_SUCCESS || 0 > app_id) {
289                 BT_ERR("HDP register_application failed: %s", status2string(ret));
290                 return -1;
291         }
292
293         app_data = g_new0(oal_hdp_app_data_t, 1);
294         app_data->app_id = app_id;
295         app_data->role = role;
296         app_data->data_type = data_type;
297         app_data->channel_type = channel_type;
298
299         app_list = g_slist_append(app_list, app_data);
300
301         return app_id;
302 }
303
304 oal_status_t hdp_unregister_application(int app_id)
305 {
306         int ret;
307
308         API_TRACE();
309
310         CHECK_OAL_HDP_ENABLED();
311
312         ret = hdp_api->unregister_application(app_id);
313         if (ret != BT_STATUS_SUCCESS) {
314                 BT_ERR("HDP unregister_application failed: %s", status2string(ret));
315                 return convert_to_oal_status(ret);
316         }
317
318         return OAL_STATUS_SUCCESS;
319 }
320
321 int hdp_connect_channel(int app_id, bt_address_t *address)
322 {
323         int channel_id = -1;
324         int mdep_index = 0;
325         int ret;
326
327         API_TRACE();
328
329         CHECK_OAL_HDP_ENABLED();
330
331         ret = hdp_api->connect_channel(app_id, (bt_bdaddr_t*)address, mdep_index, &channel_id);
332         if (BT_STATUS_SUCCESS != ret || 0 > channel_id) {
333                 BT_ERR("HDP connect_channel failed: %s", status2string(ret));
334                 return -1;
335         }
336
337         return channel_id;
338 }
339
340 oal_status_t hdp_disconnect_channel(int channel_id)
341 {
342         int ret;
343
344         API_TRACE();
345
346         CHECK_OAL_HDP_ENABLED();
347
348         ret = hdp_api->destroy_channel(channel_id);
349         if (BT_STATUS_SUCCESS != ret) {
350                 BT_ERR("HDP destroy_channel failed: %s", status2string(ret));
351                 return convert_to_oal_status(ret);
352         }
353
354         return OAL_STATUS_SUCCESS;
355 }