summaryrefslogtreecommitdiffstats
path: root/binding/telephony-binding.c
diff options
context:
space:
mode:
authorsaman <mahmoudi.saman1@gmail.com>2021-02-07 15:01:20 +0330
committerSaman Mahmoodi <mahmoudi.saman1@gmail.com>2021-03-13 15:00:29 +0330
commit8987ae42114a8b15522734e40d117fd061e7bf3b (patch)
tree78ceae43519a246d5f5f559572116fc9da833271 /binding/telephony-binding.c
parent4739f747c8fbdeda94a400122651862cfdb522b7 (diff)
Add call waiting/hold featureslamprey_11.91.0lamprey/11.91.011.91.0
I have developed most features that needed for handling waiting call response and hold call response. Also I have changed hangup verb due to have multiple active call. The changes are including getting argument for hangup specific call. For correctly working this feature you should subscribe waitingCall event as in README.md. Signed-off-by: saman <mahmoudi.saman1@gmail.com> Change-Id: I84c601ddd6f27d8d8e7b6d8c338ea04a48240447
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,
},