4 * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <dbus/dbus-glib.h>
25 #include <dbus/dbus.h>
26 #include <dbus/dbus-glib-lowlevel.h>
29 #include <TapiUtility.h>
35 #include "vconf-keys.h"
39 #include "bluetooth-hfp-agent.h"
41 static GMainLoop *gmain_loop = NULL;
42 static DBusGConnection *g_connection = NULL;
43 static DBusConnection *gconn = NULL;
44 static gboolean nrec_status = FALSE;
46 #define BT_ERROR_INTERNAL "InternalError"
47 #define BT_ERROR_NOT_AVAILABLE "NotAvailable"
48 #define BT_ERROR_NOT_CONNECTED "NotConnected"
49 #define BT_ERROR_BUSY "InProgress"
50 #define BT_ERROR_INVALID_PARAM "InvalidArguments"
51 #define BT_ERROR_ALREADY_EXSIST "AlreadyExists"
52 #define BT_ERROR_ALREADY_CONNECTED "Already Connected"
53 #define BT_ERROR_NO_MEMORY "No memory"
54 #define BT_ERROR_I_O_ERROR "I/O error"
55 #define BT_ERROR_OPERATION_NOT_AVAILABLE "Operation currently not available"
56 #define BT_ERROR_BATTERY "Battery error "
57 #define BT_ERROR_SIGNAL "Signal error"
58 #define BT_ERROR_NO_CALL_LOG "No Call log"
59 #define BT_ERROR_INVLAID_DTMF "Invalid dtmf"
61 #define BLUEZ_SERVICE_NAME "org.bluez"
62 #define TELEPHONY_CSD_INTERFACE "org.tizen.telephony.csd"
63 #define TELEPHONY_CSD_OBJECT_PATH "/org/tizen/csd"
64 #define TELEPHONY_APP_INTERFACE "org.tizen.csd.Call.Instance"
66 #define BT_HFP_AGENT_SET_PROPERTY "SetProperty"
68 #define BT_HFP_AGENT_OBJECT "/org/bluez/agent/hfp_agent"
69 #define BT_HFP_AGENT_INTERFACE "org.bluez.hfp_agent"
71 #define BT_SIGNAL_ARRAY_MAX 2
73 /* AT+CSQ : Returns received signal strength indication.
74 Command response: +CSQ: <rssi>,<ber>
75 <ber> is not supported and has a constant value of 99, included for compatibility reasons.
77 #define BT_SIGNAL_QUALITY_BER 99
79 /*Length of the string used to send telephone number to app-svc
82 #define BT_MAX_TEL_NUM_STRING 20
85 * @brief Outgoing call type status
87 * 0 : Follow last call log \n
91 #define BT_FOLLOW_CALL_LOG 0
92 #define BT_VOICE_CALL 1
93 #define BT_VIDEO_CALL 2
96 * @brief The status of making outgoing calls with BT headsets
98 * 0 : Even when device locked \n
99 * 1 : Only when device unlocked \n
101 #define BT_MO_EVEN_LOCKED 0
102 #define BT_MO_ONLY_UNLOCKED 1
112 GType bt_hfp_agent_get_type(void);
114 #define BT_HFP_TYPE_AGENT (bt_hfp_agent_get_type())
116 #define BT_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_CAST((object), \
117 BT_HFP_TYPE_AGENT , BtHfpAgent))
119 #define BT_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_CAST((klass), \
120 BT_HFP_TYPE_AGENT , BtHfpAgentClass))
122 #define BT_IS_HFP_AGENT(object)(G_TYPE_CHECK_INSTANCE_TYPE((object), \
125 #define BT_IS_HFP_AGENT_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE((klass), \
128 #define BT_HFP_AGENT_GET_CLASS(obj)(G_TYPE_INSTANCE_GET_CLASS((obj), \
129 BT_HFP_TYPE_AGENT , BtHfpAgentClass))
131 G_DEFINE_TYPE(BtHfpAgent, bt_hfp_agent, G_TYPE_OBJECT)
133 static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
134 const gchar *path, DBusGMethodInvocation *context);
136 static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
137 const gchar *path, DBusGMethodInvocation *context);
139 static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
140 const gchar *number, gint call_id,
141 DBusGMethodInvocation *context);
143 static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
144 const gchar *number, gint call_id,
145 DBusGMethodInvocation *context);
147 static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
148 const gchar *path, gint status, gint call_id,
149 DBusGMethodInvocation *context);
151 static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
152 const gchar *path, const gchar *sender,
153 DBusGMethodInvocation *context);
155 static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
156 const gchar *path, const gchar *sender,
157 DBusGMethodInvocation *context);
159 static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
160 const gchar *path, const gchar *sender,
161 DBusGMethodInvocation *context);
163 static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint call_id,
164 const gchar *path, const gchar *sender,
165 DBusGMethodInvocation *context);
167 static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
168 DBusGMethodInvocation *context);
170 static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
171 const gchar *number, guint flags,
172 DBusGMethodInvocation *context);
174 static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
175 DBusGMethodInvocation *context);
177 static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
178 const gchar *path, const gchar *sender,
179 DBusGMethodInvocation *context);
181 static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
182 DBusGMethodInvocation *context);
184 static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
185 DBusGMethodInvocation *context);
187 static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
188 DBusGMethodInvocation *context);
190 static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
191 DBusGMethodInvocation *context);
193 static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
194 DBusGMethodInvocation *context);
196 static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
197 DBusGMethodInvocation *context);
199 #include "bluetooth_hfp_agent_glue.h"
201 static void bt_hfp_agent_init(BtHfpAgent *obj)
205 g_assert(obj != NULL);
208 static void bt_hfp_agent_finalize(GObject *obj)
212 G_OBJECT_CLASS(bt_hfp_agent_parent_class)->finalize(obj);
215 static void bt_hfp_agent_class_init(BtHfpAgentClass *klass)
219 GObjectClass *object_class = (GObjectClass *)klass;
221 g_assert(klass != NULL);
223 object_class->finalize = bt_hfp_agent_finalize;
225 dbus_g_object_type_install_info(BT_HFP_TYPE_AGENT,
226 &dbus_glib_bt_hfp_agent_object_info);
229 static GQuark __bt_hfp_agent_error_quark(void)
233 static GQuark quark = 0;
235 quark = g_quark_from_static_string("agent");
240 static GError *__bt_hfp_agent_set_error(bt_hfp_agent_error_t error)
245 case BT_HFP_AGENT_ERROR_NOT_AVAILABLE:
246 return g_error_new(BT_HFP_AGENT_ERROR, error,
247 BT_ERROR_NOT_AVAILABLE);
248 case BT_HFP_AGENT_ERROR_NOT_CONNECTED:
249 return g_error_new(BT_HFP_AGENT_ERROR, error,
250 BT_ERROR_NOT_CONNECTED);
251 case BT_HFP_AGENT_ERROR_BUSY:
252 return g_error_new(BT_HFP_AGENT_ERROR, error,
254 case BT_HFP_AGENT_ERROR_INVALID_PARAM:
255 return g_error_new(BT_HFP_AGENT_ERROR, error,
256 BT_ERROR_INVALID_PARAM);
257 case BT_HFP_AGENT_ERROR_ALREADY_EXSIST:
258 return g_error_new(BT_HFP_AGENT_ERROR, error,
259 BT_ERROR_ALREADY_EXSIST);
260 case BT_HFP_AGENT_ERROR_ALREADY_CONNECTED:
261 return g_error_new(BT_HFP_AGENT_ERROR, error,
262 BT_ERROR_ALREADY_CONNECTED);
263 case BT_HFP_AGENT_ERROR_NO_MEMORY:
264 return g_error_new(BT_HFP_AGENT_ERROR, error,
266 case BT_HFP_AGENT_ERROR_I_O_ERROR:
267 return g_error_new(BT_HFP_AGENT_ERROR, error,
269 case BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE:
270 return g_error_new(BT_HFP_AGENT_ERROR, error,
271 BT_ERROR_OPERATION_NOT_AVAILABLE);
272 case BT_HFP_AGENT_ERROR_BATTERY_STATUS:
273 return g_error_new(BT_HFP_AGENT_ERROR, error,
275 case BT_HFP_AGENT_ERROR_SIGNAL_STATUS:
276 return g_error_new(BT_HFP_AGENT_ERROR, error,
278 case BT_HFP_AGENT_ERROR_NO_CALL_LOGS:
279 return g_error_new(BT_HFP_AGENT_ERROR, error,
280 BT_ERROR_NO_CALL_LOG);
281 case BT_HFP_AGENT_ERROR_INTERNAL:
283 return g_error_new(BT_HFP_AGENT_ERROR, error,
288 static int __bt_hfp_agent_get_error(const char *error_message)
290 if (error_message == NULL) {
291 DBG("Error message NULL\n");
292 return BT_HFP_AGENT_ERROR_INTERNAL;
295 DBG("Error message = %s \n", error_message);
297 if (g_strcmp0(error_message, BT_ERROR_NOT_AVAILABLE) == 0)
298 return BT_HFP_AGENT_ERROR_NOT_AVAILABLE;
299 else if (g_strcmp0(error_message, BT_ERROR_NOT_CONNECTED) == 0)
300 return BT_HFP_AGENT_ERROR_NOT_CONNECTED;
301 else if (g_strcmp0(error_message, BT_ERROR_BUSY) == 0)
302 return BT_HFP_AGENT_ERROR_BUSY;
303 else if (g_strcmp0(error_message, BT_ERROR_INVALID_PARAM) == 0)
304 return BT_HFP_AGENT_ERROR_INVALID_PARAM;
305 else if (g_strcmp0(error_message, BT_ERROR_ALREADY_EXSIST) == 0)
306 return BT_HFP_AGENT_ERROR_ALREADY_EXSIST;
307 else if (g_strcmp0(error_message, BT_ERROR_ALREADY_CONNECTED) == 0)
308 return BT_HFP_AGENT_ERROR_ALREADY_CONNECTED;
309 else if (g_strcmp0(error_message, BT_ERROR_NO_MEMORY) == 0)
310 return BT_HFP_AGENT_ERROR_NO_MEMORY;
311 else if (g_strcmp0(error_message, BT_ERROR_I_O_ERROR) == 0)
312 return BT_HFP_AGENT_ERROR_I_O_ERROR;
313 else if (g_strcmp0(error_message,
314 BT_ERROR_OPERATION_NOT_AVAILABLE) == 0)
315 return BT_HFP_AGENT_ERROR_OPERATION_NOT_AVAILABLE;
316 else if (g_strcmp0(error_message, BT_ERROR_INVLAID_DTMF) == 0)
317 return BT_HFP_AGENT_ERROR_INVALID_DTMF;
319 return BT_HFP_AGENT_ERROR_INTERNAL;
322 static int __bt_hfp_agent_dbus_method_send(const char *service,
323 const char *path, const char *interface,
324 const char *method, gboolean response,
333 DBG("__bt_hfp_agent_dbus_method_send +\n");
335 msg = dbus_message_new_method_call(service, path, interface,
338 DBG("Unable to allocate new D-Bus %s message \n", method);
339 return BT_HFP_AGENT_ERROR_INTERNAL;
342 va_start(args, type);
344 if (!dbus_message_append_args_valist(msg, type, args)) {
345 dbus_message_unref(msg);
347 return BT_HFP_AGENT_ERROR_INTERNAL;
352 dbus_error_init(&err);
355 reply = dbus_connection_send_with_reply_and_block(gconn,
357 dbus_message_unref(msg);
360 DBG("Error returned in method call\n");
361 if (dbus_error_is_set(&err)) {
362 error = __bt_hfp_agent_get_error(err.message);
363 dbus_error_free(&err);
366 DBG("Error is not set\n");
367 return BT_HFP_AGENT_ERROR_INTERNAL;
370 dbus_message_unref(reply);
372 dbus_connection_send(gconn, msg, NULL);
373 dbus_message_unref(msg);
376 DBG("__bt_hfp_agent_dbus_method_send -\n");
378 return BT_HFP_AGENT_ERROR_NONE;
381 static gboolean bt_hfp_agent_register_application(BtHfpAgent *agent,
382 const gchar *path, DBusGMethodInvocation *context)
384 gboolean flag = TRUE;
389 DBG("bt_hfp_agent_register_application + \n");
392 DBG("Invalid Argument path\n");
393 error = __bt_hfp_agent_set_error(
394 BT_HFP_AGENT_ERROR_INVALID_PARAM);
395 dbus_g_method_return_error(context, error);
400 DBG("Application path = %s\n", path);
402 sender = dbus_g_method_get_sender(context);
404 DBG("Sender = %s\n", sender);
406 ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
407 TELEPHONY_CSD_OBJECT_PATH,
408 TELEPHONY_CSD_INTERFACE,
409 "RegisterTelephonyAgent", TRUE,
410 DBUS_TYPE_BOOLEAN, &flag,
411 DBUS_TYPE_STRING, &path,
412 DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
415 if (ret != BT_HFP_AGENT_ERROR_NONE) {
416 error = __bt_hfp_agent_set_error(ret);
417 dbus_g_method_return_error(context, error);
422 dbus_g_method_return(context);
424 DBG("bt_hfp_agent_register_application - \n");
428 static gboolean bt_hfp_agent_unregister_application(BtHfpAgent *agent,
429 const gchar *path, DBusGMethodInvocation *context)
431 gboolean flag = FALSE;
436 DBG("bt_hfp_agent_unregister_application + \n");
439 DBG("Invalid Argument path\n");
440 error = __bt_hfp_agent_set_error(
441 BT_HFP_AGENT_ERROR_INVALID_PARAM);
442 dbus_g_method_return_error(context, error);
447 DBG("Application path = %s \n", path);
449 sender = dbus_g_method_get_sender(context);
451 DBG("Sender = %s\n", sender);
453 ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
454 TELEPHONY_CSD_OBJECT_PATH,
455 TELEPHONY_CSD_INTERFACE,
456 "RegisterTelephonyAgent", TRUE,
457 DBUS_TYPE_BOOLEAN, &flag,
458 DBUS_TYPE_STRING, &path,
459 DBUS_TYPE_STRING, &sender, DBUS_TYPE_INVALID);
462 if (ret != BT_HFP_AGENT_ERROR_NONE) {
463 error = __bt_hfp_agent_set_error(ret);
464 dbus_g_method_return_error(context, error);
469 dbus_g_method_return(context);
471 DBG("bt_hfp_agent_unregister_application - \n");
475 static gboolean bt_hfp_agent_incoming_call(BtHfpAgent *agent, const gchar *path,
476 const gchar *number, gint call_id,
477 DBusGMethodInvocation *context)
483 DBG("bt_hfp_agent_incoming_call + \n");
485 if (path == NULL || number == NULL) {
486 DBG("Invalid Arguments\n");
487 error = __bt_hfp_agent_set_error(
488 BT_HFP_AGENT_ERROR_INVALID_PARAM);
489 dbus_g_method_return_error(context, error);
494 DBG("Application path = %s\n", path);
495 DBG("Phone number = %s\n", number);
496 DBG("Call id = %d\n", call_id);
498 sender = dbus_g_method_get_sender(context);
500 DBG("Sender = %s\n", sender);
502 ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
503 TELEPHONY_CSD_OBJECT_PATH,
504 TELEPHONY_CSD_INTERFACE,
506 DBUS_TYPE_STRING, &path,
507 DBUS_TYPE_STRING, &number,
508 DBUS_TYPE_UINT32, &call_id,
509 DBUS_TYPE_STRING, &sender,
513 if (ret != BT_HFP_AGENT_ERROR_NONE) {
514 error = __bt_hfp_agent_set_error(ret);
515 dbus_g_method_return_error(context, error);
520 dbus_g_method_return(context);
522 DBG("bt_hfp_agent_incoming_call - \n");
526 static gboolean bt_hfp_agent_outgoing_call(BtHfpAgent *agent, const gchar *path,
527 const gchar *number, gint call_id,
528 DBusGMethodInvocation *context)
534 DBG("bt_hfp_agent_outgoing_call + \n");
536 if (path == NULL || number == NULL) {
537 DBG("Invalid Arguments\n");
538 error = __bt_hfp_agent_set_error(
539 BT_HFP_AGENT_ERROR_INVALID_PARAM);
540 dbus_g_method_return_error(context, error);
545 DBG("Application path = %s\n", path);
546 DBG("Phone number = %s\n", number);
547 DBG("Call id = %d\n", call_id);
549 sender = dbus_g_method_get_sender(context);
551 DBG("Sender = %s\n", sender);
553 ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
554 TELEPHONY_CSD_OBJECT_PATH,
555 TELEPHONY_CSD_INTERFACE,
557 DBUS_TYPE_STRING, &path,
558 DBUS_TYPE_STRING, &number,
559 DBUS_TYPE_UINT32, &call_id,
560 DBUS_TYPE_STRING, &sender,
564 if (ret != BT_HFP_AGENT_ERROR_NONE) {
565 error = __bt_hfp_agent_set_error(ret);
566 dbus_g_method_return_error(context, error);
571 dbus_g_method_return(context);
573 DBG("bt_hfp_agent_outgoing_call - \n");
577 static gboolean bt_hfp_agent_change_call_status(BtHfpAgent *agent,
578 const gchar *path, gint status, gint call_id,
579 DBusGMethodInvocation *context)
585 DBG("bt_hfp_agent_change_call_status + \n");
588 DBG("Invalid Argument path\n");
589 error = __bt_hfp_agent_set_error(
590 BT_HFP_AGENT_ERROR_INVALID_PARAM);
591 dbus_g_method_return_error(context, error);
596 DBG("Application path = %s\n", path);
597 DBG("Status = %d\n", status);
598 DBG("Call id = %d\n", call_id);
600 sender = dbus_g_method_get_sender(context);
602 DBG("Sender = %s\n", sender);
604 ret = __bt_hfp_agent_dbus_method_send(BLUEZ_SERVICE_NAME,
605 TELEPHONY_CSD_OBJECT_PATH,
606 TELEPHONY_CSD_INTERFACE,
607 "SetCallStatus", TRUE,
608 DBUS_TYPE_STRING, &path,
609 DBUS_TYPE_UINT32, &status,
610 DBUS_TYPE_UINT32, &call_id,
611 DBUS_TYPE_STRING, &sender,
615 if (ret != BT_HFP_AGENT_ERROR_NONE) {
616 error = __bt_hfp_agent_set_error(ret);
617 dbus_g_method_return_error(context, error);
622 dbus_g_method_return(context);
624 DBG("bt_hfp_agent_change_call_status - \n");
628 static gboolean bt_hfp_agent_answer_call(BtHfpAgent *agent, unsigned int call_id,
629 const gchar *path, const gchar *sender,
630 DBusGMethodInvocation *context)
636 if (path == NULL || sender == NULL) {
637 DBG("Invalid Arguments\n");
638 error = __bt_hfp_agent_set_error(
639 BT_HFP_AGENT_ERROR_INVALID_PARAM);
640 dbus_g_method_return_error(context, error);
645 DBG("Application path = %s \n", path);
646 DBG("Call Id = %d", call_id);
647 DBG("Sender = %s\n", sender);
649 ret = __bt_hfp_agent_dbus_method_send(sender,
650 path, TELEPHONY_APP_INTERFACE,
652 DBUS_TYPE_UINT32, &call_id,
655 if (ret != BT_HFP_AGENT_ERROR_NONE) {
656 error = __bt_hfp_agent_set_error(ret);
657 dbus_g_method_return_error(context, error);
662 dbus_g_method_return(context);
668 static gboolean bt_hfp_agent_release_call(BtHfpAgent *agent, unsigned int call_id,
669 const gchar *path, const gchar *sender,
670 DBusGMethodInvocation *context)
676 if (path == NULL || sender == NULL) {
677 DBG("Invalid Arguments\n");
678 error = __bt_hfp_agent_set_error(
679 BT_HFP_AGENT_ERROR_INVALID_PARAM);
680 dbus_g_method_return_error(context, error);
685 DBG("Application path = %s \n", path);
686 DBG("Call Id = %d", call_id);
687 DBG("Sender = %s\n", sender);
689 ret = __bt_hfp_agent_dbus_method_send(sender,
690 path, TELEPHONY_APP_INTERFACE,
692 DBUS_TYPE_UINT32, &call_id,
695 if (ret != BT_HFP_AGENT_ERROR_NONE) {
696 error = __bt_hfp_agent_set_error(ret);
697 dbus_g_method_return_error(context, error);
702 dbus_g_method_return(context);
707 static gboolean bt_hfp_agent_reject_call(BtHfpAgent *agent, unsigned int call_id,
708 const gchar *path, const gchar *sender,
709 DBusGMethodInvocation *context)
715 if (path == NULL || sender == NULL) {
716 DBG("Invalid Arguments\n");
717 error = __bt_hfp_agent_set_error(
718 BT_HFP_AGENT_ERROR_INVALID_PARAM);
719 dbus_g_method_return_error(context, error);
724 DBG("Application path = %s \n", path);
725 DBG("Call Id = %d", call_id);
726 DBG("Sender = %s\n", sender);
728 ret = __bt_hfp_agent_dbus_method_send(sender,
729 path, TELEPHONY_APP_INTERFACE,
731 DBUS_TYPE_UINT32, &call_id,
734 if (ret != BT_HFP_AGENT_ERROR_NONE) {
735 error = __bt_hfp_agent_set_error(ret);
736 dbus_g_method_return_error(context, error);
741 dbus_g_method_return(context);
746 static gboolean bt_hfp_agent_threeway_call(BtHfpAgent *agent, gint value,
747 const gchar *path, const gchar *sender,
748 DBusGMethodInvocation *context)
754 if (path == NULL || sender == NULL) {
755 DBG("Invalid Arguments\n");
756 error = __bt_hfp_agent_set_error(
757 BT_HFP_AGENT_ERROR_INVALID_PARAM);
758 dbus_g_method_return_error(context, error);
763 DBG("Application path = %s \n", path);
764 DBG("Value = %d", value);
765 DBG("Sender = %s\n", sender);
767 ret = __bt_hfp_agent_dbus_method_send(sender,
768 path, TELEPHONY_APP_INTERFACE,
770 DBUS_TYPE_UINT32, &value,
773 if (ret != BT_HFP_AGENT_ERROR_NONE) {
774 error = __bt_hfp_agent_set_error(ret);
775 dbus_g_method_return_error(context, error);
780 dbus_g_method_return(context);
785 void __bt_append_entry(DBusMessageIter *iter,
786 const char *key, int type, void *val)
788 DBusMessageIter entry;
789 DBusMessageIter value;
791 char signal[BT_SIGNAL_ARRAY_MAX] = { type, '\0' };
793 if (type == DBUS_TYPE_STRING) {
794 str = *((const char **) val);
800 dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
802 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
804 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
807 dbus_message_iter_append_basic(&value, type, val);
809 dbus_message_iter_close_container(&entry, &value);
811 dbus_message_iter_close_container(iter, &entry);
814 static gboolean bt_hfp_agent_get_properties(BtHfpAgent *agent,
815 DBusGMethodInvocation *context)
818 DBusMessageIter iter;
819 DBusMessageIter dict;
822 DBG("bt_hfp_agent_get_properties + \n");
824 reply = dbus_g_method_get_reply(context);
826 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
827 dbus_g_method_return_error(context, error);
832 dbus_message_iter_init_append(reply, &iter);
834 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
835 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
836 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
837 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
839 __bt_append_entry(&dict, "nrec", DBUS_TYPE_BOOLEAN, &nrec_status);
840 dbus_message_iter_close_container(&iter, &dict);
841 dbus_g_method_send_reply(context, reply);
842 DBG("bt_hfp_agent_get_properties - \n");
846 static gboolean __bt_is_phone_locked(int *phone_lock_state)
851 if (NULL == phone_lock_state)
854 ret = vconf_get_int(VCONFKEY_IDLE_LOCK_STATE, phone_lock_state);
856 DBG("Failed to read [%s]\n", VCONFKEY_IDLE_LOCK_STATE);
860 DBG("[%s] = [%d]\n", VCONFKEY_IDLE_LOCK_STATE, *phone_lock_state);
866 static gboolean __bt_get_outgoing_callapp_type(int *callapp_type)
871 if (NULL == callapp_type)
874 ret = vconf_get_int(VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, callapp_type);
876 DBG("Failed to read [%s]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT);
880 DBG(" [%s] = [%d]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_TYPE_INT, *callapp_type);
886 static gboolean __bt_get_outgoing_call_condition(int *condition)
891 if (NULL == condition)
894 ret = vconf_get_int(VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT, condition);
896 DBG("Failed to read [%s]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT);
900 DBG(" [%s] = [%d]\n", VCONFKEY_CISSAPPL_OUTGOING_CALL_CONDITIONS_INT, *condition);
906 static gboolean __bt_hfp_agent_make_call(const char *number)
909 char telnum[BT_MAX_TEL_NUM_STRING];
915 appsvc_set_operation(b, APPSVC_OPERATION_CALL);
916 snprintf(telnum, sizeof(telnum), "tel:%s", number);
917 appsvc_set_uri(b, telnum);
918 appsvc_add_data(b, "ctindex", "-1");
919 appsvc_run_service(b, 0, NULL, NULL);
925 static gboolean __bt_hfp_agent_make_video_call(const char *mo_number)
929 kb = bundle_create();
933 bundle_add(kb, "KEY_CALL_TYPE", "MO");
934 bundle_add(kb, "number", mo_number);
935 aul_launch_app("com.samsung.vtmain", kb);
941 static gboolean bt_hfp_agent_dial_last_num(BtHfpAgent *agent,
942 DBusGMethodInvocation *context)
945 int error_code = BT_HFP_AGENT_ERROR_NONE;
946 char *last_number = NULL;
949 int phone_lock_state;
951 contacts_list_h list = NULL;
952 contacts_query_h query = NULL;
953 contacts_filter_h filter = NULL;
954 contacts_record_h record = NULL;
955 unsigned int projections[] = {
956 _contacts_phone_log.address,
957 _contacts_phone_log.log_type,
962 if (contacts_connect2() != CONTACTS_ERROR_NONE) {
963 ERR(" contacts_connect2 failed \n");
964 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
965 dbus_g_method_return_error(context, error);
970 contacts_filter_create(_contacts_phone_log._uri, &filter);
975 if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
976 CONTACTS_MATCH_EQUAL,
977 CONTACTS_PLOG_TYPE_VOICE_OUTGOING) !=
978 CONTACTS_ERROR_NONE) {
979 ERR(" contacts_filter_add_int failed \n");
980 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
984 if (contacts_filter_add_operator(filter, CONTACTS_FILTER_OPERATOR_OR) !=
985 CONTACTS_ERROR_NONE) {
986 ERR(" contacts_filter_add_operator failed \n");
987 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
991 if (contacts_filter_add_int(filter, _contacts_phone_log.log_type,
992 CONTACTS_MATCH_EQUAL,
993 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) !=
994 CONTACTS_ERROR_NONE) {
995 ERR(" contacts_filter_add_int failed \n");
996 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1000 contacts_query_create(_contacts_phone_log._uri, &query);
1005 contacts_query_set_filter(query, filter);
1007 if (contacts_query_set_projection(query, projections,
1008 sizeof(projections)/sizeof(unsigned int)) !=
1009 CONTACTS_ERROR_NONE) {
1010 ERR(" contacts_query_set_projection failed \n");
1011 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1015 if (contacts_query_set_sort(query, _contacts_phone_log.log_time, false) !=
1016 CONTACTS_ERROR_NONE) {
1017 ERR(" contacts_query_set_sort failed \n");
1018 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1022 if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
1023 CONTACTS_ERROR_NONE) {
1024 ERR(" contacts_db_get_records_with_query failed \n");
1025 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1029 if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
1030 ERR(" contacts_list_first failed \n");
1031 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1035 if (contacts_list_get_current_record_p(list, &record) !=
1036 CONTACTS_ERROR_NONE) {
1037 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1044 if (contacts_record_get_str(record, _contacts_phone_log.address,
1045 &last_number)!= CONTACTS_ERROR_NONE) {
1046 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1050 if (last_number == NULL) {
1051 ERR("No last number \n");
1052 error_code = BT_HFP_AGENT_ERROR_NO_CALL_LOGS;
1056 if (!__bt_is_phone_locked(&phone_lock_state)) {
1057 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1061 if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1062 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1066 if (!__bt_get_outgoing_call_condition(&condition)) {
1067 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1071 if (condition == BT_MO_ONLY_UNLOCKED &&
1072 phone_lock_state == VCONFKEY_IDLE_LOCK) {
1073 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1077 switch (callapp_type) {
1079 if (!__bt_hfp_agent_make_call(last_number)) {
1080 ERR("Problem launching application \n");
1081 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1085 if(!__bt_hfp_agent_make_video_call(last_number)) {
1086 ERR("Problem launching application \n");
1087 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1090 case BT_FOLLOW_CALL_LOG:
1091 if(contacts_record_get_int(record,
1092 _contacts_phone_log.log_type,
1093 &log_type) != CONTACTS_ERROR_NONE) {
1094 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1097 if (log_type == CONTACTS_PLOG_TYPE_VOICE_OUTGOING) {
1098 if (!__bt_hfp_agent_make_call(last_number)) {
1099 ERR("Problem launching application \n");
1100 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1103 else if(log_type == CONTACTS_PLOG_TYPE_VIDEO_OUTGOING) {
1104 if(!__bt_hfp_agent_make_video_call(last_number)) {
1105 ERR("Problem launching application \n");
1106 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1109 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1113 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1119 contacts_list_destroy(list, TRUE);
1122 contacts_filter_destroy(filter);
1125 contacts_query_destroy(query);
1127 contacts_disconnect2();
1129 if (last_number != NULL)
1130 g_free(last_number);
1134 if (error_code == BT_HFP_AGENT_ERROR_NONE) {
1135 dbus_g_method_return(context);
1138 error = __bt_hfp_agent_set_error(error_code);
1139 dbus_g_method_return_error(context, error);
1140 g_error_free(error);
1145 static gboolean bt_hfp_agent_dial_num(BtHfpAgent *agent,
1146 const gchar *number, guint flags,
1147 DBusGMethodInvocation *context)
1152 int phone_lock_state;
1157 if (number == NULL) {
1158 ERR("Invalid Argument\n");
1159 error_code = BT_HFP_AGENT_ERROR_INVALID_PARAM;
1163 DBG("Number = %s \n", number);
1164 DBG("flags = %d", flags);
1166 /*TODO: Make use of flags*/
1168 if (!__bt_is_phone_locked(&phone_lock_state)) {
1169 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1173 if (!__bt_get_outgoing_callapp_type(&callapp_type)) {
1174 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1178 if (!__bt_get_outgoing_call_condition(&condition)) {
1179 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1183 if (condition == BT_MO_ONLY_UNLOCKED && phone_lock_state == VCONFKEY_IDLE_LOCK) {
1184 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1188 if (callapp_type == BT_VIDEO_CALL) {
1189 if(!__bt_hfp_agent_make_video_call(number)) {
1190 ERR("Problem launching application \n");
1191 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1195 if (!__bt_hfp_agent_make_call(number)) {
1196 ERR("Problem launching application \n");
1197 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1202 dbus_g_method_return(context);
1207 error = __bt_hfp_agent_set_error(error_code);
1208 dbus_g_method_return_error(context, error);
1209 g_error_free(error);
1214 static gboolean bt_hfp_agent_dial_memory(BtHfpAgent *agent, gint location,
1215 DBusGMethodInvocation *context)
1218 int error_code = BT_HFP_AGENT_ERROR_NONE;
1219 char *number = NULL;
1220 contacts_filter_h filter = NULL;
1221 contacts_query_h query = NULL;
1222 contacts_list_h list = NULL;
1223 contacts_record_h record = NULL;
1224 unsigned int projections[] = {
1225 _contacts_speeddial.number,
1230 DBG("location = %d \n", location);
1232 /*Get number from contacts location*/
1233 if (contacts_connect2() != CONTACTS_ERROR_NONE) {
1234 ERR(" contacts_connect2 failed \n");
1235 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
1236 dbus_g_method_return_error(context, error);
1237 g_error_free(error);
1241 contacts_filter_create(_contacts_speeddial._uri, &filter);
1246 if (contacts_filter_add_int(filter, _contacts_speeddial.speeddial_number,
1247 CONTACTS_MATCH_EQUAL, location) !=
1248 CONTACTS_ERROR_NONE) {
1249 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1253 contacts_query_create(_contacts_speeddial._uri, &query);
1258 contacts_query_set_filter(query, filter);
1260 if (contacts_query_set_projection(query, projections,
1261 sizeof(projections)/sizeof(unsigned int)) !=
1262 CONTACTS_ERROR_NONE) {
1263 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1267 if (contacts_db_get_records_with_query(query, 0, 1, &list) !=
1268 CONTACTS_ERROR_NONE) {
1269 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1273 if (contacts_list_first(list) != CONTACTS_ERROR_NONE) {
1274 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1278 if (contacts_list_get_current_record_p(list, &record) !=
1279 CONTACTS_ERROR_NONE) {
1280 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1287 if (contacts_record_get_str(record, _contacts_speeddial.number,
1288 &number)!= CONTACTS_ERROR_NONE) {
1289 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1293 if (number == NULL) {
1294 ERR("No number at the location \n");
1295 error_code = BT_HFP_AGENT_ERROR_INVALID_MEMORY_INDEX;
1299 DBG("number %s\n", number);
1302 if (!__bt_hfp_agent_make_call(number)) {
1303 ERR("Problem launching application \n");
1304 error_code = BT_HFP_AGENT_ERROR_INTERNAL;
1310 contacts_list_destroy(list, TRUE);
1313 contacts_filter_destroy(filter);
1316 contacts_query_destroy(query);
1318 contacts_disconnect2();
1322 if (error_code == BT_HFP_AGENT_ERROR_NONE) {
1323 dbus_g_method_return(context);
1326 error = __bt_hfp_agent_set_error(error_code);
1327 dbus_g_method_return_error(context, error);
1328 g_error_free(error);
1333 static gboolean bt_hfp_agent_send_dtmf(BtHfpAgent *agent, const gchar *dtmf,
1334 const gchar *path, const gchar *sender,
1335 DBusGMethodInvocation *context)
1342 if (dtmf == NULL || path == NULL || sender == NULL) {
1343 ERR("Invalid Argument\n");
1344 error = __bt_hfp_agent_set_error(
1345 BT_HFP_AGENT_ERROR_INVALID_PARAM);
1346 dbus_g_method_return_error(context, error);
1347 g_error_free(error);
1351 DBG("Dtmf = %s \n", dtmf);
1352 DBG("Application path = %s \n", path);
1353 DBG("Sender = %s\n", sender);
1355 ret = __bt_hfp_agent_dbus_method_send(sender,
1356 path, TELEPHONY_APP_INTERFACE,
1358 DBUS_TYPE_STRING, &dtmf,
1361 if (ret != BT_HFP_AGENT_ERROR_NONE) {
1362 error = __bt_hfp_agent_set_error(ret);
1363 dbus_g_method_return_error(context, error);
1364 g_error_free(error);
1368 /*App Selector code here needed*/
1369 dbus_g_method_return(context);
1375 static void __bt_hfp_agent_launch_voice_dial(gboolean activate)
1377 service_h service = NULL;
1379 service_create(&service);
1381 if (service == NULL) {
1382 DBG("Service create failed");
1386 service_set_package(service, "com.samsung.svoice");
1387 service_set_operation(service, SERVICE_OPERATION_DEFAULT);
1388 service_add_extra_data(service, "domain", "bt_headset");
1391 service_add_extra_data(service, "action_type", "deactivate");
1393 if (service_send_launch_request(service, NULL, NULL) !=
1395 DBG("launch failed");
1397 service_destroy(service);
1401 static gboolean bt_hfp_agent_voice_dial(BtHfpAgent *agent, gboolean activate,
1402 DBusGMethodInvocation *context)
1404 DBG("Activate = %d \n", activate);
1406 __bt_hfp_agent_launch_voice_dial(activate);
1407 dbus_g_method_return(context);
1413 static gboolean bt_hfp_agent_get_battery_status(BtHfpAgent *object,
1414 DBusGMethodInvocation *context)
1416 gint battery_chrg_status;
1417 gint battery_capacity;
1422 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
1423 &battery_chrg_status)) {
1424 DBG("VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW failed\n");
1428 DBG("Status : %d\n", battery_chrg_status);
1430 if (vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1431 &battery_capacity)) {
1432 DBG("VCONFKEY_SYSMAN_BATTERY_CAPACITY failed\n");
1436 DBG("Capacity : %d\n", battery_capacity);
1438 dbus_g_method_return(context, battery_chrg_status, battery_capacity);
1443 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_BATTERY_STATUS);
1444 dbus_g_method_return_error(context, error);
1445 g_error_free(error);
1450 static gboolean bt_hfp_agent_get_signal_quality(BtHfpAgent *object,
1451 DBusGMethodInvocation *context)
1458 if (vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &rssi)) {
1459 DBG("VCONFKEY_TELEPHONY_RSSI failed\n");
1463 DBG("RSSI : %d \n", rssi);
1465 dbus_g_method_return(context, rssi, BT_SIGNAL_QUALITY_BER);
1469 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_SIGNAL_STATUS);
1470 dbus_g_method_return_error(context, error);
1471 g_error_free(error);
1476 static gboolean bt_hfp_agent_get_operator_name(BtHfpAgent *object,
1477 DBusGMethodInvocation *context)
1479 char *operator_name;
1484 operator_name = vconf_get_str(VCONFKEY_TELEPHONY_NWNAME);
1485 if (NULL == operator_name) {
1486 DBG("vconf_get_str failed \n");
1487 error = __bt_hfp_agent_set_error(BT_HFP_AGENT_ERROR_INTERNAL);
1488 dbus_g_method_return_error(context, error);
1489 g_error_free(error);
1493 DBG("operator_name = [%s] \n", operator_name);
1495 dbus_g_method_return(context, operator_name);
1496 free(operator_name);
1502 static gboolean bt_hfp_agent_nrec_status(BtHfpAgent *agent, gboolean status,
1503 DBusGMethodInvocation *context)
1505 DBusMessage *signal;
1509 DBG("NREC status = %d \n", status);
1510 nrec_status = status;
1511 dbus_g_method_return(context);
1513 /*Emit NREC Status change signal with value*/
1514 signal = dbus_message_new_signal(BT_HFP_AGENT_OBJECT,
1515 BT_HFP_AGENT_INTERFACE,
1516 "NrecStatusChanged");
1520 if (!dbus_message_append_args(signal,
1521 DBUS_TYPE_BOOLEAN, &status,
1522 DBUS_TYPE_INVALID)) {
1523 DBG("Signal appending failed\n");
1524 dbus_message_unref(signal);
1528 dbus_connection_send(gconn, signal, NULL);
1529 dbus_message_unref(signal);
1534 static void __bt_hfp_agent_append_variant(DBusMessageIter *iter,
1535 int type, void *val)
1537 DBusMessageIter value_iter;
1538 const char *variant;
1541 case DBUS_TYPE_BOOLEAN:
1542 variant = DBUS_TYPE_BOOLEAN_AS_STRING;
1544 case DBUS_TYPE_STRING:
1545 variant = DBUS_TYPE_STRING_AS_STRING;
1547 case DBUS_TYPE_BYTE:
1548 variant = DBUS_TYPE_BYTE_AS_STRING;
1550 case DBUS_TYPE_UINT16:
1551 variant = DBUS_TYPE_UINT16_AS_STRING;
1553 case DBUS_TYPE_UINT32:
1554 variant = DBUS_TYPE_UINT32_AS_STRING;
1556 case DBUS_TYPE_INT16:
1557 variant = DBUS_TYPE_INT16_AS_STRING;
1559 case DBUS_TYPE_INT32:
1560 variant = DBUS_TYPE_INT32_AS_STRING;
1562 case DBUS_TYPE_OBJECT_PATH:
1563 variant = DBUS_TYPE_OBJECT_PATH_AS_STRING;
1566 variant = DBUS_TYPE_VARIANT_AS_STRING;
1570 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, variant,
1572 dbus_message_iter_append_basic(&value_iter, type, val);
1573 dbus_message_iter_close_container(iter, &value_iter);
1576 static gboolean __bt_hfp_agent_dbus_method_variant_send(const char *path,
1577 const char *interface, const char *method, const char *name,
1578 int type, void *value)
1583 DBusMessageIter iter;
1587 msg = dbus_message_new_method_call(BLUEZ_SERVICE_NAME,
1588 path, interface, method);
1591 DBG("Unable to allocate new D-Bus %s message", method);
1595 dbus_message_iter_init_append(msg, &iter);
1597 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
1599 __bt_hfp_agent_append_variant(&iter, type, value);
1601 dbus_error_init(&err);
1603 reply = dbus_connection_send_with_reply_and_block(gconn,
1606 dbus_message_unref(msg);
1609 DBG("Error returned in method call\n");
1610 if (dbus_error_is_set(&err)) {
1611 if (err.message != NULL) {
1612 DBG("Error message = %s\n", err.message);
1614 dbus_error_free(&err);
1619 dbus_message_unref(reply);
1625 static gboolean __bt_hfp_agent_send_registration_status_changed(
1626 bt_hfp_agent_network_registration_status_t status)
1628 const char *property = g_strdup("RegistrationChanged");
1632 if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1633 TELEPHONY_CSD_INTERFACE,
1634 BT_HFP_AGENT_SET_PROPERTY,
1635 property, DBUS_TYPE_BYTE, &status)) {
1636 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1637 g_free((void *)property);
1642 g_free((void *)property);
1646 static gboolean __bt_hfp_agent_send_subscriber_number_changed(
1649 const char *property = g_strdup("SubscriberNumberChanged");
1653 if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1654 TELEPHONY_CSD_INTERFACE,
1655 BT_HFP_AGENT_SET_PROPERTY,
1657 DBUS_TYPE_STRING, &number)) {
1658 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1659 g_free((void *)property);
1664 g_free((void *)property);
1668 static gboolean __bt_hfp_agent_send_signal_bar_changed(int signal_bar)
1670 const char *property = g_strdup("SignalBarsChanged");
1674 if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1675 TELEPHONY_CSD_INTERFACE,
1676 BT_HFP_AGENT_SET_PROPERTY,
1677 property, DBUS_TYPE_INT32, &signal_bar)) {
1678 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1679 g_free((void *)property);
1683 g_free((void *)property);
1688 static gboolean __bt_hfp_agent_send_battery_level_changed(int battery_level)
1690 const char *property = g_strdup("BatteryBarsChanged");
1695 /* We need to send battery status ranging from 0-5 */
1696 if (battery_level < 5)
1698 else if (battery_level >= 100)
1701 battery_status = battery_level / 20 + 1;
1703 if (!__bt_hfp_agent_dbus_method_variant_send(TELEPHONY_CSD_OBJECT_PATH,
1704 TELEPHONY_CSD_INTERFACE,
1705 BT_HFP_AGENT_SET_PROPERTY,
1707 DBUS_TYPE_INT32, &battery_status)) {
1708 DBG("__bt_hfp_agent_dbus_method_variant_send - ERROR\n");
1709 g_free((void *)property);
1714 g_free((void *)property);
1718 static void __bt_hfp_agent_send_battery_level(void)
1725 ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &batt);
1727 DBG("vconf_get_int failed err = %d \n", ret);
1731 DBG("Current battery Level = [%d] \n", batt);
1733 __bt_hfp_agent_send_battery_level_changed(batt);
1738 static void __bt_hfp_agent_send_signal_status(void)
1745 ret = vconf_get_int(VCONFKEY_TELEPHONY_RSSI, &signal_level);
1747 DBG("vconf_get_int failed err = %d \n", ret);
1751 DBG("Current Signal Level = [%d] \n", signal_level);
1753 __bt_hfp_agent_send_signal_bar_changed(signal_level);
1758 static void __bt_hfp_agent_network_send( int service, int roam_status)
1761 bt_hfp_agent_network_registration_status_t network_service;
1766 case VCONFKEY_TELEPHONY_SVCTYPE_NONE:
1767 case VCONFKEY_TELEPHONY_SVCTYPE_NOSVC:
1768 case VCONFKEY_TELEPHONY_SVCTYPE_SEARCH:
1776 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1778 DBG("Get roaming status failed err = %d\n", ret);
1782 if (roam_status == 0 && service == 1)
1783 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_HOME;
1784 else if (roam_status == 1 && service == 1)
1785 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_ROAMING;
1787 network_service = BT_HFP_AGENT_NETWORK_REG_STATUS_UNKOWN;
1789 DBG("Network service = %d\n", network_service);
1791 __bt_hfp_agent_send_registration_status_changed(network_service);
1796 static void __bt_hfp_agent_send_network_status(void)
1805 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1807 DBG("vconf_get_int failed for \n");
1811 DBG("roam_status = [%d] \n", roam_status);
1813 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVCTYPE, &service);
1815 DBG("vconf_get_int failed\n");
1819 DBG("service = [%d] \n", service);
1821 __bt_hfp_agent_network_send(service, roam_status);
1826 static void __bt_hfp_agent_send_vconf_values(void)
1828 __bt_hfp_agent_send_battery_level();
1829 __bt_hfp_agent_send_signal_status();
1830 __bt_hfp_agent_send_network_status();
1833 static void __bt_hfp_agent_battery_status_cb(keynode_t *node)
1835 int batt = vconf_keynode_get_int(node);
1839 DBG("Current Battery Level = [%d] \n", batt);
1841 __bt_hfp_agent_send_battery_level_changed(batt);
1846 static void __bt_hfp_agent_network_signal_status_cb(keynode_t *node)
1848 int signal_bar = vconf_keynode_get_int(node);
1852 DBG("Current Signal Level = [%d] \n", signal_bar);
1854 __bt_hfp_agent_send_signal_bar_changed(signal_bar);
1859 static void __bt_hfp_agent_network_register_status_cb(keynode_t *node)
1861 int service = vconf_keynode_get_int(node);
1867 DBG("Current Signal Level = [%d] \n", service);
1869 ret = vconf_get_int(VCONFKEY_TELEPHONY_SVC_ROAM, &roam_status);
1871 DBG("Get roaming status failed err = %d\n", ret);
1875 __bt_hfp_agent_network_send(service, roam_status);
1880 static void __bt_hfp_agent_subscribe_vconf_updates(void)
1886 ret = vconf_notify_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1887 (void *)__bt_hfp_agent_battery_status_cb, NULL);
1889 DBG("Subsrciption to battery status failed err = [%d]\n", ret);
1892 ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_RSSI,
1893 (void *)__bt_hfp_agent_network_signal_status_cb, NULL);
1895 DBG("Subsrciption to netowrk signal failed err = [%d]\n", ret);
1898 ret = vconf_notify_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
1899 (void *)__bt_hfp_agent_network_register_status_cb, NULL);
1901 DBG("Subsrciption to network failed err = [%d]\n", ret);
1907 static void __bt_hfp_agent_release_vconf_updates(void)
1913 ret = vconf_ignore_key_changed(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
1914 (vconf_callback_fn)__bt_hfp_agent_battery_status_cb);
1916 DBG("vconf_ignore_key_changed failed\n");
1919 ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_RSSI,
1920 (vconf_callback_fn)__bt_hfp_agent_network_signal_status_cb);
1922 DBG("vconf_ignore_key_changed failed\n");
1925 ret = vconf_ignore_key_changed(VCONFKEY_TELEPHONY_SVCTYPE,
1926 (vconf_callback_fn)__bt_hfp_agent_network_register_status_cb);
1928 DBG("vconf_ignore_key_changed failed\n");
1934 static void __bt_hfp_agent_dbus_init(BtHfpAgent *agent)
1936 GError *error = NULL;
1937 DBusGProxy *bus_proxy = NULL;
1940 g_connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
1941 if (error != NULL) {
1942 ERR("Failed connection to system bus[%s] \n", error->message);
1943 g_error_free(error);
1947 bus_proxy = dbus_g_proxy_new_for_name(g_connection,
1949 DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
1950 if (bus_proxy == NULL) {
1951 ERR("Failed to get a proxy for D-Bus\n");
1955 if (!dbus_g_proxy_call(bus_proxy, "RequestName", &error, G_TYPE_STRING,
1956 BT_HFP_SERVICE, G_TYPE_UINT, 0, G_TYPE_INVALID,
1957 G_TYPE_UINT, &result, G_TYPE_INVALID)) {
1958 if (error != NULL) {
1959 ERR("RequestName RPC failed[%s]\n", error->message);
1960 g_error_free(error);
1963 g_object_unref(bus_proxy);
1967 DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
1968 if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1969 ERR("Failed to get the primary well-known name.\n");
1970 g_object_unref(bus_proxy);
1974 g_object_unref(bus_proxy);
1976 dbus_g_connection_register_g_object(g_connection,
1977 BT_HFP_SERVICE_OBJECT_PATH, G_OBJECT(agent));
1979 gconn = dbus_g_connection_get_connection(g_connection);
1980 if (gconn == NULL) {
1981 ERR("Failed to get connection \n");
1985 __bt_hfp_agent_send_vconf_values();
1986 __bt_hfp_agent_subscribe_vconf_updates();
1989 static void __bt_hfp_agent_tel_cb(TapiHandle *handle,
1994 TelSimMsisdnList_t *number;
1995 gchar *subscriber_number;
2000 number = (TelSimMsisdnList_t *)data;
2001 subscriber_number = g_strdup(number->list[0].num);
2002 __bt_hfp_agent_send_subscriber_number_changed(subscriber_number);
2003 g_free(subscriber_number);
2006 static void __bt_hfp_agent_sigterm_handler(int signo)
2009 g_main_loop_quit(gmain_loop);
2011 DBG("Terminating HFP agent");
2019 BtHfpAgent *bt_hfp_obj = NULL;
2020 struct sigaction sa;
2023 DBG("Starting Bluetooth HFP agent");
2027 memset(&sa, 0, sizeof(sa));
2028 sa.sa_flags = SA_NOCLDSTOP;
2029 sa.sa_handler = __bt_hfp_agent_sigterm_handler;
2030 sigaction(SIGTERM, &sa, NULL);
2031 sigaction(SIGINT, &sa, NULL);
2033 gmain_loop = g_main_loop_new(NULL, FALSE);
2035 if (gmain_loop == NULL) {
2036 ERR("GMainLoop create failed \n");
2037 return EXIT_FAILURE;
2040 bt_hfp_obj = g_object_new(BT_HFP_TYPE_AGENT, NULL);
2041 if (bt_hfp_obj == NULL) {
2042 ERR("Failed to create BtHfpAgent instance \n");
2044 g_main_loop_unref(gmain_loop);
2046 return EXIT_FAILURE;
2049 handle = tel_init(NULL);
2050 tapi_result = tel_get_sim_msisdn(handle, __bt_hfp_agent_tel_cb,
2053 if(tapi_result != TAPI_API_SUCCESS)
2054 ERR("Fail to get sim info: %d", tapi_result);
2056 __bt_hfp_agent_dbus_init(bt_hfp_obj);
2058 g_main_loop_run(gmain_loop);
2062 __bt_hfp_agent_release_vconf_updates();
2065 dbus_g_connection_unregister_g_object(g_connection,
2066 G_OBJECT(bt_hfp_obj));
2067 g_object_unref(bt_hfp_obj);
2071 dbus_g_connection_unref(g_connection);
2074 g_main_loop_unref(gmain_loop);
2076 DBG("Terminating Bluetooth HFP agent");