2 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
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
8 * http://floralicense.org/license/
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.
18 #include <vconf-keys.h>
19 #include <bluetooth.h>
22 #include "bt-main-ug.h"
23 #include "bt-main-view.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"
31 /**********************************************************************
33 ***********************************************************************/
35 static void __bt_cb_auto_discovery(void *data)
40 bt_ug_data *ugd = NULL;
44 ugd = (bt_ug_data *)data;
46 ret_if(elm_win_focus_get(ugd->win_main) == FALSE);
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);
53 ret = bt_adapter_start_device_discovery();
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);
59 if (ugd->searched_title == NULL)
60 _bt_main_add_searched_title(ugd);
62 BT_DBG("Discovery failed : Error Cause[%d]", ret);
66 ugd->search_req = FALSE;
71 static void __bt_cb_enable(int result, void *data)
76 bt_ug_data *ugd = NULL;
80 ugd = (bt_ug_data *)data;
82 if (ugd->op_status == BT_ACTIVATED) {
83 BT_DBG("Already enabled state");
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);
93 ugd->op_status = BT_ACTIVATED;
94 ugd->aul_pairing_req = FALSE;
97 if (vconf_get_int(BT_VCONF_VISIBLE_TIME, &timeout) != 0) {
98 BT_DBG("Fail to get the timeout value");
101 if (timeout == BT_ALWAYS_ON) {
103 ugd->remain_time = 0;
104 ugd->visibility_timeout = timeout;
105 ugd->selected_radio = _bt_util_get_timeout_index(timeout);
108 _bt_util_set_phone_name();
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);
114 ret_if(ugd->bt_launch_mode == BT_LAUNCH_VISIBILITY);
116 elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
118 if (ugd->paired_title)
119 elm_genlist_item_update(ugd->paired_title);
121 if (ugd->searched_title)
122 elm_genlist_item_update(ugd->searched_title);
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);
128 __bt_cb_auto_discovery(ugd);
133 static void __bt_cb_disable(int result, void *data)
136 bt_ug_data *ugd = NULL;
138 ret_if(data == NULL);
140 ugd = (bt_ug_data *)data;
142 if (ugd->op_status == BT_DEACTIVATED) {
143 BT_DBG("Already disabled state");
148 evas_object_del(ugd->popup);
152 if (result != BT_ERROR_NONE) {
153 BT_DBG("Failed to enable Bluetooth : Error Cause[%d]", result);
154 ugd->op_status = BT_ACTIVATED;
157 /* Delete profile view */
158 _bt_profile_destroy_profile_view(ugd);
160 if (ugd->timeout_id) {
161 g_source_remove(ugd->timeout_id);
165 ugd->op_status = BT_DEACTIVATED;
166 ugd->visible = FALSE;
167 ugd->remain_time = 0;
169 if (ugd->visibility_timeout != BT_ALWAYS_ON) {
170 ugd->visibility_timeout = 0;
171 ugd->selected_radio = 0;
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,
181 elm_object_item_disabled_set(ugd->visible_item, EINA_TRUE);
183 if (ugd->bt_launch_mode != BT_LAUNCH_VISIBILITY) {
184 elm_object_disabled_set(ugd->scan_btn,
187 _bt_main_remove_all_paired_devices(ugd);
188 _bt_main_remove_all_searched_devices(ugd);
192 elm_genlist_item_update(ugd->status_item);
193 elm_genlist_item_update(ugd->visible_item);
195 if (ugd->paired_title)
196 elm_genlist_item_update(ugd->paired_title);
198 if (ugd->searched_title)
199 elm_genlist_item_update(ugd->searched_title);
204 static void __bt_cb_search_completed(int result, void *data)
208 bt_ug_data *ugd = NULL;
210 ret_if(data == NULL);
212 ugd = (bt_ug_data *)data;
214 if (ugd->op_status == BT_SEARCHING)
215 ugd->op_status = BT_ACTIVATED;
217 elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
219 if (ugd->status_item)
220 elm_genlist_item_update(ugd->status_item);
222 if (ugd->paired_title)
223 elm_genlist_item_update(ugd->paired_title);
225 if (ugd->searched_title)
226 elm_genlist_item_update(ugd->searched_title);
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);
234 if (ugd->no_device_item)
235 elm_genlist_item_update(ugd->no_device_item);
242 static bool __bt_cb_match_discovery_type(unsigned int major_class,
243 unsigned int service_class,
248 bt_device_major_mask_t major_mask = BT_DEVICE_MAJOR_MASK_MISC;
250 if (mask == 0x000000)
253 BT_DBG("mask: %x", mask);
255 BT_DBG("service_class: %x", service_class);
257 /* Check the service_class */
258 if (service_class & mask)
261 /* Check the major class */
262 switch (major_class) {
263 case BT_MAJOR_DEV_CLS_COMPUTER:
264 major_mask = BT_DEVICE_MAJOR_MASK_COMPUTER;
266 case BT_MAJOR_DEV_CLS_PHONE:
267 major_mask = BT_DEVICE_MAJOR_MASK_PHONE;
269 case BT_MAJOR_DEV_CLS_LAN_ACCESS_POINT:
270 major_mask = BT_DEVICE_MAJOR_MASK_LAN_ACCESS_POINT;
272 case BT_MAJOR_DEV_CLS_AUDIO:
273 major_mask = BT_DEVICE_MAJOR_MASK_AUDIO;
275 case BT_MAJOR_DEV_CLS_PERIPHERAL:
276 major_mask = BT_DEVICE_MAJOR_MASK_PERIPHERAL;
278 case BT_MAJOR_DEV_CLS_IMAGING:
279 major_mask = BT_DEVICE_MAJOR_MASK_IMAGING;
281 case BT_MAJOR_DEV_CLS_WEARABLE:
282 major_mask = BT_DEVICE_MAJOR_MASK_WEARABLE;
284 case BT_MAJOR_DEV_CLS_TOY:
285 major_mask = BT_DEVICE_MAJOR_MASK_TOY;
287 case BT_MAJOR_DEV_CLS_HEALTH:
288 major_mask = BT_DEVICE_MAJOR_MASK_HEALTH;
291 major_mask = BT_DEVICE_MAJOR_MASK_MISC;
295 BT_DBG("major_mask: %x", major_mask);
297 if (mask & major_mask)
306 static void __bt_cb_new_device_found(bt_adapter_device_discovery_info_s *info,
311 bt_ug_data *ugd = NULL;
312 bt_dev_t *dev = NULL;
314 ret_if(info == NULL);
315 ret_if(data == NULL);
317 ugd = (bt_ug_data *)data;
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");
328 if (info->is_bonded == TRUE) {
329 BT_DBG("Paired device found");
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);
338 dev = _bt_main_create_searched_device_item((void *)info);
340 BT_DBG("Create new device item failed \n");
344 if (_bt_main_is_matched_profile(ugd->search_type,
347 ugd->service) == TRUE) {
348 if (_bt_main_add_searched_device(ugd, dev) == NULL) {
349 BT_DBG("Fail to add the searched device \n");
353 ugd->searched_device =
354 eina_list_append(ugd->searched_device, dev);
356 _bt_update_searched_item_style(ugd);
358 BT_DBG("Searched device does not match the profile\n");
366 /**********************************************************************
368 ***********************************************************************/
370 void _bt_cb_state_changed(int result,
371 bt_adapter_state_e adapter_state,
376 if (adapter_state == BT_ADAPTER_ENABLED)
377 __bt_cb_enable(result, user_data);
379 __bt_cb_disable(result, user_data);
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,
391 bt_ug_data *ugd = NULL;
393 ret_if(user_data == NULL);
395 ugd = (bt_ug_data *)user_data;
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);
405 void _bt_cb_bonding_created(int result, bt_device_info_s *dev_info,
410 bt_ug_data *ugd = NULL;
411 bt_dev_t *dev = NULL;
413 ret_if(dev_info == NULL);
414 ret_if(user_data == NULL);
416 ugd = (bt_ug_data *)user_data;
418 if (ugd->op_status == BT_PAIRING)
419 ugd->op_status = BT_ACTIVATED;
421 /* Enable UG to send another pairing request */
422 ugd->aul_pairing_req = FALSE;
424 /* In the NFC cas, we don't need to display the paired device */
425 if (ugd->bt_launch_mode == BT_LAUNCH_USE_NFC)
428 dev = _bt_main_get_dev_info_by_address(ugd->searched_device,
429 dev_info->remote_address);
432 dev = _bt_main_get_dev_info(ugd->searched_device, ugd->searched_item);
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");
438 dev->status = BT_IDLE;
439 elm_genlist_item_update((Elm_Object_Item *)dev->genlist_item);
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);
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);
452 bt_dev_t *new_dev = NULL;
453 Elm_Object_Item *item = NULL;
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);
462 /* Remove the item in searched dialogue */
463 _bt_main_remove_searched_device(ugd, dev);
466 /* Add the item in paired dialogue group */
467 new_dev = _bt_main_create_paired_device_item(dev_info);
469 profile = _bt_get_registered_net_profile(ugd->connection,
473 _bt_set_profile_state_changed_cb(profile, new_dev);
475 item = _bt_main_add_paired_device(ugd, new_dev);
479 eina_list_append(ugd->paired_device, new_dev);
481 _bt_update_paired_item_style(ugd);
484 /* Don't try to auto-connect in the network case */
485 if (profile == NULL) {
486 _bt_main_connect_device(ugd, new_dev);
489 ugd->searched_item = NULL;
490 ugd->paired_item = item;
494 elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
499 void _bt_cb_bonding_destroyed(int result, char *remote_address,
504 bt_ug_data *ugd = NULL;
505 bt_dev_t *new_item = NULL;
506 bt_dev_t *item = NULL;
510 retm_if(remote_address == NULL, "Invalid argument: param is NULL\n");
511 retm_if(user_data == NULL, "Invalid argument: param is NULL\n");
513 ugd = (bt_ug_data *)user_data;
515 if (result != BT_ERROR_NONE) {
516 BT_DBG("Failed to unbond: [%d]", result);
520 EINA_LIST_FOREACH(ugd->paired_device, l, item) {
524 if (g_strcmp0(item->addr_str, remote_address) == 0) {
525 new_item = calloc(1, sizeof(bt_dev_t));
526 if (new_item == NULL)
529 memcpy(new_item, item, sizeof(bt_dev_t));
531 if (item->uuids && item->uuid_count > 0) {
532 new_item->uuids = g_new0(char *, item->uuid_count + 1);
534 for (i = 0; i < item->uuid_count; i++) {
535 new_item->uuids[i] = g_strdup(item->uuids[i]);
539 new_item->uuid_count = item->uuid_count;
541 _bt_main_remove_paired_device(ugd, item);
543 if (ugd->no_device_item) {
544 elm_object_item_del(ugd->no_device_item);
545 ugd->no_device_item = NULL;
548 if (_bt_main_add_searched_device(ugd, new_item) != NULL) {
549 ugd->searched_device = eina_list_append(
550 ugd->searched_device, new_item);
552 _bt_update_searched_item_style(ugd);
555 BT_DBG("unbonding_count: %d", ugd->unbonding_count);
557 if (ugd->unbonding_count <= 1) {
558 _bt_profile_delete_view((void *)new_item);
560 ugd->unbonding_count--;
570 void _bt_cb_service_searched(int result, bt_device_sdp_info_s *sdp_info,
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;
581 ret_if(user_data == NULL);
583 ugd = (bt_ug_data *)user_data;
585 ugd->op_status = BT_ACTIVATED;
587 BT_DBG("Result: %d", result);
589 item = _bt_main_get_dev_info_by_address(ugd->paired_device,
590 sdp_info->remote_address);
593 item = _bt_main_get_dev_info(ugd->paired_device, ugd->paired_item);
596 ugd->waiting_service_response = FALSE;
597 ugd->auto_service_search = FALSE;
601 item->status = BT_IDLE;
602 elm_genlist_item_update((Elm_Object_Item *)item->genlist_item);
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,
610 if (sdp_info->service_uuid != NULL && sdp_info->service_count > 0) {
612 _bt_util_free_device_uuids(item);
613 item->uuids = g_new0(char *, sdp_info->service_count + 1);
615 for (i = 0; i < sdp_info->service_count; i++) {
616 item->uuids[i] = g_strdup(sdp_info->service_uuid[i]);
619 item->uuid_count = sdp_info->service_count;
622 item->service_list = service_mask;
624 if (ugd->waiting_service_response == TRUE) {
625 _bt_main_connect_device(ugd, item);
628 BT_DBG("Failed to get the service list [%d]", result);
630 if (ugd->waiting_service_response == TRUE) {
632 evas_object_del(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;
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);
650 ugd->waiting_service_response = FALSE;
651 ugd->auto_service_search = FALSE;
656 void _bt_cb_hid_state_changed(int result, bool connected,
657 const char *remote_address,
662 bt_address_t address = { { 0 } };
664 BT_DBG("Bluetooth HID Event [%d] Received");
666 _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
668 _bt_ipc_update_connected_status(user_data, BT_HID_CONNECTED,
669 connected, result, &address);
673 void _bt_cb_audio_state_changed(int result, bool connected,
674 const char *remote_address,
675 bt_audio_profile_type_e type,
680 bt_address_t address = { { 0 } };
683 BT_DBG("Bluetooth Audio Event [%d] Received");
685 if (type == BT_AUDIO_PROFILE_TYPE_A2DP)
686 connected_type = BT_STEREO_HEADSET_CONNECTED;
688 connected_type = BT_HEADSET_CONNECTED;
690 _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
692 _bt_ipc_update_connected_status(user_data, connected_type,
693 connected, result, &address);