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;
156 if (ugd->timeout_id) {
157 g_source_remove(ugd->timeout_id);
161 ugd->op_status = BT_DEACTIVATED;
162 ugd->visible = FALSE;
163 ugd->remain_time = 0;
165 if (ugd->visibility_timeout != BT_ALWAYS_ON) {
166 ugd->visibility_timeout = 0;
167 ugd->selected_radio = 0;
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);
175 if (ugd->bt_launch_mode != BT_LAUNCH_VISIBILITY) {
176 elm_object_disabled_set(ugd->scan_btn,
179 _bt_main_remove_all_paired_devices(ugd);
180 _bt_main_remove_all_searched_devices(ugd);
184 elm_genlist_item_update(ugd->status_item);
186 if (ugd->paired_title)
187 elm_genlist_item_update(ugd->paired_title);
189 if (ugd->searched_title)
190 elm_genlist_item_update(ugd->searched_title);
195 static void __bt_cb_search_completed(int result, void *data)
199 bt_ug_data *ugd = NULL;
201 ret_if(data == NULL);
203 ugd = (bt_ug_data *)data;
205 if (ugd->op_status == BT_SEARCHING)
206 ugd->op_status = BT_ACTIVATED;
208 elm_object_text_set(ugd->scan_btn, BT_STR_SCAN);
210 if (ugd->status_item)
211 elm_genlist_item_update(ugd->status_item);
213 if (ugd->paired_title)
214 elm_genlist_item_update(ugd->paired_title);
216 if (ugd->searched_title)
217 elm_genlist_item_update(ugd->searched_title);
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);
230 static bool __bt_cb_match_discovery_type(unsigned int major_class,
231 unsigned int service_class,
236 bt_device_major_mask_t major_mask = BT_DEVICE_MAJOR_MASK_MISC;
238 if (mask == 0x000000)
241 BT_DBG("mask: %x", mask);
243 BT_DBG("service_class: %x", service_class);
245 /* Check the service_class */
246 if (service_class & mask)
249 /* Check the major class */
250 switch (major_class) {
251 case BT_MAJOR_DEV_CLS_COMPUTER:
252 major_mask = BT_DEVICE_MAJOR_MASK_COMPUTER;
254 case BT_MAJOR_DEV_CLS_PHONE:
255 major_mask = BT_DEVICE_MAJOR_MASK_PHONE;
257 case BT_MAJOR_DEV_CLS_LAN_ACCESS_POINT:
258 major_mask = BT_DEVICE_MAJOR_MASK_LAN_ACCESS_POINT;
260 case BT_MAJOR_DEV_CLS_AUDIO:
261 major_mask = BT_DEVICE_MAJOR_MASK_AUDIO;
263 case BT_MAJOR_DEV_CLS_PERIPHERAL:
264 major_mask = BT_DEVICE_MAJOR_MASK_PERIPHERAL;
266 case BT_MAJOR_DEV_CLS_IMAGING:
267 major_mask = BT_DEVICE_MAJOR_MASK_IMAGING;
269 case BT_MAJOR_DEV_CLS_WEARABLE:
270 major_mask = BT_DEVICE_MAJOR_MASK_WEARABLE;
272 case BT_MAJOR_DEV_CLS_TOY:
273 major_mask = BT_DEVICE_MAJOR_MASK_TOY;
275 case BT_MAJOR_DEV_CLS_HEALTH:
276 major_mask = BT_DEVICE_MAJOR_MASK_HEALTH;
279 major_mask = BT_DEVICE_MAJOR_MASK_MISC;
283 BT_DBG("major_mask: %x", major_mask);
285 if (mask & major_mask)
294 static void __bt_cb_new_device_found(bt_adapter_device_discovery_info_s *info,
299 bt_ug_data *ugd = NULL;
300 bt_dev_t *dev = NULL;
302 ret_if(info == NULL);
303 ret_if(data == NULL);
305 ugd = (bt_ug_data *)data;
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");
316 if (info->is_bonded == TRUE) {
317 BT_DBG("Paired device found");
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);
327 dev = _bt_main_create_searched_device_item((void *)info);
329 BT_DBG("Create new device item failed \n");
333 if (_bt_main_is_matched_profile(ugd->search_type,
336 ugd->service) == TRUE) {
337 if (_bt_main_add_searched_device(ugd, dev) == NULL) {
338 BT_DBG("Fail to add the searched device \n");
342 ugd->searched_device =
343 eina_list_append(ugd->searched_device, dev);
345 _bt_update_searched_item_style(ugd);
347 BT_DBG("Searched device does not match the profile\n");
355 /**********************************************************************
357 ***********************************************************************/
359 void _bt_cb_state_changed(int result,
360 bt_adapter_state_e adapter_state,
365 if (adapter_state == BT_ADAPTER_ENABLED)
366 __bt_cb_enable(result, user_data);
368 __bt_cb_disable(result, user_data);
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,
380 bt_ug_data *ugd = NULL;
382 ret_if(user_data == NULL);
384 ugd = (bt_ug_data *)user_data;
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);
394 void _bt_cb_bonding_created(int result, bt_device_info_s *dev_info,
399 bt_ug_data *ugd = NULL;
400 bt_dev_t *dev = NULL;
402 ret_if(dev_info == NULL);
403 ret_if(user_data == NULL);
405 ugd = (bt_ug_data *)user_data;
407 if (ugd->op_status == BT_PAIRING)
408 ugd->op_status = BT_ACTIVATED;
410 /* Enable UG to send another pairing request */
411 ugd->aul_pairing_req = FALSE;
413 /* In the NFC cas, we don't need to display the paired device */
414 if (ugd->bt_launch_mode == BT_LAUNCH_USE_NFC)
417 dev = _bt_main_get_dev_info_by_address(ugd->searched_device,
418 dev_info->remote_address);
421 dev = _bt_main_get_dev_info(ugd->searched_device, ugd->searched_item);
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");
427 dev->status = BT_IDLE;
428 elm_genlist_item_update((Elm_Object_Item *)dev->genlist_item);
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);
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);
441 bt_dev_t *new_dev = NULL;
442 Elm_Object_Item *item = NULL;
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);
452 /* Remove the item in searched dialogue */
453 _bt_main_remove_searched_device(ugd, dev);
456 /* Add the item in paired dialogue group */
457 new_dev = _bt_main_create_paired_device_item(dev_info);
459 profile = _bt_get_registered_net_profile(ugd->connection,
463 _bt_set_profile_state_changed_cb(profile, new_dev);
465 item = _bt_main_add_paired_device(ugd, new_dev);
469 eina_list_append(ugd->paired_device, new_dev);
471 _bt_update_paired_item_style(ugd);
474 _bt_main_connect_device(ugd, new_dev);
476 ugd->searched_item = NULL;
477 ugd->paired_item = item;
481 elm_object_disabled_set(ugd->scan_btn, EINA_FALSE);
486 void _bt_cb_bonding_destroyed(int result, char *remote_address,
491 bt_ug_data *ugd = NULL;
492 bt_dev_t *new_item = NULL;
493 bt_dev_t *item = NULL;
497 retm_if(remote_address == NULL, "Invalid argument: param is NULL\n");
498 retm_if(user_data == NULL, "Invalid argument: param is NULL\n");
500 ugd = (bt_ug_data *)user_data;
502 if (result != BT_ERROR_NONE) {
503 BT_DBG("Failed to unbond: [%d]", result);
507 EINA_LIST_FOREACH(ugd->paired_device, l, item) {
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)
518 memcpy(new_item, item, sizeof(bt_dev_t));
520 if (item->uuids && item->uuid_count > 0) {
521 new_item->uuids = g_new0(char *, item->uuid_count + 1);
523 for (i = 0; i < item->uuid_count; i++) {
524 new_item->uuids[i] = g_strdup(item->uuids[i]);
528 new_item->uuid_count = item->uuid_count;
530 _bt_main_remove_paired_device(ugd, item);
532 if (ugd->no_device_item) {
533 elm_object_item_del(ugd->no_device_item);
534 ugd->no_device_item = NULL;
537 if (_bt_main_add_searched_device(ugd, new_item) != NULL) {
538 ugd->searched_device = eina_list_append(
539 ugd->searched_device, new_item);
541 _bt_update_searched_item_style(ugd);
544 BT_DBG("unbonding_count: %d", ugd->unbonding_count);
546 if (ugd->unbonding_count <= 1) {
547 _bt_profile_delete_view((void *)new_item);
549 ugd->unbonding_count--;
559 void _bt_cb_service_searched(int result, bt_device_sdp_info_s *sdp_info,
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;
570 ret_if(user_data == NULL);
572 ugd = (bt_ug_data *)user_data;
574 ugd->op_status = BT_ACTIVATED;
576 BT_DBG("Result: %d", result);
578 item = _bt_main_get_dev_info_by_address(ugd->paired_device,
579 sdp_info->remote_address);
582 item = _bt_main_get_dev_info(ugd->paired_device, ugd->paired_item);
585 ugd->waiting_service_response = FALSE;
586 ugd->auto_service_search = FALSE;
590 item->status = BT_IDLE;
591 elm_genlist_item_update((Elm_Object_Item *)item->genlist_item);
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,
599 if (sdp_info->service_uuid != NULL && sdp_info->service_count > 0) {
601 _bt_util_free_device_uuids(item);
602 item->uuids = g_new0(char *, sdp_info->service_count + 1);
604 for (i = 0; i < sdp_info->service_count; i++) {
605 item->uuids[i] = g_strdup(sdp_info->service_uuid[i]);
608 item->uuid_count = sdp_info->service_count;
611 item->service_list = service_mask;
613 if (ugd->waiting_service_response == TRUE) {
614 _bt_main_connect_device(ugd, item);
617 BT_DBG("Failed to get the service list [%d]", result);
619 if (ugd->waiting_service_response == TRUE) {
621 evas_object_del(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;
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);
639 ugd->waiting_service_response = FALSE;
640 ugd->auto_service_search = FALSE;
645 void _bt_cb_hid_state_changed(int result, bool connected,
646 const char *remote_address,
651 bt_address_t address = { { 0 } };
653 BT_DBG("Bluetooth HID Event [%d] Received");
655 _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
657 _bt_ipc_update_connected_status(user_data, BT_HID_CONNECTED,
658 connected, result, &address);
662 void _bt_cb_audio_state_changed(int result, bool connected,
663 const char *remote_address,
664 bt_audio_profile_type_e type,
669 bt_address_t address = { { 0 } };
672 BT_DBG("Bluetooth Audio Event [%d] Received");
674 if (type == BT_AUDIO_PROFILE_TYPE_A2DP)
675 connected_type = BT_STEREO_HEADSET_CONNECTED;
677 connected_type = BT_HEADSET_CONNECTED;
679 _bt_util_addr_string_to_addr_type(address.bd_addr, remote_address);
681 _bt_ipc_update_connected_status(user_data, connected_type,
682 connected, result, &address);