Tizen 2.1 base
[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                 if (ugd->timeout_id) {
157                         g_source_remove(ugd->timeout_id);
158                         ugd->timeout_id = 0;
159                 }
160
161                 ugd->op_status = BT_DEACTIVATED;
162                 ugd->visible = FALSE;
163                 ugd->remain_time = 0;
164
165                 if (ugd->visibility_timeout != BT_ALWAYS_ON) {
166                         ugd->visibility_timeout = 0;
167                         ugd->selected_radio = 0;
168                 }
169
170                 elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
171                 elm_genlist_item_update(ugd->visible_item);
172                 elm_genlist_item_subitems_clear(ugd->visible_item);
173                 elm_object_item_disabled_set(ugd->visible_item, EINA_TRUE);
174
175                 if (ugd->bt_launch_mode != BT_LAUNCH_VISIBILITY) {
176                         elm_object_disabled_set(ugd->scan_btn,
177                                                         EINA_FALSE);
178
179                         _bt_main_remove_all_paired_devices(ugd);
180                         _bt_main_remove_all_searched_devices(ugd);
181                 }
182         }
183
184         elm_genlist_item_update(ugd->status_item);
185
186         if (ugd->paired_title)
187                 elm_genlist_item_update(ugd->paired_title);
188
189         if (ugd->searched_title)
190                 elm_genlist_item_update(ugd->searched_title);
191
192         FN_END;
193 }
194
195 static void __bt_cb_search_completed(int result, void *data)
196 {
197         FN_START;
198
199         bt_ug_data *ugd = NULL;
200
201         ret_if(data == NULL);
202
203         ugd = (bt_ug_data *)data;
204
205         if (ugd->op_status == BT_SEARCHING)
206                 ugd->op_status = BT_ACTIVATED;
207
208         elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
209
210         if (ugd->status_item)
211                 elm_genlist_item_update(ugd->status_item);
212
213         if (ugd->paired_title)
214                 elm_genlist_item_update(ugd->paired_title);
215
216         if (ugd->searched_title)
217                 elm_genlist_item_update(ugd->searched_title);
218
219         if (ugd->searched_device == NULL ||
220              eina_list_count(ugd->searched_device) == 0) {
221                 /* Don't add the no device item, if no device item already exist */
222                 ret_if(ugd->no_device_item != NULL);
223                 ugd->no_device_item = _bt_main_add_no_device_found(ugd);
224         }
225
226         FN_END;
227 }
228
229
230 static bool __bt_cb_match_discovery_type(unsigned int major_class,
231                                                 unsigned int service_class,
232                                                 unsigned int mask)
233 {
234         FN_START;
235
236         bt_device_major_mask_t major_mask = BT_DEVICE_MAJOR_MASK_MISC;
237
238         if (mask == 0x000000)
239                 return TRUE;
240
241         BT_DBG("mask: %x", mask);
242
243         BT_DBG("service_class: %x", service_class);
244
245         /* Check the service_class */
246         if (service_class & mask)
247                 return TRUE;
248
249         /* Check the major class */
250         switch (major_class) {
251                 case BT_MAJOR_DEV_CLS_COMPUTER:
252                         major_mask = BT_DEVICE_MAJOR_MASK_COMPUTER;
253                         break;
254                 case BT_MAJOR_DEV_CLS_PHONE:
255                         major_mask = BT_DEVICE_MAJOR_MASK_PHONE;
256                         break;
257                 case BT_MAJOR_DEV_CLS_LAN_ACCESS_POINT:
258                         major_mask = BT_DEVICE_MAJOR_MASK_LAN_ACCESS_POINT;
259                         break;
260                 case BT_MAJOR_DEV_CLS_AUDIO:
261                         major_mask = BT_DEVICE_MAJOR_MASK_AUDIO;
262                         break;
263                 case BT_MAJOR_DEV_CLS_PERIPHERAL:
264                         major_mask = BT_DEVICE_MAJOR_MASK_PERIPHERAL;
265                         break;
266                 case BT_MAJOR_DEV_CLS_IMAGING:
267                         major_mask = BT_DEVICE_MAJOR_MASK_IMAGING;
268                         break;
269                 case BT_MAJOR_DEV_CLS_WEARABLE:
270                         major_mask = BT_DEVICE_MAJOR_MASK_WEARABLE;
271                         break;
272                 case BT_MAJOR_DEV_CLS_TOY:
273                         major_mask = BT_DEVICE_MAJOR_MASK_TOY;
274                         break;
275                 case BT_MAJOR_DEV_CLS_HEALTH:
276                         major_mask = BT_DEVICE_MAJOR_MASK_HEALTH;
277                         break;
278                 default:
279                         major_mask = BT_DEVICE_MAJOR_MASK_MISC;
280                         break;
281         }
282
283         BT_DBG("major_mask: %x", major_mask);
284
285         if (mask & major_mask)
286                 return TRUE;
287
288         FN_END;
289
290         return FALSE;
291 }
292
293
294 static void __bt_cb_new_device_found(bt_adapter_device_discovery_info_s *info,
295                                      void *data)
296 {
297         FN_START;
298
299         bt_ug_data *ugd = NULL;
300         bt_dev_t *dev = NULL;
301
302         ret_if(info == NULL);
303         ret_if(data == NULL);
304
305         ugd = (bt_ug_data *)data;
306
307         /* Check the service_class */
308         if (__bt_cb_match_discovery_type(
309                                 info->bt_class.major_device_class,
310                                 info->bt_class.major_service_class_mask,
311                                 ugd->search_type) == FALSE) {
312                 BT_DBG("No matched device type");
313                 return;
314         }
315
316         if (info->is_bonded == TRUE) {
317                 BT_DBG("Paired device found");
318                 return;
319         }
320
321         if (_bt_main_check_and_update_device(ugd->searched_device,
322                                         info->remote_address,
323                                         info->remote_name) >= 0) {
324                 /* Update all realized items */
325                 elm_genlist_realized_items_update(ugd->main_genlist);
326         } else {
327                 dev = _bt_main_create_searched_device_item((void *)info);
328                 if (NULL == dev) {
329                         BT_DBG("Create new device item failed \n");
330                         return;
331                 }
332
333                 if (_bt_main_is_matched_profile(ugd->search_type,
334                                                 dev->major_class,
335                                                 dev->service_class,
336                                                 ugd->service) == TRUE) {
337                         if (_bt_main_add_searched_device(ugd, dev) == NULL) {
338                                 BT_DBG("Fail to add the searched device \n");
339                                 return;
340                         }
341
342                         ugd->searched_device =
343                             eina_list_append(ugd->searched_device, dev);
344
345                         _bt_update_searched_item_style(ugd);
346                 } else {
347                         BT_DBG("Searched device does not match the profile\n");
348                         free(dev);
349                 }
350         }
351
352         FN_END;
353 }
354
355 /**********************************************************************
356 *                                                Common Functions
357 ***********************************************************************/
358
359 void _bt_cb_state_changed(int result,
360                         bt_adapter_state_e adapter_state,
361                         void *user_data)
362 {
363         FN_START;
364
365         if (adapter_state == BT_ADAPTER_ENABLED)
366                 __bt_cb_enable(result, user_data);
367         else
368                 __bt_cb_disable(result, user_data);
369
370         FN_END;
371 }
372
373 void _bt_cb_discovery_state_changed(int result,
374                         bt_adapter_device_discovery_state_e discovery_state,
375                         bt_adapter_device_discovery_info_s *discovery_info,
376                         void *user_data)
377 {
378         FN_START;
379
380         bt_ug_data *ugd = NULL;
381
382         ret_if(user_data == NULL);
383
384         ugd = (bt_ug_data *)user_data;
385
386         if (discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FOUND)
387                 __bt_cb_new_device_found(discovery_info, user_data);
388         else if (discovery_state == BT_ADAPTER_DEVICE_DISCOVERY_FINISHED)
389                 __bt_cb_search_completed(result, user_data);
390
391         FN_END;
392 }
393
394 void _bt_cb_bonding_created(int result, bt_device_info_s *dev_info,
395                                 void *user_data)
396 {
397         FN_START;
398
399         bt_ug_data *ugd = NULL;
400         bt_dev_t *dev = NULL;
401
402         ret_if(dev_info == NULL);
403         ret_if(user_data == NULL);
404
405         ugd = (bt_ug_data *)user_data;
406
407         if (ugd->op_status == BT_PAIRING)
408                 ugd->op_status = BT_ACTIVATED;
409
410         /* Enable UG to send another pairing request */
411         ugd->aul_pairing_req = FALSE;
412
413         /* In the NFC cas, we don't need to display the paired device */
414         if (ugd->bt_launch_mode == BT_LAUNCH_USE_NFC)
415                 return;
416
417         dev = _bt_main_get_dev_info_by_address(ugd->searched_device,
418                                         dev_info->remote_address);
419
420         if (dev == NULL)
421                 dev = _bt_main_get_dev_info(ugd->searched_device, ugd->searched_item);
422
423         if (result != BT_ERROR_NONE) {
424                 BT_DBG("Failed to pair with device : Error Cause[%d]", result);
425                 retm_if(dev == NULL, "dev is NULL\n");
426
427                 dev->status = BT_IDLE;
428                 elm_genlist_item_update((Elm_Object_Item *)dev->genlist_item);
429
430                 if (result != BT_ERROR_CANCELLED) {
431                         if (_bt_util_is_battery_low() == TRUE) {
432                                 _bt_main_create_information_popup(ugd, BT_STR_LOW_BATTERY);
433                         } else {
434                                 ugd->confirm_req = BT_PAIRING_REQ;
435                                 _bt_main_launch_syspopup(ugd, BT_SYSPOPUP_REQUEST_NAME,
436                                                 BT_STR_BLUETOOTH_ERROR_TRY_AGAIN_Q,
437                                                 BT_SYSPOPUP_TWO_BUTTON_TYPE);
438                         }
439                 }
440         } else {
441                 bt_dev_t *new_dev = NULL;
442                 Elm_Object_Item *item = NULL;
443                 void *profile;
444
445                 if (_bt_main_check_and_update_device(ugd->paired_device,
446                                         dev_info->remote_address,
447                                         dev_info->remote_name) >= 0) {
448                         /* Update all realized items */
449                         elm_genlist_realized_items_update(ugd->main_genlist);
450                 } else {
451                         if (dev != NULL) {
452                                 /* Remove the item in searched dialogue */
453                                 _bt_main_remove_searched_device(ugd, dev);
454                         }
455
456                         /* Add the item in paired dialogue group */
457                         new_dev = _bt_main_create_paired_device_item(dev_info);
458
459                         profile = _bt_get_registered_net_profile(ugd->connection,
460                                                                 new_dev->bd_addr);
461
462                         if (profile)
463                                 _bt_set_profile_state_changed_cb(profile, new_dev);
464
465                         item = _bt_main_add_paired_device(ugd, new_dev);
466
467                         if (item) {
468                                 ugd->paired_device =
469                                     eina_list_append(ugd->paired_device, new_dev);
470
471                                 _bt_update_paired_item_style(ugd);
472                         }
473
474                         _bt_main_connect_device(ugd, new_dev);
475
476                         ugd->searched_item = NULL;
477                         ugd->paired_item = item;
478                 }
479         }
480
481         elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
482
483         FN_END;
484 }
485
486 void _bt_cb_bonding_destroyed(int result, char *remote_address,
487                                         void *user_data)
488 {
489         FN_START;
490
491         bt_ug_data *ugd = NULL;
492         bt_dev_t *new_item = NULL;
493         bt_dev_t *item = NULL;
494         Eina_List *l = NULL;
495         int i;
496
497         retm_if(remote_address == NULL, "Invalid argument: param is NULL\n");
498         retm_if(user_data == NULL, "Invalid argument: param is NULL\n");
499
500         ugd = (bt_ug_data *)user_data;
501
502         if (result != BT_ERROR_NONE) {
503                 BT_DBG("Failed to unbond: [%d]", result);
504                 return;
505         }
506
507         EINA_LIST_FOREACH(ugd->paired_device, l, item) {
508                 if (item == NULL)
509                         break;
510
511                 if (memcmp((const char *)item->addr_str,
512                     (const char *)remote_address,
513                     BT_ADDRESS_LENGTH_MAX) == 0) {
514                         new_item = calloc(1, sizeof(bt_dev_t));
515                         if (new_item == NULL)
516                                 break;
517
518                         memcpy(new_item, item, sizeof(bt_dev_t));
519
520                         if (item->uuids && item->uuid_count > 0) {
521                                 new_item->uuids = g_new0(char *, item->uuid_count + 1);
522
523                                 for (i = 0; i < item->uuid_count; i++) {
524                                         new_item->uuids[i] = g_strdup(item->uuids[i]);
525                                 }
526                         }
527
528                         new_item->uuid_count = item->uuid_count;
529
530                         _bt_main_remove_paired_device(ugd, item);
531
532                         if (ugd->no_device_item) {
533                                 elm_object_item_del(ugd->no_device_item);
534                                 ugd->no_device_item = NULL;
535                         }
536
537                         if (_bt_main_add_searched_device(ugd, new_item) != NULL) {
538                                 ugd->searched_device = eina_list_append(
539                                                 ugd->searched_device, new_item);
540
541                                 _bt_update_searched_item_style(ugd);
542                         }
543
544                         BT_DBG("unbonding_count: %d", ugd->unbonding_count);
545
546                         if (ugd->unbonding_count <= 1) {
547                                 _bt_profile_delete_view((void *)new_item);
548                         } else {
549                                 ugd->unbonding_count--;
550                         }
551
552                         break;
553                 }
554         }
555
556         FN_END;
557 }
558
559 void _bt_cb_service_searched(int result, bt_device_sdp_info_s *sdp_info,
560                                 void* user_data)
561 {
562         FN_START;
563
564         int i;
565         bt_ug_data *ugd = NULL;
566         bt_service_class_t service_mask = 0;
567         bt_dev_t *item = NULL;
568         Evas_Object *btn = NULL;
569
570         ret_if(user_data == NULL);
571
572         ugd = (bt_ug_data *)user_data;
573
574         ugd->op_status = BT_ACTIVATED;
575
576         BT_DBG("Result: %d", result);
577
578         item = _bt_main_get_dev_info_by_address(ugd->paired_device,
579                                         sdp_info->remote_address);
580
581         if (item == NULL)
582                 item = _bt_main_get_dev_info(ugd->paired_device, ugd->paired_item);
583
584         if (item == NULL) {
585                 ugd->waiting_service_response = FALSE;
586                 ugd->auto_service_search = FALSE;
587                 return;
588         }
589
590         item->status = BT_IDLE;
591         elm_genlist_item_update((Elm_Object_Item *)item->genlist_item);
592
593         if (result == BT_ERROR_NONE) {
594                 _bt_util_get_service_mask_from_uuid_list(
595                                                 sdp_info->service_uuid,
596                                                 sdp_info->service_count,
597                                                 &service_mask);
598
599                 if (sdp_info->service_uuid != NULL && sdp_info->service_count > 0) {
600
601                         _bt_util_free_device_uuids(item);
602                         item->uuids = g_new0(char *, sdp_info->service_count + 1);
603
604                         for (i = 0; i < sdp_info->service_count; i++) {
605                                 item->uuids[i] = g_strdup(sdp_info->service_uuid[i]);
606                         }
607
608                         item->uuid_count = sdp_info->service_count;
609                 }
610
611                 item->service_list = service_mask;
612
613                 if (ugd->waiting_service_response == TRUE) {
614                         _bt_main_connect_device(ugd, item);
615                 }
616         } else {
617                 BT_DBG("Failed to get the service list [%d]", result);
618
619                 if (ugd->waiting_service_response == TRUE) {
620                         if (ugd->popup) {
621                                 evas_object_del(ugd->popup);
622                                 ugd->popup = NULL;
623                         }
624
625                         ugd->popup =
626                             _bt_create_popup(ugd->win_main, BT_STR_ERROR,
627                                         BT_STR_UNABLE_TO_GET_THE_SERVICE_LIST,
628                                         _bt_main_popup_del_cb, ugd, 2);
629                         ugd->back_cb = _bt_util_launch_no_event;
630
631                         btn = elm_button_add(ugd->popup);
632                         elm_object_text_set(btn, BT_STR_CANCEL);
633                         elm_object_part_content_set(ugd->popup, "button1", btn);
634                         evas_object_smart_callback_add(btn, "clicked",
635                                 (Evas_Smart_Cb)_bt_main_popup_del_cb, ugd);
636                 }
637         }
638
639         ugd->waiting_service_response = FALSE;
640         ugd->auto_service_search = FALSE;
641
642         FN_END;
643 }
644
645 void _bt_cb_hid_state_changed(int result, bool connected,
646                         const char *remote_address,
647                         void *user_data)
648 {
649         FN_START;
650
651         bt_address_t address = { { 0 } };
652
653         BT_DBG("Bluetooth HID Event [%d] Received");
654
655         _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
656
657         _bt_ipc_update_connected_status(user_data, BT_HID_CONNECTED,
658                                         connected, result, &address);
659         FN_END;
660 }
661
662 void _bt_cb_audio_state_changed(int result, bool connected,
663                                 const char *remote_address,
664                                 bt_audio_profile_type_e type,
665                                 void *user_data)
666 {
667         FN_START;
668
669         bt_address_t address = { { 0 } };
670         int connected_type;
671
672         BT_DBG("Bluetooth Audio Event [%d] Received");
673
674         if (type == BT_AUDIO_PROFILE_TYPE_A2DP)
675                 connected_type = BT_STEREO_HEADSET_CONNECTED;
676         else
677                 connected_type = BT_HEADSET_CONNECTED;
678
679         _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
680
681         _bt_ipc_update_connected_status(user_data, connected_type,
682                                         connected, result, &address);
683         FN_END;
684 }
685