summaryrefslogtreecommitdiffstats
path: root/binding/telephony-binding.c
diff options
context:
space:
mode:
Diffstat (limited to 'binding/telephony-binding.c')
-rw-r--r--binding/telephony-binding.c188
1 files changed, 165 insertions, 23 deletions
diff --git a/binding/telephony-binding.c b/binding/telephony-binding.c
index 10c00fc..9e47c76 100644
--- a/binding/telephony-binding.c
+++ b/binding/telephony-binding.c
@@ -30,15 +30,25 @@
#define OFONO_MODEM_INTERFACE "org.ofono.Modem"
static OrgOfonoVoiceCallManager *vcm;
-static OrgOfonoVoiceCall *incoming_call, *voice_call;
+static OrgOfonoVoiceCall *incoming_call;
static afb_event_t call_state_changed_event;
static afb_event_t dialing_call_event;
static afb_event_t incoming_call_event;
+static afb_event_t waiting_call_event;
static afb_event_t terminated_call_event;
static afb_event_t online_event;
static afb_event_t battery_event;
static afb_event_t signal_event;
+static GList *voice_calls = NULL;
+
+static void remover(gpointer data, gchar *path) {
+ if (!g_strcmp0(path, g_dbus_proxy_get_object_path(G_DBUS_PROXY((OrgOfonoVoiceCall*)data)))) {
+ ofono_voicecall_free((OrgOfonoVoiceCall*)data);
+ voice_calls = g_list_remove(voice_calls, (gconstpointer)data);
+ }
+}
+
static void dial(afb_req_t request)
{
struct json_object *query, *val;
@@ -48,7 +58,7 @@ static void dial(afb_req_t request)
json_object_object_get_ex(query, "value", &val);
if (json_object_is_type(val, json_type_string)) {
number = json_object_get_string(val);
- if (voice_call) {
+ if (voice_calls) {
AFB_ERROR("dial: cannot dial with active call");
afb_req_fail(request, "active call", NULL);
} else {
@@ -68,7 +78,7 @@ static void dial(afb_req_t request)
static void last_dial(afb_req_t request)
{
- if (voice_call) {
+ if (voice_calls) {
AFB_ERROR("dial: cannot dial with active call");
afb_req_fail(request, "active call", NULL);
} else {
@@ -85,7 +95,7 @@ static void send_tones(afb_req_t request)
{
const char *value = afb_req_value(request, "value");
- if (!voice_call) {
+ if (!voice_calls) {
AFB_ERROR("send_tones: cannot send tone without active call");
afb_req_fail(request, "there is no active call", NULL);
} else {
@@ -98,19 +108,43 @@ static void send_tones(afb_req_t request)
}
}
-static void hangup(afb_req_t request)
+static void hangup_all (afb_req_t request)
{
- if (voice_call) {
- AFB_DEBUG("Hangup voice call\n");
- ofono_voicecall_hangup(voice_call);
- afb_req_success(request, NULL, NULL);
- } else if (incoming_call) {
- AFB_DEBUG("Reject incoming call\n");
- ofono_voicecall_hangup(incoming_call);
- afb_req_success(request, NULL, NULL);
+ if (!voice_calls) {
+ AFB_ERROR("hangup_all: cannot hang up without active call");
+ afb_req_fail(request, "there is no active call", NULL);
} else {
+ ofono_voicecallmanager_hangup_all(vcm);
+ afb_req_success(request, NULL, NULL);
+ }
+}
+
+static void hangup(afb_req_t request)
+{
+ const char* value = afb_req_value(request, "id");
+ const gchar *modem = ofono_manager_get_default_modem_path();
+ gchar *op = g_strconcat(modem, "/" , value, NULL);
+ if (g_list_length(voice_calls) > 0) {
+ GList *list;
+ for (list = voice_calls; list != NULL; list = list->next)
+ {
+ if (!g_strcmp0(op, g_dbus_proxy_get_object_path(G_DBUS_PROXY((OrgOfonoVoiceCall*)list->data)))) {
+ AFB_ERROR("object path = %s", g_dbus_proxy_get_object_path(G_DBUS_PROXY((OrgOfonoVoiceCall*)list->data)));
+ ofono_voicecall_hangup((OrgOfonoVoiceCall*)list->data);
+ afb_req_success(request, NULL, NULL);
+ g_free(op);
+ return;
+ }
+ }
+ AFB_ERROR("Hangup: Invalid ID");
+ afb_req_fail(request, "Invalid ID", NULL);
+ g_free(op);
+ return;
+ }
+ else {
AFB_ERROR("Hangup: no active call");
afb_req_fail(request, "failed hangup", NULL);
+ return;
}
}
@@ -118,13 +152,86 @@ static void answer(afb_req_t request)
{
if (incoming_call) {
AFB_DEBUG("Answer voice call\n");
- voice_call = incoming_call;
- ofono_voicecall_answer(voice_call);
+ voice_calls = g_list_append(voice_calls, (gpointer)incoming_call);
+ ofono_voicecall_answer(incoming_call);
+ ofono_voicecall_free(incoming_call);
+ incoming_call = NULL;
} else {
AFB_ERROR("Answer: no incoming call");
}
}
+static void hangup_multiparty(afb_req_t request)
+{
+ if (g_list_length(voice_calls) < 2) {
+ afb_req_fail(request, "failed hangup multiparty", NULL);
+ } else {
+ ofono_voicecallmanager_hangup_multiparty(vcm);
+ afb_req_success(request, NULL, NULL);
+ }
+}
+
+static void create_multiparty(afb_req_t request)
+{
+ gchar **reply = NULL;
+ if (g_list_length(voice_calls) > 1) {
+ reply = ofono_voicecallmanager_create_multiparty(vcm);
+ if (reply)
+ afb_req_success(request, NULL, NULL);
+ else
+ afb_req_fail(request, "failed create multiparty", NULL);
+ }
+ else {
+ AFB_ERROR("Create MultiParty: It should be greater than 1 active call");
+ afb_req_fail(request, "failed create multiparty", NULL);
+ }
+}
+
+static void hold_and_answer(afb_req_t request)
+{
+ if (g_list_length(voice_calls) > 1) {
+ if (ofono_voicecallmanager_hold_and_answer(vcm)) {
+ afb_req_success(request, NULL, NULL);
+ } else {
+ AFB_ERROR("hold_and_answer: failed");
+ afb_req_fail(request, "failed hold and answer", NULL);
+ }
+ } else {
+ AFB_ERROR("hold_and_answer: cannot hold and answer without waiting call");
+ afb_req_fail(request, "no waiting call", NULL);
+ }
+}
+
+static void release_and_answer(afb_req_t request)
+{
+ if (g_list_length(voice_calls) > 1) {
+ if (ofono_voicecallmanager_release_and_answer(vcm)) {
+ afb_req_success(request, NULL, NULL);
+ } else {
+ AFB_ERROR("release_and_answer: failed to release and answer\n");
+ afb_req_fail(request, "failed release and answer", NULL);
+ }
+ } else {
+ AFB_ERROR("release_and_answer: cannot release and answer without waiting call");
+ afb_req_fail(request, "does not exist waiting call", NULL);
+ }
+}
+
+static void swap_calls(afb_req_t request)
+{
+ if (g_list_length(voice_calls) > 1) {
+ if (ofono_voicecallmanager_swap_calls(vcm)) {
+ afb_req_success(request, NULL, NULL);
+ } else {
+ AFB_ERROR("dial: failed to swap calls\n");
+ afb_req_fail(request, "failed swap_calls", NULL);
+ }
+ } else {
+ AFB_ERROR("swap: there is no waiting call");
+ afb_req_fail(request, "swap calls", NULL);
+ }
+}
+
static void get_battery_level(afb_req_t request)
{
const gchar *device;
@@ -171,6 +278,8 @@ static void subscribe(afb_req_t request)
afb_req_subscribe(request, dialing_call_event);
} else if (!strcasecmp(value, "incomingCall")) {
afb_req_subscribe(request, incoming_call_event);
+ } else if (!strcasecmp(value, "waitingCall")) {
+ afb_req_subscribe(request, waiting_call_event);
} else if (!strcasecmp(value, "terminatedCall")) {
afb_req_subscribe(request, terminated_call_event);
} else if (!strcasecmp(value, "battery")) {
@@ -204,6 +313,8 @@ static void unsubscribe(afb_req_t request)
afb_req_unsubscribe(request, dialing_call_event);
} else if (!strcasecmp(value, "incomingCall")) {
afb_req_unsubscribe(request, incoming_call_event);
+ } else if (!strcasecmp(value, "waitingCall")) {
+ afb_req_unsubscribe(request, waiting_call_event);
} else if (!strcasecmp(value, "terminatedCall")) {
afb_req_unsubscribe(request, terminated_call_event);
} else {
@@ -231,6 +342,7 @@ static void incoming_call_cb(OrgOfonoVoiceCallManager *manager, gchar *op, gchar
json_object_object_add(call_info, "clip", json_object_new_string(clip));
afb_event_push(incoming_call_event, call_info);
incoming_call = ofono_voicecall_new(op, call_state_changed_cb);
+ voice_calls = g_list_append(voice_calls, (gpointer)incoming_call);
}
static void dialing_call_cb(OrgOfonoVoiceCallManager *manager, gchar *op, gchar *colp)
@@ -240,18 +352,22 @@ static void dialing_call_cb(OrgOfonoVoiceCallManager *manager, gchar *op, gchar
call_info = json_object_new_object();
json_object_object_add(call_info, "colp", json_object_new_string(colp));
afb_event_push(dialing_call_event, call_info);
- voice_call = ofono_voicecall_new(op, call_state_changed_cb);
+ voice_calls = g_list_append(voice_calls, (gpointer)ofono_voicecall_new(op, call_state_changed_cb));
+}
+
+static void waiting_call_cb(OrgOfonoVoiceCallManager *manager, gchar *op, gchar *colp)
+{
+ struct json_object *call_info;
+ call_info = json_object_new_object();
+ json_object_object_add(call_info, "colp", json_object_new_string(colp));
+ afb_event_push(waiting_call_event, call_info);
+ voice_calls = g_list_append(voice_calls, (gpointer)ofono_voicecall_new(op, call_state_changed_cb));
}
static void terminated_call_cb(OrgOfonoVoiceCallManager *manager, gchar *op)
{
- if (incoming_call) {
- ofono_voicecall_free(incoming_call);
- incoming_call = NULL;
- } else if (voice_call) {
- ofono_voicecall_free(voice_call);
- }
- voice_call = NULL;
+ if (g_list_length(voice_calls) > 0)
+ g_list_foreach(voice_calls, (GFunc)remover, op);
afb_event_push(terminated_call_event, NULL);
}
@@ -271,6 +387,7 @@ static int ofono_init_default_modem(void)
vcm = ofono_voicecallmanager_init(modem_path,
incoming_call_cb,
dialing_call_cb,
+ waiting_call_cb,
terminated_call_cb);
if (!vcm) {
AFB_ERROR("failed to initialize voice call manager\n");
@@ -455,6 +572,7 @@ static int ofono_init(afb_api_t api)
call_state_changed_event = afb_daemon_make_event("callStateChanged");
dialing_call_event = afb_daemon_make_event("dialingCall");
incoming_call_event = afb_daemon_make_event("incomingCall");
+ waiting_call_event = afb_daemon_make_event("waitingCall");
terminated_call_event = afb_daemon_make_event("terminatedCall");
online_event = afb_daemon_make_event("online");
battery_event = afb_daemon_make_event("battery");
@@ -492,10 +610,34 @@ static const afb_verb_t verbs[]= {
.callback = hangup,
},
{
+ .verb = "hangup_all",
+ .callback = hangup_all,
+ },
+ {
.verb = "answer",
.callback = answer,
},
{
+ .verb = "hangup_multiparty",
+ .callback = hangup_multiparty,
+ },
+ {
+ .verb = "create_multiparty",
+ .callback = create_multiparty,
+ },
+ {
+ .verb = "swap_calls",
+ .callback = swap_calls,
+ },
+ {
+ .verb = "hold_and_answer",
+ .callback = hold_and_answer,
+ },
+ {
+ .verb = "release_and_answer",
+ .callback = release_and_answer,
+ },
+ {
.verb = "get_battery_level",
.callback = get_battery_level,
},