4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Jaganath K <jaganath.k@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
27 #include <dbus/dbus.h>
30 #include <vconf-keys.h>
32 #include "bt-common.h"
33 #include "bluetooth-telephony-api.h"
36 #define BT_SCO_TIMEOUT 3000
38 #define BT_CVSD_CODEC_ID 1
39 #define BT_MSBC_CODEC_ID 2
42 GDBusConnection *conn;
44 GDBusProxy *dbus_proxy;
45 GDBusProxy *manager_proxy;
46 } telephony_dbus_info_t;
49 bt_telephony_func_ptr cb;
50 unsigned int call_count;
52 char address[BT_ADDRESS_STR_LEN];
53 char call_path[BT_AUDIO_CALL_PATH_LEN];
54 bluetooth_headset_state_t headset_state;
56 } bt_telephony_info_t;
59 char *src_addr = NULL;
62 #define BLUETOOTH_TELEPHONY_ERROR (__bluetooth_telephony_error_quark())
64 #define BLUEZ_SERVICE_NAME "org.bluez"
65 #define BLUEZ_HEADSET_INTERFACE "org.bluez.Headset"
67 #define BLUEZ_MANAGER_INTERFACE "org.freedesktop.DBus.ObjectManager"
68 #define BLUEZ_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"
69 #define BLUEZ_ADAPTER_INTERFACE "org.bluez.Adapter1"
70 #define BLUEZ_DEVICE_INTERFACE "org.bluez.Device1"
71 #define HFP_AGENT_SERVICE "org.bluez.ag_agent"
74 #define HFP_AGENT_PATH "/org/bluez/hfp_agent"
75 #define HFP_AGENT_INTERFACE "Org.Hfp.App.Interface"
77 #define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
78 #define CSD_CALL_APP_PATH "/org/tizen/csd/%d"
79 #define HFP_NREC_STATUS_CHANGE "NrecStatusChanged"
80 #define HFP_ANSWER_CALL "Answer"
81 #define HFP_REJECT_CALL "Reject"
82 #define HFP_RELEASE_CALL "Release"
83 #define HFP_THREEWAY_CALL "Threeway"
85 #define DEFAULT_ADAPTER_OBJECT_PATH "/org/bluez/hci0"
87 /*Below Inrospection data is exposed to bluez from agent*/
88 static const gchar bt_telephony_introspection_xml[] =
90 " <interface name='org.tizen.csd.Call.Instance'>"
91 " <method name='SendDtmf'>"
92 " <arg type='s' name='dtmf' direction='in'/>"
94 " <method name='VendorCmd'>"
95 " <arg type='s' name='vendor' direction='in'/>"
100 #define BT_TELEPHONY_CHECK_ENABLED() \
102 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED) \
104 BT_ERR("BT is not enabled"); \
105 return BLUETOOTH_TELEPHONY_ERROR_NOT_ENABLED; \
109 static gboolean is_initialized = FALSE;
110 #define BT_TELEPHONY_CHECK_INITIALIZED() \
112 if (is_initialized == FALSE) \
114 BT_ERR("Bluetooth telephony not initilized"); \
115 return BLUETOOTH_TELEPHONY_ERROR_NOT_INITIALIZED; \
119 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
120 const gchar *sender_name,
121 const gchar *object_path,
122 const gchar *interface_name,
123 const gchar *signal_name,
124 GVariant *parameters,
127 static int __bt_telephony_get_src_addr(GVariant *value);
129 static bt_telephony_info_t telephony_info;
130 static telephony_dbus_info_t telephony_dbus_info;
131 static gboolean is_active = FALSE;
133 /*Function Declaration*/
134 static int __bt_telephony_get_error(const char *error_message);
135 static void __bt_telephony_event_cb(int event, int result, void *param_data);
136 static GQuark __bluetooth_telephony_error_quark(void);
137 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
138 const char *interface, const char *method,
139 GError **err, GVariant *parameters);
140 static int __bluetooth_telephony_send_call_status(
141 bt_telephony_call_status_t call_status,
142 unsigned int call_id, const char *ph_number);
143 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
144 bluetooth_telephony_error_t error, const char *err_msg);
146 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
147 const gchar *sender_name,
148 const gchar *object_path,
149 const gchar *interface_name,
150 const gchar *signal_name,
151 GVariant *parameters,
154 static int __bluetooth_telephony_proxy_init(void);
155 static void __bluetooth_telephony_proxy_deinit(void);
156 static int __bluetooth_telephony_register(void);
157 static int __bluetooth_telephony_unregister(void);
159 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class);
160 static int __bluetooth_telephony_get_connected_device(void);
161 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void);
163 /*Function Definition*/
164 static void __bt_telephony_method(GDBusConnection *connection,
166 const gchar *object_path,
167 const gchar *interface_name,
168 const gchar *method_name,
169 GVariant *parameters,
170 GDBusMethodInvocation *invocation,
175 BT_INFO("method %s", method_name);
176 BT_INFO("object_path %s", object_path);
178 if (g_strcmp0(method_name, "SendDtmf") == 0) {
180 telephony_event_dtmf_t call_data = { 0, };
182 g_variant_get(parameters, "(&s)", &dtmf);
185 BT_ERR("Number dial failed");
186 __bluetooth_telephony_error(invocation,
187 BLUETOOTH_TELEPHONY_ERROR_INVALID_DTMF,
190 DBG_SECURE("Dtmf = %s", dtmf);
192 call_data.dtmf = g_strdup(dtmf);
193 __bt_telephony_event_cb(
194 BLUETOOTH_EVENT_TELEPHONY_SEND_DTMF,
195 BLUETOOTH_TELEPHONY_ERROR_NONE,
198 g_free(call_data.dtmf);
200 g_dbus_method_invocation_return_value(invocation, NULL);
202 } else if (g_strcmp0(method_name, "VendorCmd") == 0) {
205 g_variant_get(parameters, "(&s)", &at_cmd);
206 BT_INFO("Vendor %s", at_cmd);
207 if (at_cmd == NULL) {
208 BT_ERR("Vendor command is NULL\n");
209 __bluetooth_telephony_error(invocation,
210 BLUETOOTH_TELEPHONY_ERROR_APPLICATION,
211 "Invalid at vendor cmd");
213 DBG_SECURE("Vendor AT cmd = %s", at_cmd);
215 __bt_telephony_event_cb(
216 BLUETOOTH_EVENT_TELEPHONY_VENDOR_AT_CMD,
217 BLUETOOTH_TELEPHONY_ERROR_NONE,
220 g_dbus_method_invocation_return_value(invocation, NULL);
227 static const GDBusInterfaceVTable method_table = {
228 __bt_telephony_method,
233 static int __bt_telephony_get_error(const char *error_message)
235 if (error_message == NULL) {
236 BT_ERR("Error message NULL");
237 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
240 BT_ERR("Error message = %s", error_message);
241 if (g_strcmp0(error_message, "NotAvailable") == 0)
242 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
243 else if (g_strcmp0(error_message, "NotConnected") == 0)
244 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
245 else if (g_strcmp0(error_message, "InProgress") == 0)
246 return BLUETOOTH_TELEPHONY_ERROR_BUSY;
247 else if (g_strcmp0(error_message, "InvalidArguments") == 0)
248 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
249 else if (g_strcmp0(error_message, "AlreadyExists") == 0)
250 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_EXSIST;
251 else if (g_strcmp0(error_message, "Already Connected") == 0)
252 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
253 else if (g_strcmp0(error_message, "No memory") == 0)
254 return BLUETOOTH_TELEPHONY_ERROR_NO_MEMORY;
255 else if (g_strcmp0(error_message, "I/O error") == 0)
256 return BLUETOOTH_TELEPHONY_ERROR_I_O_ERROR;
257 else if (g_strcmp0(error_message,
258 "Operation currently not available") == 0)
259 return BLUETOOTH_TELEPHONY_ERROR_OPERATION_NOT_AVAILABLE;
260 else if (g_strrstr(error_message, BT_ACCESS_DENIED_MSG))
261 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
263 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
266 static int __bt_telephony_check_privilege(void)
273 reply = __bluetooth_telephony_dbus_method_send(
274 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
275 "CheckPrivilege", &err, NULL);
278 BT_ERR("Error returned in method call");
280 g_dbus_error_strip_remote_error(err);
281 ret = __bt_telephony_get_error(err->message);
285 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
287 g_variant_unref(reply);
290 return BLUETOOTH_TELEPHONY_ERROR_NONE;
293 static void __bt_telephony_event_cb(int event, int result, void *param_data)
295 telephony_event_param_t bt_event = { 0, };
297 bt_event.event = event;
298 bt_event.result = result;
299 bt_event.param_data = param_data;
301 ret_if(telephony_info.cb == NULL);
302 telephony_info.cb(bt_event.event, &bt_event, telephony_info.user_data);
306 static GQuark __bluetooth_telephony_error_quark(void)
308 static GQuark quark = 0;
310 quark = g_quark_from_static_string("telephony");
315 static GVariant *__bluetooth_telephony_dbus_method_send(const char *path,
316 const char *interface, const char *method,
317 GError **err, GVariant *parameters)
319 #ifdef TIZEN_WEARABLE
326 GDBusConnection *conn;
330 conn = telephony_dbus_info.conn;
331 retv_if(conn == NULL, NULL);
333 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE,
334 NULL, HFP_AGENT_SERVICE, path, interface, NULL, err);
336 BT_ERR("Unable to allocate new proxy");
340 reply = g_dbus_proxy_call_sync(proxy, method, parameters,
341 G_DBUS_CALL_FLAGS_NONE, timeout, NULL, err);
343 g_object_unref(proxy);
348 static int __bluetooth_telephony_send_call_status(
349 bt_telephony_call_status_t call_status,
350 unsigned int call_id, const char *ph_number)
355 char *path = g_strdup(telephony_info.call_path);
361 if (NULL == ph_number)
362 phone_number = g_strdup("");
364 phone_number = g_strdup(ph_number);
366 param = g_variant_new("(ssii)", path, phone_number,
367 call_status, call_id);
368 reply = __bluetooth_telephony_dbus_method_send(
369 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
370 "ChangeCallStatus", &err, param);
373 g_free(phone_number);
376 BT_ERR("Error returned in method call");
378 g_dbus_error_strip_remote_error(err);
379 ret = __bt_telephony_get_error(err->message);
383 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
386 g_variant_unref(reply);
388 return BLUETOOTH_TELEPHONY_ERROR_NONE;
391 static void __bluetooth_telephony_error(GDBusMethodInvocation *invocation,
392 bluetooth_telephony_error_t error, const char *err_msg)
394 g_dbus_method_invocation_return_error(invocation,
395 BLUETOOTH_TELEPHONY_ERROR, error,
399 static void __bluetooth_telephony_answer_call(GVariant *var)
401 telephony_event_callid_t call_data = { 0, };
406 g_variant_get(var, "(u)", &callid);
407 BT_DBG("call_id = [%d]", callid);
408 call_data.callid = callid;
410 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_ANSWER_CALL,
411 BLUETOOTH_TELEPHONY_ERROR_NONE,
416 static void __bluetooth_telephony_release_call(GVariant *var)
418 telephony_event_callid_t call_data = { 0, };
423 g_variant_get(var, "(u)", &callid);
424 BT_DBG("call_id = [%d]", callid);
425 call_data.callid = callid;
427 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_RELEASE_CALL,
428 BLUETOOTH_TELEPHONY_ERROR_NONE,
433 static void __bluetooth_telephony_reject_call(GVariant *var)
435 telephony_event_callid_t call_data = { 0, };
440 g_variant_get(var, "(u)", &callid);
441 BT_DBG("call_id = [%d]", callid);
442 call_data.callid = callid;
444 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_REJECT_CALL,
445 BLUETOOTH_TELEPHONY_ERROR_NONE,
450 static void __bluetooth_telephony_threeway_call(GVariant *var)
453 unsigned int chld_value;
457 g_variant_get(var, "(u)", &chld_value);
458 BT_DBG("chld value = [%d]", chld_value);
460 switch (chld_value) {
462 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_0_RELEASE_ALL_HELD_CALL;
465 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_1_RELEASE_ALL_ACTIVE_CALL;
468 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_2_ACTIVE_HELD_CALL;
471 event = BLUETOOTH_EVENT_TELEPHONY_CHLD_3_MERGE_CALL;
474 BT_ERR("Invalid CHLD command");
478 __bt_telephony_event_cb(event,
479 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
483 static void __bluetooth_handle_nrec_status_change(GVariant *var)
485 gboolean status = FALSE;
487 g_variant_get(var, "(b)", &status);
488 BT_INFO("NREC status = %d", status);
490 __bt_telephony_event_cb(BLUETOOTH_EVENT_TELEPHONY_NREC_CHANGED,
491 BLUETOOTH_TELEPHONY_ERROR_NONE, (void *)&status);
495 static void __bluetooth_telephony_event_filter(GDBusConnection *connection,
496 const gchar *sender_name,
497 const gchar *object_path,
498 const gchar *interface_name,
499 const gchar *signal_name,
500 GVariant *parameters,
505 if (strcasecmp(interface_name, HFP_AGENT_SERVICE) == 0) {
506 if (strcasecmp(signal_name, HFP_NREC_STATUS_CHANGE) == 0)
507 __bluetooth_handle_nrec_status_change(parameters);
508 else if (strcasecmp(signal_name, HFP_ANSWER_CALL) == 0)
509 __bluetooth_telephony_answer_call(parameters);
510 else if (strcasecmp(signal_name, HFP_REJECT_CALL) == 0)
511 __bluetooth_telephony_reject_call(parameters);
512 else if (strcasecmp(signal_name, HFP_RELEASE_CALL) == 0)
513 __bluetooth_telephony_release_call(parameters);
514 else if (strcasecmp(signal_name, HFP_THREEWAY_CALL) == 0)
515 __bluetooth_telephony_threeway_call(parameters);
516 } else if (strcasecmp(interface_name, BLUEZ_HEADSET_INTERFACE) == 0) {
517 if (strcasecmp(signal_name, "PropertyChanged") == 0) {
521 g_variant_get(parameters, "(&sv)", &property, &values);
522 BT_DBG("Property: %s", property);
524 if (strcasecmp(property, "State") == 0) {
526 state = (gchar *)g_variant_get_string(values, NULL);
529 BT_ERR("State is null");
532 BT_DBG("state: %s", state);
533 if (g_strcmp0(state, "connected") == 0) {
534 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
535 } else if (g_strcmp0(state, "playing") == 0) {
536 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
537 } else if (g_strcmp0(state, "disconnected") == 0) {
538 /* Headset state: playing -> disconnected */
539 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING) {
540 __bt_telephony_event_cb(
541 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
542 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
545 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
547 } else if (strcasecmp(property, "Connected") == 0) {
548 gboolean connected = FALSE;
549 char *dev_addr = NULL;
550 connected = g_variant_get_boolean(values);
551 BT_INFO("connected %d", connected);
553 /*Get device address*/
554 if (object_path != NULL)
555 dev_addr = strstr(object_path, "dev_");
557 if (dev_addr != NULL) {
559 g_strlcpy(telephony_info.address,
561 sizeof(telephony_info.address));
562 g_strdelimit(telephony_info.address, "_", ':');
563 BT_DBG("address is %s",
564 telephony_info.address);
566 telephony_info.headset_state =
567 BLUETOOTH_STATE_CONNECTED;
569 if (telephony_dbus_info.proxy != NULL) {
570 g_object_unref(telephony_dbus_info.proxy);
571 telephony_dbus_info.proxy = NULL;
574 telephony_dbus_info.proxy =
575 __bluetooth_telephony_get_connected_device_proxy();
577 BT_INFO("Headset Connected");
579 __bt_telephony_event_cb(
580 BLUETOOTH_EVENT_TELEPHONY_HFP_CONNECTED,
581 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
583 } else { /*Device disconnected*/
584 memset(telephony_info.address, 0x00,
585 sizeof(telephony_info.address));
586 telephony_info.headset_state =
587 BLUETOOTH_STATE_DISCONNETED;
589 if (telephony_dbus_info.proxy != NULL) {
590 g_object_unref(telephony_dbus_info.proxy);
591 telephony_dbus_info.proxy = NULL;
594 BT_INFO("Headset Disconnected");
596 __bt_telephony_event_cb(
597 BLUETOOTH_EVENT_TELEPHONY_HFP_DISCONNECTED,
598 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
600 } else if (strcasecmp(property, "SpeakerGain") == 0) {
601 unsigned int spkr_gain;
602 guint16 gain = g_variant_get_uint16(values);
604 spkr_gain = (unsigned int)gain;
605 BT_DBG("spk_gain[%d]", spkr_gain);
607 __bt_telephony_event_cb(
608 BLUETOOTH_EVENT_TELEPHONY_SET_SPEAKER_GAIN,
609 BLUETOOTH_TELEPHONY_ERROR_NONE,
611 } else if (strcasecmp(property, "MicrophoneGain") == 0) {
612 unsigned int mic_gain;
613 guint16 gain = g_variant_get_uint16(values);
615 mic_gain = (unsigned int)gain;
616 BT_DBG("mic_gain[%d]", mic_gain);
618 __bt_telephony_event_cb(
619 BLUETOOTH_EVENT_TELEPHONY_SET_MIC_GAIN,
620 BLUETOOTH_TELEPHONY_ERROR_NONE,
622 } else if (strcasecmp(property, "Playing") == 0) {
623 gboolean audio_sink_playing;
625 audio_sink_playing = g_variant_get_boolean(values);
626 if (audio_sink_playing) {
627 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
628 __bt_telephony_event_cb(
629 BLUETOOTH_EVENT_TELEPHONY_AUDIO_CONNECTED,
630 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
632 telephony_info.headset_state =
633 BLUETOOTH_STATE_CONNECTED;
634 __bt_telephony_event_cb(
635 BLUETOOTH_EVENT_TELEPHONY_AUDIO_DISCONNECTED,
636 BLUETOOTH_TELEPHONY_ERROR_NONE, NULL);
640 g_variant_unref(values);
646 static GDBusNodeInfo *__bt_telephony_create_method_node_info
647 (const gchar *introspection_data)
650 GDBusNodeInfo *node_info = NULL;
652 if (introspection_data == NULL)
655 node_info = g_dbus_node_info_new_for_xml(introspection_data, &err);
658 BT_ERR("Unable to create node: %s", err->message);
665 int __bluetooth_telephony_register_object(int reg, GDBusNodeInfo *node_info)
667 static guint bt_tel_id = 0;
668 GError *error = NULL;
672 if (node_info == NULL)
673 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
675 path = g_strdup(telephony_info.call_path);
676 BT_DBG("path is [%s]", path);
678 bt_tel_id = g_dbus_connection_register_object(telephony_dbus_info.conn,
679 path, node_info->interfaces[0],
684 if (bt_tel_id == 0) {
685 BT_ERR("Failed to register: %s", error->message);
687 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
691 g_dbus_connection_unregister_object(telephony_dbus_info.conn,
697 return BLUETOOTH_TELEPHONY_ERROR_NONE;
700 static int __bluetooth_telephony_proxy_init(void)
704 GDBusNodeInfo *node_info;
706 owner_id = g_bus_own_name(G_BUS_TYPE_SYSTEM,
707 TELEPHONY_APP_INTERFACE,
708 G_BUS_NAME_OWNER_FLAGS_NONE,
711 BT_DBG("owner_id is [%d]", owner_id);
713 node_info = __bt_telephony_create_method_node_info(
714 bt_telephony_introspection_xml);
716 if (node_info == NULL) {
717 BT_ERR("node_info NULL");
718 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
720 if (__bluetooth_telephony_register_object(TRUE, node_info) !=
721 BLUETOOTH_TELEPHONY_ERROR_NONE) {
722 BT_ERR("Registation of Method Failed");
723 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
727 return BLUETOOTH_TELEPHONY_ERROR_NONE;
730 static void __bluetooth_telephony_proxy_deinit(void)
734 __bluetooth_telephony_register_object(FALSE, NULL);
740 static int __bluetooth_telephony_register(void)
745 char *path = g_strdup(telephony_info.call_path);
750 param = g_variant_new("(ss)", path, src_addr);
751 BT_DBG("Path[%s] Src_Address[%s]", path, src_addr);
753 reply = __bluetooth_telephony_dbus_method_send(
754 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
755 "RegisterApplication", &err, param);
760 BT_ERR("Error returned in method call");
762 g_dbus_error_strip_remote_error(err);
763 ret = __bt_telephony_get_error(err->message);
764 BT_ERR("Error here %d\n", ret);
768 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
771 g_variant_unref(reply);
772 BT_DBG("__bluetooth_telephony_register completed");
774 return BLUETOOTH_TELEPHONY_ERROR_NONE;
777 static int __bluetooth_telephony_unregister(void)
782 char *path = g_strdup(telephony_info.call_path);
787 param = g_variant_new("(s)", path);
788 reply = __bluetooth_telephony_dbus_method_send(
789 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
790 "UnregisterApplication", &err, param);
795 BT_ERR("Error returned in method call");
797 g_dbus_error_strip_remote_error(err);
798 ret = __bt_telephony_get_error(err->message);
802 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
805 g_variant_unref(reply);
806 BT_DBG("__bluetooth_telephony_unregister completed");
808 return BLUETOOTH_TELEPHONY_ERROR_NONE;
811 #ifndef TIZEN_WEARABLE
812 static void __bluetooth_telephony_init_headset_state(void)
816 gboolean status = FALSE;
820 if (telephony_dbus_info.conn == NULL) {
821 BT_ERR("Bluetooth telephony not initilized");
825 reply = __bluetooth_telephony_dbus_method_send(
826 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
827 "IsConnected", &err, NULL);
829 BT_ERR("Error returned in method call\n");
831 BT_ERR("Error message = %s", err->message);
837 g_variant_get(reply, "(b)", &status);
838 g_variant_unref(reply);
840 BT_INFO("Headset Connected Status = [%d]", status);
842 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
846 if (bluetooth_telephony_is_sco_connected())
847 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
853 static gboolean __bluetooth_telephony_is_headset(uint32_t device_class)
855 gboolean flag = FALSE;
858 switch ((device_class & 0x1f00) >> 8) {
860 switch ((device_class & 0xfc) >> 2) {
878 /* Tizen Wearable device */
880 switch ((device_class & 0xfc) >> 2) {
881 case 0x01: /* Wrist Watch */
889 BT_DBG("[%d]", flag);
894 static gboolean __bluetooth_telephony_is_headset_by_uuid(gchar **uuids)
898 unsigned int service = 0;
902 retv_if(uuids == NULL, FALSE);
904 for (i = 0; uuids[i] != NULL; i++) {
905 parts = g_strsplit(uuids[i], "-", -1);
907 if (parts == NULL || parts[0] == NULL) {
912 service = g_ascii_strtoull(parts[0], NULL, 16);
915 if (service == BLUETOOTH_HS_PROFILE_UUID ||
916 service == BLUETOOTH_HF_PROFILE_UUID)
925 static int __bluetooth_telephony_get_connected_device(void)
927 GDBusConnection *conn;
928 GDBusProxy *headset_agent_proxy = NULL;
929 GDBusProxy *manager_proxy = NULL;
930 GDBusProxy *proxy = NULL;
931 GVariant *reply = NULL;
932 GVariant *getall = NULL;
933 GVariant *isPlayingReply = NULL;
934 GVariant *isConnectedReply = NULL;
935 GVariant *param = NULL;
936 GVariant *var_path = NULL;
937 GVariant *path_values = NULL;
938 GVariant *value = NULL;
939 GError *error = NULL;
941 GVariantIter iter_path;
942 GVariantIter property_iter;
943 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
946 conn = _bt_gdbus_get_system_gconn();
947 retv_if(conn == NULL, BLUETOOTH_TELEPHONY_ERROR_INTERNAL);
949 manager_proxy = g_dbus_proxy_new_sync(
950 conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
951 BLUEZ_SERVICE_NAME, "/",
952 BLUEZ_MANAGER_INTERFACE, NULL, &error);
953 if (manager_proxy == NULL) {
954 BT_ERR("Unable to allocate new proxy \n");
955 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
957 g_dbus_error_strip_remote_error(error);
958 ret = __bt_telephony_get_error(error->message);
959 BT_ERR("Error here %d\n", ret);
965 /* Synchronous call */
966 reply = g_dbus_proxy_call_sync(manager_proxy, "GetManagedObjects", NULL,
967 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
968 g_object_unref(manager_proxy);
971 BT_ERR("Can't get managed objects");
972 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
974 g_dbus_error_strip_remote_error(error);
975 ret = __bt_telephony_get_error(error->message);
976 BT_ERR("Error here %d\n", ret);
982 /* signature of GetManagedObjects: a{oa{sa{sv}}} */
983 g_variant_iter_init(&iter, reply);
985 while ((param = g_variant_iter_next_value(&iter))) {
986 g_variant_iter_init(&iter_path, param);
988 while ((var_path = g_variant_iter_next_value(&iter_path))) {
990 uint32_t device_class = 0;
991 gboolean playing = FALSE;
992 gboolean connected = FALSE;
993 char *object_path = NULL;
994 gchar *address = NULL;
996 gchar **uuids = NULL;
997 GVariant *getall_param = NULL;
999 g_variant_get(var_path, "{&o*}", &object_path,
1001 g_variant_unref(path_values); /* path_values unused*/
1003 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1004 G_DBUS_PROXY_FLAGS_NONE, NULL,
1005 BLUEZ_SERVICE_NAME, object_path,
1006 BLUEZ_PROPERTIES_INTERFACE, NULL, &error);
1007 if (proxy == NULL) {
1008 BT_ERR("Unable to allocate new proxy \n");
1009 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1011 g_dbus_error_strip_remote_error(error);
1012 ret = __bt_telephony_get_error(error->message);
1013 BT_ERR("Error here %d\n", ret);
1014 g_error_free(error);
1020 getall_param = g_variant_new("s", BLUEZ_DEVICE_INTERFACE);
1021 getall = g_dbus_proxy_call_sync(proxy,
1022 "GetAll", getall_param,
1023 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1024 g_object_unref(proxy);
1027 BT_ERR("Can't get managed objects");
1028 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1030 g_dbus_error_strip_remote_error(error);
1031 ret = __bt_telephony_get_error(error->message);
1032 BT_ERR("Error here %d\n", ret);
1033 g_error_free(error);
1038 g_variant_iter_init(&property_iter, getall);
1040 while (g_variant_iter_loop(&property_iter, "{&sv}", &key, &value)) {
1041 if (!g_strcmp0(key, "Class")) {
1042 device_class = g_variant_get_uint32(value);
1043 BT_DBG("Device Class: %d", device_class);
1044 } else if (!g_strcmp0(key, "UUID")) {
1046 uuids = (gchar **)g_variant_get_strv(value, &len);
1047 BT_DBG_UUID(uuids, len, i);
1048 } else if (!g_strcmp0(key, "Address")) {
1049 address = (gchar *)g_variant_get_string(
1052 BT_DBG("Device Class: %s", address);
1054 g_variant_unref(value);
1056 g_variant_unref(getall);
1058 if (device_class == 0) {
1059 BT_DBG("COD is NULL (maybe paired by nfc)... Checking UUIDs");
1060 if (!__bluetooth_telephony_is_headset_by_uuid(uuids)) {
1061 BT_DBG("UUID checking completed. None HF device");
1064 BT_DBG("UUID checking completed. HF device");
1066 if (!__bluetooth_telephony_is_headset(device_class))
1070 /* this is headset; Check for Connection */
1071 headset_agent_proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1072 G_DBUS_PROXY_FLAGS_NONE, NULL,
1073 HFP_AGENT_SERVICE, object_path,
1074 HFP_AGENT_INTERFACE, NULL, &error);
1075 if (headset_agent_proxy == NULL) {
1076 BT_ERR("Unable to allocate new headset_agent_proxy");
1077 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1079 g_dbus_error_strip_remote_error(error);
1080 ret = __bt_telephony_get_error(error->message);
1081 BT_ERR("Error here %d\n", ret);
1082 g_error_free(error);
1087 isConnectedReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1088 "IsConnected", NULL,
1089 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1092 if (!isConnectedReply) {
1093 BT_ERR("Can't get managed objects");
1094 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1096 g_dbus_error_strip_remote_error(error);
1097 ret = __bt_telephony_get_error(error->message);
1098 BT_ERR("Error here %d\n", ret);
1099 g_error_free(error);
1103 connected = g_variant_get_boolean(isConnectedReply);
1104 g_variant_unref(isConnectedReply);
1107 g_strlcpy(telephony_info.address,
1109 sizeof(telephony_info.address));
1111 isPlayingReply = g_dbus_proxy_call_sync(headset_agent_proxy,
1113 G_DBUS_CALL_FLAGS_NONE,
1115 if (!isPlayingReply) {
1116 BT_ERR("Can't get managed objects");
1117 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1119 g_dbus_error_strip_remote_error(error);
1120 ret = __bt_telephony_get_error(error->message);
1121 BT_ERR("Error here %d\n", ret);
1122 g_error_free(error);
1125 playing = g_variant_get_boolean(isPlayingReply);
1126 g_variant_unref(isPlayingReply);
1129 telephony_info.headset_state =
1130 BLUETOOTH_STATE_PLAYING;
1132 telephony_info.headset_state =
1133 BLUETOOTH_STATE_CONNECTED;
1140 g_object_unref(headset_agent_proxy);
1141 g_variant_unref(var_path);
1143 g_variant_unref(param);
1147 if (headset_agent_proxy)
1148 g_object_unref(headset_agent_proxy);
1150 g_variant_unref(reply);
1152 g_variant_unref(var_path);
1154 g_variant_unref(param);
1159 static GDBusProxy *__bluetooth_telephony_get_connected_device_proxy(void)
1161 GDBusProxy *proxy = NULL;
1162 GError *error = NULL;
1166 if (strlen(telephony_info.address) == 0)
1167 __bluetooth_telephony_get_connected_device();
1169 if (strlen(telephony_info.address) == 0)
1172 proxy = g_dbus_proxy_new_sync(telephony_dbus_info.conn,
1173 G_DBUS_PROXY_FLAGS_NONE, NULL,
1174 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1175 HFP_AGENT_INTERFACE, NULL, &error);
1176 if (proxy == NULL) {
1177 BT_ERR("Unable to allocate new proxy");
1179 g_dbus_error_strip_remote_error(error);
1180 ret = __bt_telephony_get_error(error->message);
1181 BT_ERR("Error here %d\n", ret);
1182 g_error_free(error);
1191 int __bt_telephony_subscribe_adapter_signal(GDBusConnection *conn,
1197 static int subscribe_adapter_id = -1;
1198 if (subscribe == TRUE) {
1199 if (subscribe_adapter_id == -1) {
1200 subscribe_adapter_id = g_dbus_connection_signal_subscribe(conn,
1201 NULL, "org.freedesktop.DBus.ObjectManager",
1202 "InterfacesAdded", NULL, NULL, 0,
1203 __bt_telephony_adapter_filter,
1206 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1208 if (subscribe_adapter_id != -1) {
1209 g_dbus_connection_signal_unsubscribe(conn,
1210 subscribe_adapter_id);
1211 subscribe_adapter_id = -1;
1213 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1217 int __bt_telephony_event_subscribe_signal(GDBusConnection *conn,
1223 static int subscribe_event1_id = -1;
1224 static int subscribe_event2_id = -1;
1225 static int subscribe_event3_id = -1;
1226 static int subscribe_event4_id = -1;
1227 static int subscribe_event5_id = -1;
1228 static int subscribe_event6_id = -1;
1229 if (subscribe == TRUE) {
1230 if (subscribe_event1_id == -1) {
1231 subscribe_event1_id = g_dbus_connection_signal_subscribe(conn,
1232 NULL, BLUEZ_HEADSET_INTERFACE,
1233 "PropertyChanged", NULL, NULL, 0,
1234 __bluetooth_telephony_event_filter,
1237 if (subscribe_event2_id == -1) {
1238 subscribe_event2_id = g_dbus_connection_signal_subscribe(conn,
1239 NULL, HFP_AGENT_SERVICE,
1240 HFP_NREC_STATUS_CHANGE, NULL, NULL, 0,
1241 __bluetooth_telephony_event_filter,
1245 if (subscribe_event3_id == -1) {
1246 subscribe_event3_id = g_dbus_connection_signal_subscribe(conn,
1247 NULL, HFP_AGENT_SERVICE,
1248 HFP_ANSWER_CALL, NULL, NULL, 0,
1249 __bluetooth_telephony_event_filter,
1252 if (subscribe_event4_id == -1) {
1253 subscribe_event4_id = g_dbus_connection_signal_subscribe(conn,
1254 NULL, HFP_AGENT_SERVICE,
1255 HFP_REJECT_CALL, NULL, NULL, 0,
1256 __bluetooth_telephony_event_filter,
1259 if (subscribe_event5_id == -1) {
1260 subscribe_event5_id = g_dbus_connection_signal_subscribe(conn,
1261 NULL, HFP_AGENT_SERVICE,
1262 HFP_RELEASE_CALL, NULL, NULL, 0,
1263 __bluetooth_telephony_event_filter,
1266 if (subscribe_event6_id == -1) {
1267 subscribe_event6_id = g_dbus_connection_signal_subscribe(conn,
1268 NULL, HFP_AGENT_SERVICE,
1269 HFP_THREEWAY_CALL, NULL, NULL, 0,
1270 __bluetooth_telephony_event_filter,
1274 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1276 if (subscribe_event1_id != -1) {
1277 g_dbus_connection_signal_unsubscribe(conn,
1278 subscribe_event1_id);
1279 subscribe_event1_id = -1;
1281 if (subscribe_event2_id != -1) {
1282 g_dbus_connection_signal_unsubscribe(conn,
1283 subscribe_event2_id);
1284 subscribe_event2_id = -1;
1286 if (subscribe_event3_id != -1) {
1287 g_dbus_connection_signal_unsubscribe(conn,
1288 subscribe_event3_id);
1289 subscribe_event3_id = -1;
1291 if (subscribe_event4_id != -1) {
1292 g_dbus_connection_signal_unsubscribe(conn,
1293 subscribe_event4_id);
1294 subscribe_event4_id = -1;
1296 if (subscribe_event5_id != -1) {
1297 g_dbus_connection_signal_unsubscribe(conn,
1298 subscribe_event5_id);
1299 subscribe_event5_id = -1;
1301 if (subscribe_event6_id != -1) {
1302 g_dbus_connection_signal_unsubscribe(conn,
1303 subscribe_event6_id);
1304 subscribe_event6_id = -1;
1306 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1310 BT_EXPORT_API int bluetooth_telephony_init(bt_telephony_func_ptr cb,
1313 bluetooth_device_address_t loc_address = { {0} };
1314 char src_address[BT_ADDRESS_STRING_SIZE] = { 0 };
1315 int ret = BLUETOOTH_TELEPHONY_ERROR_NONE;
1316 GError *error = NULL;
1320 if (is_initialized == TRUE) {
1321 BT_ERR("Bluetooth telephony already initilized");
1322 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_INITIALIZED;
1325 is_initialized = TRUE;
1327 telephony_dbus_info.conn = _bt_gdbus_init_system_gconn();
1328 if (!telephony_dbus_info.conn) {
1329 is_initialized = FALSE;
1330 BT_ERR("Could not get DBus Connection");
1331 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1335 snprintf(telephony_info.call_path, sizeof(telephony_info.call_path),
1336 CSD_CALL_APP_PATH, getpid());
1337 BT_DBG("Call Path = %s", telephony_info.call_path);
1338 memset(telephony_info.address, 0x00, sizeof(telephony_info.address));
1340 if (__bluetooth_telephony_proxy_init()) {
1341 BT_ERR("__bluetooth_telephony_proxy_init failed\n");
1342 telephony_dbus_info.conn = NULL;
1343 is_initialized = FALSE;
1344 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1347 telephony_dbus_info.manager_proxy = g_dbus_proxy_new_sync(
1348 telephony_dbus_info.conn,
1349 G_DBUS_PROXY_FLAGS_NONE, NULL,
1350 BLUEZ_SERVICE_NAME, "/",
1351 BLUEZ_MANAGER_INTERFACE, NULL, &error);
1352 if (telephony_dbus_info.manager_proxy == NULL) {
1353 BT_ERR("Could not create a manager proxy");
1354 __bluetooth_telephony_proxy_deinit();
1355 telephony_dbus_info.conn = NULL;
1356 is_initialized = FALSE;
1358 g_dbus_error_strip_remote_error(error);
1359 ret = __bt_telephony_get_error(error->message);
1360 BT_ERR("Error here %d\n", ret);
1361 g_error_free(error);
1364 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1367 telephony_dbus_info.dbus_proxy = g_dbus_proxy_new_sync(
1368 telephony_dbus_info.conn,
1369 G_DBUS_PROXY_FLAGS_NONE, NULL,
1370 DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
1371 DBUS_INTERFACE_DBUS, NULL, &error);
1372 if (NULL == telephony_dbus_info.dbus_proxy) {
1373 __bluetooth_telephony_proxy_deinit();
1374 telephony_dbus_info.conn = NULL;
1375 g_object_unref(telephony_dbus_info.manager_proxy);
1376 telephony_dbus_info.manager_proxy = NULL;
1377 is_initialized = FALSE;
1378 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1381 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, TRUE) != 0) {
1382 BT_ERR("Fail to Subscribe Adapter Signal");
1386 /*Callback and user applicaton data*/
1387 telephony_info.cb = cb;
1388 telephony_info.user_data = user_data;
1389 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1391 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, TRUE) != 0) {
1392 BT_ERR("Fail to Subscribe telephony event Signal");
1396 if (bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED)
1397 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1399 /*Bluetooth is active, therefore set the flag */
1402 ret = bluetooth_get_local_address(&loc_address);
1403 if (ret != BLUETOOTH_ERROR_NONE) {
1404 BT_ERR("Fail to get local address\n");
1405 ret = BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1408 _bt_convert_addr_type_to_string(src_address, loc_address.addr);
1409 src_addr = g_strdup(src_address);
1411 ret = __bluetooth_telephony_register();
1412 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1413 BT_ERR("__bluetooth_telephony_register failed\n");
1417 #ifndef TIZEN_WEARABLE
1418 __bluetooth_telephony_init_headset_state();
1424 bluetooth_telephony_deinit();
1428 BT_EXPORT_API int bluetooth_telephony_deinit(void)
1431 BT_TELEPHONY_CHECK_INITIALIZED();
1433 is_initialized = FALSE;
1435 if (__bt_telephony_event_subscribe_signal(telephony_dbus_info.conn, FALSE) != 0)
1436 BT_ERR("Fail to UnSubscribe telephony event Signal");
1438 if (bluetooth_check_adapter() != BLUETOOTH_ADAPTER_DISABLED ||
1439 bluetooth_check_adapter_le() != BLUETOOTH_ADAPTER_LE_DISABLED)
1440 __bluetooth_telephony_unregister();
1442 __bluetooth_telephony_proxy_deinit();
1444 telephony_info.cb = NULL;
1445 telephony_info.user_data = NULL;
1446 telephony_info.call_count = 0;
1447 telephony_info.headset_state = BLUETOOTH_STATE_DISCONNETED;
1449 /* Remove BT enabled signal */
1450 if (__bt_telephony_subscribe_adapter_signal(telephony_dbus_info.conn, FALSE) != 0)
1451 BT_ERR("Fail to UnSubscribe Adapter event Signal");
1456 if (telephony_dbus_info.manager_proxy != NULL) {
1457 g_object_unref(telephony_dbus_info.manager_proxy);
1458 telephony_dbus_info.manager_proxy = NULL;
1461 if (telephony_dbus_info.conn != NULL) {
1462 telephony_dbus_info.conn = NULL;
1465 if (telephony_dbus_info.dbus_proxy != NULL) {
1466 g_object_unref(telephony_dbus_info.dbus_proxy);
1467 telephony_dbus_info.dbus_proxy = NULL;
1471 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1474 BT_EXPORT_API gboolean bluetooth_telephony_is_sco_connected(void)
1478 gboolean status = FALSE;
1482 retv_if(is_initialized == FALSE, FALSE);
1483 retv_if(bluetooth_check_adapter() == BLUETOOTH_ADAPTER_DISABLED, FALSE);
1485 reply = __bluetooth_telephony_dbus_method_send(
1486 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1487 "IsPlaying", &err, NULL);
1490 BT_ERR("Error returned in method call\n");
1492 BT_ERR("Error message = %s", err->message);
1497 g_variant_get(reply, "(b)", &status);
1498 g_variant_unref(reply);
1500 #ifdef TIZEN_WEARABLE
1501 if (status == TRUE && telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1502 telephony_info.headset_state = BLUETOOTH_STATE_PLAYING;
1505 BT_INFO("SCO Connected Status = [%d]", status);
1509 BT_EXPORT_API int bluetooth_telephony_is_nrec_enabled(gboolean *status)
1514 GVariant *param_inner;
1518 BT_TELEPHONY_CHECK_INITIALIZED();
1519 BT_TELEPHONY_CHECK_ENABLED();
1522 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1524 if (telephony_info.headset_state == BLUETOOTH_STATE_DISCONNETED)
1525 return BLUETOOTH_TELEPHONY_ERROR_AUDIO_NOT_CONNECTED;
1527 reply = __bluetooth_telephony_dbus_method_send(
1528 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1529 "GetProperties", &err, NULL);
1532 BT_ERR("Error returned in method call\n");
1534 BT_DBG("Error message = %s", err->message);
1537 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1540 g_variant_iter_init(&iter, reply);
1541 while ((param_inner = g_variant_iter_next_value(&iter))) {
1544 value = g_variant_lookup_value(param_inner,
1545 "nrec", G_VARIANT_TYPE_BOOLEAN);
1547 BT_DBG("Property NREC Found");
1548 *status = g_variant_get_boolean(value);
1549 BT_DBG("NREC status = [%d]", *status);
1550 g_variant_unref(value);
1551 g_variant_unref(param_inner);
1554 g_variant_unref(param_inner);
1556 BT_DBG("NREC status = [%d]", *status);
1557 g_variant_unref(reply);
1560 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1563 BT_EXPORT_API int bluetooth_telephony_is_wbs_mode(gboolean *status)
1569 GVariant *param_inner;
1573 BT_TELEPHONY_CHECK_INITIALIZED();
1574 BT_TELEPHONY_CHECK_ENABLED();
1577 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
1581 reply = __bluetooth_telephony_dbus_method_send(
1582 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1583 "GetProperties", &err, NULL);
1586 BT_ERR("Error returned in method call");
1588 BT_ERR("Error message = %s", err->message);
1591 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1594 g_variant_iter_init(&iter, reply);
1595 while ((param_inner = g_variant_iter_next_value(&iter))) {
1598 value = g_variant_lookup_value(param_inner,
1599 "codec", G_VARIANT_TYPE_UINT32);
1601 BT_DBG("Property CODEC Found");
1602 codec = g_variant_get_uint32(value);
1603 g_variant_unref(value);
1604 BT_DBG("Codec = [%d]", codec);
1606 *status = codec == BT_MSBC_CODEC_ID ? TRUE : FALSE;
1607 BT_DBG("NREC status = [%d]", *status);
1608 g_variant_unref(value);
1609 g_variant_unref(param_inner);
1612 g_variant_unref(param_inner);
1615 g_variant_unref(reply);
1616 BT_DBG("MSBC status = [%d]", *status);
1619 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1622 BT_EXPORT_API int bluetooth_telephony_send_vendor_cmd(const char *cmd)
1624 GError *error = NULL;
1625 GVariant *reply, *parameters;
1629 BT_TELEPHONY_CHECK_INITIALIZED();
1630 BT_TELEPHONY_CHECK_ENABLED();
1632 BT_DBG("Send Vendor %s", cmd);
1634 if (telephony_dbus_info.proxy == NULL)
1635 telephony_dbus_info.proxy =
1636 __bluetooth_telephony_get_connected_device_proxy();
1638 if (telephony_dbus_info.proxy == NULL)
1639 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1641 parameters = g_variant_new("s", cmd);
1642 reply = g_dbus_proxy_call_sync(telephony_dbus_info.proxy,
1643 "SendVendorAtCmd", parameters,
1644 G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
1646 g_variant_unref(reply);
1649 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1652 BT_EXPORT_API int bluetooth_telephony_start_voice_recognition(void)
1658 gboolean state = TRUE;
1662 BT_TELEPHONY_CHECK_INITIALIZED();
1663 BT_TELEPHONY_CHECK_ENABLED();
1665 param = g_variant_new("(b)", &state);
1666 reply = __bluetooth_telephony_dbus_method_send(
1667 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1668 "SetVoiceDial", &err, param);
1671 BT_ERR("Error returned in method call\n");
1673 g_dbus_error_strip_remote_error(err);
1674 ret = __bt_telephony_get_error(err->message);
1678 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1681 g_variant_unref(reply);
1683 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1686 BT_EXPORT_API int bluetooth_telephony_stop_voice_recognition(void)
1692 gboolean state = FALSE;
1696 BT_TELEPHONY_CHECK_INITIALIZED();
1697 BT_TELEPHONY_CHECK_ENABLED();
1699 param = g_variant_new("(b)", &state);
1700 reply = __bluetooth_telephony_dbus_method_send(
1701 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
1702 "SetVoiceDial", &err, param);
1705 BT_ERR("Error returned in method call\n");
1707 g_dbus_error_strip_remote_error(err);
1708 ret = __bt_telephony_get_error(err->message);
1712 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1715 g_variant_unref(reply);
1718 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1721 static void __bluetooth_telephony_sco_start_cb(GDBusProxy *proxy,
1722 GAsyncResult *res, gpointer user_data)
1724 GError *error = NULL;
1727 value = g_dbus_proxy_call_finish(proxy, res, &error);
1728 if (value == NULL) {
1729 if (error != NULL) {
1730 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1731 error->code, error->message);
1732 g_clear_error(&error);
1734 BT_ERR("SCo Start Failed");
1738 BT_DBG("sco_start_cb : -");
1739 g_object_unref(proxy);
1740 g_variant_unref(value);
1743 BT_EXPORT_API int bluetooth_telephony_audio_open(void)
1745 GDBusConnection *conn;
1752 BT_TELEPHONY_CHECK_INITIALIZED();
1753 BT_TELEPHONY_CHECK_ENABLED();
1755 /* Because this API is async call, so can't use dbus SMACK */
1756 if (__bt_telephony_check_privilege() ==
1757 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1758 BT_ERR("Don't have a privilege to use this API");
1759 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1762 conn = _bt_gdbus_get_system_gconn();
1764 BT_DBG("No System Bus found\n");
1765 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1768 if (telephony_info.headset_state == BLUETOOTH_STATE_PLAYING)
1769 return BLUETOOTH_TELEPHONY_ERROR_ALREADY_CONNECTED;
1771 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1772 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1773 HFP_AGENT_INTERFACE, NULL, &err);
1774 if (proxy == NULL) {
1775 BT_ERR("Unable to allocate new proxy");
1777 g_dbus_error_strip_remote_error(err);
1778 ret = __bt_telephony_get_error(err->message);
1779 BT_ERR("Error here %d\n", ret);
1783 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1786 g_dbus_proxy_call(proxy, "Play", NULL, G_DBUS_CALL_FLAGS_NONE,
1787 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_start_cb, NULL);
1790 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1793 static void __bluetooth_telephony_sco_close_cb(GDBusProxy *proxy,
1794 GAsyncResult *res, gpointer user_data)
1796 GError *error = NULL;
1799 value = g_dbus_proxy_call_finish(proxy, res, &error);
1800 if (value == NULL) {
1801 if (error != NULL) {
1802 BT_ERR("sco_close_cb error. errCode[%x],message[%s]",
1803 error->code, error->message);
1804 g_clear_error(&error);
1806 BT_ERR("SCo close Failed");
1810 BT_DBG("sco_close_cb : -");
1811 g_object_unref(proxy);
1812 g_variant_unref(value);
1814 BT_EXPORT_API int bluetooth_telephony_audio_close(void)
1816 GDBusConnection *conn;
1823 BT_TELEPHONY_CHECK_INITIALIZED();
1824 BT_TELEPHONY_CHECK_ENABLED();
1826 /* Because this API is async call, so can't use dbus SMACK */
1827 if (__bt_telephony_check_privilege() ==
1828 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
1829 BT_ERR("Don't have a privilege to use this API");
1830 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
1833 conn = _bt_gdbus_get_system_gconn();
1835 BT_DBG("No System Bus found\n");
1836 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1839 if (telephony_info.headset_state != BLUETOOTH_STATE_PLAYING)
1840 return BLUETOOTH_TELEPHONY_ERROR_NOT_CONNECTED;
1842 proxy = g_dbus_proxy_new_sync(conn, G_DBUS_PROXY_FLAGS_NONE, NULL,
1843 HFP_AGENT_SERVICE, HFP_AGENT_PATH,
1844 HFP_AGENT_INTERFACE, NULL, &err);
1845 if (proxy == NULL) {
1846 BT_ERR("Unable to allocate new proxy");
1848 g_dbus_error_strip_remote_error(err);
1849 ret = __bt_telephony_get_error(err->message);
1850 BT_ERR("Error here %d\n", ret);
1854 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1857 g_dbus_proxy_call(proxy, "Stop", NULL, G_DBUS_CALL_FLAGS_NONE,
1858 -1, NULL, (GAsyncReadyCallback)__bluetooth_telephony_sco_close_cb, NULL);
1860 telephony_info.headset_state = BLUETOOTH_STATE_CONNECTED;
1863 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1866 BT_EXPORT_API int bluetooth_telephony_call_remote_ringing(unsigned int call_id)
1870 BT_TELEPHONY_CHECK_INITIALIZED();
1871 BT_TELEPHONY_CHECK_ENABLED();
1874 BT_DBG("call_id = [%d]", call_id);
1876 /*Make sure SCO is already connected */
1877 ret = __bluetooth_telephony_send_call_status(
1878 CSD_CALL_STATUS_MO_ALERTING, call_id, NULL);
1879 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1880 BT_ERR("send call status Failed = [%d]", ret);
1881 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1884 return BLUETOOTH_TELEPHONY_ERROR_NONE;
1887 BT_EXPORT_API int bluetooth_telephony_call_answered(unsigned int call_id,
1888 unsigned int bt_audio)
1893 BT_DBG("call_id = [%d]", call_id);
1895 BT_TELEPHONY_CHECK_INITIALIZED();
1896 BT_TELEPHONY_CHECK_ENABLED();
1898 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1900 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1901 BT_ERR("send call status Failed = [%d]", ret);
1906 if (!bluetooth_telephony_is_sco_connected()) {
1907 ret = bluetooth_telephony_audio_open();
1909 BT_ERR("Audio connection call Failed[%d]", ret);
1910 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
1919 BT_EXPORT_API int bluetooth_telephony_call_end(unsigned int call_id)
1924 BT_DBG("call_id = [%d]", call_id);
1926 BT_TELEPHONY_CHECK_INITIALIZED();
1927 BT_TELEPHONY_CHECK_ENABLED();
1929 if (telephony_info.call_count > 0)
1930 telephony_info.call_count = telephony_info.call_count - 1;
1932 if (telephony_info.call_count == 0) {
1933 if (bluetooth_telephony_is_sco_connected()) {
1934 ret = bluetooth_telephony_audio_close();
1935 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1936 BT_ERR(" Failed = [%d]", ret);
1940 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_MT_RELEASE,
1942 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
1943 BT_ERR("send call status Failed = [%d]", ret);
1951 BT_EXPORT_API int bluetooth_telephony_call_held(unsigned int call_id)
1956 BT_DBG("call_id = [%d]", call_id);
1958 BT_TELEPHONY_CHECK_INITIALIZED();
1959 BT_TELEPHONY_CHECK_ENABLED();
1961 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_HOLD,
1963 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1964 BT_ERR("send call status Failed = [%d]", ret);
1970 BT_EXPORT_API int bluetooth_telephony_call_retrieved(unsigned int call_id)
1975 BT_DBG("call_id = [%d]", call_id);
1977 BT_TELEPHONY_CHECK_INITIALIZED();
1978 BT_TELEPHONY_CHECK_ENABLED();
1980 ret = __bluetooth_telephony_send_call_status(CSD_CALL_STATUS_ACTIVE,
1982 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
1983 BT_ERR("send call status Failed = [%d]", ret);
1989 BT_EXPORT_API int bluetooth_telephony_call_swapped(void *call_list,
1990 unsigned int call_count)
1994 GList *list = call_list;
1995 bt_telephony_call_status_info_t *call_status;
1999 BT_TELEPHONY_CHECK_INITIALIZED();
2000 BT_TELEPHONY_CHECK_ENABLED();
2003 BT_ERR("call_list is invalid");
2004 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2007 /* Because this API is async call, so can't use dbus SMACK */
2008 if (__bt_telephony_check_privilege() ==
2009 BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED) {
2010 BT_ERR("Don't have a privilege to use this API");
2011 return BLUETOOTH_TELEPHONY_ERROR_PERMISSION_DENIED;
2014 BT_DBG(" call_count = [%d]", call_count);
2016 for (i = 0; i < call_count; i++) {
2017 call_status = g_list_nth_data(list, i);
2019 if (NULL == call_status)
2022 BT_DBG(" %d : Call id [%d] status[%d]", i,
2023 call_status->call_id,
2024 call_status->call_status);
2026 if (NULL != call_status->phone_number)
2027 DBG_SECURE("Number [%s]", call_status->phone_number);
2029 switch (call_status->call_status) {
2030 case BLUETOOTH_CALL_STATE_HELD:
2031 ret = __bluetooth_telephony_send_call_status(
2032 CSD_CALL_STATUS_HOLD,
2033 call_status->call_id,
2034 call_status->phone_number);
2035 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2036 BT_ERR("Failed = %d", ret);
2041 case BLUETOOTH_CALL_STATE_CONNECTED:
2042 ret = __bluetooth_telephony_send_call_status(
2043 CSD_CALL_STATUS_ACTIVE,
2044 call_status->call_id,
2045 call_status->phone_number);
2046 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2047 BT_ERR("Failed = [%d]", ret);
2053 if ((call_status->call_status <
2054 BLUETOOTH_CALL_STATE_NONE) ||
2055 (call_status->call_status >=
2056 BLUETOOTH_CALL_STATE_ERROR)) {
2057 BT_ERR("Unknown Call state");
2058 return BLUETOOTH_TELEPHONY_ERROR_NOT_AVAILABLE;
2064 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2067 BT_EXPORT_API int bluetooth_telephony_set_call_status(void *call_list,
2068 unsigned int call_count)
2074 ret = bluetooth_telephony_call_swapped(call_list, call_count);
2076 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE) {
2077 BT_ERR("Failed = [%d]", ret);
2081 telephony_info.call_count = call_count;
2084 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2087 BT_EXPORT_API int bluetooth_telephony_indicate_outgoing_call(
2088 const char *ph_number, unsigned int call_id,
2089 unsigned int bt_audio)
2094 const char *path = telephony_info.call_path;
2099 BT_TELEPHONY_CHECK_INITIALIZED();
2100 BT_TELEPHONY_CHECK_ENABLED();
2102 if (NULL == ph_number)
2103 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2105 param = g_variant_new("(ssi)", path, ph_number, call_id);
2106 reply = __bluetooth_telephony_dbus_method_send(
2107 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2108 "OutgoingCall", &err, param);
2111 BT_ERR("Error returned in method call\n");
2113 g_dbus_error_strip_remote_error(err);
2114 ret = __bt_telephony_get_error(err->message);
2118 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2121 g_variant_unref(reply);
2123 telephony_info.call_count++;
2124 BT_DBG(" ag_info.ag_call_count = [%d]", telephony_info.call_count);
2127 if (!bluetooth_telephony_is_sco_connected()) {
2128 ret = bluetooth_telephony_audio_open();
2130 BT_ERR(" Audio connection Failed = %d", ret);
2131 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2137 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2140 BT_EXPORT_API int bluetooth_telephony_indicate_incoming_call(
2141 const char *ph_number, unsigned int call_id)
2146 const char *path = telephony_info.call_path;
2151 BT_TELEPHONY_CHECK_INITIALIZED();
2152 BT_TELEPHONY_CHECK_ENABLED();
2154 if (NULL == ph_number)
2155 return BLUETOOTH_TELEPHONY_ERROR_INVALID_PARAM;
2157 param = g_variant_new("(ssi)", path, ph_number, call_id);
2158 reply = __bluetooth_telephony_dbus_method_send(
2159 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2160 "IncomingCall", &err, param);
2163 BT_ERR("Error returned in method call\n");
2165 g_dbus_error_strip_remote_error(err);
2166 ret = __bt_telephony_get_error(err->message);
2170 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2173 g_variant_unref(reply);
2174 telephony_info.call_count++;
2175 BT_DBG("telephony_info.call_count = [%d]", telephony_info.call_count);
2177 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2180 BT_EXPORT_API int bluetooth_telephony_set_speaker_gain(
2181 unsigned short speaker_gain)
2190 BT_TELEPHONY_CHECK_INITIALIZED();
2191 BT_TELEPHONY_CHECK_ENABLED();
2193 BT_DBG("set speaker_gain= [%d]", speaker_gain);
2195 param = g_variant_new("(q)", speaker_gain);
2196 reply = __bluetooth_telephony_dbus_method_send(
2197 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2198 "SetSpeakerGain", &err, param);
2201 BT_ERR("Error returned in method call\n");
2203 g_dbus_error_strip_remote_error(err);
2204 ret = __bt_telephony_get_error(err->message);
2208 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2211 g_variant_unref(reply);
2213 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2216 BT_EXPORT_API int bluetooth_telephony_get_headset_volume(
2217 unsigned int *speaker_gain)
2226 BT_TELEPHONY_CHECK_INITIALIZED();
2227 BT_TELEPHONY_CHECK_ENABLED();
2229 reply = __bluetooth_telephony_dbus_method_send(
2230 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2231 "GetSpeakerGain", &err, NULL);
2234 BT_ERR("Error returned in method call\n");
2236 g_dbus_error_strip_remote_error(err);
2237 ret = __bt_telephony_get_error(err->message);
2241 return BLUETOOTH_TELEPHONY_ERROR_INTERNAL;
2243 g_variant_get(reply, "(q)", &gain);
2244 *speaker_gain = gain;
2245 BT_DBG("Get speaker_gain= [%d]", *speaker_gain);
2247 g_variant_unref(reply);
2250 return BLUETOOTH_TELEPHONY_ERROR_NONE;
2253 BT_EXPORT_API int bluetooth_telephony_is_connected(gboolean *ag_connected)
2258 gboolean ag_connected_from_bt_agent;
2260 BT_CHECK_ENABLED(return);
2262 reply = __bluetooth_telephony_dbus_method_send(
2263 HFP_AGENT_PATH, HFP_AGENT_INTERFACE,
2264 "IsConnected", &err, NULL);
2267 BT_ERR("Error returned in method call\n");
2269 g_dbus_error_strip_remote_error(err);
2270 ret = __bt_telephony_get_error(err->message);
2274 return BLUETOOTH_ERROR_INTERNAL;
2276 g_variant_get(reply, "(b)", &ag_connected_from_bt_agent);
2277 *ag_connected = ag_connected_from_bt_agent;
2279 BT_DBG("Conn Status: %s", *ag_connected ? "Connected" : "Disconnected");
2281 g_variant_unref(reply);
2283 return BLUETOOTH_ERROR_NONE;
2286 static void __bt_telephony_adapter_filter(GDBusConnection *connection,
2287 const gchar *sender_name,
2288 const gchar *object_path,
2289 const gchar *interface_name,
2290 const gchar *signal_name,
2291 GVariant *parameters,
2298 if (strcasecmp(signal_name, "InterfacesAdded") == 0) {
2299 GVariant *optional_param = NULL;
2301 g_variant_get(parameters, "(&o@a{sa{sv}})",
2302 &path, &optional_param);
2305 BT_ERR("Invalid adapter path");
2309 BT_INFO("Adapter Path = [%s]", path);
2310 if (strcasecmp(path, DEFAULT_ADAPTER_OBJECT_PATH) == 0) {
2311 if (__bt_telephony_get_src_addr(optional_param))
2312 BT_ERR("Fail to get the local adapter address");
2314 ret = __bluetooth_telephony_register();
2315 if (ret != BLUETOOTH_TELEPHONY_ERROR_NONE)
2316 BT_ERR("__bluetooth_telephony_register failed");
2323 static int __bt_telephony_get_src_addr(GVariant *value)
2326 GVariant *param = NULL;
2329 /* signature a{sa{sv}} */
2330 g_variant_iter_init(&iter, value);
2331 while ((param = g_variant_iter_next_value(&iter))) {
2332 char *interface_name;
2333 GVariant *interface_var = NULL;
2334 GVariant *param_inner = NULL;
2336 g_variant_get(param, "{&s*}", &interface_name, &interface_var);
2337 g_variant_unref(param);
2339 BT_DBG("interface_name: %s", interface_name);
2340 /* format of interface_var: a{sv}*/
2341 if (strcasecmp(interface_name, BLUEZ_ADAPTER_INTERFACE) == 0) {
2342 GVariantIter iter_inner;
2344 g_variant_iter_init(&iter_inner, interface_var);
2345 while ((param_inner = g_variant_iter_next_value(&iter_inner))) {
2346 char *property_name;
2347 GVariant *property_var;
2349 g_variant_get(param_inner, "{&sv}",
2352 g_variant_unref(param_inner);
2354 if (strcasecmp(property_name, "Address") == 0) {
2355 const gchar *bd_addr;
2357 bd_addr = g_variant_get_string(
2360 src_addr = g_strdup(bd_addr);
2361 BT_DBG("Address: %s", src_addr);
2363 g_variant_unref(interface_var);
2364 g_variant_unref(property_var);
2367 g_variant_unref(property_var);
2370 g_variant_unref(interface_var);
2374 return BLUETOOTH_ERROR_NONE;