Merge branch 'master' into tizen_2.1
[apps/native/ug-bluetooth-efl.git] / src / libraries / bt-callback.c
1 /*
2  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <vconf.h>
18 #include <vconf-keys.h>
19 #include <bluetooth.h>
20
21 #include "bt-debug.h"
22 #include "bt-main-ug.h"
23 #include "bt-main-view.h"
24 #include "bt-util.h"
25 #include "bt-widget.h"
26 #include "bt-string-define.h"
27 #include "bt-ipc-handler.h"
28 #include "bt-resource.h"
29 #include "bt-net-connection.h"
30
31 /**********************************************************************
32 *                                                 Static Functions
33 ***********************************************************************/
34
35 static void __bt_cb_auto_discovery(void *data)
36 {
37         FN_START;
38
39         int ret;
40         bt_ug_data *ugd = NULL;
41
42         ret_if(data == NULL);
43
44         ugd = (bt_ug_data *)data;
45
46         ret_if(elm_win_focus_get(ugd->win_main) == FALSE);
47
48         /* If there is no paired devices, device searching starts. */
49         if (ugd->search_req == TRUE ||
50              eina_list_count(ugd->paired_device) == 0) {
51                 _bt_main_remove_all_searched_devices(ugd);
52
53                 ret = bt_adapter_start_device_discovery();
54                 if (!ret) {
55                         ugd->op_status = BT_SEARCHING;
56                         elm_object_text_set(ugd->scan_btn, BT_STR_STOP);;
57                         elm_genlist_item_update(ugd->status_item);
58
59                         if (ugd->searched_title == NULL)
60                                 _bt_main_add_searched_title(ugd);
61                 } else {
62                         BT_DBG("Discovery failed : Error Cause[%d]", ret);
63                 }
64         }
65
66         ugd->search_req = FALSE;
67
68         FN_END;
69 }
70
71 static void __bt_cb_enable(int result, void *data)
72 {
73         FN_START;
74
75         int timeout = 0;
76         bt_ug_data *ugd = NULL;
77
78         ret_if(data == NULL);
79
80         ugd = (bt_ug_data *)data;
81
82         if (ugd->op_status == BT_ACTIVATED) {
83                 BT_DBG("Already enabled state");
84                 return;
85         }
86
87         if (result != BT_ERROR_NONE) {
88                 BT_DBG("Failed to enable Bluetooth : Error Cause[%d]", result);
89                 ugd->op_status = BT_DEACTIVATED;
90                 elm_genlist_item_update(ugd->status_item);
91                 return;
92         } else {
93                 ugd->op_status = BT_ACTIVATED;
94                 ugd->aul_pairing_req = FALSE;
95         }
96
97         if (vconf_get_int(BT_VCONF_VISIBLE_TIME, &timeout) != 0) {
98                 BT_DBG("Fail to get the timeout value");
99         }
100
101         if (timeout == BT_ALWAYS_ON) {
102                 ugd->visible = TRUE;
103                 ugd->remain_time = 0;
104                 ugd->visibility_timeout = timeout;
105                 ugd->selected_radio = _bt_util_get_timeout_index(timeout);
106         }
107
108         _bt_util_set_phone_name();
109
110         elm_object_item_disabled_set(ugd->visible_item, EINA_FALSE);
111         elm_genlist_item_update(ugd->status_item);
112         elm_genlist_item_update(ugd->visible_item);
113
114         ret_if(ugd->bt_launch_mode == BT_LAUNCH_VISIBILITY);
115
116         elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
117
118         if (ugd->paired_title)
119                 elm_genlist_item_update(ugd->paired_title);
120
121         if (ugd->searched_title)
122                 elm_genlist_item_update(ugd->searched_title);
123
124         /* In the NFC case, we don't need to display the paired device */
125         if (ugd->bt_launch_mode != BT_LAUNCH_USE_NFC)
126                 _bt_main_draw_paired_devices(ugd);
127
128         __bt_cb_auto_discovery(ugd);
129
130         FN_END;
131 }
132
133 static void __bt_cb_disable(int result, void *data)
134 {
135         FN_START;
136         bt_ug_data *ugd = NULL;
137
138         ret_if(data == NULL);
139
140         ugd = (bt_ug_data *)data;
141
142         if (ugd->op_status == BT_DEACTIVATED) {
143                 BT_DBG("Already disabled state");
144                 return;
145         }
146
147         if (ugd->popup) {
148                 evas_object_del(ugd->popup);
149                 ugd->popup = NULL;
150         }
151
152         if (result != BT_ERROR_NONE) {
153                 BT_DBG("Failed to enable Bluetooth : Error Cause[%d]", result);
154                 ugd->op_status = BT_ACTIVATED;
155         } else {
156
157                 /* Delete profile view */
158                 _bt_profile_destroy_profile_view(ugd);
159
160                 if (ugd->timeout_id) {
161                         g_source_remove(ugd->timeout_id);
162                         ugd->timeout_id = 0;
163                 }
164
165                 ugd->op_status = BT_DEACTIVATED;
166                 ugd->visible = FALSE;
167                 ugd->remain_time = 0;
168
169                 if (ugd->visibility_timeout != BT_ALWAYS_ON) {
170                         ugd->visibility_timeout = 0;
171                         ugd->selected_radio = 0;
172                 }
173
174                 elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
175                 if (EINA_TRUE == elm_genlist_item_expanded_get(
176                                                         ugd->visible_item)) {
177                         elm_genlist_item_expanded_set(ugd->visible_item,
178                                                         EINA_FALSE);
179                 }
180
181                 elm_object_item_disabled_set(ugd->visible_item, EINA_TRUE);
182
183                 if (ugd->bt_launch_mode != BT_LAUNCH_VISIBILITY) {
184                         elm_object_disabled_set(ugd->scan_btn,
185                                                         EINA_FALSE);
186
187                         _bt_main_remove_all_paired_devices(ugd);
188                         _bt_main_remove_all_searched_devices(ugd);
189                 }
190         }
191
192         elm_genlist_item_update(ugd->status_item);
193         elm_genlist_item_update(ugd->visible_item);
194
195         if (ugd->paired_title)
196                 elm_genlist_item_update(ugd->paired_title);
197
198         if (ugd->searched_title)
199                 elm_genlist_item_update(ugd->searched_title);
200
201         FN_END;
202 }
203
204 static void __bt_cb_search_completed(int result, void *data)
205 {
206         FN_START;
207
208         bt_ug_data *ugd = NULL;
209
210         ret_if(data == NULL);
211
212         ugd = (bt_ug_data *)data;
213
214         if (ugd->op_status == BT_SEARCHING)
215                 ugd->op_status = BT_ACTIVATED;
216
217         elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
218
219         if (ugd->status_item)
220                 elm_genlist_item_update(ugd->status_item);
221
222         if (ugd->paired_title)
223                 elm_genlist_item_update(ugd->paired_title);
224
225         if (ugd->searched_title)
226                 elm_genlist_item_update(ugd->searched_title);
227
228         if (ugd->searched_device == NULL ||
229                 eina_list_count(ugd->searched_device) == 0) {
230                 /* Don't add the no device item, if no device item already exist */
231                 ret_if(ugd->no_device_item != NULL);
232                 ugd->no_device_item = _bt_main_add_no_device_found(ugd);
233
234                 if (ugd->no_device_item)
235                         elm_genlist_item_update(ugd->no_device_item);
236         }
237
238         FN_END;
239 }
240
241
242 static bool __bt_cb_match_discovery_type(unsigned int major_class,
243                                                 unsigned int service_class,
244                                                 unsigned int mask)
245 {
246         FN_START;
247
248         bt_device_major_mask_t major_mask = BT_DEVICE_MAJOR_MASK_MISC;
249
250         if (mask == 0x000000)
251                 return TRUE;
252
253         BT_DBG("mask: %x", mask);
254
255         BT_DBG("service_class: %x", service_class);
256
257         /* Check the service_class */
258         if (service_class & mask)
259                 return TRUE;
260
261         /* Check the major class */
262         switch (major_class) {
263                 case BT_MAJOR_DEV_CLS_COMPUTER:
264                         major_mask = BT_DEVICE_MAJOR_MASK_COMPUTER;
265                         break;
266                 case BT_MAJOR_DEV_CLS_PHONE:
267                         major_mask = BT_DEVICE_MAJOR_MASK_PHONE;
268                         break;
269                 case BT_MAJOR_DEV_CLS_LAN_ACCESS_POINT:
270                         major_mask = BT_DEVICE_MAJOR_MASK_LAN_ACCESS_POINT;
271                         break;
272                 case BT_MAJOR_DEV_CLS_AUDIO:
273                         major_mask = BT_DEVICE_MAJOR_MASK_AUDIO;
274                         break;
275                 case BT_MAJOR_DEV_CLS_PERIPHERAL:
276                         major_mask = BT_DEVICE_MAJOR_MASK_PERIPHERAL;
277                         break;
278                 case BT_MAJOR_DEV_CLS_IMAGING:
279                         major_mask = BT_DEVICE_MAJOR_MASK_IMAGING;
280                         break;
281                 case BT_MAJOR_DEV_CLS_WEARABLE:
282                         major_mask = BT_DEVICE_MAJOR_MASK_WEARABLE;
283                         break;
284                 case BT_MAJOR_DEV_CLS_TOY:
285                         major_mask = BT_DEVICE_MAJOR_MASK_TOY;
286                         break;
287                 case BT_MAJOR_DEV_CLS_HEALTH:
288                         major_mask = BT_DEVICE_MAJOR_MASK_HEALTH;
289                         break;
290                 default:
291                         major_mask = BT_DEVICE_MAJOR_MASK_MISC;
292                         break;
293         }
294
295         BT_DBG("major_mask: %x", major_mask);
296
297         if (mask & major_mask)
298                 return TRUE;
299
300         FN_END;
301
302         return FALSE;
303 }
304
305
306 static void __bt_cb_new_device_found(bt_adapter_device_discovery_info_s *info,
307                                      void *data)
308 {
309         FN_START;
310
311         bt_ug_data *ugd = NULL;
312         bt_dev_t *dev = NULL;
313
314         ret_if(info == NULL);
315         ret_if(data == NULL);
316
317         ugd = (bt_ug_data *)data;
318
319         /* Check the service_class */
320         if (__bt_cb_match_discovery_type(
321                                 info->bt_class.major_device_class,
322                                 info->bt_class.major_service_class_mask,
323                                 ugd->search_type) == FALSE) {
324                 BT_DBG("No matched device type");
325                 return;
326         }
327
328         if (info->is_bonded == TRUE) {
329                 BT_DBG("Paired device found");
330                 return;
331         }
332
333         if (_bt_main_check_and_update_device(ugd->searched_device,
334                                         info->remote_address,
335                                         info->remote_name) >= 0) {
336                 _bt_update_device_list(ugd);
337         } else {
338                 dev = _bt_main_create_searched_device_item((void *)info);
339                 if (NULL == dev) {
340                         BT_DBG("Create new device item failed \n");
341                         return;
342                 }
343
344                 if (_bt_main_is_matched_profile(ugd->search_type,
345                                                 dev->major_class,
346                                                 dev->service_class,
347                                                 ugd->service) == TRUE) {
348                         if (_bt_main_add_searched_device(ugd, dev) == NULL) {
349                                 BT_DBG("Fail to add the searched device \n");
350                                 return;
351                         }
352
353                         ugd->searched_device =
354                             eina_list_append(ugd->searched_device, dev);
355
356                         _bt_update_searched_item_style(ugd);
357                 } else {
358                         BT_DBG("Searched device does not match the profile\n");
359                         free(dev);
360                 }
361         }
362
363         FN_END;
364 }
365
366 /**********************************************************************
367 *                                                Common Functions
368 ***********************************************************************/
369
370 void _bt_cb_state_changed(int result,
371                         bt_adapter_state_e adapter_state,
372                         void *user_data)
373 {
374         FN_START;
375
376         if (adapter_state == BT_ADAPTER_ENABLED)
377                 __bt_cb_enable(result, user_data);
378         else
379                 __bt_cb_disable(result, user_data);
380
381         FN_END;
382 }
383
384 void _bt_cb_discovery_state_changed(int result,
385                         bt_adapter_device_discovery_state_e discovery_state,
386                         bt_adapter_device_discovery_info_s *discovery_info,
387                         void *user_data)
388 {
389         FN_START;
390
391         bt_ug_data *ugd = NULL;
392
393         ret_if(user_data == NULL);
394
395         ugd = (bt_ug_data *)user_data;
396
397         if (discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FOUND)
398                 __bt_cb_new_device_found(discovery_info, user_data);
399         else if (discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FINISHED)
400                 __bt_cb_search_completed(result, user_data);
401
402         FN_END;
403 }
404
405 void _bt_cb_bonding_created(int result, bt_device_info_s *dev_info,
406                                 void *user_data)
407 {
408         FN_START;
409
410         bt_ug_data *ugd = NULL;
411         bt_dev_t *dev = NULL;
412
413         ret_if(dev_info == NULL);
414         ret_if(user_data == NULL);
415
416         ugd = (bt_ug_data *)user_data;
417
418         if (ugd->op_status == BT_PAIRING)
419                 ugd->op_status = BT_ACTIVATED;
420
421         /* Enable UG to send another pairing request */
422         ugd->aul_pairing_req = FALSE;
423
424         /* In the NFC cas, we don't need to display the paired device */
425         if (ugd->bt_launch_mode == BT_LAUNCH_USE_NFC)
426                 return;
427
428         dev = _bt_main_get_dev_info_by_address(ugd->searched_device,
429                                         dev_info->remote_address);
430
431         if (dev == NULL)
432                 dev = _bt_main_get_dev_info(ugd->searched_device, ugd->searched_item);
433
434         if (result != BT_ERROR_NONE) {
435                 BT_DBG("Failed to pair with device : Error Cause[%d]", result);
436                 retm_if(dev == NULL, "dev is NULL\n");
437
438                 dev->status = BT_IDLE;
439                 elm_genlist_item_update((Elm_Object_Item *)dev->genlist_item);
440
441                 if (result != BT_ERROR_CANCELLED) {
442                         if (_bt_util_is_battery_low() == TRUE) {
443                                 _bt_main_create_information_popup(ugd, BT_STR_LOW_BATTERY);
444                         } else {
445                                 ugd->confirm_req = BT_PAIRING_REQ;
446                                 _bt_main_launch_syspopup(ugd, BT_SYSPOPUP_REQUEST_NAME,
447                                                 BT_STR_BLUETOOTH_ERROR_TRY_AGAIN_Q,
448                                                 BT_SYSPOPUP_TWO_BUTTON_TYPE);
449                         }
450                 }
451         } else {
452                 bt_dev_t *new_dev = NULL;
453                 Elm_Object_Item *item = NULL;
454                 void *profile;
455
456                 if (_bt_main_check_and_update_device(ugd->paired_device,
457                                         dev_info->remote_address,
458                                         dev_info->remote_name) >= 0) {
459                         _bt_update_device_list(ugd);
460                 } else {
461                         if (dev != NULL) {
462                                 /* Remove the item in searched dialogue */
463                                 _bt_main_remove_searched_device(ugd, dev);
464                         }
465
466                         /* Add the item in paired dialogue group */
467                         new_dev = _bt_main_create_paired_device_item(dev_info);
468
469                         profile = _bt_get_registered_net_profile(ugd->connection,
470                                                                 new_dev->bd_addr);
471
472                         if (profile)
473                                 _bt_set_profile_state_changed_cb(profile, new_dev);
474
475                         item = _bt_main_add_paired_device(ugd, new_dev);
476
477                         if (item) {
478                                 ugd->paired_device =
479                                     eina_list_append(ugd->paired_device, new_dev);
480
481                                 _bt_update_paired_item_style(ugd);
482                         }
483
484                         /* Don't try to auto-connect in the network case */
485                         if (profile == NULL) {
486                                 _bt_main_connect_device(ugd, new_dev);
487                         }
488
489                         ugd->searched_item = NULL;
490                         ugd->paired_item = item;
491                 }
492         }
493
494         elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
495
496         FN_END;
497 }
498
499 void _bt_cb_bonding_destroyed(int result, char *remote_address,
500                                         void *user_data)
501 {
502         FN_START;
503
504         bt_ug_data *ugd = NULL;
505         bt_dev_t *new_item = NULL;
506         bt_dev_t *item = NULL;
507         Eina_List *l = NULL;
508         int i;
509
510         retm_if(remote_address == NULL, "Invalid argument: param is NULL\n");
511         retm_if(user_data == NULL, "Invalid argument: param is NULL\n");
512
513         ugd = (bt_ug_data *)user_data;
514
515         if (result != BT_ERROR_NONE) {
516                 BT_DBG("Failed to unbond: [%d]", result);
517                 return;
518         }
519
520         EINA_LIST_FOREACH(ugd->paired_device, l, item) {
521                 if (item == NULL)
522                         break;
523
524                 if (g_strcmp0(item->addr_str, remote_address) == 0) {
525                         new_item = calloc(1, sizeof(bt_dev_t));
526                         if (new_item == NULL)
527                                 break;
528
529                         memcpy(new_item, item, sizeof(bt_dev_t));
530
531                         if (item->uuids && item->uuid_count > 0) {
532                                 new_item->uuids = g_new0(char *, item->uuid_count + 1);
533
534                                 for (i = 0; i < item->uuid_count; i++) {
535                                         new_item->uuids[i] = g_strdup(item->uuids[i]);
536                                 }
537                         }
538
539                         new_item->uuid_count = item->uuid_count;
540
541                         _bt_main_remove_paired_device(ugd, item);
542
543                         if (ugd->no_device_item) {
544                                 elm_object_item_del(ugd->no_device_item);
545                                 ugd->no_device_item = NULL;
546                         }
547
548                         if (_bt_main_add_searched_device(ugd, new_item) != NULL) {
549                                 ugd->searched_device = eina_list_append(
550                                                 ugd->searched_device, new_item);
551
552                                 _bt_update_searched_item_style(ugd);
553                         }
554
555                         BT_DBG("unbonding_count: %d", ugd->unbonding_count);
556
557                         if (ugd->unbonding_count <= 1) {
558                                 _bt_profile_delete_view((void *)new_item);
559                         } else {
560                                 ugd->unbonding_count--;
561                         }
562
563                         break;
564                 }
565         }
566
567         FN_END;
568 }
569
570 void _bt_cb_service_searched(int result, bt_device_sdp_info_s *sdp_info,
571                                 void* user_data)
572 {
573         FN_START;
574
575         int i;
576         bt_ug_data *ugd = NULL;
577         bt_service_class_t service_mask = 0;
578         bt_dev_t *item = NULL;
579         Evas_Object *btn = NULL;
580
581         ret_if(user_data == NULL);
582
583         ugd = (bt_ug_data *)user_data;
584
585         ugd->op_status = BT_ACTIVATED;
586
587         BT_DBG("Result: %d", result);
588
589         item = _bt_main_get_dev_info_by_address(ugd->paired_device,
590                                         sdp_info->remote_address);
591
592         if (item == NULL)
593                 item = _bt_main_get_dev_info(ugd->paired_device, ugd->paired_item);
594
595         if (item == NULL) {
596                 ugd->waiting_service_response = FALSE;
597                 ugd->auto_service_search = FALSE;
598                 return;
599         }
600
601         item->status = BT_IDLE;
602         elm_genlist_item_update((Elm_Object_Item *)item->genlist_item);
603
604         if (result == BT_ERROR_NONE) {
605                 _bt_util_get_service_mask_from_uuid_list(
606                                                 sdp_info->service_uuid,
607                                                 sdp_info->service_count,
608                                                 &service_mask);
609
610                 if (sdp_info->service_uuid != NULL && sdp_info->service_count > 0) {
611
612                         _bt_util_free_device_uuids(item);
613                         item->uuids = g_new0(char *, sdp_info->service_count + 1);
614
615                         for (i = 0; i < sdp_info->service_count; i++) {
616                                 item->uuids[i] = g_strdup(sdp_info->service_uuid[i]);
617                         }
618
619                         item->uuid_count = sdp_info->service_count;
620                 }
621
622                 item->service_list = service_mask;
623
624                 if (ugd->waiting_service_response == TRUE) {
625                         _bt_main_connect_device(ugd, item);
626                 }
627         } else {
628                 BT_DBG("Failed to get the service list [%d]", result);
629
630                 if (ugd->waiting_service_response == TRUE) {
631                         if (ugd->popup) {
632                                 evas_object_del(ugd->popup);
633                                 ugd->popup = NULL;
634                         }
635
636                         ugd->popup =
637                             _bt_create_popup(ugd->win_main, BT_STR_ERROR,
638                                         BT_STR_UNABLE_TO_GET_THE_SERVICE_LIST,
639                                         _bt_main_popup_del_cb, ugd, 2);
640                         ugd->back_cb = _bt_util_launch_no_event;
641
642                         btn = elm_button_add(ugd->popup);
643                         elm_object_text_set(btn, BT_STR_CANCEL);
644                         elm_object_part_content_set(ugd->popup, "button1", btn);
645                         evas_object_smart_callback_add(btn, "clicked",
646                                 (Evas_Smart_Cb)_bt_main_popup_del_cb, ugd);
647                 }
648         }
649
650         ugd->waiting_service_response = FALSE;
651         ugd->auto_service_search = FALSE;
652
653         FN_END;
654 }
655
656 void _bt_cb_hid_state_changed(int result, bool connected,
657                         const char *remote_address,
658                         void *user_data)
659 {
660         FN_START;
661
662         bt_address_t address = { { 0 } };
663
664         BT_DBG("Bluetooth HID Event [%d] Received");
665
666         _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
667
668         _bt_ipc_update_connected_status(user_data, BT_HID_CONNECTED,
669                                         connected, result, &address);
670         FN_END;
671 }
672
673 void _bt_cb_audio_state_changed(int result, bool connected,
674                                 const char *remote_address,
675                                 bt_audio_profile_type_e type,
676                                 void *user_data)
677 {
678         FN_START;
679
680         bt_address_t address = { { 0 } };
681         int connected_type;
682
683         BT_DBG("Bluetooth Audio Event [%d] Received");
684
685         if (type == BT_AUDIO_PROFILE_TYPE_A2DP)
686                 connected_type = BT_STEREO_HEADSET_CONNECTED;
687         else
688                 connected_type = BT_HEADSET_CONNECTED;
689
690         _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
691
692         _bt_ipc_update_connected_status(user_data, connected_type,
693                                         connected, result, &address);
694         FN_END;
695 }
696