summaryrefslogtreecommitdiffstats
path: root/drivers/hfpmodem/voicecall.c
diff options
context:
space:
mode:
authorZhenhua Zhang <zhenhua.zhang@intel.com>2009-12-09 08:59:13 +0800
committerDenis Kenzior <denkenz@gmail.com>2009-12-09 02:37:02 -0600
commitc7902b83e6708a08feb8ce730d5ce043455ad87c (patch)
tree2f2a6f4f89e4ca2aad49b61de15149d720230e85 /drivers/hfpmodem/voicecall.c
parent7f9e4038a2a76310c53396003e45107c8c476ec5 (diff)
downloadofono-c7902b83e6708a08feb8ce730d5ce043455ad87c.tar.bz2
Add poll_clcc if we are in multiparty call
If we are in multiparty call, remote AG won't update indicator if any call in multiparty call is released by CHLD=1x. So we have to poll it periodically.
Diffstat (limited to 'drivers/hfpmodem/voicecall.c')
-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);