4 * Copyright (c) 2014 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Chethan T N <chethan.tn@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
9 * Rakesh MK <rakesh.mk@samsung.com>
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
29 #include <gio/gunixfdlist.h>
30 #include <bundle_internal.h>
31 #include "bluetooth-ag-agent.h"
32 #include "bluetooth-ag-handler.h"
33 #include "bluetooth-agent-profile.h"
35 #include <bluetooth.h>
36 #include <bluetooth_internal.h>
38 #include <TapiUtility.h>
40 #include <ITapiModem.h>
41 #include <ITapiCall.h>
42 #include <TelNetwork.h>
46 #include <system_info.h>
50 #include <device-error.h>
51 #include <device/battery.h>
52 #include <device/callback.h>
54 static GMainLoop *gmain_loop;
55 static GDBusProxy *profile_gproxy;
56 static guint interface_added_sig_id;
57 static guint interface_removed_sig_id;
58 static guint proterty_changed_sig_id;
59 static guint name_owner_sig_id;
60 GDBusConnection *ag_dbus_conn = NULL;
61 gchar *remote_dev_path = NULL;
65 static TapiHandle *tapi_handle[3];
68 static TapiHandle *tapi_handle_preferred_sim;
69 extern wbs_options wbs_opts;
70 GSList *active_devices = NULL;
71 static gchar *local_addr;
72 static gboolean call_launch_requested = FALSE;
73 static gchar* sco_owner;
74 static guint sco_open_timer_id;
75 static gboolean sco_open_request;
76 static guint hf_bluez_id;
77 static guint hs_bluez_id;
79 static guint device_property_id;
80 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
81 static guint media_sig_id;
82 static guint media_state_sig_id;
83 static bt_ag_media_transport_state_t transport_state;
85 static int last_speaker_gain = 9;
87 #define GET_TAPI_HANDLE \
88 (tapi_handle_preferred_sim != NULL) ? tapi_handle_preferred_sim : \
89 ((sim1 == 1) ? tapi_handle[0] : tapi_handle[1])
91 #define HSP_AG_UUID "00001112-0000-1000-8000-00805f9b34fb"
92 #define HFP_AG_UUID "0000111f-0000-1000-8000-00805f9b34fb"
93 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
94 #define A2DP_SINK_UUID "0000110b-0000-1000-8000-00805f9b34fb"
96 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
97 #define VCONF_KEY_BT_LUNAR_ENABLED "db/wms/bt_loop_device_hfp_connected"
99 #define CALL_ALIAS_APP_ID "tizen.call"
101 #if defined(TIZEN_SUPPORT_DUAL_HF)
102 #define VCONF_KEY_BT_HOST_BT_MAC_ADDR "db/wms/host_bt_mac"
103 #define MAX_CONNECTED_DEVICES 2
105 #define MAX_CONNECTED_DEVICES 1
108 #define BT_AG_SIG_NUM 3
109 static struct sigaction bt_ag_sigoldact[BT_AG_SIG_NUM];
110 static int bt_ag_sig_to_handle[] = { SIGABRT, SIGSEGV, SIGTERM };
112 /*Below Inrospection data is exposed to bluez from agent*/
113 static const gchar ag_agent_bluez_introspection_xml[] =
115 " <interface name='org.bluez.Profile1'>"
116 " <method name='NewConnection'>"
117 " <arg type='o' name='device' direction='in'/>"
118 " <arg type='h' name='fd' direction='in'/>"
119 " <arg type='a{sv}' name='options' direction='in'/>"
121 " <method name='RequestDisconnection'>"
122 " <arg type='o' name='device' direction='in'/>"
124 " <method name='ReplyAuthorize'>"
125 " <arg type='u' name='accept' direction='in'/>"
130 /*Below Introspection data is exposed to application from agent*/
131 static const gchar ag_agent_app_introspection_xml[] =
133 " <interface name='Org.Hfp.App.Interface'>"
134 " <method name='RegisterApplication'>"
135 " <arg type='s' name='path' direction='in'/>"
136 " <arg type='s' name='address' direction='in'/>"
138 " <method name='UnregisterApplication'>"
139 " <arg type='s' name='path' direction='in'/>"
141 " <method name='IncomingCall'>"
142 " <arg type='s' name='path' direction='in'/>"
143 " <arg type='s' name='number' direction='in'/>"
144 " <arg type='i' name='id' direction='in'/>"
146 " <method name='OutgoingCall'>"
147 " <arg type='s' name='path' direction='in'/>"
148 " <arg type='s' name='number' direction='in'/>"
149 " <arg type='i' name='id' direction='in'/>"
151 " <method name='ChangeCallStatus'>"
152 " <arg type='s' name='path' direction='in'/>"
153 " <arg type='s' name='number' direction='in'/>"
154 " <arg type='i' name='status' direction='in'/>"
155 " <arg type='i' name='id' direction='in'/>"
157 " <method name='GetProperties'>"
158 " <arg type='a{sv}' name='properties' direction='out'/>"
160 " <method name='Disconnect'>"
162 " <method name='IsConnected'>"
163 " <arg type='b' name='connected' direction='out'/>"
165 " <method name='IndicateCall'>"
167 " <method name='CancelCall'>"
169 " <method name='Play'>"
171 " <method name='Stop'>"
173 " <method name='IsPlaying'>"
174 " <arg type='b' name='playing' direction='out'/>"
176 " <method name='GetSpeakerGain'>"
177 " <arg type='q' name='gain' direction='out'/>"
179 " <method name='GetMicrophoneGain'>"
180 " <arg type='q' name='gain' direction='out'/>"
182 " <method name='SetSpeakerGain'>"
183 " <arg type='q' name='gain' direction='in'/>"
185 " <method name='SetMicrophoneGain'>"
186 " <arg type='q' name='gain' direction='in'/>"
188 " <method name='SetVoiceDial'>"
189 " <arg type='b' name='enable' direction='in'/>"
191 " <method name='CheckPrivilege'>"
193 " <method name='SwapHeadset'>"
194 " <arg type='s' name='remote_addr' direction='in'/>"
201 int (*callback)(bt_ag_info_t *hs, const char *buf);
204 struct sco_socket_addr {
205 sa_family_t sco_family;
213 bt_ag_status_t ag = {
214 .telephony_ready = FALSE,
218 .rh = BT_RSP_HOLD_NOT_SUPPORTED,
224 static void __bt_ag_agent_sigterm_handler(int signo);
225 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
226 const gchar *object_path);
227 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs);
228 static gboolean __bt_ag_event_handler(GIOChannel *channel, GIOCondition cond,
230 static int __bt_ag_sco_connect(bt_ag_info_t *hs);
231 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state);
232 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data);
233 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle);
234 static uint32_t __bt_ag_agent_get_ag_features(void);
235 static void __bt_ag_agent_tel_cb(TapiHandle *handle, int result, void *data, void *user_data);
236 static void __bt_ag_agent_subscribe_tapi_updates(TapiHandle *handle);
237 static void __bt_ag_agent_unsubscribe_tapi_updates(TapiHandle *handle);
238 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
239 const gchar *sender_name,
240 const gchar *object_path,
241 const gchar *interface_name,
242 const gchar *signal_name,
243 GVariant *parameters,
245 static GError *__bt_ag_agent_set_error(bt_hfp_agent_error_t error);
247 static void __bt_convert_addr_type_to_rev_string(char *address,
250 ret_if(address == NULL);
251 ret_if(addr == NULL);
253 g_snprintf(address, BT_ADDRESS_STRING_SIZE,
254 "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
255 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0]);
258 static GDBusProxy *__bt_ag_gdbus_init_profile_proxy(void)
265 if (ag_dbus_conn == NULL)
266 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
270 ERR("Unable to connect to gdbus: %s", err->message);
276 proxy = g_dbus_proxy_new_sync(ag_dbus_conn,
277 G_DBUS_PROXY_FLAGS_NONE, NULL,
278 BLUEZ_SERVICE_NAME, "/org/bluez",
279 BLUEZ_PROFILE_MGMT_INTERFACE, NULL, &err);
282 ERR("Unable to create proxy: %s", err->message);
288 profile_gproxy = proxy;
294 static GDBusProxy *__bt_ag_gdbus_get_app_proxy(const gchar *service,
295 const gchar *path, const gchar *interface)
302 if (ag_dbus_conn == NULL)
303 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
307 ERR("Unable to connect to gdbus: %s", err->message);
313 DBG("%s %s %s", service, path, interface);
315 proxy = g_dbus_proxy_new_sync(ag_dbus_conn,
316 G_DBUS_PROXY_FLAGS_NONE, NULL,
318 interface, NULL, &err);
322 ERR("Unable to create proxy: %s", err->message);
332 static int __bt_ag_agent_gdbus_method_send(const char *service,
333 const gchar *path, const char *interface,
334 const char *method, gboolean response,
335 GVariant *parameters)
341 GError *error = NULL;
343 proxy = __bt_ag_gdbus_get_app_proxy(service, path, interface);
345 return BT_HFP_AGENT_ERROR_INTERNAL;
348 ret = g_dbus_proxy_call_sync(proxy,
350 G_DBUS_CALL_FLAGS_NONE, -1,
353 /* dBUS-RPC is failed */
354 ERR("dBUS-RPC is failed");
356 /* dBUS gives error cause */
357 ERR("D-Bus API failure: errCode[%x], message[%s]",
358 error->code, error->message);
360 g_clear_error(&error);
362 g_object_unref(proxy);
363 return BT_HFP_AGENT_ERROR_INTERNAL;
366 g_variant_unref(ret);
368 g_dbus_proxy_call(proxy,
370 G_DBUS_CALL_FLAGS_NONE, 2000,
373 g_object_unref(proxy);
375 return BT_HFP_AGENT_ERROR_NONE;
378 gboolean _bt_ag_agent_emit_signal(
379 GDBusConnection *connection,
381 const char *interface,
387 GError *error = NULL;
389 ret = g_dbus_connection_emit_signal(connection,
390 NULL, path, interface,
395 /* dBUS gives error cause */
396 ERR("D-Bus API failure: errCode[%x], message[%s]",
397 error->code, error->message);
398 g_clear_error(&error);
401 INFO_C("Emit Signal done = [%s]", name);
407 gboolean _bt_ag_agent_emit_property_changed(
408 GDBusConnection *connection,
410 const char *interface,
419 var_data = g_variant_new("(sv)", name, property);
421 ret = _bt_ag_agent_emit_signal(connection,
423 "PropertyChanged", var_data);
428 static void __bt_ag_agent_start_watch(bt_ag_info_t *bt_ag_info)
430 bt_ag_info->watch_id = g_io_add_watch(bt_ag_info->io_chan,
431 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
432 (GIOFunc) __bt_ag_event_handler, bt_ag_info);
435 static void __bt_ag_agent_remove_watch(guint *watch_id)
437 DBG("Remove IO watch ID %d", *watch_id);
439 g_source_remove(*watch_id);
444 #if defined(TIZEN_SUPPORT_DUAL_HF)
445 gboolean __bt_ag_agent_is_companion_device(const char *addr)
447 if (TIZEN_PROFILE_WEARABLE) {
448 char *host_device_address = NULL;
449 host_device_address = vconf_get_str(VCONF_KEY_BT_HOST_BT_MAC_ADDR);
451 if (!host_device_address) {
452 INFO("Failed to get a companion device address");
456 if (g_strcmp0(host_device_address, addr) == 0) {
457 INFO("addr[%s] is companion device", addr);
458 free(host_device_address);
461 free(host_device_address);
467 void __bt_convert_device_path_to_address(const gchar *device_path,
468 char *device_address)
470 char address[BT_ADDRESS_STRING_SIZE] = { 0 };
473 ret_if(device_path == NULL);
474 ret_if(device_address == NULL);
476 dev_addr = strstr(device_path, "dev_");
477 if (dev_addr != NULL) {
480 g_strlcpy(address, dev_addr, sizeof(address));
482 while ((pos = strchr(address, '_')) != NULL)
485 g_strlcpy(device_address, address, BT_ADDRESS_STRING_SIZE);
489 static gboolean __bt_ag_agent_is_companion_device_connected(void)
493 for (l = active_devices ; l; l = l->next) {
494 bt_ag_info_t *data = l->data;
496 if (data->is_companion_device) {
497 DBG("Companion device found");
505 gboolean __bt_ag_agent_check_dual_hf_condition(const gchar *device_path)
507 char device_address[BT_ADDRESS_STRING_SIZE] = { 0 };
508 gboolean is_companion_device;
510 __bt_convert_device_path_to_address(device_path, device_address);
511 is_companion_device = __bt_ag_agent_is_companion_device(device_address);
513 DBG_SECURE(" device_address[%s]", device_address);
514 DBG(" is_companion_device[%d]", is_companion_device);
516 if (__bt_ag_agent_is_companion_device_connected()) {
517 if (is_companion_device)
520 if (!is_companion_device)
525 #endif /* TIZEN_SUPPORT_DUAL_HF */
527 static gboolean __bt_is_phone_locked(int *phone_lock_state)
532 if (NULL == phone_lock_state)
535 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, phone_lock_state);
537 ERR("Failed to read [%s]\n", VCONFKEY_IDLE_LOCK_STATE);
545 static gboolean __bt_get_outgoing_callapp_type(int *callapp_type)
549 if (NULL == callapp_type)
552 *callapp_type = BT_VOICE_CALL;
557 static gboolean __bt_get_outgoing_call_condition(int *condition)
561 if (NULL == condition)
564 *condition = BT_MO_ONLY_UNLOCKED;
569 static gboolean __bt_ag_agent_launch_call_app(const char *number)
574 DBG_SECURE("number(%s)", number);
578 ERR("bundle_create() Failed");
582 bundle_add(b, "launch-type", "MO");
583 bundle_add(b, "dial-type", "HEADSET");
585 if (strlen(number) != 0)
586 bundle_add(b, "number", number);
588 aul_launch_app_async(CALL_ALIAS_APP_ID, b);
595 static gboolean __bt_ag_agent_launch_call_req(void *arg)
598 bundle *b = (bundle *)arg;
600 if (appsvc_run_service(b, 0, NULL, NULL) < 0)
601 ERR("Unable to run app svc");
603 call_launch_requested = FALSE;
608 static gboolean __bt_ag_agent_make_call(const char *number)
612 char telnum[BT_MAX_TEL_NUM_STRING];
615 if (TIZEN_PROFILE_WEARABLE)
616 return __bt_ag_agent_launch_call_app(number);
618 if (call_launch_requested == TRUE) {
619 DBG("Launch request is in progress");
627 appsvc_set_operation(b, APPSVC_OPERATION_CALL);
628 snprintf(telnum, sizeof(telnum), "tel:%s", number);
629 appsvc_set_uri(b, telnum);
630 appsvc_add_data(b, "ctindex", "-1");
632 call_launch_requested = TRUE;
633 g_idle_add(__bt_ag_agent_launch_call_req, b);
639 static gboolean __bt_ag_agent_make_video_call(const char *mo_number)
644 kb = bundle_create();
648 bundle_add(kb, "KEY_CALL_TYPE", "MO");
649 bundle_add(kb, "number", mo_number);
650 aul_launch_app("org.tizen.vtmain", kb);
657 gboolean _bt_ag_agent_answer_call(unsigned int call_id,
658 const gchar *path, const gchar *sender)
662 if (path == NULL || sender == NULL) {
663 DBG("Invalid Arguments");
667 DBG("Application path = %s", path);
668 DBG("Call Id = %d", call_id);
669 DBG("Sender = %s", sender);
671 _bt_ag_agent_emit_signal(ag_dbus_conn, path,
672 BT_AG_SERVICE_NAME, "Answer",
673 g_variant_new("(u)", call_id));
678 gboolean _bt_ag_agent_reject_call(unsigned int call_id,
679 const gchar *path, const gchar *sender)
683 if (path == NULL || sender == NULL) {
684 DBG("Invalid Arguments");
688 DBG("Application path = %s", path);
689 DBG("Call Id = %d", call_id);
690 DBG("Sender = %s", sender);
692 _bt_ag_agent_emit_signal(ag_dbus_conn, path,
693 BT_AG_SERVICE_NAME, "Reject",
694 g_variant_new("(u)", call_id));
699 gboolean _bt_ag_agent_release_call(unsigned int call_id,
700 const gchar *path, const gchar *sender)
704 if (path == NULL || sender == NULL) {
705 DBG("Invalid Arguments");
709 DBG("Application path = %s", path);
710 DBG("Call Id = %d", call_id);
711 DBG("Sender = %s", sender);
713 _bt_ag_agent_emit_signal(ag_dbus_conn, path,
714 BT_AG_SERVICE_NAME, "Release",
715 g_variant_new("(u)", call_id));
721 bt_hfp_agent_error_t _bt_ag_agent_dial_num(const gchar *number, guint flags)
723 bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
725 int phone_lock_state;
730 if (number == NULL) {
731 ERR("Invalid Argument");
732 error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
736 DBG_SECURE("Number = %s", number);
737 DBG("flags = %d", flags);
739 if (!__bt_is_phone_locked(&phone_lock_state)) {
740 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
744 if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
745 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
749 if (!__bt_get_outgoing_call_condition(&condition)) {
750 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
754 if (condition == BT_MO_ONLY_UNLOCKED && phone_lock_state ==
755 VCONFKEY_IDLE_LOCK) {
756 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
760 if (callapp_type == BT_VIDEO_CALL) {
761 if (!__bt_ag_agent_make_video_call(number)) {
762 ERR("Problem launching application");
763 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
767 if (!__bt_ag_agent_make_call(number)) {
768 ERR("Problem launching application");
769 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
779 bt_hfp_agent_error_t _bt_ag_agent_dial_memory(unsigned int location)
781 bt_hfp_agent_error_t error_code = BT_HFP_AGENT_ERROR_NONE;
783 contacts_filter_h filter = NULL;
784 contacts_query_h query = NULL;
785 contacts_list_h list = NULL;
786 contacts_record_h record = NULL;
787 unsigned int projections[] = {
788 _contacts_speeddial.number,
793 DBG("location = %d", location);
795 /*Get number from contacts location*/
796 if (contacts_connect() != CONTACTS_ERROR_NONE) {
797 ERR(" contacts_connect failed");
798 return BT_HFP_AGENT_ERROR_INTERNAL;
801 contacts_filter_create(_contacts_speeddial._uri, &filter);
806 if (contacts_filter_add_int(filter,
807 _contacts_speeddial.speeddial_number,
808 CONTACTS_MATCH_EQUAL, location) !=
809 CONTACTS_ERROR_NONE) {
810 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
814 contacts_query_create(_contacts_speeddial._uri, &query);
819 contacts_query_set_filter(query, filter);
821 if (contacts_query_set_projection(query, projections,
822 sizeof(projections)/sizeof(unsigned int)) !=
823 CONTACTS_ERROR_NONE) {
824 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
828 if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
829 CONTACTS_ERROR_NONE) {
830 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
834 if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
835 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
839 if (contacts_list_get_current_record_p(list, &record) !=
840 CONTACTS_ERROR_NONE) {
841 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
848 if (contacts_record_get_str(record, _contacts_speeddial.number, &number)
849 != CONTACTS_ERROR_NONE) {
850 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
854 if (number == NULL) {
855 ERR("No number at the location");
856 error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
860 DBG_SECURE("number %s", number);
863 if (!__bt_ag_agent_make_call(number)) {
864 ERR("Problem launching application");
865 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
871 contacts_list_destroy(list, TRUE);
874 contacts_filter_destroy(filter);
877 contacts_query_destroy(query);
879 contacts_disconnect();
886 bt_hfp_agent_error_t _bt_ag_agent_send_dtmf(const gchar *dtmf,
887 const gchar *path, const gchar *sender)
889 bt_hfp_agent_error_t ret;
893 if (dtmf == NULL || path == NULL || sender == NULL) {
894 ERR("Invalid Argument");
895 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
898 DBG("Dtmf = %s", dtmf);
899 DBG("Application path = %s", path);
900 DBG("Sender = %s", sender);
902 ret = __bt_ag_agent_gdbus_method_send(sender,
903 path, TELEPHONY_APP_INTERFACE,
905 g_variant_new("(s)", dtmf));
910 gboolean _bt_ag_agent_threeway_call(unsigned int chld_value,
911 const gchar *path, const gchar *sender)
915 if (path == NULL || sender == NULL) {
916 DBG("Invalid Arguments");
920 DBG("Application path = %s", path);
921 DBG("Value = %d", chld_value);
922 DBG("Sender = %s", sender);
924 if (TIZEN_PROFILE_WEARABLE) {
925 /* Check if AG supports (i.e. ag_chld_str = "0,1,2") the requested CHLD;
926 if not return FALSE */
927 if (chld_value != 0 && chld_value != 1 && chld_value != 2)
930 if (chld_value != 0 && chld_value != 1 && chld_value != 2 &&
935 _bt_ag_agent_emit_signal(ag_dbus_conn, path,
936 BT_AG_SERVICE_NAME, "Threeway",
937 g_variant_new("(u)", chld_value));
942 bt_hfp_agent_error_t _bt_ag_agent_dial_last_num(void *device)
944 bt_hfp_agent_error_t err_code = BT_HFP_AGENT_ERROR_NONE;
945 char *last_num = NULL;
948 int phone_lock_state;
950 contacts_list_h list = NULL;
951 contacts_query_h query = NULL;
952 contacts_filter_h filter = NULL;
953 contacts_record_h record = NULL;
954 unsigned int projections[] = {
955 _contacts_phone_log.address,
956 _contacts_phone_log.log_type,
961 if (contacts_connect() != CONTACTS_ERROR_NONE) {
962 ERR(" contacts_connect failed");
963 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
967 contacts_filter_create(_contacts_phone_log._uri, &filter);
972 if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
973 CONTACTS_MATCH_EQUAL,
974 CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
975 CONTACTS_ERROR_NONE) {
976 ERR(" contacts_filter_add_int failed");
977 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
981 if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
982 CONTACTS_ERROR_NONE) {
983 ERR(" contacts_filter_add_operator failed");
984 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
988 if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
989 CONTACTS_MATCH_EQUAL,
990 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
991 CONTACTS_ERROR_NONE) {
992 ERR(" contacts_filter_add_int failed");
993 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
997 contacts_query_create(_contacts_phone_log._uri, &query);
1002 contacts_query_set_filter(query, filter);
1004 if (contacts_query_set_projection(query, projections,
1005 sizeof(projections)/sizeof(unsigned int)) !=
1006 CONTACTS_ERROR_NONE) {
1007 ERR(" contacts_query_set_projection failed");
1008 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1012 if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false)
1013 != CONTACTS_ERROR_NONE) {
1014 ERR(" contacts_query_set_sort failed");
1015 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1019 if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
1020 CONTACTS_ERROR_NONE) {
1021 ERR(" contacts_db_get_records_with_query failed");
1022 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1026 if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
1027 ERR(" contacts_list_first failed");
1028 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1032 if (contacts_list_get_current_record_p(list, &record) !=
1033 CONTACTS_ERROR_NONE) {
1034 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1041 if (contacts_record_get_str(record, _contacts_phone_log.address,
1042 &last_num) != CONTACTS_ERROR_NONE) {
1043 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1047 if (last_num == NULL) {
1048 ERR("No last number");
1049 err_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
1053 if (!__bt_is_phone_locked(&phone_lock_state)) {
1054 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1058 if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1059 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1063 if (!__bt_get_outgoing_call_condition(&condition)) {
1064 ERR(" Failed to get the call condition");
1065 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1069 if (condition == BT_MO_ONLY_UNLOCKED &&
1070 phone_lock_state == VCONFKEY_IDLE_LOCK) {
1071 ERR(" call condition and phone lock state check fail");
1072 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1076 switch (callapp_type) {
1078 if (!__bt_ag_agent_make_call(last_num)) {
1079 ERR("Problem launching application");
1080 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1084 if (!__bt_ag_agent_make_video_call(last_num)) {
1085 ERR("Problem launching application");
1086 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1089 case BT_FOLLOW_CALL_LOG:
1090 if (contacts_record_get_int(record,
1091 _contacts_phone_log.log_type,
1092 &type) != CONTACTS_ERROR_NONE) {
1093 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1096 if (type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING) {
1097 if (!__bt_ag_agent_make_call(last_num)) {
1098 ERR("Problem launching application");
1099 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1101 } else if (type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) {
1102 if (!__bt_ag_agent_make_video_call(last_num)) {
1103 ERR("Problem launching application");
1104 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1107 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1111 err_code = BT_HFP_AGENT_ERROR_INTERNAL;
1118 contacts_list_destroy(list, TRUE);
1121 contacts_filter_destroy(filter);
1124 contacts_query_destroy(query);
1126 contacts_disconnect();
1128 if (last_num != NULL)
1136 bt_hfp_agent_error_t _bt_ag_agent_vendor_cmd(const gchar *cmd,
1137 const gchar *path, const gchar *sender)
1139 bt_hfp_agent_error_t ret;
1143 if (cmd == NULL || path == NULL || sender == NULL) {
1144 ERR("Invalid Argument");
1145 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
1148 DBG("cmd = %s", cmd);
1149 DBG("Application path = %s", path);
1150 DBG("Sender = %s", sender);
1152 ret = __bt_ag_agent_gdbus_method_send(sender,
1153 path, TELEPHONY_APP_INTERFACE,
1155 g_variant_new("(s)", cmd));
1160 gboolean _bt_ag_agent_get_signal_quality(void *device)
1166 ret = tel_get_property_int(GET_TAPI_HANDLE,
1167 TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL, &rssi);
1168 if (ret != TAPI_API_SUCCESS) {
1169 ERR("Get signal status failed err = %d\n", ret);
1173 DBG("RSSI : %d", rssi);
1175 _bt_hfp_signal_quality_reply(rssi, BT_SIGNAL_QUALITY_BER,
1182 _bt_hfp_signal_quality_reply(-1, -1, device);
1186 gboolean _bt_ag_agent_get_battery_status(void *device)
1188 bool battery_chrg_status;
1189 int battery_capacity;
1194 ret = device_battery_is_charging(&battery_chrg_status);
1195 if (ret != DEVICE_ERROR_NONE) {
1196 ERR("Get battery charge status failed. Err = %d\n", ret);
1200 DBG("Status : %d\n", battery_chrg_status);
1202 ret = device_battery_get_percent(&battery_capacity);
1203 if (ret != DEVICE_ERROR_NONE) {
1204 ERR("Get battery capacity status failed. Err = %d\n", ret);
1208 DBG("Capacity : %d\n", battery_capacity);
1210 _bt_hfp_battery_property_reply(device,
1211 battery_chrg_status, battery_capacity);
1216 _bt_hfp_battery_property_reply(device, -1, -1);
1221 gboolean _bt_ag_agent_get_operator_name(void *device)
1223 char *operator_name = NULL;
1227 ret = tel_get_property_string(GET_TAPI_HANDLE,
1228 TAPI_PROP_NETWORK_NETWORK_NAME, &operator_name);
1229 if (NULL == operator_name) {
1230 DBG("TAPI_PROP_NETWORK_NETWORK_NAME failed (%d)", ret);
1231 _bt_hfp_operator_reply(NULL, device);
1235 DBG("operator_name = [%s]", operator_name);
1237 _bt_hfp_operator_reply(operator_name, device);
1239 free(operator_name);
1245 gboolean _bt_hfp_agent_nrec_status(gboolean status,
1249 bt_ag_info_t *hs = (bt_ag_info_t *)t_device;
1251 DBG("NREC status = %d", status);
1253 hs->nrec_status = FALSE;
1255 hs->nrec_status = TRUE;
1257 _bt_ag_agent_emit_signal(ag_dbus_conn, hs->path,
1258 BT_AG_SERVICE_NAME, "NrecStatusChanged",
1259 g_variant_new("(b)", hs->nrec_status));
1264 gboolean _bt_ag_agent_get_imei_number(void *device)
1269 imei_number = tel_get_misc_me_imei_sync(GET_TAPI_HANDLE);
1270 if (NULL == imei_number) {
1271 ERR("tel_get_misc_me_imei_sync for imei_number failed");
1275 if (!g_utf8_validate(imei_number, -1, NULL)) {
1277 ERR("get_imei_number : invalid UTF8");
1281 DBG_SECURE("imei_number = [%s]", imei_number);
1282 _bt_hfp_get_imei_number_reply(imei_number, device);
1288 _bt_hfp_get_imei_number_reply(NULL, device);
1293 void _bt_ag_agent_get_manufacturer_name(void *device)
1296 char *manufacturer_name;
1299 ret = system_info_get_platform_string("http://tizen.org/system/manufacturer",
1300 &manufacturer_name);
1301 if (SYSTEM_INFO_ERROR_NONE != ret) {
1302 ERR("Get manufacturer_name failed : %d", ret);
1303 if (NULL != manufacturer_name)
1304 free(manufacturer_name);
1306 manufacturer_name = g_strdup("Unknown");
1307 } else if (!g_utf8_validate(manufacturer_name, -1, NULL)) {
1308 free(manufacturer_name);
1309 manufacturer_name = g_strdup("Unknown");
1310 ERR("get_manufacturer_name : invalid UTF8");
1313 DBG_SECURE("manufacturer_name = [%s]", manufacturer_name);
1314 _bt_hfp_get_device_manufacturer_reply(manufacturer_name, device);
1315 free(manufacturer_name);
1319 void _bt_ag_agent_get_imsi(void *device)
1322 TelSimImsiInfo_t imsi;
1323 memset(&imsi, 0, sizeof(TelSimImsiInfo_t));
1324 if (tel_get_sim_imsi(GET_TAPI_HANDLE, &imsi) != TAPI_API_SUCCESS) {
1325 ERR("tel_get_sim_imsi failed");
1328 DBG_SECURE("tapi values %s %s %s", imsi.szMcc, imsi.szMnc, imsi.szMsin);
1330 _bt_hfp_get_imsi_reply(imsi.szMcc, imsi.szMnc, imsi.szMsin, device);
1334 _bt_hfp_get_imsi_reply(NULL, NULL, NULL, device);
1338 int _bt_ag_agent_registration_status_convert(int result)
1341 case TAPI_NETWORK_SERVICE_LEVEL_NO:
1342 return BT_AGENT_NETWORK_REG_STATUS_NOT_REGISTER;
1343 case TAPI_NETWORK_SERVICE_LEVEL_EMERGENCY:
1344 return BT_AGENT_NETWORK_REG_STATUS_EMERGENCY;
1345 case TAPI_NETWORK_SERVICE_LEVEL_FULL:
1346 return BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK;
1347 case TAPI_NETWORK_SERVICE_LEVEL_SEARCH:
1348 return BT_AGENT_NETWORK_REG_STATUS_SEARCH;
1350 return BT_AGENT_NETWORK_REG_STATUS_UNKNOWN;
1355 void _bt_ag_agent_get_creg_status(void *device)
1361 int registration_status = 0;
1362 int roam_status = 0;
1364 ret = tel_get_property_int(GET_TAPI_HANDLE,
1365 TAPI_PROP_NETWORK_CIRCUIT_STATUS, &result);
1366 if (ret != TAPI_API_SUCCESS) {
1367 ERR("tel_get_property_int failed");
1370 registration_status =
1371 _bt_ag_agent_registration_status_convert(result);
1373 DBG_SECURE("Registration status %d", result);
1374 DBG_SECURE("Mapped Status %d", registration_status);
1375 if (registration_status ==
1376 BT_AGENT_NETWORK_REG_STATUS_REGISTER_HOME_NETWORK) {
1377 ret = tel_get_property_int(GET_TAPI_HANDLE,
1378 TAPI_PROP_NETWORK_ROAMING_STATUS, &roam_status);
1379 if (ret != TAPI_API_SUCCESS) {
1380 ERR("Get roaming status failed err = %d\n", ret);
1383 DBG_SECURE("Roam status %d", roam_status);
1384 if (roam_status == 1) {
1385 registration_status =
1386 BT_AGENT_NETWORK_REG_STATUS_REGISTERED_ROAMING;
1390 _bt_hfp_get_creg_status_reply(n, registration_status, device);
1396 void _bt_ag_agent_get_model_name(void *device)
1402 ret = system_info_get_platform_string("http://tizen.org/system/model_name", &model_name);
1403 if (SYSTEM_INFO_ERROR_NONE != ret) {
1404 ERR("Get model_name failed: %d", ret);
1405 if (NULL != model_name)
1408 model_name = g_strdup("Unknown");
1409 } else if (!g_utf8_validate(model_name, -1, NULL)) {
1411 model_name = g_strdup("Unknown");
1412 ERR("get_model_name : invalid UTF8");
1415 DBG_SECURE("model_name = [%s]", model_name);
1416 _bt_hfp_get_model_info_reply(model_name, device);
1421 void _bt_ag_agent_get_revision_information(void *device)
1424 char *revision_info;
1427 ret = system_info_get_platform_string("http://tizen.org/system/build.string",
1429 if (SYSTEM_INFO_ERROR_NONE != ret) {
1430 ERR("Get revision_info failed: %d", ret);
1431 if (NULL != revision_info)
1432 free(revision_info);
1434 revision_info = g_strdup("Unknown");
1435 } else if (!g_utf8_validate(revision_info, -1, NULL)) {
1436 free(revision_info);
1437 revision_info = g_strdup("Unknown");
1438 ERR("get_revision_info: invalid UTF8");
1441 DBG_SECURE("revision_info = [%s]", revision_info);
1442 _bt_hfp_get_revision_info_reply(revision_info, device);
1443 free(revision_info);
1447 void _bt_ag_agent_set_last_speaker_gain(int gain)
1449 last_speaker_gain = gain;
1452 static gboolean __bt_ag_agent_launch_voice_dial(gboolean activate)
1455 if (TIZEN_PROFILE_WEARABLE) {
1458 b = bundle_create();
1460 ERR("bundle_create() Failed");
1464 bundle_add(b, "domain", "bt_headset");
1466 bundle_add(b, "action_type", "deactivate");
1468 aul_launch_app_async("org.tizen.svoice", b);
1473 app_control_h service = NULL;
1475 app_control_create(&service);
1477 if (service == NULL) {
1478 ERR("Service create failed");
1482 app_control_set_app_id(service, "org.tizen.svoice");
1483 app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
1484 if (app_control_add_extra_data(service, "domain", "bt_headset")
1485 != APP_CONTROL_ERROR_NONE) {
1486 ERR("app_control_add_extra_data failed");
1487 app_control_destroy(service);
1492 if (app_control_add_extra_data(service, "action_type", "deactivate")
1493 != APP_CONTROL_ERROR_NONE) {
1494 ERR("app_control_add_extra_data failed");
1495 app_control_destroy(service);
1499 if (app_control_send_launch_request(service, NULL, NULL) !=
1500 APP_CONTROL_ERROR_NONE) {
1501 ERR("launch failed");
1502 app_control_destroy(service);
1506 app_control_destroy(service);
1512 gboolean _bt_ag_agent_voice_dial(gboolean activate)
1514 DBG("Activate = %d", activate);
1516 return __bt_ag_agent_launch_voice_dial(activate);
1519 static void __bt_ag_codec_negotiation_info_reset(bt_ag_info_t *hs,
1522 hs->codec_info.is_negotiating = FALSE;
1523 hs->codec_info.requested_by_hf = FALSE;
1524 hs->codec_info.sending_codec = 0;
1525 g_free(hs->codec_info.status);
1526 hs->codec_info.status = NULL;
1529 hs->codec_info.remote_codecs = 0;
1530 hs->codec_info.final_codec = 0;
1531 hs->nrec_status = FALSE;
1534 if (hs->codec_info.nego_timer) {
1535 g_source_remove(hs->codec_info.nego_timer);
1536 hs->codec_info.nego_timer = 0;
1538 wbs_opts.wbs_enable = wbs_en;
1541 static gboolean __bt_ag_codec_negotiation_finished(gpointer user_data)
1543 bt_ag_info_t *hs = (bt_ag_info_t *)user_data;
1545 if (g_strcmp0(hs->codec_info.status, "finish") == 0) {
1546 DBG("Codec negotiation finished");
1547 __bt_ag_sco_connect(hs);
1548 __bt_ag_codec_negotiation_info_reset(hs, FALSE);
1550 } else if (g_strcmp0(hs->codec_info.status, "timeout") == 0) {
1551 ERR("Timeout is occured in codec negotiation");
1552 /* Codec negotiation is timedout fall back to default NB */
1553 hs->codec = BT_CVSD_CODEC_ID;
1554 hs->codec_info.final_codec = BT_CVSD_CODEC_ID;
1557 if (hs->codec_info.requested_by_hf) {
1558 __bt_ag_codec_negotiation_info_reset(hs, FALSE);
1560 __bt_ag_sco_connect(hs);
1561 __bt_ag_codec_negotiation_info_reset(hs, FALSE);
1567 static bt_hfp_agent_error_t __bt_ag_set_codec(void *device, char *method)
1572 bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)device;
1574 proxy = g_dbus_proxy_new_sync(ag_dbus_conn,
1575 G_DBUS_PROXY_FLAGS_NONE, NULL,
1576 BLUEZ_SERVICE_NAME, DEFAULT_ADAPTER_OBJECT_PATH,
1577 BT_ADAPTER_INTERFACE, NULL, &err);
1581 ERR("Unable to create proxy: %s", err->message);
1582 g_clear_error(&err);
1584 return BT_HFP_AGENT_ERROR_INTERNAL;
1587 ret = g_dbus_proxy_call_sync(proxy, method,
1588 g_variant_new("(ss)", "Gateway", bt_ag_info->remote_addr),
1589 G_DBUS_CALL_FLAGS_NONE, -1,
1592 /* dBUS-RPC is failed */
1593 ERR("dBUS-RPC is failed");
1595 /* dBUS gives error cause */
1596 ERR("D-Bus API failure: errCode[%x], message[%s]",
1597 err->code, err->message);
1599 g_clear_error(&err);
1601 g_object_unref(proxy);
1602 return BT_HFP_AGENT_ERROR_INTERNAL;
1604 g_variant_unref(ret);
1605 g_object_unref(proxy);
1607 return BT_HFP_AGENT_ERROR_NONE;
1610 static bt_hfp_agent_error_t __bt_ag_codec_selection_setup(bt_ag_info_t *hs,
1613 bt_hfp_agent_error_t err = BT_HFP_AGENT_ERROR_NONE;
1615 DBG("Codec setup [%x]", codec);
1617 /* 1. Compare sending codec & recieved code */
1618 if (hs->codec_info.sending_codec != codec)
1619 err = BT_HFP_AGENT_ERROR_INTERNAL;
1621 /* 2. Send WB or NB command */
1623 case BT_CVSD_CODEC_ID:
1624 err = __bt_ag_set_codec(hs, "SetNbParameters");
1626 case BT_MSBC_CODEC_ID:
1627 err = __bt_ag_set_codec(hs, "SetWbsParameters");
1630 err = BT_HFP_AGENT_ERROR_INTERNAL;
1634 /* If the vendor specific calling returns error or codec is not correct,
1635 * we send CVSD Codec parameter to MM module. and also returns
1636 * normal value to HF
1638 if (err != BT_HFP_AGENT_ERROR_NONE)
1639 codec = BT_CVSD_CODEC_ID;
1641 hs->codec_info.final_codec = codec;
1646 static bt_hfp_agent_error_t __bt_hfp_send_bcs_command(bt_ag_info_t *hs,
1647 gboolean init_by_hf)
1651 #ifdef TIZEN_FEATURE_BT_SCO_WIDEBAND
1652 if (hs->codec_info.remote_codecs & BT_MSBC_CODEC_MASK)
1653 codec = BT_MSBC_CODEC_ID;
1655 codec = BT_CVSD_CODEC_ID;
1657 codec = BT_CVSD_CODEC_ID;
1660 if (wbs_opts.wbs_enable == FALSE)
1661 codec = BT_CVSD_CODEC_ID;
1665 if (_bt_ag_send_at(hs, "\r\n+BCS: %d\r\n", codec) < 0)
1666 return BT_HFP_AGENT_ERROR_INTERNAL;
1668 DBG("Send +BCS:%d\n", codec);
1670 /* Send +BCS command to HF, and wait some times */
1671 hs->codec_info.is_negotiating = TRUE;
1672 hs->codec_info.sending_codec = codec;
1673 hs->codec_info.requested_by_hf = init_by_hf;
1674 hs->codec_info.final_codec = codec;
1675 hs->codec_info.status = g_strdup("timeout");
1677 hs->codec_info.nego_timer = g_timeout_add_seconds(
1678 HFP_CODEC_NEGOTIATION_TIMEOUT,
1679 (GSourceFunc)__bt_ag_codec_negotiation_finished,
1682 return BT_HFP_AGENT_ERROR_NONE;
1686 static bt_hfp_agent_error_t __bt_hfp_codec_connection_setup(
1687 bt_ag_info_t *hs, gboolean init_by_hf)
1689 DBG("Request to codec connection by %s", init_by_hf ? "HF" : "AG");
1691 if (hs->state < HEADSET_STATE_CONNECTED)
1692 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1694 if (hs->codec_info.is_negotiating == TRUE) {
1695 /* In codec negotiation, return and wait */
1696 ERR("Codec nogotiation is in progress");
1697 return BT_HFP_AGENT_ERROR_BUSY;
1700 /* Not support Codec Negotiation or Not recieved BAC command */
1701 if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) ||
1702 hs->codec_info.remote_codecs == 0) {
1703 ERR("No support for Codec Negotiation or receive BAC command");
1705 return BT_HFP_AGENT_ERROR_INTERNAL;
1707 __bt_ag_sco_connect(hs);
1708 return BT_HFP_AGENT_ERROR_INTERNAL;
1712 /* If HF initiated codec connection setup, it should send OK command
1713 * before +BCS command transmission.
1716 return HFP_STATE_MNGR_ERR_NONE;
1718 return __bt_hfp_send_bcs_command(hs, init_by_hf);
1722 static int __hfp_parse_available_codecs(const char *cmd, uint32_t *codecs)
1725 *codecs = 0x00000000;
1727 str = strchr(cmd, '=');
1731 while (str != NULL) {
1734 if (atoi(str) == BT_CVSD_CODEC_ID)
1735 *codecs |= BT_CVSD_CODEC_MASK;
1736 else if (atoi(str) == BT_MSBC_CODEC_ID)
1737 *codecs |= BT_MSBC_CODEC_MASK;
1739 str = strchr(str, ',');
1742 if (*codecs == 0x00000000)
1748 /* AT+BAC (Bluetooth Available Codecs) */
1749 static int __bt_hfp_available_codecs(bt_ag_info_t *hs, const char *buf)
1751 uint32_t codecs = 0x00000000;
1752 hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1754 if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION)) {
1755 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1756 } else if (__hfp_parse_available_codecs(buf, &codecs) < 0) {
1757 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1759 DBG("Update remote available codecs [%x]", codecs);
1760 hs->codec_info.remote_codecs = codecs;
1763 _bt_ag_send_response(hs, err);
1765 /* Reset codec information and
1766 * restart codec connection setup by AG
1768 hs->codec_info.final_codec = 0;
1769 if (hs->codec_info.nego_timer) {
1770 hs->codec_info.is_negotiating = FALSE;
1771 hs->codec_info.requested_by_hf = FALSE;
1772 hs->codec_info.sending_codec = 0;
1773 g_free(hs->codec_info.status);
1774 hs->codec_info.status = NULL;
1775 g_source_remove(hs->codec_info.nego_timer);
1776 __bt_hfp_codec_connection_setup(hs, FALSE);
1782 /* AT+BCC (Bluetooth Codec Connection) */
1783 static int __bt_hfp_codec_connection(bt_ag_info_t *hs, const char *buf)
1785 hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1787 err = __bt_hfp_codec_connection_setup(hs, TRUE);
1789 _bt_ag_send_response(hs, err);
1791 if (err == HFP_STATE_MNGR_ERR_NONE)
1792 err = __bt_hfp_send_bcs_command(hs, TRUE);
1794 if (err != HFP_STATE_MNGR_ERR_NONE)
1795 ERR("Fail to request codec connection setup");
1800 /* AT+BCS (Bluetooth Codec Selection) */
1801 static int __bt_hfp_codec_selection(bt_ag_info_t *hs, const char *buf)
1803 uint32_t codec = 0x00000000;
1804 hfp_state_manager_err_t err = HFP_STATE_MNGR_ERR_NONE;
1807 if (hs->codec_info.nego_timer) {
1808 g_source_remove(hs->codec_info.nego_timer);
1809 hs->codec_info.nego_timer = 0;
1810 g_free(hs->codec_info.status);
1811 hs->codec_info.status = NULL;
1814 if (!(ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION))
1815 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1816 else if (__hfp_parse_available_codecs(buf, &codec) < 0)
1817 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1818 else if (__bt_ag_codec_selection_setup(hs, codec) !=
1819 BT_HFP_AGENT_ERROR_NONE)
1820 err = HFP_STATE_MNGR_ERR_AG_FAILURE;
1822 hs->codec_info.status = g_strdup("finish");
1823 _bt_ag_send_response(hs, err);
1824 __bt_ag_codec_negotiation_finished(hs);
1829 static void __bt_ag_str2ba(const char *str, bt_addr *ba)
1832 for (i = 5; i >= 0; i--, str += 3)
1833 ba->b[i] = strtol(str, NULL, 16);
1836 static const char *__bt_ag_state2str(hs_state_t state)
1839 case HEADSET_STATE_DISCONNECTED:
1840 return "disconnected";
1841 case HEADSET_STATE_CONNECTING:
1842 return "connecting";
1843 case HEADSET_STATE_CONNECTED:
1845 case HEADSET_STATE_PLAY_IN_PROGRESS:
1846 return "Play In Progress";
1847 case HEADSET_STATE_ON_CALL:
1854 static void __bt_convert_addr_string_to_type_rev(unsigned char *addr,
1855 const char *address)
1860 ret_if(address == NULL);
1861 ret_if(addr == NULL);
1863 for (i = 0; i < 6; i++) {
1864 addr[5 - i] = strtol(address, &ptr, 16);
1865 if (ptr[0] != '\0') {
1874 static gboolean __bt_ag_check_nval(GIOChannel *chan)
1876 struct pollfd file_desc;
1878 memset(&file_desc, 0, sizeof(file_desc));
1879 file_desc.fd = g_io_channel_unix_get_fd(chan);
1880 file_desc.events = POLLNVAL;
1882 if (poll(&file_desc, 1, 0) > 0 && (POLLNVAL & file_desc.revents))
1888 static int __bt_ag_sco_connect(bt_ag_info_t *hs)
1890 struct sco_socket_addr sco_addr;
1895 bt_ag_slconn_t *slconn = hs->slc;
1898 if (hs->state == HEADSET_STATE_ON_CALL)
1899 return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
1901 if (hs->state != HEADSET_STATE_CONNECTED)
1902 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
1903 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
1904 _bt_ag_agent_check_transport_state();
1907 /* Create Sco socket */
1908 sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
1910 ERR("ERROR: Create socket failed.\n");
1911 return BT_HFP_AGENT_ERROR_INTERNAL;
1914 /* Bind Sco Socket to Local BD addr */
1915 memset(&sco_addr, 0, sizeof(sco_addr));
1916 sco_addr.sco_family = AF_BLUETOOTH;
1919 __bt_ag_str2ba(local_addr, &sco_addr.sco_bdaddr);
1920 DBG_SECURE("Local BD address: %s", local_addr);
1922 ERR("Local address is NULL");
1923 ERR("Close SCO skt");
1925 return BT_HFP_AGENT_ERROR_INTERNAL;
1929 err = bind(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1931 ERR("ERROR: sco socket binding failed");
1932 ERR("Close SCO skt");
1934 return BT_HFP_AGENT_ERROR_INTERNAL;
1937 DBG_SECURE("Socket FD : %d", sco_skt);
1939 io = g_io_channel_unix_new(sco_skt);
1940 g_io_channel_set_close_on_unref(io, TRUE);
1941 /*g_io_channel_set_flags(io, G_IO_FLAG_NONBLOCK, NULL);
1942 g_io_channel_set_buffered(io, FALSE);
1943 g_io_channel_set_encoding(io, NULL, NULL);*/
1945 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
1946 (slconn && (slconn->hs_features &
1947 BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
1948 wbs_opts.wbs_enable == TRUE) {
1949 bt_vo.setting = (hs->codec == BT_MSBC_CODEC_ID) ?
1950 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
1952 DBG("set Bluetooth voice: %d", bt_vo.setting);
1953 err = setsockopt(sco_skt, BT_SOCKET_LEVEL,
1954 BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
1956 ERR("ERROR: sco socket set socket option failed");
1957 ERR("Close SCO skt");
1958 g_io_channel_unref(io);
1960 return BT_HFP_AGENT_ERROR_INTERNAL;
1963 DBG("Set NB codec parameter");
1964 __bt_ag_set_codec(hs, "SetNbParameters");
1967 memset(&sco_addr, 0, sizeof(sco_addr));
1968 sco_addr.sco_family = AF_BLUETOOTH;
1969 __bt_ag_str2ba(hs->remote_addr, &sco_addr.sco_bdaddr);
1970 DBG_SECURE("remotel BD address: %s", hs->remote_addr);
1972 err = connect(sco_skt, (struct sockaddr *) &sco_addr, sizeof(sco_addr));
1973 if (err < 0 && !(errno == EINPROGRESS || errno == EAGAIN)) {
1975 ERR("sco socket connect failed : %s (%d)", strerror(-err), -err);
1976 ERR("Close SCO skt");
1977 g_io_channel_unref(io);
1979 return BT_HFP_AGENT_ERROR_INTERNAL;
1982 /* Disabling the watch since SCO is connected */
1983 /*watch_id = __bt_ag_set_watch(io,
1984 (GIOFunc) __bt_ag_sco_connect_cb, hs);
1986 DBG("SCO watch set Success");*/
1990 _bt_ag_set_headset_state(hs, HEADSET_STATE_ON_CALL);
1991 return BT_HFP_AGENT_ERROR_NONE;
1994 static void __bt_ag_close_sco(bt_ag_info_t *hs)
1998 int sock = g_io_channel_unix_get_fd(hs->sco);
1999 shutdown(sock, SHUT_RDWR);
2000 g_io_channel_unref(hs->sco);
2005 __bt_ag_agent_remove_watch(&hs->sco_id);
2007 if (hs->sco_incoming_id)
2008 __bt_ag_agent_remove_watch(&hs->sco_incoming_id);
2011 static gboolean __bt_ag_sco_server_conn_cb(GIOChannel *chan,
2012 GIOCondition cond, gpointer user_data)
2014 bt_ag_info_t *ag_info = user_data;
2017 if (cond & G_IO_NVAL)
2020 if (cond & (G_IO_HUP | G_IO_ERR)) {
2021 ag_info->sco = NULL;
2022 if (ag_info->sco_id)
2023 __bt_ag_agent_remove_watch(&ag_info->sco_id);
2025 if (ag_info->sco_incoming_id)
2026 __bt_ag_agent_remove_watch(&ag_info->sco_incoming_id);
2028 if (ag_info->watch_id)
2029 _bt_ag_set_headset_state(ag_info, HEADSET_STATE_CONNECTED);
2035 static gboolean __bt_ag_sco_server_cb(GIOChannel *chan,
2036 GIOCondition cond, gpointer user_data)
2038 bt_ag_info_t *ag_info = user_data;
2042 bt_ag_slconn_t *slconn = ag_info->slc;
2046 if ((cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) ||
2047 __bt_ag_check_nval(chan)) {
2048 ERR("cond or chan is not valid");
2052 INFO_C("Incoming SCO....");
2054 if (ag_info->state < HEADSET_STATE_CONNECTED)
2055 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
2057 sco_skt = g_io_channel_unix_get_fd(chan);
2059 cli_sco_sock = accept(sco_skt, NULL, NULL);
2060 if (cli_sco_sock < 0) {
2061 ERR("accept is failed");
2065 sco_io = g_io_channel_unix_new(cli_sco_sock);
2066 g_io_channel_set_close_on_unref(sco_io, TRUE);
2067 g_io_channel_set_encoding(sco_io, NULL, NULL);
2068 g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2069 g_io_channel_set_buffered(sco_io, FALSE);
2071 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2072 (slconn && (slconn->hs_features &
2073 BT_HF_FEATURE_CODEC_NEGOTIATION)) &&
2074 wbs_opts.wbs_enable == TRUE) {
2075 bt_vo.setting = (ag_info->codec == BT_MSBC_CODEC_ID) ?
2076 BT_HFP_MSBC_VOICE : BT_HFP_CVSD_VOICE;
2078 DBG("set Bluetooth voice: %d", bt_vo.setting);
2079 err = setsockopt(cli_sco_sock, BT_SOCKET_LEVEL,
2080 BT_VOICE_NUM, &bt_vo, sizeof(bt_vo));
2082 ERR("Sco socket set socket option failed");
2083 g_io_channel_unref(sco_io);
2084 close(cli_sco_sock);
2089 ag_info->sco = sco_io;
2090 ag_info->sco_incoming_id = g_io_add_watch(sco_io, G_IO_HUP | G_IO_ERR | G_IO_NVAL,
2091 __bt_ag_sco_server_conn_cb, ag_info);
2093 if (remote_dev_path)
2094 g_free(remote_dev_path);
2096 remote_dev_path = g_strdup(ag_info->path);
2098 _bt_ag_set_headset_state(ag_info, HEADSET_STATE_ON_CALL);
2103 static int __bt_ag_start_sco_server(bt_ag_info_t *hs)
2105 DBG("Start SCO server");
2106 struct sco_socket_addr addr;
2109 bdaddr_t bd_addr = {{0},};
2111 if (hs->sco_server_started) {
2112 DBG("Already exsist");
2113 return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
2117 sco_skt = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BT_SCO_PRTCL);
2119 ERR("Can't create socket:\n");
2120 return BT_HFP_AGENT_ERROR_INTERNAL;
2123 /* Bind to local address */
2124 memset(&addr, 0, sizeof(addr));
2125 addr.sco_family = AF_BLUETOOTH;
2127 __bt_convert_addr_string_to_type_rev(bd_addr.b, hs->remote_addr);
2128 DBG_SECURE("Bind to address %s", hs->remote_addr);
2129 memcpy(&addr.sco_bdaddr, &bd_addr, sizeof(bdaddr_t));
2131 if (bind(sco_skt, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
2132 ERR("Can't bind socket:\n");
2136 if (listen(sco_skt, 1)) {
2137 ERR("Can not listen on the socket:\n");
2141 sco_io = g_io_channel_unix_new(sco_skt);
2142 g_io_channel_set_close_on_unref(sco_io, TRUE);
2143 g_io_channel_set_encoding(sco_io, NULL, NULL);
2144 g_io_channel_set_flags(sco_io, G_IO_FLAG_NONBLOCK, NULL);
2145 g_io_channel_set_buffered(sco_io, FALSE);
2147 hs->sco_server = sco_io;
2148 hs->sco_watch_id = g_io_add_watch(sco_io,
2149 G_IO_IN | G_IO_HUP | G_IO_ERR |
2150 G_IO_NVAL, __bt_ag_sco_server_cb, hs);
2152 hs->sco_server_started = TRUE;
2153 return BT_HFP_AGENT_ERROR_NONE;
2157 return BT_HFP_AGENT_ERROR_INTERNAL;
2160 void __bt_ag_stop_sco_server(bt_ag_info_t *hs)
2162 DBG("Stop SCO server");
2163 if (hs->sco_server) {
2164 g_io_channel_shutdown(hs->sco_server, TRUE, NULL);
2165 g_io_channel_unref(hs->sco_server);
2166 hs->sco_server = NULL;
2168 __bt_ag_agent_remove_watch(&hs->sco_watch_id);
2169 hs->sco_server_started = FALSE;
2172 static int __bt_ag_headset_close_rfcomm(bt_ag_info_t *hs)
2174 GIOChannel *rfcomm = hs->rfcomm;
2177 g_io_channel_shutdown(rfcomm, TRUE, NULL);
2178 g_io_channel_unref(rfcomm);
2188 static gboolean __bt_ag_sco_cb(GIOChannel *chan, GIOCondition cond,
2191 if (cond & G_IO_NVAL)
2194 if (name_owner_sig_id)
2195 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
2197 name_owner_sig_id = 0;
2201 DBG("Audio connection disconnected");
2202 _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2207 void _bt_ag_set_headset_state(bt_ag_info_t *hs, hs_state_t state)
2209 bt_ag_slconn_t *slconn = hs->slc;
2210 const char *hs_state;
2211 hs_state_t org_state = hs->state;
2212 gboolean val = FALSE;
2214 if (org_state == state)
2217 hs_state = __bt_ag_state2str(state);
2220 case HEADSET_STATE_CONNECTING:
2221 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2223 BT_HEADSET_INTERFACE, "State",
2224 g_variant_new("s", hs_state));
2226 active_devices = g_slist_append(active_devices, hs);
2229 case HEADSET_STATE_CONNECTED:
2230 if (hs->state != HEADSET_STATE_PLAY_IN_PROGRESS)
2231 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2233 BT_HEADSET_INTERFACE, "State",
2234 g_variant_new("s", hs_state));
2236 if (hs->state < state) {
2238 if (!g_slist_find(active_devices, hs))
2239 active_devices = g_slist_append(active_devices, hs);
2240 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2242 BT_HEADSET_INTERFACE,
2244 g_variant_new("b", val));
2246 DBG_SECURE("Device %s connected", hs->remote_addr);
2248 /* update remote dev path to last connected device. */
2249 if (remote_dev_path)
2250 g_free(remote_dev_path);
2251 remote_dev_path = g_strdup(hs->path);
2253 #if defined(TIZEN_SUPPORT_DUAL_HF)
2254 if (!hs->is_companion_device)
2255 __bt_ag_start_sco_server(hs);
2257 __bt_ag_start_sco_server(hs);
2260 /* Set default code as Gateway NB */
2261 __bt_ag_set_codec(hs, "SetNbParameters");
2262 } else if (hs->state == HEADSET_STATE_ON_CALL) {
2264 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2266 BT_HEADSET_INTERFACE,
2268 g_variant_new("b", val));
2273 case HEADSET_STATE_DISCONNECTED:
2274 if (sco_open_timer_id > 0) {
2275 g_source_remove(sco_open_timer_id);
2276 sco_open_timer_id = 0;
2277 if (hs->invocation) {
2278 INFO("Disconnected before SCO Connection");
2279 /* Reply with error */
2281 err = __bt_ag_agent_set_error(BT_HFP_AGENT_ERROR_NOT_CONNECTED);
2282 g_dbus_method_invocation_return_gerror(hs->invocation, err);
2283 hs->invocation = NULL;
2288 __bt_ag_close_sco(hs);
2289 __bt_ag_headset_close_rfcomm(hs);
2291 if (hs->state == HEADSET_STATE_ON_CALL) {
2293 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2295 BT_HEADSET_INTERFACE,
2297 g_variant_new("b", val));
2301 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2303 BT_HEADSET_INTERFACE,
2305 g_variant_new("b", val));
2306 if (hs->state > HEADSET_STATE_CONNECTING)
2307 _bt_hfp_device_disconnected(hs);
2309 active_devices = g_slist_remove(active_devices, hs);
2311 __bt_ag_codec_negotiation_info_reset(hs, TRUE);
2312 #if 0 /* SCO is crashed if below is called when SCO is opened by hf-agent */
2313 __bt_ag_set_codec(hs, "SetNbParameters");
2317 /* Since SCO server is binded on remote address */
2318 /* Need to stop SCO server once heasdet disconencted*/
2319 if (hs->sco_server_started)
2320 __bt_ag_stop_sco_server(hs);
2322 g_free(hs->remote_addr);
2327 case HEADSET_STATE_PLAY_IN_PROGRESS:
2328 case HEADSET_STATE_ON_CALL:
2330 _bt_ag_agent_emit_property_changed(ag_dbus_conn,
2332 BT_HEADSET_INTERFACE, "State",
2333 g_variant_new("s", hs_state));
2335 /*add watch for sco data */
2336 hs->sco_id = g_io_add_watch(hs->sco,
2337 G_IO_ERR | G_IO_NVAL,
2338 (GIOFunc) __bt_ag_sco_cb, hs);
2340 _bt_ag_agent_emit_property_changed(
2341 ag_dbus_conn, hs->path,
2342 BT_HEADSET_INTERFACE, "Playing",
2343 g_variant_new("b", val));
2345 if (slconn->microphone_gain >= 0 &&
2346 !slconn->is_voice_recognition_running)
2347 _bt_ag_send_at(hs, "\r\n+VGM=%u\r\n",
2348 slconn->microphone_gain);
2350 if (slconn->speaker_gain >= 0 &&
2351 !slconn->is_voice_recognition_running)
2352 _bt_ag_send_at(hs, "\r\n+VGS=%u\r\n",
2353 slconn->speaker_gain);
2363 INFO("STATE CHANGED from [%s(%d)] to [%s(%d)]",
2364 __bt_ag_state2str(org_state), org_state, __bt_ag_state2str(state), state);
2367 static struct event at_event_callbacks[] = {
2368 { "AT+BRSF", _bt_hfp_supported_features },
2369 { "AT+CIND", _bt_hfp_report_indicators },
2370 { "AT+CMER", _bt_hfp_enable_indicators },
2371 { "AT+CHLD", _bt_hfp_call_hold },
2372 { "ATA", _bt_hfp_answer_call },
2373 { "ATD", _bt_hfp_dial_number },
2374 { "AT+VG", _bt_hfp_signal_gain_setting },
2375 { "AT+CHUP", _bt_hfp_terminate_call },
2376 { "AT+CKPD", _bt_hfp_key_press },
2377 { "AT+CLIP", _bt_hfp_cli_notification },
2378 { "AT+BTRH", _bt_hfp_response_and_hold },
2379 { "AT+BLDN", _bt_hfp_last_dialed_number },
2380 { "AT+VTS", _bt_hfp_dtmf_tone },
2381 { "AT+CNUM", _bt_hfp_subscriber_number },
2382 { "AT+CLCC", _bt_hfp_list_current_calls },
2383 { "AT+CMEE", _bt_hfp_extended_errors },
2384 { "AT+CCWA", _bt_hfp_call_waiting_notify },
2385 { "AT+COPS", _bt_hfp_operator_selection },
2386 { "AT+NREC", _bt_hfp_nr_and_ec },
2387 { "AT+BVRA", _bt_hfp_voice_dial },
2388 { "AT+XAPL", _bt_hfp_apl_command },
2389 { "AT+IPHONEACCEV", _bt_hfp_apl_command },
2390 { "AT+BIA", _bt_hfp_indicators_activation },
2391 { "AT+CPBS", _bt_hfp_select_pb_memory },
2392 { "AT+CPBR", _bt_hfp_read_pb_entries},
2393 { "AT+CPBF", _bt_hfp_find_pb_entires },
2394 { "AT+CSCS", _bt_hfp_select_character_set },
2395 { "AT+CSQ", _bt_hfp_get_signal_quality },
2396 { "AT+CBC", _bt_hfp_get_battery_charge_status },
2397 { "AT+CPAS", _bt_hfp_get_activity_status },
2398 { "AT+CGSN", _bt_hfp_get_equipment_identity },
2399 { "AT+CGMM", _bt_hfp_get_model_information },
2400 { "AT+CGMI", _bt_hfp_get_device_manufacturer },
2401 { "AT+CGMR", _bt_hfp_get_revision_information },
2402 { "AT+BAC", __bt_hfp_available_codecs },
2403 { "AT+BCC", __bt_hfp_codec_connection },
2404 { "AT+BCS", __bt_hfp_codec_selection },
2405 { "AT+XSAT", _bt_hfp_vendor_cmd },
2406 { "AT+CIMI", _bt_hfp_get_imsi },
2407 { "AT+CREG", _bt_hfp_get_creg_status },
2411 int num_of_secure_command = 4;
2412 static const char* secure_command[] = {"CLCC", "CLIP", "CPBR", "CCWA"};
2414 static void __bt_ag_agent_print_at_buffer(char *message, const char *buf)
2418 char s[MAX_BUFFER_SIZE] = {0, };
2419 gboolean hide = FALSE;
2421 gboolean is_security_command = FALSE;
2424 strncpy(s, buf, MAX_BUFFER_SIZE - 1);
2426 for (i = 0; i < num_of_secure_command; i++) {
2427 if (strstr(buf, secure_command[i])) {
2428 is_security_command = TRUE;
2433 /* +XSAT: 11,DISC */
2434 xsat_ptr = strstr(s, "11,DISC,");
2436 xsat_ptr = xsat_ptr + 8;
2438 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2444 /* AT+XSAT=11,Q_CT,X,XXXX */
2445 xsat_ptr = strstr(s, "11,Q_CT,");
2447 xsat_ptr = xsat_ptr + 8;
2449 while (xsat_ptr[x] != '\0' && xsat_ptr[x] != '\r' && xsat_ptr[x] != '\n') {
2450 if (x > 1) /* ignore 0 and 1 position */
2457 while (s[i] != '\0') {
2458 if (s[i] == '\r' || s[i] == '\n') {
2462 hide = hide ? FALSE : TRUE;
2463 else if (is_security_command && hide) {
2471 INFO("%s Buffer = [%s], Len(%d)", message, s, strlen(s));
2476 static int __bt_ag_at_handler(bt_ag_info_t *hs, const char *buf)
2480 __bt_ag_agent_print_at_buffer("[AG AT CMD][RCVD] :", buf);
2482 for (ev = at_event_callbacks; ev->cmd; ev++) {
2483 if (!strncmp(buf, ev->cmd, strlen(ev->cmd)))
2484 return ev->callback(hs, buf);
2490 static int __bt_ag_send_at_valist(bt_ag_info_t *hdset, va_list list,
2493 ssize_t final_written, count;
2494 char rsp_buffer[MAX_BUFFER_SIZE];
2498 count = vsnprintf(rsp_buffer, sizeof(rsp_buffer), list_format, list);
2500 ERR("count is %d", count);
2504 if (!hdset->io_chan) {
2505 ERR("__bt_ag_send_at_valist: headset not connected");
2511 fd = g_io_channel_unix_get_fd(hdset->io_chan);
2514 while (final_written < count) {
2518 written = write(fd, rsp_buffer + final_written,
2519 count - final_written);
2520 } while (written < 0 && errno == EINTR);
2524 ERR("write failed : %s (%d)", strerror(-err), -err);
2528 final_written += written;
2531 /* Synchronize the sending buffer */
2533 /* Don't do sync call as it may block process untill all buffers are cleared
2534 * On Z300F device this issue is reproduciable just connect with meacap
2535 * select phonebook and call CPBR when we call CPBR multiple times it is
2536 * blocking for 5 seconds.*/
2541 ERR_SECURE("FD is 0. remote_addr : %s", hdset->remote_addr);
2545 __bt_ag_agent_print_at_buffer("[AG AT CMD][SENT]", rsp_buffer);
2550 int __attribute__((format(printf, 2, 3)))
2551 _bt_ag_send_at(bt_ag_info_t *hs, char *format, ...)
2556 va_start(ap, format);
2557 ret = __bt_ag_send_at_valist(hs, ap, format);
2563 void __attribute__((format(printf, 3, 4)))
2564 _bt_ag_send_foreach_headset(GSList *devices,
2565 int (*cmp) (bt_ag_info_t *hs),
2571 for (l = devices; l != NULL; l = l->next) {
2572 bt_ag_info_t *hs = l->data;
2575 if (cmp && cmp(hs) != 0)
2578 va_start(ap, format);
2579 ret = __bt_ag_send_at_valist(hs, ap, format);
2581 ERR("Failed to send to headset: %s (%d)",
2582 strerror(-ret), -ret);
2587 int _bt_ag_send_response(bt_ag_info_t *hs, hfp_state_manager_err_t err)
2589 if ((err != HFP_STATE_MNGR_ERR_NONE) && hs->slc->is_cme_enabled)
2590 return _bt_ag_send_at(hs, "\r\n+CME ERROR: %d\r\n", err);
2593 case HFP_STATE_MNGR_ERR_NONE:
2594 return _bt_ag_send_at(hs, "\r\nOK\r\n");
2595 case HFP_STATE_MNGR_ERR_NO_NETWORK_SERVICE:
2596 return _bt_ag_send_at(hs, "\r\nNO CARRIER\r\n");
2598 return _bt_ag_send_at(hs, "\r\nERROR\r\n");
2602 static gboolean __bt_ag_event_handler(GIOChannel *channel,
2603 GIOCondition cond, void *user_data)
2605 bt_ag_slconn_t *slconn;
2606 unsigned char event_buf[MAX_BUFFER_SIZE];
2608 size_t available_buffer;
2610 bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2614 if (cond & G_IO_NVAL)
2617 slconn = bt_ag_info->slc;
2618 if (cond & (G_IO_ERR | G_IO_HUP)) {
2619 if (bt_ag_info->watch_id)
2620 __bt_ag_agent_remove_watch(&bt_ag_info->watch_id);
2622 ERR("ERR or HUP on RFCOMM socket");
2623 INFO_C("Disconnected [AG role] [Terminated by remote dev]");
2627 fd = g_io_channel_unix_get_fd(channel);
2628 len = read(fd, event_buf, sizeof(event_buf) - 1);
2632 available_buffer = sizeof(slconn->buffer) - (slconn->start) -
2633 (slconn->length) - 1;
2634 if (available_buffer < (size_t) len) {
2635 ERR("Buffer over flow");
2639 memcpy(&slconn->buffer[slconn->start + slconn->length], event_buf, len);
2640 slconn->length += len;
2642 slconn->buffer[slconn->start + slconn->length] = '\0';
2644 while (slconn->length > 0) {
2649 get_cr = strchr(&slconn->buffer[slconn->start], '\r');
2651 ERR("Broken AT command received, break");
2655 cmd_len = 1 + (off_t) get_cr -
2656 (off_t) &slconn->buffer[slconn->start];
2660 DBG("Call AT handler");
2661 err = __bt_ag_at_handler(bt_ag_info,
2662 &slconn->buffer[slconn->start]);
2664 ERR("Failed to call AT handler");
2671 err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
2674 err_return = HFP_STATE_MNGR_ERR_NOT_ALLOWED;
2677 err_return = HFP_STATE_MNGR_ERR_NOT_SUPPORTED;
2680 ERR("Error handling command %s: %s (%d)",
2681 &slconn->buffer[slconn->start],
2682 strerror(-err), -err);
2683 err = _bt_ag_send_response(bt_ag_info,
2689 slconn->start += cmd_len;
2690 slconn->length -= cmd_len;
2692 if (slconn->length <= 0)
2697 ERR("Failed in event handler - SLC Disconnect");
2698 _bt_ag_set_headset_state(bt_ag_info,
2699 HEADSET_STATE_DISCONNECTED);
2703 static gboolean __bt_ag_agent_connection(gint32 fd, const gchar *device_path,
2704 const gchar *object_path)
2708 bt_ag_info_t *bt_ag_info = g_new0(bt_ag_info_t, 1);
2709 struct sockaddr_remote address;
2710 socklen_t address_len;
2712 INFO_C("Connected [AG role]");
2713 bt_ag_info->rfcomm = NULL;
2714 bt_ag_info->slc = NULL;
2715 bt_ag_info->hfp_active = TRUE;
2716 bt_ag_info->vr_blacklisted = FALSE;
2717 bt_ag_info->state = HEADSET_STATE_DISCONNECTED;
2718 bt_ag_info->sco_server_started = FALSE;
2719 __bt_ag_codec_negotiation_info_reset(bt_ag_info, TRUE);
2721 bt_ag_info->path = device_path;
2722 DBG_SECURE("device_path = [%s]", device_path);
2724 address_len = sizeof(address);
2725 if (getpeername(fd, (struct sockaddr *) &address, &address_len) != 0)
2726 ERR("BD_ADDR is NULL");
2728 DBG("RFCOMM connection for HFP/HSP is completed. Fd = [%d]", fd);
2729 bt_ag_info->fd = fd;
2730 bt_ag_info->io_chan = g_io_channel_unix_new(bt_ag_info->fd);
2731 flags = g_io_channel_get_flags(bt_ag_info->io_chan);
2733 flags &= ~G_IO_FLAG_NONBLOCK;
2734 flags &= G_IO_FLAG_MASK;
2735 g_io_channel_set_flags(bt_ag_info->io_chan, flags, NULL);
2736 g_io_channel_set_encoding(bt_ag_info->io_chan, NULL, NULL);
2737 g_io_channel_set_buffered(bt_ag_info->io_chan, FALSE);
2739 bt_ag_info->rfcomm = g_io_channel_ref(bt_ag_info->io_chan);
2741 bt_ag_info->remote_addr = g_malloc0(BT_ADDRESS_STRING_SIZE);
2742 __bt_convert_addr_type_to_rev_string(bt_ag_info->remote_addr,
2743 address.remote_bdaddr.b);
2745 #if defined(TIZEN_SUPPORT_DUAL_HF)
2746 bt_ag_info->is_companion_device =
2747 __bt_ag_agent_is_companion_device(bt_ag_info->remote_addr);
2750 DBG_SECURE("remote Device Address = [%s]", bt_ag_info->remote_addr);
2752 if (g_strcmp0(object_path, BT_HS_AG_AGENT_OBJECT_PATH) == 0) {
2753 DBG("HSP connection completed");
2754 _bt_ag_set_headset_state(bt_ag_info,
2755 HEADSET_STATE_CONNECTED);
2757 DBG("HFP connection connecting");
2758 _bt_ag_set_headset_state(bt_ag_info,
2759 HEADSET_STATE_CONNECTING);
2762 __bt_ag_agent_start_watch(bt_ag_info);
2764 bt_ag_info->slc = g_new0(bt_ag_slconn_t, 1);
2765 bt_ag_info->slc->speaker_gain = last_speaker_gain;
2766 bt_ag_info->slc->microphone_gain = 9;
2767 bt_ag_info->slc->is_nrec = TRUE;
2772 static gboolean __bt_ag_agent_is_device_vr_blacklisted(const char *lap_addr)
2781 fp = fopen(AGENT_VR_BLACKLIST_FILE, "r");
2784 ERR("Unable to open VR blacklist file");
2788 fseek(fp, 0, SEEK_END);
2791 ERR("size is not a positive number");
2798 buffer = g_malloc0(sizeof(char) * size);
2799 if (buffer == NULL) {
2800 ERR("g_malloc0 is failed");
2804 result = fread((char *)buffer, 1, size, fp);
2806 if (result != size) {
2812 token = strtok_r(buffer, "=", &saveptr);
2813 if (token == NULL) {
2818 while ((token = strtok_r(NULL, ",", &saveptr))) {
2819 if (strlen(token) > 8)
2821 if (0 == g_strcmp0(token, lap_addr)) {
2822 INFO("Voice Recognition blacklisted");
2831 static gboolean __bt_sco_open_delay_timeout_cb(gpointer user_data)
2833 bt_ag_info_t *bt_ag_info = (bt_ag_info_t *)user_data;
2834 sco_open_timer_id = 0;
2835 DBG("sco_open_request (%d)", sco_open_request);
2837 if (sco_open_request && bt_ag_info->state == HEADSET_STATE_CONNECTED) {
2838 bt_ag_slconn_t *slconn = bt_ag_info->slc;
2840 INFO("try to open SCO");
2841 sco_open_request = FALSE;
2843 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
2844 (slconn && (slconn->hs_features &
2845 BT_HF_FEATURE_CODEC_NEGOTIATION))) {
2846 switch (bt_ag_info->codec_info.final_codec) {
2847 case BT_CVSD_CODEC_ID:
2848 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
2849 __bt_ag_sco_connect(bt_ag_info);
2851 case BT_MSBC_CODEC_ID:
2852 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
2853 __bt_ag_sco_connect(bt_ag_info);
2856 __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
2860 __bt_ag_sco_connect(bt_ag_info);
2862 DBG("Dbus Reply for SCO Connection request");
2863 g_dbus_method_invocation_return_value(bt_ag_info->invocation, NULL);
2870 * Service level connection complete
2871 * indication and state management
2873 void _bt_ag_slconn_complete(bt_ag_info_t *hs)
2875 char lap_address[BT_LOWER_ADDRESS_LENGTH];
2877 DBG("HFP Service Level Connection established\n");
2879 /* Check device Voice Recognition blacklist status */
2880 g_strlcpy(lap_address, hs->remote_addr, sizeof(lap_address));
2881 hs->vr_blacklisted =
2882 __bt_ag_agent_is_device_vr_blacklisted(lap_address);
2884 if (sco_open_timer_id > 0) {
2885 g_source_remove(sco_open_timer_id);
2886 sco_open_timer_id = 0;
2889 sco_open_request = FALSE;
2890 sco_open_timer_id = g_timeout_add(BT_SCO_OPEN_DELAY_TIMER,
2891 __bt_sco_open_delay_timeout_cb, hs);
2893 _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2896 static gboolean __bt_ag_agent_connection_release(bt_ag_info_t *hs)
2899 g_io_channel_shutdown(hs->io_chan, TRUE, NULL);
2900 g_io_channel_unref(hs->io_chan);
2904 __bt_ag_close_sco(hs);
2905 _bt_ag_set_headset_state(hs, HEADSET_STATE_CONNECTED);
2907 __bt_ag_agent_remove_watch(&hs->watch_id);
2909 _bt_ag_set_headset_state(hs, HEADSET_STATE_DISCONNECTED);
2913 static GQuark __bt_ag_agent_error_quark(void)
2917 static GQuark quark = 0;
2919 quark = g_quark_from_static_string("ag-agent");
2925 static GError *__bt_ag_agent_set_error(bt_hfp_agent_error_t error)
2928 ERR("error[%d]\n", error);
2931 case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
2932 return g_error_new(BT_AG_AGENT_ERROR, error,
2933 BT_ERROR_NOT_AVAILABLE);
2934 case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
2935 return g_error_new(BT_AG_AGENT_ERROR, error,
2936 BT_ERROR_NOT_CONNECTED);
2937 case BT_HFP_AGENT_ERROR_BUSY:
2938 return g_error_new(BT_AG_AGENT_ERROR, error,
2940 case BT_HFP_AGENT_ERROR_INVALID_PARAM:
2941 return g_error_new(BT_AG_AGENT_ERROR, error,
2942 BT_ERROR_INVALID_PARAM);
2943 case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
2944 return g_error_new(BT_AG_AGENT_ERROR, error,
2945 BT_ERROR_ALREADY_EXSIST);
2946 case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
2947 return g_error_new(BT_AG_AGENT_ERROR, error,
2948 BT_ERROR_ALREADY_CONNECTED);
2949 case BT_HFP_AGENT_ERROR_NO_MEMORY:
2950 return g_error_new(BT_AG_AGENT_ERROR, error,
2951 BT_ERROR_NO_MEMORY);
2952 case BT_HFP_AGENT_ERROR_I_O_ERROR:
2953 return g_error_new(BT_AG_AGENT_ERROR, error,
2954 BT_ERROR_I_O_ERROR);
2955 case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
2956 return g_error_new(BT_AG_AGENT_ERROR, error,
2957 BT_ERROR_OPERATION_NOT_AVAILABLE);
2958 case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
2959 return g_error_new(BT_AG_AGENT_ERROR, error,
2961 case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
2962 return g_error_new(BT_AG_AGENT_ERROR, error,
2964 case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
2965 return g_error_new(BT_AG_AGENT_ERROR, error,
2966 BT_ERROR_NO_CALL_LOG);
2967 case BT_HFP_AGENT_ERROR_INTERNAL:
2969 return g_error_new(BT_AG_AGENT_ERROR, error,
2975 static bt_ag_info_t *__bt_get_active_headset(const gchar *device_path)
2979 for (l = active_devices ; l; l = l->next) {
2980 bt_ag_info_t *data = l->data;
2981 if (device_path == NULL) /*just to avoid crash incase of "play" when dailed from device[NEEDS TO BE CHANGED]*/
2983 if (g_strcmp0(data->path, device_path) == 0) {
2984 INFO("Active device found");
2989 INFO("Active device not found");
2993 static void __bt_ag_agent_method(GDBusConnection *connection,
2994 const gchar *sender,
2995 const gchar *object_path,
2996 const gchar *interface_name,
2997 const gchar *method_name,
2998 GVariant *parameters,
2999 GDBusMethodInvocation *invocation,
3004 INFO("method %s", method_name);
3005 INFO("object_path %s", object_path);
3006 int ret = BT_HFP_AGENT_ERROR_NONE;
3008 const gchar *device_path = NULL;
3011 if (g_strcmp0(method_name, "NewConnection") == 0) {
3015 GUnixFDList *fd_list;
3016 GVariant *options = NULL;
3017 int device_count = 0;
3019 device_count = g_slist_length(active_devices);
3021 INFO("device_count %d", device_count);
3023 if (device_count >= MAX_CONNECTED_DEVICES) {
3024 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3028 g_variant_get(parameters, "(oha{sv})",
3029 &device_path, &index, &options);
3030 #if defined(TIZEN_SUPPORT_DUAL_HF)
3031 if (TIZEN_PROFILE_WEARABLE) {
3033 * Below code is not required for dual HF support for
3037 __bt_ag_agent_check_dual_hf_condition(device_path) == FALSE) {
3038 INFO("not allow to connect 2nd HF connection");
3039 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3044 msg = g_dbus_method_invocation_get_message(invocation);
3045 fd_list = g_dbus_message_get_unix_fd_list(msg);
3046 if (fd_list == NULL) {
3047 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3051 fd = g_unix_fd_list_get(fd_list, index, NULL);
3053 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3057 DBG_SECURE("FD is = [%d], device_path = [%s]\n", fd, device_path);
3059 if (!__bt_ag_agent_connection(fd, device_path, object_path)) {
3060 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3064 g_dbus_method_invocation_return_value(invocation, NULL);
3065 } else if (g_strcmp0(method_name, "RequestDisconnection") == 0) {
3067 g_variant_get(parameters, "(o)", &device_path);
3068 INFO_SECURE("device_path %s", device_path);
3070 for (l = active_devices; l; l = l->next) {
3071 bt_ag_info_t *data = l->data;
3073 INFO_SECURE("data->path %s", data->path);
3074 if (g_strcmp0(data->path, device_path) == 0) {
3075 if (!__bt_ag_agent_connection_release(data)) {
3076 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3079 INFO_C("Disconnected [AG role] [Terminated by local host]");
3080 g_dbus_method_invocation_return_value(invocation, NULL);
3083 } else if (g_strcmp0(method_name, "ReplyAuthorize") == 0) {
3086 g_variant_get(parameters, "(u)", &accept);
3087 INFO("Accept: %d", accept);
3091 INFO_SECURE("data->path %s", data->path);
3092 data->pbap_trusted = accept;
3094 _bt_hfp_select_phonebook_memory_status_reply(data);
3096 INFO("pbap_trusted %d", data->pbap_trusted);
3098 if (data->pbap_trusted == BT_AG_FEATURE_PBAP_ALLOWED) {
3099 /* Allow Access update this to bluez */
3100 bt_device_set_profile_trusted(data->remote_addr,
3102 } else if (data->pbap_trusted == BT_AG_FEATURE_PBAP_BLOCKED) {
3103 /* Blocked Access update this to bluez */
3104 bt_device_set_profile_trusted(data->remote_addr,
3107 } else if (g_strcmp0(method_name, "RegisterApplication") == 0) {
3109 gchar *address = NULL;
3110 g_variant_get(parameters, "(&s&s)", &path, &address);
3111 /*local_addr = malloc(strlen(address));
3112 memcpy(local_addr, address, strlen(address));*/
3114 DBG("Sender = %s, Application path = %s\n", sender, path);
3115 ret = _bt_hfp_register_telephony_agent(TRUE, path, sender);
3120 local_addr = g_strdup(address);
3121 DBG_SECURE("Address = %s\n", local_addr);
3122 g_dbus_method_invocation_return_value(invocation, NULL);
3123 } else if (g_strcmp0(method_name, "UnregisterApplication") == 0) {
3125 g_variant_get(parameters, "(&s)", &path);
3127 DBG("Application path = %s\n", path);
3128 DBG("Sender = %s\n", sender);
3130 ret = _bt_hfp_register_telephony_agent(FALSE, path, sender);
3134 g_dbus_method_invocation_return_value(invocation, NULL);
3135 } else if (g_strcmp0(method_name, "IncomingCall") == 0) {
3137 gchar *number = NULL;
3140 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3142 DBG("Application path = %s", path);
3143 DBG_SECURE("Phone number = %s", number);
3144 DBG("Call id = %d", call_id);
3146 DBG("Sender = %s", sender);
3148 ret = _bt_hfp_incoming_call(path, number, call_id, sender);
3151 g_dbus_method_invocation_return_value(invocation, NULL);
3152 } else if (g_strcmp0(method_name, "OutgoingCall") == 0) {
3154 gchar *number = NULL;
3157 g_variant_get(parameters, "(&s&si)", &path, &number, &call_id);
3159 DBG("Application path = %s", path);
3160 DBG_SECURE("Phone number = %s", number);
3161 DBG("Call id = %d", call_id);
3163 DBG("Sender = %s", sender);
3165 ret = _bt_hfp_outgoing_call(path, number, call_id, sender);
3168 g_dbus_method_invocation_return_value(invocation, NULL);
3169 } else if (g_strcmp0(method_name, "ChangeCallStatus") == 0) {
3171 gchar *number = NULL;
3176 g_variant_get(parameters, "(&s&sii)",
3177 &path, &number, &status, &call_id);
3178 DBG("Application path = %s\n", path);
3179 DBG_SECURE("Number = %s\n", number);
3180 DBG("Status = %d\n", status);
3181 DBG("Call id = %d\n", call_id);
3182 DBG("Sender = %s\n", sender);
3184 ret = _bt_hfp_change_call_status(path,
3185 number, status, call_id, sender);
3187 if (_bt_hfp_is_call_exist() == FALSE) {
3188 for (l = active_devices; l; l = l->next) {
3189 bt_ag_info_t *data = l->data;
3191 if (data->state == HEADSET_STATE_ON_CALL) {
3192 __bt_ag_close_sco(data);
3193 _bt_ag_set_headset_state(data,
3194 HEADSET_STATE_CONNECTED);
3201 g_dbus_method_invocation_return_value(invocation, NULL);
3202 } else if (g_strcmp0(method_name, "GetProperties") == 0) {
3203 GVariantBuilder *builder;
3205 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3208 gchar *codec = g_strdup("codec");
3209 gchar *nrec = g_strdup("nrec");
3211 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3213 g_variant_builder_add(builder, "{sv}",
3214 codec, g_variant_new("u", bt_ag_info->codec_info.final_codec));
3215 g_variant_builder_add(builder, "{sv}",
3216 nrec, g_variant_new("b", bt_ag_info->nrec_status));
3218 var_data = g_variant_new("(a{sv})", builder);
3219 g_variant_builder_unref(builder);
3220 g_dbus_method_invocation_return_value(invocation, var_data);
3225 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3228 } else if (g_strcmp0(method_name, "Disconnect") == 0) {
3229 char hdset_address[18] = { 0, };
3231 for (l = active_devices; l; l = l->next) {
3232 bt_ag_info_t *data = l->data;
3234 __bt_convert_addr_type_to_rev_string(hdset_address,
3235 (unsigned char *)data->remote_addr);
3237 DBG_SECURE("Disconnect Headset %s, %s\n",
3238 hdset_address, data->path);
3239 _bt_ag_set_headset_state(data,
3240 HEADSET_STATE_DISCONNECTED);
3242 g_dbus_method_invocation_return_value(invocation, NULL);
3243 } else if (g_strcmp0(method_name, "IsConnected") == 0) {
3244 gboolean is_connected = FALSE;
3246 for (l = active_devices; l; l = l->next) {
3247 bt_ag_info_t *data = l->data;
3249 if (data->state >= HEADSET_STATE_CONNECTED)
3250 is_connected = TRUE;
3252 DBG("is_connected : %s",
3253 is_connected ? "Connected" : "Disconnected");
3255 g_dbus_method_invocation_return_value(invocation,
3256 g_variant_new("(b)", is_connected));
3257 } else if (g_strcmp0(method_name, "IndicateCall") == 0) {
3259 if (0 == g_slist_length(active_devices)) {
3260 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3264 if (ag.ring_timer) {
3265 DBG("IndicateCall received when already indicating");
3266 g_dbus_method_invocation_return_value(invocation, NULL);
3269 for (l = active_devices; l; l = l->next) {
3270 bt_ag_info_t *data = l->data;
3272 if (data->state >= HEADSET_STATE_CONNECTED)
3273 _bt_ag_send_at(data, "\r\nRING\r\n");
3276 __bt_ring_timer_cb(NULL);
3277 ag.ring_timer = g_timeout_add(AG_RING_INTERVAL,
3278 __bt_ring_timer_cb, NULL);
3279 g_dbus_method_invocation_return_value(invocation, NULL);
3280 } else if (g_strcmp0(method_name, "CancelCall") == 0) {
3281 if (0 == g_slist_length(active_devices)) {
3282 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3286 if (ag.ring_timer) {
3287 g_source_remove(ag.ring_timer);
3290 DBG("Got CancelCall method call but no call is active");
3292 g_dbus_method_invocation_return_value(invocation, NULL);
3293 } else if (g_strcmp0(method_name, "Play") == 0) {
3294 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3295 bt_ag_slconn_t *slconn = NULL;
3298 slconn = bt_ag_info->slc;
3300 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3304 #ifndef __TIZEN_OPEN__
3307 if (slconn && FALSE == slconn->is_voice_recognition_running &&
3308 mdm_get_service() == MDM_RESULT_SUCCESS) {
3309 mode = mdm_get_allow_bluetooth_outgoing_call();
3310 mdm_release_service();
3312 if (mode == MDM_RESTRICTED) {
3313 ERR("[MDM] Not allow the outgoing call");
3314 ret = BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
3321 switch (bt_ag_info->state) {
3322 case HEADSET_STATE_CONNECTING:
3323 case HEADSET_STATE_DISCONNECTED:
3324 ERR("HEADSET_STATE ERROR");
3325 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3327 case HEADSET_STATE_CONNECTED:
3329 case HEADSET_STATE_PLAY_IN_PROGRESS:
3330 ERR("Play In Progress");
3331 ret = BT_HFP_AGENT_ERROR_BUSY;
3333 case HEADSET_STATE_ON_CALL:
3334 ERR("SCO is already established");
3335 ret = BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
3343 if (sco_open_timer_id > 0) {
3344 INFO("SCO open delay");
3345 sco_open_request = TRUE;
3346 bt_ag_info->invocation = invocation;
3350 if ((ag.features & BT_AG_FEATURE_CODEC_NEGOTIATION) &&
3351 (slconn && (slconn->hs_features &
3352 BT_HF_FEATURE_CODEC_NEGOTIATION))) {
3353 switch (bt_ag_info->codec_info.final_codec) {
3354 case BT_CVSD_CODEC_ID:
3355 __bt_ag_set_codec(bt_ag_info, "SetNbParameters");
3356 ret = __bt_ag_sco_connect(bt_ag_info);
3358 case BT_MSBC_CODEC_ID:
3359 __bt_ag_set_codec(bt_ag_info, "SetWbsParameters");
3360 ret = __bt_ag_sco_connect(bt_ag_info);
3363 ret = __bt_hfp_codec_connection_setup(bt_ag_info, FALSE);
3367 ret = __bt_ag_sco_connect(bt_ag_info);
3373 sco_owner = g_strdup(sender);
3375 g_dbus_method_invocation_return_value(invocation, NULL);
3377 if (name_owner_sig_id == 0)
3378 name_owner_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
3379 NULL, NULL, "NameOwnerChanged", NULL, NULL, 0,
3380 __bt_ag_name_owner_changed_cb, NULL, NULL);
3381 } else if (g_strcmp0(method_name, "Stop") == 0) {
3383 for (l = active_devices; l; l = l->next) {
3384 bt_ag_info_t *data = l->data;
3386 if (data->state > HEADSET_STATE_CONNECTED) {
3387 __bt_ag_close_sco(data);
3388 _bt_ag_set_headset_state(data,
3389 HEADSET_STATE_CONNECTED);
3393 g_dbus_method_invocation_return_value(invocation, NULL);
3394 } else if (g_strcmp0(method_name, "IsPlaying") == 0) {
3395 gboolean is_playing = FALSE;
3397 for (l = active_devices; l; l = l->next) {
3398 bt_ag_info_t *data = l->data;
3400 if (data->state == HEADSET_STATE_ON_CALL)
3403 DBG("is_playing : %s", is_playing ? "Playing" : "Not Playing");
3405 g_dbus_method_invocation_return_value(invocation,
3406 g_variant_new("(b)", is_playing));
3407 } else if (g_strcmp0(method_name, "GetSpeakerGain") == 0) {
3408 bt_ag_slconn_t *slconn = NULL;
3409 guint16 gain_value = 0;
3410 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3412 if (bt_ag_info == NULL ||
3413 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3414 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3418 slconn = bt_ag_info->slc;
3420 gain_value = (guint16) slconn->speaker_gain;
3422 g_dbus_method_invocation_return_value(invocation,
3423 g_variant_new("(q)", gain_value));
3424 } else if (g_strcmp0(method_name, "SetSpeakerGain") == 0) {
3426 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3427 if (bt_ag_info == NULL ||
3428 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3429 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3433 g_variant_get(parameters, "(q)", &gain);
3434 DBG("Speaker gain = %d\n", gain);
3436 ret = _bt_hfp_set_speaker_gain(bt_ag_info, gain);
3439 g_dbus_method_invocation_return_value(invocation, NULL);
3440 } else if (g_strcmp0(method_name, "GetMicrophoneGain") == 0) {
3441 bt_ag_slconn_t *slconn = NULL;
3442 guint16 gain_value = 0;
3443 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3445 if (bt_ag_info == NULL ||
3446 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3447 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3451 if (bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3452 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3456 slconn = bt_ag_info->slc;
3458 gain_value = (guint16) slconn->microphone_gain;
3460 g_dbus_method_invocation_return_value(invocation,
3461 g_variant_new("(q)", gain_value));
3462 } else if (g_strcmp0(method_name, "SetMicrophoneGain") == 0) {
3464 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3465 if (bt_ag_info == NULL ||
3466 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3467 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3471 g_variant_get(parameters, "(q)", &gain);
3472 DBG("Microphone gain = %d\n", gain);
3474 ret = _bt_hfp_set_microphone_gain(bt_ag_info, gain);
3477 g_dbus_method_invocation_return_value(invocation, NULL);
3478 } else if (g_strcmp0(method_name, "SetVoiceDial") == 0) {
3479 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3480 if (bt_ag_info == NULL ||
3481 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3482 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3486 bt_ag_slconn_t *slconn = bt_ag_info->slc;
3489 g_variant_get(parameters, "(b)", &enable);
3490 DBG("VoiceDail enable = %d\n", enable);
3492 if ((slconn && !(slconn->hs_features &
3493 BT_HF_FEATURE_VOICE_RECOGNITION)))
3494 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3495 else if (bt_ag_info->vr_blacklisted)
3496 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3498 ret = _bt_hfp_set_voice_dial(bt_ag_info, enable);
3501 slconn->is_voice_recognition_running = enable;
3505 g_dbus_method_invocation_return_value(invocation, NULL);
3506 } else if (g_strcmp0(method_name, "SendVendorAtCmd") == 0) {
3508 bt_ag_info_t *bt_ag_info = __bt_get_active_headset(remote_dev_path);
3509 if (bt_ag_info == NULL ||
3510 bt_ag_info->state < HEADSET_STATE_CONNECTED) {
3511 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3515 g_variant_get(parameters, "(&s)", &cmd);
3517 ret = BT_HFP_AGENT_ERROR_INVALID_PARAM;
3521 DBG("vendor cmd = %s", cmd);
3523 ret = _bt_hfp_send_vendor_cmd(bt_ag_info, cmd);
3526 g_dbus_method_invocation_return_value(invocation, NULL);
3527 } else if (g_strcmp0(method_name, "CheckPrivilege") == 0) {
3528 DBG("Already pass dbus SMACK for bt-service::platform");
3529 /* Return success */
3530 g_dbus_method_invocation_return_value(invocation, NULL);
3531 } else if (g_strcmp0(method_name, "SwapHeadset") == 0) {
3534 char address[BT_ADDRESS_STRING_SIZE];
3535 char remote_addr[BT_ADDRESS_STRING_SIZE];
3536 gboolean device_found = FALSE;
3538 g_variant_get(parameters, "(s)", &addr);
3539 g_strlcpy(address, addr, sizeof(address));
3540 DBG("Sender = %s", sender);
3542 /* Loop through connected headset list
3543 * If found, update the remote_dev_path.
3545 for (l = active_devices ; l; l = l->next) {
3546 bt_ag_info_t *data = l->data;
3547 g_strlcpy(remote_addr, data->remote_addr, sizeof(remote_addr));
3548 if (g_strcmp0(remote_addr, address) == 0) {
3549 DBG("Active device found");
3550 if (data->path == NULL) {
3551 DBG("device path is null");
3552 ret = BT_HFP_AGENT_ERROR_INTERNAL;
3555 remote_dev_path = g_strdup(data->path);
3556 DBG("Setting device path %s as active device path", remote_dev_path);
3557 device_found = TRUE;
3562 if (!device_found) {
3563 ret = BT_HFP_AGENT_ERROR_NOT_CONNECTED;
3567 g_dbus_method_invocation_return_value(invocation, NULL);
3574 err = __bt_ag_agent_set_error(ret);
3575 g_dbus_method_invocation_return_gerror(invocation, err);
3580 static const GDBusInterfaceVTable method_table = {
3581 __bt_ag_agent_method,
3586 static GDBusNodeInfo *__bt_ag_create_method_node_info
3587 (const gchar *introspection_data)
3590 GDBusNodeInfo *node_info = NULL;
3592 if (introspection_data == NULL)
3595 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
3598 ERR("Unable to create node: %s", err->message);
3599 g_clear_error(&err);
3604 static GDBusConnection *__bt_ag_get_gdbus_connection(void)
3610 if (ag_dbus_conn == NULL)
3611 ag_dbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
3613 if (!ag_dbus_conn) {
3615 ERR("Unable to connect to dbus: %s", err->message);
3616 g_clear_error(&err);
3622 return ag_dbus_conn;
3625 static gboolean __bt_ag_register_profile_methods(void)
3628 GError *error = NULL;
3630 GDBusNodeInfo *node_info = NULL;
3633 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
3635 G_BUS_NAME_OWNER_FLAGS_NONE,
3639 DBG("owner_id is [%d]", owner_id);
3641 node_info = __bt_ag_create_method_node_info(
3642 ag_agent_bluez_introspection_xml);
3643 if (node_info == NULL)
3646 path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3647 DBG("path is [%s]", path);
3649 hf_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3650 node_info->interfaces[0],
3652 NULL, NULL, &error);
3653 if (hf_bluez_id == 0) {
3654 ERR("Failed to register: %s", error->message);
3655 g_error_free(error);
3657 g_dbus_node_info_unref(node_info);
3662 /* Ag register profile methods for HSP*/
3664 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
3665 DBG("path is [%s]", path);
3667 hs_bluez_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3668 node_info->interfaces[0],
3670 NULL, NULL, &error);
3671 if (hs_bluez_id == 0) {
3672 ERR("Failed to register: %s", error->message);
3673 g_error_free(error);
3675 g_dbus_node_info_unref(node_info);
3679 g_dbus_node_info_unref(node_info);
3681 node_info = __bt_ag_create_method_node_info
3682 (ag_agent_app_introspection_xml);
3683 if (node_info == NULL)
3686 path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
3687 DBG("path is [%s]", path);
3689 app_id = g_dbus_connection_register_object(ag_dbus_conn, path,
3690 node_info->interfaces[0],
3692 NULL, NULL, &error);
3694 ERR("Failed to register: %s", error->message);
3695 g_error_free(error);
3697 g_dbus_node_info_unref(node_info);
3701 g_dbus_node_info_unref(node_info);
3707 static void __bt_ag_unregister_profile_methods(void)
3711 if (hf_bluez_id > 0) {
3712 g_dbus_connection_unregister_object(ag_dbus_conn,
3717 if (hs_bluez_id > 0) {
3718 g_dbus_connection_unregister_object(ag_dbus_conn,
3724 g_dbus_connection_unregister_object(ag_dbus_conn,
3730 static GDBusProxy *__bt_ag_gdbus_get_profile_proxy(void)
3732 return (profile_gproxy) ? profile_gproxy :
3733 __bt_ag_gdbus_init_profile_proxy();
3736 static void __bt_ag_agent_register(gchar *path, uint16_t profile_version,
3737 char *profile_uuid, const char* profile_name)
3742 GError *error = NULL;
3743 GVariantBuilder *builder;
3745 proxy = __bt_ag_gdbus_get_profile_proxy();
3749 builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
3751 g_variant_builder_add(builder, "{sv}",
3752 "Name", g_variant_new("s",
3754 g_variant_builder_add(builder, "{sv}",
3755 "Version", g_variant_new("q", profile_version));
3756 /*g_variant_builder_add(builder, "{sv}",
3757 "Role", g_variant_new("s","client"));*/
3758 if (g_strcmp0(path, BT_AG_AGENT_OBJECT_PATH) == 0) {
3759 g_variant_builder_add(builder, "{sv}",
3760 "features", g_variant_new("q", ag.sdp_features));
3763 ret = g_dbus_proxy_call_sync(proxy, "RegisterProfile",
3764 g_variant_new("(osa{sv})", path,
3765 profile_uuid, builder),
3766 G_DBUS_CALL_FLAGS_NONE, -1,
3768 g_variant_builder_unref(builder);
3769 /* set the name and role for the profile*/
3771 /* dBUS-RPC is failed */
3772 ERR("dBUS-RPC is failed");
3774 if (error != NULL) {
3775 /* dBUS gives error cause */
3776 ERR("D-Bus API failure: errCode[%x], message[%s]",
3777 error->code, error->message);
3779 g_clear_error(&error);
3784 g_variant_unref(ret);
3791 static void __bt_ag_agent_unregister(gchar *path)
3796 GError *error = NULL;
3798 proxy = __bt_ag_gdbus_get_profile_proxy();
3802 ret = g_dbus_proxy_call_sync(proxy, "UnregisterProfile",
3803 g_variant_new("(o)", path),
3804 G_DBUS_CALL_FLAGS_NONE, 100,
3807 /* set the name and role for the profile*/
3809 /* dBUS-RPC is failed */
3810 ERR("dBUS-RPC is failed");
3812 if (error != NULL) {
3813 /* dBUS gives error cause */
3814 ERR("D-Bus API failure: errCode[%x], message[%s]",
3815 error->code, error->message);
3817 g_clear_error(&error);
3821 g_variant_unref(ret);
3831 static void __bt_ag_agent_battery_status_cb(device_callback_e type,
3832 void *value, void *user_data)
3835 if (type == DEVICE_CALLBACK_BATTERY_CAPACITY) {
3836 device_battery_get_percent(&batt_cap);
3837 _bt_hfp_set_property_value("BatteryBarsChanged", batt_cap);
3841 static void __bt_ag_agent_network_signal_status_cb(TapiHandle *handle,
3842 const char *noti_id, void *data, void *user_data)
3844 int *signal_bar = data;
3846 BT_CHECK_SIGNAL_STRENGTH(*signal_bar);
3847 _bt_hfp_set_property_value("SignalBarsChanged", *signal_bar);
3850 static void __bt_ag_agent_lunar_connection_status_cb(keynode_t *node)
3852 gboolean status = vconf_keynode_get_bool(node);
3854 DBG("status = %d", status);
3856 if (status == TRUE) {
3857 for (l = active_devices; l; l = l->next) {
3858 bt_ag_info_t *data = l->data;
3859 _bt_ag_send_at(data, "\r\n+BSIR:1\r\n");
3864 static void __bt_ag_agent_call_preferred_voice_subscription_cb(TapiHandle *handle,
3865 const char *noti_id, void *data, void *user_data)
3867 TelCallPreferredVoiceSubsNoti_t *noti_data = (TelCallPreferredVoiceSubsNoti_t *)data;
3868 uint32_t ag_features;
3871 ERR("Error happen during voice subscription data noti");
3875 INFO("TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION = Value %d",
3876 noti_data->preferred_subs);
3877 ag_features = __bt_ag_agent_get_ag_features();
3878 switch (noti_data->preferred_subs) {
3879 case TAPI_CALL_PREFERRED_VOICE_SUBS_SIM1:
3880 case TAPI_CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS:
3881 if (tapi_handle_preferred_sim == tapi_handle[0]) {
3882 INFO("No handler change. Preferred sim is same as SIM1");
3885 __bt_ag_agent_unsubscribe_tapi_updates(tapi_handle_preferred_sim);
3886 tapi_handle_preferred_sim = tapi_handle[0];
3887 _bt_hfp_initialize_telephony_manager(ag_features, tapi_handle_preferred_sim);
3888 __bt_ag_agent_subscribe_tapi_updates(tapi_handle_preferred_sim);
3889 tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb, NULL);
3890 if (tapi_result != TAPI_API_SUCCESS)
3891 ERR("Fail to get sim info: %d", tapi_result);
3893 case TAPI_CALL_PREFERRED_VOICE_SUBS_SIM2:
3894 if (tapi_handle_preferred_sim == tapi_handle[1]) {
3895 INFO("No handler change. Preferred sim is same as SIM2");
3898 __bt_ag_agent_unsubscribe_tapi_updates(tapi_handle_preferred_sim);
3899 tapi_handle_preferred_sim = tapi_handle[1];
3900 _bt_hfp_initialize_telephony_manager(ag_features, tapi_handle_preferred_sim);
3901 __bt_ag_agent_subscribe_tapi_updates(tapi_handle_preferred_sim);
3902 tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb, NULL);
3903 if (tapi_result != TAPI_API_SUCCESS)
3904 ERR("Fail to get sim info: %d", tapi_result);
3908 case TAPI_CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK:
3909 case TAPI_CALL_PREFERRED_VOICE_SUBS_UNKNOWN:
3915 static void __bt_ag_agent_network_register_status_cb(TapiHandle *handle,
3916 const char *noti_id, void *data, void *user_data)
3919 bt_hfp_agent_network_registration_status_t network_service;
3923 int *service_type = data;
3925 DBG("Network service type changed = [%d]", *service_type);
3927 switch (*service_type) {
3928 case TAPI_NETWORK_SERVICE_TYPE_UNKNOWN:
3929 case TAPI_NETWORK_SERVICE_TYPE_NO_SERVICE:
3930 case TAPI_NETWORK_SERVICE_TYPE_SEARCH:
3938 ret = tel_get_property_int(GET_TAPI_HANDLE,
3939 TAPI_PROP_NETWORK_ROAMING_STATUS, &roam_status);
3940 if (ret != TAPI_API_SUCCESS) {
3941 ERR("Get roaming status failed err = %d\n", ret);
3945 if (roam_status == 0 && service == 1)
3946 network_service = BT_AGENT_NETWORK_REG_STATUS_HOME;
3947 else if (roam_status == 1 && service == 1)
3948 network_service = BT_AGENT_NETWORK_REG_STATUS_ROAMING;
3950 network_service = BT_AGENT_NETWORK_REG_STATUS_UNKOWN;
3952 _bt_hfp_set_property_value("RegistrationChanged", network_service);
3955 static void __bt_ag_agent_subscribe_vconf_updates(void)
3960 ret = device_add_callback(DEVICE_CALLBACK_BATTERY_CAPACITY,
3961 __bt_ag_agent_battery_status_cb, NULL);
3962 if (ret != DEVICE_ERROR_NONE) {
3963 ERR("Subscription to battery status failed err = [%d]\n", ret);
3966 if (TIZEN_PROFILE_WEARABLE) {
3967 ret = vconf_notify_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
3968 (void *)__bt_ag_agent_lunar_connection_status_cb, NULL);
3970 ERR("Subsrciption to lunar connection failed err = [%d]\n", ret);
3974 static void __bt_ag_agent_release_vconf_updates(void)
3979 ret = device_remove_callback(DEVICE_CALLBACK_BATTERY_CAPACITY,
3980 __bt_ag_agent_battery_status_cb);
3981 if (ret != DEVICE_ERROR_NONE) {
3982 ERR("Unsubscription to battery status failed err = [%d]\n", ret);
3985 if (TIZEN_PROFILE_WEARABLE) {
3986 ret = vconf_ignore_key_changed(VCONF_KEY_BT_LUNAR_ENABLED,
3987 (void *)__bt_ag_agent_lunar_connection_status_cb);
3989 ERR("Subsrciption to lunar connection failed err = [%d]\n", ret);
3993 static gboolean __bt_ag_agent_send_subscriber_number_changed(
3996 const char *property = g_strdup("SubscriberNumberChanged");
4000 DBG_SECURE("Number is %s", number);
4002 if (!_bt_hfp_set_property_name(property, number)) {
4003 DBG("Error- set property for subscriber no change - ERROR\n");
4004 g_free((void *)property);
4007 g_free((void *)property);
4011 static void __bt_ag_agent_sigterm_handler(int signo)
4016 ERR_C("***** Signal handler came with signal %d *****", signo);
4018 for (l = active_devices ; l; l = l->next) {
4019 bt_ag_info_t *data = l->data;
4020 if (!__bt_ag_agent_connection_release(data))
4021 ERR("__bt_ag_agent_connection_release failed");
4024 g_dbus_connection_flush(ag_dbus_conn, NULL, NULL, NULL);
4027 g_main_loop_quit(gmain_loop);
4031 INFO("Terminating AG agent");
4035 if (signo == SIGTERM)
4038 for (i = 0; i < BT_AG_SIG_NUM; i++)
4039 sigaction(bt_ag_sig_to_handle[i], &(bt_ag_sigoldact[i]), NULL);
4044 static void __bt_ag_agent_tel_cb(TapiHandle *handle,
4049 TelSimMsisdnList_t *number;
4050 gchar *subscriber_number;
4052 ERR("*********** Result =%d **********", result);
4054 if (result == TAPI_ERROR_OPERATION_FAILED ||
4055 result == TAPI_ERROR_ACCESS_DENIED ||
4056 result == TAPI_ERROR_OPERATION_NOT_SUPPORTED) {
4057 ERR("SIM has limited capabilities");
4058 __bt_ag_agent_send_subscriber_number_changed("");
4062 if (result == TAPI_API_SIM_LOCKED ||
4063 result == TAPI_API_SIM_NOT_INITIALIZED ||
4064 result == TAPI_API_SERVICE_NOT_READY) {
4065 DBG("initializing the tapi event for SIM status");
4066 __bt_ag_agent_reg_sim_event(handle, user_data);
4073 number = (TelSimMsisdnList_t *)data;
4074 subscriber_number = g_strdup(number->list[0].num);
4075 __bt_ag_agent_send_subscriber_number_changed(subscriber_number);
4076 g_free(subscriber_number);
4079 static void __bt_ag_agent_on_noti_sim_status(TapiHandle *handle,
4080 const char *noti_id, void *data, void *user_data)
4082 TelSimCardStatus_t *status = data;
4085 DBG("event TAPI_NOTI_SIM_STATUS received!! status[%d]", *status);
4087 if (*status == TAPI_SIM_STATUS_SIM_INIT_COMPLETED) {
4088 __bt_ag_agent_dereg_sim_event(handle);
4089 tapi_result = tel_get_sim_msisdn(handle, __bt_ag_agent_tel_cb,
4091 if (tapi_result != TAPI_API_SUCCESS)
4092 ERR("Fail to get sim info: %d", tapi_result);
4096 static void __bt_ag_agent_reg_sim_event(TapiHandle *handle, void *user_data)
4099 ret = tel_register_noti_event(handle, TAPI_NOTI_SIM_STATUS,
4100 __bt_ag_agent_on_noti_sim_status, user_data);
4102 if (ret != TAPI_API_SUCCESS)
4103 ERR("event register failed(%d)", ret);
4106 static void __bt_ag_agent_dereg_sim_event(TapiHandle *handle)
4109 ret = tel_deregister_noti_event(handle, TAPI_NOTI_SIM_STATUS);
4111 if (ret != TAPI_API_SUCCESS)
4112 ERR("event deregister failed(%d)", ret);
4115 static void __bt_ag_name_owner_changed_cb(GDBusConnection *connection,
4116 const gchar *sender_name,
4117 const gchar *object_path,
4118 const gchar *interface_name,
4119 const gchar *signal_name,
4120 GVariant *parameters,
4124 char *name_owner = NULL;
4125 char *old_owner = NULL;
4126 char *new_owner = NULL;
4128 if (strcasecmp(signal_name, "NameOwnerChanged") == 0) {
4131 g_variant_get(parameters, "(sss)", &name_owner, &old_owner, &new_owner);
4133 _bt_hfp_release_all_calls_by_sender(name_owner);
4135 if (sco_owner == NULL)
4138 if (strcasecmp(name_owner, sco_owner) == 0) {
4139 if (name_owner_sig_id)
4140 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4142 name_owner_sig_id = 0;
4146 for (l = active_devices ; l; l = l->next) {
4147 bt_ag_info_t *data = l->data;
4150 __bt_ag_close_sco(data);
4151 _bt_ag_set_headset_state(data,
4152 HEADSET_STATE_CONNECTED);
4159 static void __bt_ag_agent_bluez_interface_signal_cb(GDBusConnection *connection,
4160 const gchar *sender_name,
4161 const gchar *object_path,
4162 const gchar *interface_name,
4163 const gchar *signal_name,
4164 GVariant *parameters,
4169 GVariant *optional_param = NULL;
4171 if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
4173 g_variant_get(parameters, "(&o@a{sa{sv}})",
4174 &path, &optional_param);
4177 g_variant_unref(optional_param);
4178 ERR("Invalid adapter path");
4182 INFO_SECURE("Adapter Path = [%s]", path);
4183 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4184 gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4185 __bt_ag_agent_register(path, hfp_ver,
4186 HFP_AG_UUID, "Hands-Free Audio Gateway");
4188 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4189 __bt_ag_agent_register(path, hsp_ver,
4190 HSP_AG_UUID, "Headset Audio Gateway");
4192 } else if (strcasecmp(signal_name, "InterfacesRemoved") == 0) {
4193 g_variant_get(parameters, "(&o@as)", &path, &optional_param);
4196 g_variant_unref(optional_param);
4197 ERR("Invalid adapter path");
4201 INFO_SECURE("Adapter Path = [%s]", path);
4202 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
4203 gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4204 __bt_ag_agent_unregister(path);
4206 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4207 __bt_ag_agent_unregister(path);
4212 g_variant_unref(optional_param);
4217 static void __bt_ag_agent_bluez_property_changed_cb(GDBusConnection *connection,
4218 const gchar *sender_name,
4219 const gchar *object_path,
4220 const gchar *interface_name,
4221 const gchar *signal_name,
4222 GVariant *parameters,
4225 GVariant *optional_param = NULL;
4227 GVariant *dict_param = NULL;
4229 if (strcasecmp(signal_name, BT_PROPERTY_CHANGED) == 0) {
4230 if (g_strcmp0(g_variant_get_type_string(parameters),
4232 ERR("Incorrect parameters\n");
4235 g_variant_get(parameters, "(&s@a{sv}@as)",
4236 &inter, &dict_param, &optional_param);
4237 if (strcasecmp(inter, BLUEZ_DEVICE_INTERFACE) == 0) {
4240 g_variant_dict_init(&dict, dict_param);
4241 if (g_variant_dict_lookup(
4242 &dict, "TrustedProfiles", "u", &trusted)) {
4244 for (l = active_devices ; l; l = l->next) {
4245 bt_ag_info_t *data = l->data;
4246 if (g_strcmp0(data->path, object_path) != 0)
4248 if (trusted == BT_PROFILE_SUPPORTED_TRUSTED) {
4249 data->pbap_trusted =
4250 BT_AG_FEATURE_PBAP_ALLOWED;
4251 DBG("[%s] PBAP is TRUSTED", object_path);
4252 } else if (trusted == BT_PROFILE_SUPPORTED_BLOCKED) {
4253 data->pbap_trusted =
4254 BT_AG_FEATURE_PBAP_BLOCKED;
4255 DBG("[%s] PBAP is BLOCKED", object_path);
4259 g_variant_dict_end(&dict);
4262 g_variant_unref(dict_param);
4266 g_variant_unref(optional_param);
4269 static void __bt_ag_agent_dbus_deinit(void)
4271 if (profile_gproxy) {
4272 g_object_unref(profile_gproxy);
4273 profile_gproxy = NULL;
4277 __bt_ag_unregister_profile_methods();
4279 if (interface_added_sig_id)
4280 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4281 interface_added_sig_id);
4283 if (interface_removed_sig_id)
4284 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4285 interface_removed_sig_id);
4287 if (proterty_changed_sig_id)
4288 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4289 proterty_changed_sig_id);
4291 if (name_owner_sig_id)
4292 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4294 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4296 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4301 if (device_property_id)
4302 g_dbus_connection_signal_unsubscribe(ag_dbus_conn,
4303 device_property_id);
4305 device_property_id = 0;
4306 interface_added_sig_id = 0;
4307 interface_removed_sig_id = 0;
4308 proterty_changed_sig_id = 0;
4309 name_owner_sig_id = 0;
4313 g_object_unref(ag_dbus_conn);
4314 ag_dbus_conn = NULL;
4318 static int __bt_ag_agent_get_adapter_path(GDBusConnection *conn, char *path)
4321 GDBusProxy *manager_proxy = NULL;
4322 GVariant *result = NULL;
4323 char *adapter_path = NULL;
4326 return BT_HFP_AGENT_ERROR_INTERNAL;
4328 manager_proxy = g_dbus_proxy_new_sync(conn,
4329 G_DBUS_PROXY_FLAGS_NONE, NULL,
4332 BT_MANAGER_INTERFACE,
4335 if (!manager_proxy) {
4336 ERR("Unable to create proxy: %s", err->message);
4340 result = g_dbus_proxy_call_sync(manager_proxy, "DefaultAdapter", NULL,
4341 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
4344 ERR("Fail to get DefaultAdapter (Error: %s)", err->message);
4346 ERR("Fail to get DefaultAdapter");
4351 if (g_strcmp0(g_variant_get_type_string(result), "(o)")) {
4352 ERR("Incorrect result\n");
4356 g_variant_get(result, "(&o)", &adapter_path);
4358 if (adapter_path == NULL ||
4359 strlen(adapter_path) >= BT_ADAPTER_OBJECT_PATH_MAX) {
4360 ERR("Adapter path is inproper\n");
4365 g_strlcpy(path, adapter_path, BT_ADAPTER_OBJECT_PATH_MAX);
4367 g_variant_unref(result);
4368 g_object_unref(manager_proxy);
4373 g_clear_error(&err);
4376 g_variant_unref(result);
4379 g_object_unref(manager_proxy);
4381 return BT_HFP_AGENT_ERROR_INTERNAL;
4385 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4386 void _bt_ag_agent_check_transport_state(void)
4390 if (transport_state == MEDIA_TRANSPORT_STATE_PLAYING) {
4394 proxy = g_dbus_proxy_new_sync(ag_dbus_conn,
4395 G_DBUS_PROXY_FLAGS_NONE, NULL,
4396 "org.PulseAudio2", A2DP_SOURCE_ENDPOINT,
4397 BLUEZ_MEDIA_ENDPOINT_INTERFACE, NULL, &err);
4401 ERR("Unable to create proxy: %s", err->message);
4402 g_clear_error(&err);
4406 INFO_C("SuspendMedia initiated");
4408 g_dbus_proxy_call(proxy,
4409 "SuspendMedia", NULL,
4410 G_DBUS_CALL_FLAGS_NONE, 2000,
4412 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4413 g_object_unref(proxy);
4419 static void __bt_ag_agent_transport_state_update(const char *value)
4422 if (!g_strcmp0(value, "idle"))
4423 transport_state = MEDIA_TRANSPORT_STATE_IDLE;
4424 else if (!g_strcmp0(value, "pending") || !g_strcmp0(value, "active"))
4425 transport_state = MEDIA_TRANSPORT_STATE_PLAYING;
4427 transport_state = MEDIA_TRANSPORT_STATE_DISCONNECTED;
4429 INFO_C("transport_state %d", transport_state);
4432 static void __bt_ag_agent_media_filter_cb(GDBusConnection *connection,
4433 const gchar *sender_name,
4434 const gchar *object_path,
4435 const gchar *interface_name,
4436 const gchar *signal_name,
4437 GVariant *parameters,
4442 GVariant *dict_param = NULL;
4443 GVariant *optional_param = NULL;
4445 if (strcasecmp(signal_name, "PropertiesChanged") == 0) {
4446 if (g_strcmp0(g_variant_get_type_string(parameters),
4448 ERR("Incorrect parameters\n");
4452 g_variant_get(parameters, "(&s@a{sv}@as)",
4453 &inter, &dict_param, &optional_param);
4454 if (dict_param && (!g_strcmp0(inter,
4455 BLUEZ_MEDIA_TRANSPORT_INTERFACE))){
4456 GVariantIter *iter = NULL;
4457 const gchar *key = NULL;
4458 GVariant *value_var = NULL;
4459 const gchar *value = NULL;
4460 g_variant_get(dict_param, "a{sv}", &iter);
4461 while (g_variant_iter_loop(
4462 iter, "{sv}", &key, &value_var)) {
4464 if (g_strcmp0(key, "State") == 0) {
4465 value = (gchar *)g_variant_get_string(
4468 DBG("value %s", value);
4469 __bt_ag_agent_transport_state_update(value);
4473 g_variant_iter_free(iter);
4475 } else if (strcasecmp(signal_name, "ProfileStateChanged") == 0) {
4476 char *profile_uuid = NULL;
4479 g_variant_get(parameters, "(&si)", &profile_uuid, &state);
4480 if ((g_strcmp0(profile_uuid, A2DP_SINK_UUID) == 0) &&
4481 (state == BT_PROFILE_STATE_DISCONNECTED)) {
4482 DBG("Updating the transport state");
4483 __bt_ag_agent_transport_state_update("Disconnect");
4488 g_variant_unref(dict_param);
4491 g_variant_unref(optional_param);
4496 static void __bt_ag_agent_dbus_init(void)
4500 if (__bt_ag_get_gdbus_connection() == NULL) {
4501 ERR("Error in creating the gdbus connection\n");
4504 if (!__bt_ag_register_profile_methods()) {
4505 ERR("Error in HFP / HSP register_profile_methods\n");
4509 if (!__bt_ag_agent_get_adapter_path(ag_dbus_conn , NULL)) {
4511 gchar *path = g_strdup(BT_AG_AGENT_OBJECT_PATH);
4512 __bt_ag_agent_register(path, hfp_ver,
4513 HFP_AG_UUID, "Hands-Free Audio Gateway");
4515 path = g_strdup(BT_HS_AG_AGENT_OBJECT_PATH);
4516 __bt_ag_agent_register(path, hsp_ver,
4517 HSP_AG_UUID, "Headset Audio Gateway");
4520 interface_added_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4521 NULL, BT_MANAGER_INTERFACE,
4522 BT_INTERFACES_ADDED, NULL, NULL, 0,
4523 __bt_ag_agent_bluez_interface_signal_cb, NULL, NULL);
4525 interface_removed_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4526 NULL, BT_MANAGER_INTERFACE,
4527 BT_INTERFACES_REMOVED, NULL, NULL, 0,
4528 __bt_ag_agent_bluez_interface_signal_cb, NULL, NULL);
4530 proterty_changed_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4531 NULL, BT_MANAGER_INTERFACE,
4532 BT_PROPERTY_CHANGED, NULL, NULL, 0,
4533 __bt_ag_agent_bluez_property_changed_cb, NULL, NULL);
4535 #ifdef TIZEN_FEATURE_BT_MEDIA_ENHANCE
4536 media_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4537 NULL, BT_PROPERTIES_INTERFACE, NULL, NULL,
4538 NULL, 0, __bt_ag_agent_media_filter_cb,
4541 media_state_sig_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4542 NULL, BLUEZ_DEVICE_INTERFACE, NULL, NULL,
4543 NULL, 0, __bt_ag_agent_media_filter_cb,
4546 transport_state = MEDIA_TRANSPORT_STATE_DISCONNECTED;
4548 device_property_id = g_dbus_connection_signal_subscribe(ag_dbus_conn,
4549 NULL, BT_PROPERTIES_INTERFACE, BT_PROPERTY_CHANGED, NULL,
4550 NULL, 0, __bt_ag_agent_bluez_property_changed_cb,
4556 static void __bt_ag_agent_subscribe_tapi_updates(TapiHandle *handle)
4560 DBG("\nSubscribe tapi update for handler %p", handle);
4562 ret = tel_register_noti_event(handle, TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL,
4563 __bt_ag_agent_network_signal_status_cb, NULL);
4564 if (ret != TAPI_API_SUCCESS) {
4565 ERR("Subsrciption to netowrk signal failed err = [%d]\n", ret);
4568 ret = tel_register_noti_event(handle, TAPI_PROP_NETWORK_SERVICE_TYPE,
4569 __bt_ag_agent_network_register_status_cb, NULL);
4570 if (ret != TAPI_API_SUCCESS) {
4571 ERR("Subsrciption to network failed err = [%d]\n", ret);
4574 ret = tel_register_noti_event(handle, TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION,
4575 __bt_ag_agent_call_preferred_voice_subscription_cb, NULL);
4576 if (ret != TAPI_API_SUCCESS) {
4577 ERR("Subsrciption to preferred voice err = [%d]\n", ret);
4582 static void __bt_ag_agent_unsubscribe_tapi_updates(TapiHandle *handle)
4586 DBG("\nUnsubscribe tapi update for handler %p", handle);
4588 ret = tel_deregister_noti_event(handle, TAPI_PROP_NETWORK_SIGNALSTRENGTH_LEVEL);
4589 if (ret != TAPI_API_SUCCESS) {
4590 ERR("Subsrciption to netowrk signal failed err = [%d]\n", ret);
4593 ret = tel_deregister_noti_event(handle, TAPI_PROP_NETWORK_SERVICE_TYPE);
4594 if (ret != TAPI_API_SUCCESS) {
4595 ERR("Subsrciption to network failed err = [%d]\n", ret);
4598 ret = tel_deregister_noti_event(handle, TAPI_NOTI_CALL_PREFERRED_VOICE_SUBSCRIPTION);
4599 if (ret != TAPI_API_SUCCESS) {
4600 ERR("Subsrciption to preferred voice err = [%d]\n", ret);
4604 static uint32_t __bt_ag_agent_get_ag_features(void)
4607 uint32_t ag_features = BT_AG_FEATURE_EC_AND_NR |
4608 BT_AG_FEATURE_REJECT_CALL |
4609 BT_AG_FEATURE_ENHANCED_CALL_STATUS |
4610 BT_AG_FEATURE_THREE_WAY_CALL |
4611 #if !defined(TIZEN_FEATURE_BT_VENDOR_SPRD)
4612 BT_AG_FEATURE_VOICE_RECOGNITION |
4614 BT_AG_FEATURE_EXTENDED_ERROR_RESULT_CODES;
4616 #ifdef TIZEN_FEATURE_BT_SCO_WIDEBAND
4622 hfp_ver = HFP_VERSION_1_7;
4623 hsp_ver = HSP_VERSION_1_2;
4625 if (hfp_ver > HFP_VERSION_1_5)
4626 ag_features |= BT_AG_FEATURE_CODEC_NEGOTIATION;
4627 if (hfp_ver == HFP_VERSION_1_7)
4628 ag_features |= BT_AG_FEATURE_ESCO_S4_T2_SUPPORT;
4633 static void __bt_ag_agent_tel_get_preferred_sim(TapiHandle *handler)
4635 TelCallPreferredVoiceSubs_t preferredSubscription;
4636 int err_code = tel_get_call_preferred_voice_subscription(handler, &preferredSubscription);
4637 if (err_code == TAPI_API_SUCCESS) {
4638 if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_SIM1) {
4639 tapi_handle_preferred_sim = tapi_handle[0];
4640 INFO("Preferred SIM 1");
4641 } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_SIM2) {
4642 tapi_handle_preferred_sim = tapi_handle[1];
4643 INFO("Preferred SIM 2");
4644 } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_CURRENT_NETWORK) {
4645 INFO("Preferred SIM Current Network");
4646 } else if (preferredSubscription == TAPI_CALL_PREFERRED_VOICE_SUBS_ASK_ALWAYS) {
4647 tapi_handle_preferred_sim = tapi_handle[0];
4648 INFO("Preferred SIM Always Ask");
4650 ERR("Unknown Preferred voice subscription");
4655 static void __bt_ag_agent_tel_init_multisim(void)
4657 INFO_C("Initializing the telephony multi sim info");
4659 char **cp_list = NULL;
4660 unsigned int modem_num = 0;
4662 TelSimCardStatus_t simStatus = 0;
4663 int card_changed = 0;
4667 /* Get CP name list ? cp_list */
4668 cp_list = tel_get_cp_name_list();
4669 if (cp_list == NULL) {
4670 ERR("tel_get_cp_name_list() Failed");
4674 while (cp_list[modem_num]) {
4675 /* Initialize TAPI handle */
4676 tapi_handle[modem_num] = tel_init(cp_list[modem_num]);
4678 if (tapi_handle[modem_num] == NULL) {
4679 /* TAPI initialization ? Failure */
4680 ERR_SECURE("tel_init failed for Modem SIM number = %d", modem_num);
4682 /* TAPI initialization ? Success */
4683 DBG_SECURE("Success for Modem SIM number = %d, handler = %p",
4684 modem_num, tapi_handle[modem_num]);
4685 err_code = tel_get_sim_init_info(tapi_handle[modem_num],
4686 &simStatus, &card_changed);
4687 INFO_SECURE("Sim number = %d SIM status = %d", modem_num, simStatus);
4688 if ((TAPI_API_SUCCESS == err_code) &&
4689 (TAPI_SIM_STATUS_SIM_INIT_COMPLETED == simStatus)) {
4697 /* Move to next CP Name in cp_list */
4701 tapi_handle[modem_num] = NULL;
4703 g_strfreev(cp_list);
4706 static void __bt_ag_agent_tel_deinit_multisim(void)
4708 INFO_C("DeInitializing the telephony multi sim info");
4710 char **cp_list = NULL;
4711 unsigned int modem_num = 0;
4714 cp_list = tel_get_cp_name_list();
4715 if (cp_list == NULL) {
4716 ERR("tel_get_cp_name_list() Failed");
4720 while (cp_list[modem_num]) {
4721 result = tel_deinit(tapi_handle[modem_num]);
4722 if (result != TAPI_API_SUCCESS)
4723 ERR("Fail to tel_deinit");
4724 /* Move to next CP Name in cp_list */
4728 g_strfreev(cp_list);
4731 gboolean __bt_ag_agent_telephony_init(void *arg)
4734 uint32_t ag_features = *((uint32_t *)arg);
4736 INFO_C("Initializing the telephony info");
4737 __bt_ag_agent_tel_init_multisim();
4738 __bt_ag_agent_tel_get_preferred_sim(GET_TAPI_HANDLE);
4739 _bt_hfp_initialize_telephony_manager(ag_features, GET_TAPI_HANDLE);
4740 __bt_ag_agent_subscribe_tapi_updates(GET_TAPI_HANDLE);
4741 __bt_ag_agent_subscribe_vconf_updates();
4742 tapi_result = tel_get_sim_msisdn(GET_TAPI_HANDLE, __bt_ag_agent_tel_cb,
4744 if (tapi_result != TAPI_API_SUCCESS)
4745 ERR("Fail to get sim info: %d", tapi_result);
4752 uint32_t ag_features;
4753 struct sigaction sa;
4755 INFO_C("### Starting Bluetooth AG agent");
4757 #if GLIB_VERSION_MIN_REQUIRED < GLIB_VERSION_2_36
4760 ag_features = __bt_ag_agent_get_ag_features();
4762 ag.sdp_features = (uint16_t) ag_features & 0x1F;
4764 if (hfp_ver >= HFP_VERSION_1_6 && wbs_en == TRUE)
4765 ag.sdp_features |= BT_AG_FEATURE_SDP_WIDEBAND_SPEECH;
4767 __bt_ag_agent_dbus_init();
4769 g_idle_add(__bt_ag_agent_telephony_init, &ag_features);
4771 memset(&sa, 0, sizeof(sa));
4772 sa.sa_flags = SA_NOCLDSTOP;
4773 sa.sa_handler = __bt_ag_agent_sigterm_handler;
4775 for (i = 0; i < BT_AG_SIG_NUM; i++)
4776 sigaction(bt_ag_sig_to_handle[i], &sa, &(bt_ag_sigoldact[i]));
4778 gmain_loop = g_main_loop_new(NULL, FALSE);
4780 if (gmain_loop == NULL) {
4781 ERR("GMainLoop create failed");
4782 return EXIT_FAILURE;
4785 g_main_loop_run(gmain_loop);
4789 __bt_ag_agent_dbus_deinit();
4790 _bt_hfp_deinitialize_telephony_manager();
4791 __bt_ag_agent_release_vconf_updates();
4792 __bt_ag_agent_unsubscribe_tapi_updates(GET_TAPI_HANDLE);
4793 __bt_ag_agent_tel_deinit_multisim();
4794 if (remote_dev_path)
4795 g_free(remote_dev_path);
4798 g_main_loop_unref(gmain_loop);
4800 INFO_C("### Terminating Bluetooth AG agent");