summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/hfpmodem/voicecall.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/hfpmodem/voicecall.c b/drivers/hfpmodem/voicecall.c
index b619dc0d..96de1cc7 100644
--- a/drivers/hfpmodem/voicecall.c
+++ b/drivers/hfpmodem/voicecall.c
@@ -39,6 +39,8 @@
#include "hfpmodem.h"
+#define POLL_CLCC_INTERVAL 2000
+
static const char *none_prefix[] = { NULL };
static const char *clcc_prefix[] = { "+CLCC:", NULL };
@@ -50,6 +52,7 @@ struct voicecall_data {
unsigned char cind_pos[HFP_INDICATOR_LAST];
int cind_val[HFP_INDICATOR_LAST];
unsigned int local_release;
+ unsigned int clcc_source;
};
struct release_id_req {
@@ -66,6 +69,8 @@ struct change_state_req {
int affected_types;
};
+static gboolean poll_clcc(gpointer user_data);
+
static GSList *find_dialing(GSList *calls)
{
GSList *c;
@@ -197,6 +202,8 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
GSList *calls;
GSList *n, *o;
struct ofono_call *nc, *oc;
+ unsigned int num_active = 0;
+ unsigned int num_held = 0;
dump_response("clcc_poll_cb", ok, result);
@@ -212,6 +219,12 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
nc = n ? n->data : NULL;
oc = o ? o->data : NULL;
+ if (nc && (nc->status == CALL_STATUS_ACTIVE))
+ num_active++;
+
+ if (nc && (nc->status == CALL_STATUS_HELD))
+ num_held++;
+
if (oc && (!nc || (nc->id > oc->id))) {
enum ofono_disconnect_reason reason;
@@ -255,6 +268,27 @@ static void clcc_poll_cb(gboolean ok, GAtResult *result, gpointer user_data)
g_slist_free(vd->calls);
vd->calls = calls;
+
+ /* If either active/held call is more than 1, we are in mpty calls.
+ * we won't get indicator update if any of them is released by CHLD=1x.
+ * So we have to poll it.
+ */
+ if (num_active > 1 || num_held > 1)
+ vd->clcc_source = g_timeout_add(POLL_CLCC_INTERVAL, poll_clcc,
+ vc);
+}
+
+static gboolean poll_clcc(gpointer user_data)
+{
+ struct ofono_voicecall *vc = user_data;
+ struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+
+ g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
+ clcc_poll_cb, vc, NULL);
+
+ vd->clcc_source = 0;
+
+ return FALSE;
}
static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -1089,6 +1123,9 @@ static void hfp_voicecall_remove(struct ofono_voicecall *vc)
{
struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+ if (vd->clcc_source)
+ g_source_remove(vd->clcc_source);
+
g_slist_foreach(vd->calls, (GFunc) g_free, NULL);
g_slist_free(vd->calls);