Initialize Tizen 2.3
[apps/connectivity/bt-connection-popup.git] / src / bt-connection-handler.c
1 /*
2 * bt-connection-popup
3 *
4 * Copyright 2012 Samsung Electronics Co., Ltd
5 *
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 *           Injun Yang <injun.yang@samsung.com>
8 *           Seungyoun Ju <sy39.ju@samsung.com>
9 *
10 * Licensed under the Flora License, Version 1.1 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.tizenopensource.org/license
15 *
16 * Unless required by applicable law or agreed to in writing,
17 * software distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
21 *
22 */
23
24 #include <aul.h>
25 #include <bluetooth.h>
26 #include <vconf.h>
27
28 #include "bt-connection-main.h"
29 #include "bt-connection-view.h"
30 #include "bt-connection-handler.h"
31
32 #define VCONFKEY_SAP_STATUS  "memory/private/sap/conn_status"
33 #define BT_ADDRESS_LENGTH 18
34
35 static bool is_le_disconnecting;
36
37 static int __bt_app_destory_cb(void *data)
38 {
39         bt_app_data_t *ad = NULL;
40
41         DBG("");
42
43         ad = (bt_app_data_t *)data;
44         if (ad == NULL) {
45                 ERR("Invalid param");
46                 return 0;
47         }
48
49         if (ad->timer) {
50                 ecore_timer_del(ad->timer);
51                 ad->timer = NULL;
52         }
53
54         _bt_destroy_app(ad);
55
56         return 0;
57 }
58
59 static void __bt_wms_status_handler(keynode_t *key, void *data)
60 {
61         int status;
62         int type;
63         bt_app_data_t *ad;
64
65         ad = (bt_app_data_t *)data;
66         if (ad == NULL) {
67                 ERR("Invalid param");
68                 return;
69         }
70
71         type = vconf_keynode_get_type(key);
72         if (type == VCONF_TYPE_BOOL)
73                 status = vconf_keynode_get_bool(key);
74         else {
75                 ERR("Invalid vconf type : %d", type);
76                 return;
77         }
78
79         DBG("WMS is %s", status == WMS_CONNECTED ?
80                         "connected" : "disconnected" );
81
82         if (status == WMS_CONNECTED) {
83                 /* To show connected view, create new popup */
84                 /* or update edc part */
85                 /* See _bt_update_connect_status_popup() */
86                 if (ad->timer) {
87                         ecore_timer_del(ad->timer);
88                         ad->timer = NULL;
89                 }
90                 _bt_create_connected_popup(ad);
91
92                 _bt_send_result(ad, KEY_VAL_CONNECTED);
93
94                 ad->timer = ecore_timer_add(APP_DESTORY_TIMEOUT,
95                             (Ecore_Task_Cb) __bt_app_destory_cb, ad);
96         }
97
98         return;
99 }
100
101 static void __bt_hf_connection_state_changed(int result, bool connected, const char *remote_address, bt_audio_profile_type_e type, void *user_data)
102 {
103         if (connected == true) {
104                 DBG("Bluetooth HF is connected");
105         }
106         else {
107                 DBG("Bluetooth HF is disconnected");
108         }
109 }
110
111 static bool __bt_adapter_bonded_device_cb(bt_device_info_s *device_info, void *user_data)
112 {
113         int ret;
114         bool is_connected = false;
115         char* remote_address = (char*)user_data;
116
117         if (!(device_info->bt_class.major_device_class & BT_MAJOR_DEVICE_CLASS_COMPUTER) &&
118                 !(device_info->bt_class.major_device_class & BT_MAJOR_DEVICE_CLASS_PHONE))
119                 return true;
120
121         memcpy(remote_address, device_info->remote_address, BT_ADDRESS_LENGTH);
122         ret = bt_device_is_profile_connected(device_info->remote_address, BT_PROFILE_AG, &is_connected);
123         if (ret == BT_ERROR_NONE && is_connected) {
124                 remote_address[0] = '\0';
125                 return false;
126         }
127
128         return true;
129 }
130
131 static gboolean __bt_hf_is_connected(const char* remote_address)
132 {
133         int ret;
134         gboolean is_connected = FALSE;
135
136         ret = bt_adapter_foreach_bonded_device(__bt_adapter_bonded_device_cb, (void*)remote_address);
137         if (ret != BT_ERROR_NONE) {
138                 ERR("bt_adapter_foreach_bonded_device is failed 0x%X", ret);
139                 return FALSE;
140         }
141
142         if (remote_address[0] == '\0')
143                 is_connected = TRUE;
144         DBG("Aleady HF is %s", is_connected ? "connected" : "disconnected");
145
146         return is_connected;
147 }
148
149 static void __bt_adapter_state_changed(int result,
150                         bt_adapter_state_e adapter_state, void *user_data)
151 {
152         int ret;
153         char remote_address[BT_ADDRESS_LENGTH] = { 0, };
154
155         if (user_data == NULL) {
156                 ERR("Invalid param");
157                 return;
158         }
159
160         if (result != BT_ERROR_NONE) {
161                 ERR("BT Adapter operation is failed : %d", result);
162                 return;
163         }
164
165         DBG("BT Adapter is %s", adapter_state == BT_ADAPTER_ENABLED ?
166                         "enabled" : "disabled");
167
168         if (adapter_state == BT_ADAPTER_ENABLED) {
169                 if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
170                         DBG("Make a HF connection");
171                         ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
172                         if (ret != BT_ERROR_NONE) {
173                                 ERR("HF Connection is failed");
174                                 return;
175                         }
176                 }
177         }
178
179         return;
180 }
181
182 int _bt_get_wms_status(void)
183 {
184         int ret;
185         int status = WMS_DISCONNECTED;
186
187         ret = vconf_get_bool(VCONFKEY_WMS_WMANAGER_CONNECTED, &status);
188         if (ret != 0) {
189                 ERR("Vconf get failed");
190                 return WMS_DISCONNECTED;
191         }
192
193         DBG("WMS status : %d", status);
194
195         return status;
196 }
197
198 void _bt_get_sap_status(void)
199 {
200         int ret;
201         int status = 0;
202
203         ret = vconf_get_int(VCONFKEY_SAP_STATUS, &status);
204         if (ret != 0) {
205                 ERR("Vconf get failed");
206         }
207
208         DBG("SAP status : %d", status);
209
210         return;
211 }
212
213 gboolean _bt_send_result(bt_app_data_t *ad, const char *val)
214 {
215         if (ad == NULL)
216                 return FALSE;
217
218         bundle *kb;
219         bundle *res_b;
220         int ret;
221         static gboolean is_sent = FALSE;
222
223         DBG("");
224
225         if (ad->service_clone == NULL) {
226                 ERR("Invalid param");
227                 return FALSE;
228         }
229
230         if (is_sent == TRUE) {
231                 ERR("Aleady send response !!!");
232                 return FALSE;
233         }
234
235         ret = service_to_bundle(ad->service_clone, &kb);
236         if (ret != SERVICE_ERROR_NONE) {
237                 ERR("service is failed : %d", ret);
238                 return FALSE;
239         }
240
241         aul_create_result_bundle(kb, &res_b);
242         if (res_b == NULL)
243                 return FALSE;
244
245         bundle_add(res_b, "__BT_CONNECTION__", val);
246
247         aul_send_service_result(res_b);
248         bundle_free(res_b);
249         bundle_free(kb);
250
251         is_sent = TRUE;
252
253         DBG("Send result : %s", val);
254
255         return TRUE;
256 }
257
258 bool __device_check_gatt_cb(bt_profile_e profile, void *user_data)
259 {
260         bool *is_connected = (bool *)user_data;
261
262         if (profile == BT_PROFILE_GATT) {
263                 *is_connected = true;
264                 return false;
265         }
266
267         return true;
268 }
269
270 bool __bt_le_is_connected(const char *remote_address)
271 {
272         int ret;
273         bool is_connected = false;
274
275         if (remote_address == NULL) {
276                 return false;
277         }
278
279         ret = bt_device_foreach_connected_profiles(remote_address,
280                         __device_check_gatt_cb, &is_connected);
281         if (ret != BT_ERROR_NONE) {
282                 ERR("bt_device_foreach_connected_profiles fail (0x%08x)", ret);
283                 return false;
284         }
285
286         return is_connected;
287 }
288
289 void __bt_gatt_disconnected_cb(int result, void *user_data)
290 {
291         DBG("called");
292         if (result != BT_ERROR_NONE) {
293                 ERR("GATT disconnect fail (0x%08x)", result);
294                 is_le_disconnecting = false;
295         }
296
297         return;
298 #if 0
299         char remote_address[BT_ADDRESS_LENGTH] = { 0, };
300         bool is_advertising = false;
301         int ret;
302
303         if (result != BT_ERROR_NONE) {
304                 ERR("GATT disconnect fail (0x%08x)", result);
305                 return;
306         }
307
308         if (__bt_hf_is_connected(&remote_address[0]) == TRUE) {
309                 DBG("Handsfree is already connected");
310                 return;
311         }
312
313         ret = bt_adapter_is_advertising(&is_advertising);
314         if (ret == BT_ERROR_NONE && is_advertising) {
315                 ret = bt_adapter_stop_advertising();
316                 if (ret != BT_ERROR_NONE) {
317                         ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
318                 }
319         }
320
321         DBG("Make a HF connection");
322         ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
323         if (ret != BT_ERROR_NONE) {
324                 ERR("HF Connection is failed");
325                 return;
326         }
327
328         return;
329 #endif
330 }
331
332 static void __bt_device_connection_state_changed_cb(bool connected,
333                                                 const char *remote_address,
334                                                 void *user_data)
335 {
336         bool is_advertising = false;
337         int ret;
338         char remote_add[BT_ADDRESS_LENGTH] = { 0, };
339
340         DBG("address: %s, connected: %d", remote_address, connected);
341
342         if (is_le_disconnecting == false || connected == true) {
343                 DBG("is_le_disconnecting IS FALSE");
344                 return;
345         }
346         is_le_disconnecting = false;
347
348         if (__bt_hf_is_connected(&remote_add[0]) == true) {
349                 DBG("Handsfree is already connected");
350                 return;
351         }
352
353         if (strncmp(remote_address, remote_add, BT_ADDRESS_LENGTH-1) != 0) {
354                 DBG("remote address is different");
355                 return;
356         }
357
358         ret = bt_adapter_is_advertising(&is_advertising);
359         if (ret == BT_ERROR_NONE && is_advertising) {
360                 ret = bt_adapter_stop_advertising();
361                 if (ret != BT_ERROR_NONE) {
362                         ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
363                 }
364         }
365
366         DBG("Make a HF connection");
367         ret = bt_audio_connect(&remote_add[0], BT_AUDIO_PROFILE_TYPE_AG);
368         if (ret != BT_ERROR_NONE) {
369                 ERR("HF Connection is failed");
370                 return;
371         }
372
373         return;
374 }
375
376 gboolean _bt_init(void *data)
377 {
378         int ret;
379         bt_adapter_state_e adapter_state = BT_ADAPTER_DISABLED;
380         char remote_address[BT_ADDRESS_LENGTH] = { 0, };
381         bool is_advertising = false;
382
383         bt_app_data_t *ad;
384         ad = (bt_app_data_t *)data;
385
386         is_le_disconnecting = false;
387
388         if (ad == NULL) {
389                 return FALSE;
390         }
391
392         if (ad->initialize == TRUE) {
393                 DBG("bt_initialize already done");
394                 return TRUE;
395         }
396
397         ret = bt_initialize();
398         if (ret != BT_ERROR_NONE) {
399                 ERR("bt_initialize is failed : %d", ret);
400                 return FALSE;
401         }
402
403         ret = bt_adapter_set_state_changed_cb(__bt_adapter_state_changed, data);
404         if (ret != BT_ERROR_NONE) {
405                 ERR("bt_adapter_set_state_changed_cb is failed : %d", ret);
406                 bt_deinitialize();
407                 return FALSE;
408         }
409
410         ret = bt_device_set_connection_state_changed_cb(__bt_device_connection_state_changed_cb,
411                                                         NULL);
412         if (ret != BT_ERROR_NONE) {
413                 ERR("bt_device_set_connection_state_changed_cb is failed : %d", ret);
414                 return FALSE;
415         }
416
417         ret = bt_adapter_get_state(&adapter_state);
418         if (ret != BT_ERROR_NONE) {
419                 ERR("bt_adapter_get_state is failed : %d", ret);
420                 return FALSE;
421         }
422
423         ret = bt_audio_initialize();
424         if (ret != BT_ERROR_NONE) {
425                 ERR("bt_audio_initialize is failed : %d", ret);
426                 return FALSE;
427         }
428
429         ret = bt_audio_set_connection_state_changed_cb(__bt_hf_connection_state_changed, NULL);
430         if (ret != BT_ERROR_NONE) {
431                 ERR("bt_audio_set_connection_state_changed_cb is failed : %d", ret);
432                 bt_hf_deinitialize();
433                 return FALSE;
434         }
435
436         if (adapter_state == BT_ADAPTER_ENABLED) {
437                 DBG("Aleady BT enabled");
438 #ifdef FEATURE_TIZENW
439                 if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
440                         DBG("Make a HF connection");
441                         ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
442                         if (ret != BT_ERROR_NONE) {
443                                 ERR("HF Connection is failed");
444                                 return FALSE;
445                         }
446                 }
447 #else
448                 if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
449                         if (__bt_le_is_connected(&remote_address[0])) {
450
451                                 ret = bt_adapter_is_advertising(&is_advertising);
452                                 if (ret == BT_ERROR_NONE && is_advertising) {
453                                         ret = bt_adapter_stop_advertising();
454                                         if (ret != BT_ERROR_NONE) {
455                                                 ERR("bt_adapter_stop_advertising failed (0x%08x)",
456                                                         ret);
457                                         }
458                                 }
459
460                                 ret = bt_device_disconnect_le(__bt_gatt_disconnected_cb, &remote_address[0]);
461                                 if (ret == BT_ERROR_NONE)
462                                         is_le_disconnecting = true;
463                                 return TRUE;
464                         }
465
466                         DBG("Make a HF connection");
467                         ret = bt_audio_connect(&remote_address[0], BT_AUDIO_PROFILE_TYPE_AG);
468                         if (ret != BT_ERROR_NONE) {
469                                 ERR("HF Connection is failed");
470                                 return FALSE;
471                         }
472                 }
473 #endif /* FEATURE_TIZENW */
474                 return TRUE;
475         } else {
476                 DBG("Enable BT adapter");
477                 ret = bt_adapter_enable();
478                 if (ret != BT_ERROR_NONE) {
479                         ERR("bt_adapter_enable is failed : %d", ret);
480                         return FALSE;
481                 }
482         }
483
484         return TRUE;
485 }
486
487 void _bt_deinit(void *data)
488 {
489         int ret;
490         char remote_address[BT_ADDRESS_LENGTH] = { 0, };
491         bool is_advertising = FALSE;
492         bt_app_data_t *ad;
493         ad = (bt_app_data_t *)data;
494
495         if (ad == NULL) return;
496
497         if (ad->initialize == FALSE) {
498                 DBG("bt_deinitialize already done");
499                 return;
500         }
501
502         if (__bt_hf_is_connected(&remote_address[0]) == FALSE) {
503                 ret = bt_adapter_is_advertising(&is_advertising);
504                 if (ret == BT_ERROR_NONE && !is_advertising) {
505                         ret = bt_adapter_start_advertising(NULL);
506                         if (ret != BT_ERROR_NONE) {
507                                 ERR("bt_adapter_stop_advertising failed (0x%08x)", ret);
508                         }
509                 }
510         }
511
512         ret = bt_audio_unset_connection_state_changed_cb();
513         if (ret != BT_ERROR_NONE)
514                 ERR("bt_audio_unset_connection_state_changed_cb is failed : %d", ret);
515
516         ret = bt_audio_deinitialize();
517         if (ret != BT_ERROR_NONE)
518                 ERR("bt_audio_deinitialize is failed : %d", ret);
519
520         ret = bt_hf_deinitialize();
521         if (ret != BT_ERROR_NONE)
522                 ERR("bt_hf_deinitialize is failed : %d", ret);
523
524         ret = bt_device_unset_connection_state_changed_cb();
525         if (ret != BT_ERROR_NONE)
526                 ERR("bt_device_unset_connection_state_changed_cb is failed : %d", ret);
527
528         ret = bt_adapter_unset_state_changed_cb();
529         if (ret != BT_ERROR_NONE)
530                 ERR("bt_adapter_unset_state_changed_cb is failed : %d", ret);
531
532         ret = bt_deinitialize();
533         if (ret != BT_ERROR_NONE)
534                 ERR("bt_deinitialize is failed : %d", ret);
535
536         return;
537 }
538
539 gboolean _bt_register_vconf_handler(void *data)
540 {
541         int ret;
542
543         ret =
544             vconf_notify_key_changed(VCONFKEY_WMS_WMANAGER_CONNECTED,
545                                      (vconf_callback_fn) __bt_wms_status_handler, data);
546         if (ret < 0) {
547                 ERR("Unable to register key handler");
548                 return FALSE;
549         }
550
551         return TRUE;
552 }
553
554 void _bt_unregister_vconf_handler(void)
555 {
556         vconf_ignore_key_changed(VCONFKEY_WMS_WMANAGER_CONNECTED,
557                         (vconf_callback_fn) __bt_wms_status_handler);
558
559         return;
560 }