All of lore.kernel.org
 help / color / mirror / Atom feed
* RE: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
       [not found] <1257545952-2776-1-git-send-email-zhenhua.zhang@intel.com>
@ 2009-11-09  1:03 ` Zhang, Zhenhua
  0 siblings, 0 replies; 7+ messages in thread
From: Zhang, Zhenhua @ 2009-11-09  1:03 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 254 bytes --]

Hi,

Please ignore the mails I just sent today. It seems git-send-email cached my mail threads locally
and still try to resend them when I come back to the office.

The mail contents are exactly the same as I sent last week.

Regards,
Zhenhua


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
  2009-11-11 22:23 ` Denis Kenzior
  2009-11-12  2:34   ` Zhang, Zhenhua
@ 2009-11-12  9:25   ` Zhang, Zhenhua
  1 sibling, 0 replies; 7+ messages in thread
From: Zhang, Zhenhua @ 2009-11-12  9:25 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 688 bytes --]

Hi Denis,

Denis Kenzior wrote:
> Hi Zhenhua,
> 
>> +	ofono_voicecall_notify(vc, call);
>> +
> 
> As I mentioned above, you do not need to do this.  oFono will
> synthesize the outgoing call properly.  Worst case we will
> send a PropertyChanged signal after CLCC is polled and the new number
> is obtained. 

I recreate the patch to use the way you mentioned. We notify the voicecall
to core after CLCC is polled. Instead of notify it in atd_cb. The comments
in patch is also updated.

> Regards,
> -Denis
> _______________________________________________
> ofono mailing list
> ofono(a)ofono.org
> http://lists.ofono.org/listinfo/ofono



Regards,
Zhenhua


[-- Attachment #2: 0001-Fix-Fill-in-the-phone-number-info-for-outgoing-call.patch --]
[-- Type: application/octet-stream, Size: 5243 bytes --]

From f5eac114fb03851ac02ee71641e11e3153614521 Mon Sep 17 00:00:00 2001
From: Zhenhua Zhang <zhenhua.zhang@intel.com>
Date: Fri, 13 Nov 2009 00:52:08 +0800
Subject: [PATCH] Fix: Fill in the phone number info for outgoing call

There're two cases of outgoing call: dial from HF or dial from
phone. We could receive callsetup=2 indicator in both case. So
adding AT+CLCC query to sync the outgoing call.

In the first case, we only need to sync the phone number.  In
the second case, the phone is dialing from phone and we know
nothing. Create a new call and notify the core.

If phone does not support AT+CLCC and there's no call dialing
from HF, we fake a new call for it.
---
 drivers/hfpmodem/voicecall.c |  134 ++++++++++++++++++++++++++++++++---------
 1 files changed, 104 insertions(+), 30 deletions(-)

diff --git a/drivers/hfpmodem/voicecall.c b/drivers/hfpmodem/voicecall.c
index 9ba72e4..2ba53de 100644
--- a/drivers/hfpmodem/voicecall.c
+++ b/drivers/hfpmodem/voicecall.c
@@ -49,6 +49,7 @@
 
 static const char *none_prefix[] = { NULL };
 static const char *chld_prefix[] = { "+CHLD:", NULL };
+static const char *clcc_prefix[] = { "+CLCC:", NULL };
 
 struct voicecall_data {
 	GAtChat *chat;
@@ -108,6 +109,20 @@ static struct ofono_call *create_call(struct voicecall_data *d, int type,
 	return call;
 }
 
+static struct ofono_call *new_call_notify(struct ofono_voicecall *vc, int type,
+					int direction, int status,
+					const char *num, int num_type, int clip)
+{
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_call *c;
+
+	c = create_call(vd, type, direction, status, num, num_type, clip);
+
+	ofono_voicecall_notify(vc, c);
+
+	return c;
+}
+
 static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct change_state_req *req = user_data;
@@ -351,23 +366,70 @@ static void ciev_call_notify(struct ofono_voicecall *vc,
 {
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			release_call(vc, call);
-			break;
-		case 1:
-			call->status = CALL_STATUS_ACTIVE;
-			ofono_voicecall_notify(vc, call);
-			break;
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		release_call(vc, call);
+		break;
+	case 1:
+		call->status = CALL_STATUS_ACTIVE;
+		ofono_voicecall_notify(vc, call);
+		break;
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALL] = value;
 }
 
+static void sync_dialing_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_voicecall *vc = user_data;
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_error error;
+	GSList *calls = NULL;
+	GSList *l = NULL;
+	struct ofono_call *nc = NULL;
+	struct ofono_call *oc = vd->call;
+
+	dump_response("sync_dialing_cb", ok, result);
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok)
+		return;
+
+	calls = at_util_parse_clcc(result);
+
+	if (calls == NULL)
+		return;
+
+	while (calls) {
+		nc = calls->data;
+
+		if (vd->calls)
+			l = g_slist_find_custom(vd->calls, nc,
+						at_util_call_compare);
+
+		if (l) {
+			oc = l->data;
+
+			if (memcmp(nc, oc, sizeof(struct ofono_call))) {
+				ofono_voicecall_notify(vc, nc);
+
+				memcpy(oc, nc, sizeof(struct ofono_call));
+			}
+		} else
+			new_call_notify(vc, nc->type, nc->direction, nc->status,
+						nc->phone_number.number,
+						nc->phone_number.type,
+						nc->clip_validity);
+
+		calls = calls->next;
+	}
+
+	g_slist_foreach(calls, (GFunc) g_free, NULL);
+	g_slist_free(calls);
+}
+
 static void ciev_callsetup_notify(struct ofono_voicecall *vc,
 					struct ofono_call *call,
 					unsigned int value)
@@ -376,24 +438,36 @@ static void ciev_callsetup_notify(struct ofono_voicecall *vc,
 	unsigned int ciev_callsetup = vd->cind_val[HFP_INDICATOR_CALLSETUP];
 	unsigned int ciev_call = vd->cind_val[HFP_INDICATOR_CALL];
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			/* call=0 and callsetup=1: reject an incoming call
-			 * call=0 and callsetup=2,3: interrupt an outgoing call
-			 */
-			if (ciev_call == 0 && ciev_callsetup > 0)
-				release_call(vc, call);
-			break;
-		case 1:
-		case 2:
-			break;
-		case 3:
-			call->status = CALL_STATUS_ALERTING;
-			ofono_voicecall_notify(vc, call);
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		/* call=0 and callsetup=1: reject an incoming call
+		 * call=0 and callsetup=2,3: interrupt an outgoing call
+		 */
+		if ((ciev_call == 0) && (ciev_callsetup > 0))
+			release_call(vc, call);
+		break;
+	case 1:
+		break;
+	case 2:
+		/* two cases of outgoing call: dial from HF or AG.
+		 * from HF: query and sync the phone number.
+		 * from AG: query and create call.
+		 * if phone does not support CLLC, we guess the call.
+		 */
+		if (vd->ag_features & AG_FEATURE_ENHANCED_CALL_STATUS)
+			g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
+						sync_dialing_cb,
+						vc, NULL);
+		else if (!vd->call)
+			vd->call = new_call_notify(vc, 0, 0,
+						CALL_STATUS_DIALING,
+						NULL, 128, 2);
+		break;
+	case 3:
+		call->status = CALL_STATUS_ALERTING;
+		ofono_voicecall_notify(vc, call);
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALLSETUP] = value;
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
  2009-11-11 22:23 ` Denis Kenzior
@ 2009-11-12  2:34   ` Zhang, Zhenhua
  2009-11-12  9:25   ` Zhang, Zhenhua
  1 sibling, 0 replies; 7+ messages in thread
From: Zhang, Zhenhua @ 2009-11-12  2:34 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 3001 bytes --]

Hi Denis,

Denis Kenzior wrote:
> Hi Zhenhua,
> 
>> There're two cases of outgoing call: dial from HF or dial from phone.
>> 
>> In the first case, some phones may not support enhanced call status
>> (AT+CLCC) to query outgoing number. So we need to pass struct
>> atd_cb_data to fill in the number and type. Later, we invoke
>> AT+CLCC to query phone number and overwrite ours if we are wrong.
> 
> This is actually not necessary.  The core already tracks the
> outgoing number and fills it in if the dial returns before the
> new call is notified.  This should be always the case in HFP,
> since the ATD returns before CIEV is signaled, correct?

The reason to record outgoing number is for later clcc_poll_cb in multicall
hanlding, because HFP doesn't have COLP so it don't know the outgoing
number unless we do +CLCC poll. So we need to sync it.

>> +static GSList *parse_clcc(GAtResult *result) {
>> +	GAtResultIter iter;
>> +	GSList *l = NULL;
>> +	int id, dir, status, type;
>> +	struct ofono_call *call;
>> +
>> +	g_at_result_iter_init(&iter, result);
>> +
>> +	while (g_at_result_iter_next(&iter, "+CLCC:")) {
>> +		const char *str = "";
>> +		int number_type = 129;
>> +
>> +		if (!g_at_result_iter_next_number(&iter, &id))
>> +			continue;
>> +
>> +		if (!g_at_result_iter_next_number(&iter, &dir))
>> +			continue;
>> +
>> +		if (!g_at_result_iter_next_number(&iter, &status)) +			continue;
>> +
>> +		if (!g_at_result_iter_next_number(&iter, &type)) +			continue;
>> +
>> +		if (!g_at_result_iter_skip_next(&iter))
>> +			continue;
>> +
>> +		if (g_at_result_iter_next_string(&iter, &str))
>> +			g_at_result_iter_next_number(&iter, &number_type); +
>> +		call = g_try_new0(struct ofono_call, 1);
>> +
>> +		if (!call)
>> +			break;
>> +
>> +		call->id = id;
>> +		call->direction = dir;
>> +		call->status = status;
>> +		call->type = type;
>> +		strncpy(call->phone_number.number, str,
>> +				OFONO_MAX_PHONE_NUMBER_LENGTH);
>> +		call->phone_number.type = number_type;
>> +
>> +		if (strlen(call->phone_number.number) > 0)
>> +			call->clip_validity = 0;
>> +		else
>> +			call->clip_validity = 2;
>> +
>> +		l = g_slist_insert_sorted(l, call, at_util_call_compare); +	}
>> +
>> +	return l;
>> +}
> 
> If this function is a copy from atmodem, please put it into
> atutils instead of duplicating it here.

I will send a separate patch for that.

>> +	ofono_voicecall_notify(vc, call);
>> +
> 
> As I mentioned above, you do not need to do this.  oFono will
> synthesize the outgoing call properly.  Worst case we will
> send a PropertyChanged signal after CLCC is polled and the new number
> is obtained. 
>
> Also, there's actually two separate cases here.  Ideally I'd
> like them separated into two patches.
> 
> Regards,
> -Denis
> _______________________________________________
> ofono mailing list
> ofono(a)ofono.org
> http://lists.ofono.org/listinfo/ofono



Regards,
Zhenhua


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
  2009-11-07  7:15 Zhenhua Zhang
@ 2009-11-11 22:23 ` Denis Kenzior
  2009-11-12  2:34   ` Zhang, Zhenhua
  2009-11-12  9:25   ` Zhang, Zhenhua
  0 siblings, 2 replies; 7+ messages in thread
From: Denis Kenzior @ 2009-11-11 22:23 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 2560 bytes --]

Hi Zhenhua,

> This is the latest version. Sorry for the noising from previous patches.
>
> There're two cases of outgoing call: dial from HF or dial from
> phone.
>
> In the first case, some phones may not support enhanced call status
> (AT+CLCC) to query outgoing number. So we need to pass struct
> atd_cb_data to fill in the number and type. Later, we invoke
> AT+CLCC to query phone number and overwrite ours if we are wrong.

This is actually not necessary.  The core already tracks the outgoing number 
and fills it in if the dial returns before the new call is notified.  This 
should be always the case in HFP, since the ATD returns before CIEV is 
signaled, correct?

> +static GSList *parse_clcc(GAtResult *result)
> +{
> +	GAtResultIter iter;
> +	GSList *l = NULL;
> +	int id, dir, status, type;
> +	struct ofono_call *call;
> +
> +	g_at_result_iter_init(&iter, result);
> +
> +	while (g_at_result_iter_next(&iter, "+CLCC:")) {
> +		const char *str = "";
> +		int number_type = 129;
> +
> +		if (!g_at_result_iter_next_number(&iter, &id))
> +			continue;
> +
> +		if (!g_at_result_iter_next_number(&iter, &dir))
> +			continue;
> +
> +		if (!g_at_result_iter_next_number(&iter, &status))
> +			continue;
> +
> +		if (!g_at_result_iter_next_number(&iter, &type))
> +			continue;
> +
> +		if (!g_at_result_iter_skip_next(&iter))
> +			continue;
> +
> +		if (g_at_result_iter_next_string(&iter, &str))
> +			g_at_result_iter_next_number(&iter, &number_type);
> +
> +		call = g_try_new0(struct ofono_call, 1);
> +
> +		if (!call)
> +			break;
> +
> +		call->id = id;
> +		call->direction = dir;
> +		call->status = status;
> +		call->type = type;
> +		strncpy(call->phone_number.number, str,
> +				OFONO_MAX_PHONE_NUMBER_LENGTH);
> +		call->phone_number.type = number_type;
> +
> +		if (strlen(call->phone_number.number) > 0)
> +			call->clip_validity = 0;
> +		else
> +			call->clip_validity = 2;
> +
> +		l = g_slist_insert_sorted(l, call, at_util_call_compare);
> +	}
> +
> +	return l;
> +}

If this function is a copy from atmodem, please put it into atutils instead of 
duplicating it here.

> +	ofono_voicecall_notify(vc, call);
> +

As I mentioned above, you do not need to do this.  oFono will synthesize the 
outgoing call properly.  Worst case we will send a PropertyChanged signal 
after CLCC is polled and the new number is obtained.

Also, there's actually two separate cases here.  Ideally I'd like them 
separated into two patches.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
@ 2009-11-07  7:15 Zhenhua Zhang
  2009-11-11 22:23 ` Denis Kenzior
  0 siblings, 1 reply; 7+ messages in thread
From: Zhenhua Zhang @ 2009-11-07  7:15 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 8689 bytes --]

This is the latest version. Sorry for the noising from previous patches.

There're two cases of outgoing call: dial from HF or dial from
phone.

In the first case, some phones may not support enhanced call status
(AT+CLCC) to query outgoing number. So we need to pass struct
atd_cb_data to fill in the number and type. Later, we invoke
AT+CLCC to query phone number and overwrite ours if we are wrong.

In the second case, the phone is dialing from phone and we know
nothing. So we have to query it through AT+CLCC when callsetup=2.
If phone does not support AT+CLCC, we fake a new call for it.

Update: change algorithm in sync_dialing_cb to handle multi calls
situation.
---
 drivers/hfpmodem/voicecall.c |  216
+++++++++++++++++++++++++++++++++++-------
 1 files changed, 181 insertions(+), 35 deletions(-)

diff --git a/drivers/hfpmodem/voicecall.c b/drivers/hfpmodem/voicecall.c
index 15a8b49..5104afa 100644
--- a/drivers/hfpmodem/voicecall.c
+++ b/drivers/hfpmodem/voicecall.c
@@ -49,6 +49,7 @@
 
 static const char *none_prefix[] = { NULL };
 static const char *chld_prefix[] = { "+CHLD:", NULL };
+static const char *clcc_prefix[] = { "+CLCC:", NULL };
 
 struct voicecall_data {
 	GAtChat *chat;
@@ -76,6 +77,13 @@ struct change_state_req {
 	int affected_types;
 };
 
+struct atd_cb_data {
+	void *cb;
+	void *data;
+	void *user;
+	struct ofono_phone_number ph;
+};
+
 static struct ofono_call *create_call(struct voicecall_data *d, int
type,
 					int direction, int status,
 					const char *num, int num_type, int clip)
@@ -108,6 +116,75 @@ static struct ofono_call *create_call(struct
voicecall_data *d, int type,
 	return call;
 }
 
+static struct ofono_call *new_call_notify(struct ofono_voicecall *vc,
int type,
+					int direction, int status,
+					const char *num, int num_type, int clip)
+{
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_call *c;
+
+	c = create_call(vd, type, direction, status, num, num_type, clip);
+
+	ofono_voicecall_notify(vc, c);
+
+	return c;
+}
+
+static GSList *parse_clcc(GAtResult *result)
+{
+	GAtResultIter iter;
+	GSList *l = NULL;
+	int id, dir, status, type;
+	struct ofono_call *call;
+
+	g_at_result_iter_init(&iter, result);
+
+	while (g_at_result_iter_next(&iter, "+CLCC:")) {
+		const char *str = "";
+		int number_type = 129;
+
+		if (!g_at_result_iter_next_number(&iter, &id))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &dir))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &status))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &type))
+			continue;
+
+		if (!g_at_result_iter_skip_next(&iter))
+			continue;
+
+		if (g_at_result_iter_next_string(&iter, &str))
+			g_at_result_iter_next_number(&iter, &number_type);
+
+		call = g_try_new0(struct ofono_call, 1);
+
+		if (!call)
+			break;
+
+		call->id = id;
+		call->direction = dir;
+		call->status = status;
+		call->type = type;
+		strncpy(call->phone_number.number, str,
+				OFONO_MAX_PHONE_NUMBER_LENGTH);
+		call->phone_number.type = number_type;
+
+		if (strlen(call->phone_number.number) > 0)
+			call->clip_validity = 0;
+		else
+			call->clip_validity = 2;
+
+		l = g_slist_insert_sorted(l, call, at_util_call_compare);
+	}
+
+	return l;
+}
+
 static void generic_cb(gboolean ok, GAtResult *result, gpointer
user_data)
 {
 	struct change_state_req *req = user_data;
@@ -134,12 +211,11 @@ static void generic_cb(gboolean ok, GAtResult
*result, gpointer user_data)
 
 static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
-	struct cb_data *cbd = user_data;
+	struct atd_cb_data *cbd = user_data;
 	struct ofono_voicecall *vc = cbd->user;
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
 	ofono_voicecall_cb_t cb = cbd->cb;
-	int type = 128;
-	int validity = 2;
+	struct ofono_phone_number ph = cbd->ph;
 	struct ofono_error error;
 	struct ofono_call *call;
 
@@ -150,7 +226,8 @@ static void atd_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 	if (!ok)
 		goto out;
 
-	call = create_call(vd, 0, 0, CALL_STATUS_DIALING, NULL, type,
validity);
+	call = create_call(vd, 0, 0, CALL_STATUS_DIALING,
+					ph.number, ph.type, 0);
 
 	if (!call) {
 		ofono_error("Unable to allocate call, "
@@ -158,6 +235,8 @@ static void atd_cb(gboolean ok, GAtResult *result,
gpointer user_data)
 		return;
 	}
 
+	ofono_voicecall_notify(vc, call);
+
 out:
 	cb(&error, cbd->data);
 }
@@ -168,13 +247,20 @@ static void hfp_dial(struct ofono_voicecall *vc,
 			ofono_voicecall_cb_t cb, void *data)
 {
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
-	struct cb_data *cbd = cb_data_new(cb, data);
+	struct atd_cb_data *cbd;
 	char buf[256];
 
+	cbd = g_try_new0(struct atd_cb_data, 1);
+
 	if (!cbd)
 		goto error;
 
+	cbd->cb = cb;
+	cbd->data = data;
 	cbd->user = vc;
+
+	memcpy(&cbd->ph, ph, sizeof(struct ofono_phone_number));
+
 	if (ph->type == 145)
 		sprintf(buf, "ATD+%s", ph->number);
 	else
@@ -351,23 +437,71 @@ static void ciev_call_notify(struct
ofono_voicecall *vc,
 {
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			release_call(vc, call);
-			break;
-		case 1:
-			call->status = CALL_STATUS_ACTIVE;
-			ofono_voicecall_notify(vc, call);
-			break;
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		release_call(vc, call);
+		break;
+	case 1:
+		call->status = CALL_STATUS_ACTIVE;
+		ofono_voicecall_notify(vc, call);
+		break;
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALL] = value;
 }
 
+static void sync_dialing_cb(gboolean ok, GAtResult *result, gpointer
user_data)
+{
+	struct ofono_voicecall *vc = user_data;
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_error error;
+	GSList *calls = NULL;
+	GSList *l = NULL;
+	struct ofono_call *nc = NULL;
+	struct ofono_call *oc = vd->call;
+
+	dump_response("sync_dialing_cb", ok, result);
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok)
+		return;
+
+	calls = parse_clcc(result);
+
+	if (calls == NULL)
+		return;
+
+	while (calls) {
+		nc = calls->data;
+
+		if (vd->calls)
+			l = g_slist_find_custom(vd->calls, nc,
+						at_util_call_compare);
+
+		if (l) {
+			oc = l->data;
+
+			if (memcmp(nc, oc, sizeof(struct ofono_call))) {
+				ofono_voicecall_notify(vc, nc);
+
+				memcpy(oc, nc, sizeof(struct ofono_call));
+			}
+
+		} else
+			new_call_notify(vc, nc->type, nc->direction, nc->status,
+						nc->phone_number.number,
+						nc->phone_number.type,
+						nc->clip_validity);
+
+		calls = calls->next;
+	}
+
+	g_slist_foreach(calls, (GFunc) g_free, NULL);
+	g_slist_free(calls);
+}
+
 static void ciev_callsetup_notify(struct ofono_voicecall *vc,
 					struct ofono_call *call,
 					unsigned int value)
@@ -376,24 +510,36 @@ static void ciev_callsetup_notify(struct
ofono_voicecall *vc,
 	unsigned int ciev_callsetup = vd->cind_val[HFP_INDICATOR_CALLSETUP];
 	unsigned int ciev_call = vd->cind_val[HFP_INDICATOR_CALL];
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			/* call=0 and callsetup=1: reject an incoming call
-			 * call=0 and callsetup=2,3: interrupt an outgoing call
-			 */
-			if (ciev_call == 0 && ciev_callsetup > 0)
-				release_call(vc, call);
-			break;
-		case 1:
-		case 2:
-			break;
-		case 3:
-			call->status = CALL_STATUS_ALERTING;
-			ofono_voicecall_notify(vc, call);
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		/* call=0 and callsetup=1: reject an incoming call
+		 * call=0 and callsetup=2,3: interrupt an outgoing call
+		 */
+		if ((ciev_call == 0) && (ciev_callsetup > 0))
+			release_call(vc, call);
+		break;
+	case 1:
+		break;
+	case 2:
+		/* two cases of outgoing call: dial from HF or AG.
+		 * from HF: query and sync the phone number.
+		 * from AG: query and create call.
+		 * if phone does not support CLLC, we guess the call.
+		 */
+		if (vd->ag_features & AG_FEATURE_ENHANCED_CALL_STATUS)
+			g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
+						sync_dialing_cb,
+						vc, NULL);
+		else if (!vd->call)
+			vd->call = new_call_notify(vc, 0, 0,
+						CALL_STATUS_DIALING,
+						NULL, 128, 2);
+		break;
+	case 3:
+		call->status = CALL_STATUS_ALERTING;
+		ofono_voicecall_notify(vc, call);
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALLSETUP] = value;
-- 
1.6.2.5




^ permalink raw reply related	[flat|nested] 7+ messages in thread

* RE: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
  2009-11-05 13:57 ` Zhang, Zhenhua
@ 2009-11-06 14:02   ` Zhang, Zhenhua
  0 siblings, 0 replies; 7+ messages in thread
From: Zhang, Zhenhua @ 2009-11-06 14:02 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 253 bytes --]

Hi,

Zhang, Zhenhua wrote:
> 
> The new patch is attached.
> 
> Regards,
> Zhenhua

Please ignore this patch since it contains trailing space. I will send it again with
other 4 bug fixing patches soon. Sorry for noise.

Regards,
Zhenhua


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call
       [not found] <1257337416-8647-1-git-send-email-zhenhua.zhang@intel.com>
@ 2009-11-05 13:57 ` Zhang, Zhenhua
  2009-11-06 14:02   ` Zhang, Zhenhua
  0 siblings, 1 reply; 7+ messages in thread
From: Zhang, Zhenhua @ 2009-11-05 13:57 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 904 bytes --]

Hi,

Zhang, Zhenhua wrote:
> Hi,
> 
> There're two cases of outgoing call: dial from HF or dial from phone.
> 
> In the first case, some phones may not support enhanced call status
> (AT+CLCC) to query outgoing number. So we need to pass struct
> atd_cb_data to fill in the number and type. Later, we invoke
> AT+CLCC to query phone number and overwrite ours if we are wrong.
> 
> In the second case, the phone is dialing from phone and we
> know nothing. So we have to query it through AT+CLCC when callsetup=2.
> If phone does not support AT+CLCC, we fake a new call for it. ---
> drivers/hfpmodem/voicecall.c |  219

I updated the algorithm of sync_dialing_cb to handle the multi calls case.

It is possible to dial the second call from phone and we only have the first call
record. So we need a loop to scan the +CLCC result.

The new patch is attached.

Regards,
Zhenhua


[-- Attachment #2: 0004-Fix-Fill-in-the-phone-number-info-for-outgoing-call.patch --]
[-- Type: application/octet-stream, Size: 8283 bytes --]

From 62ee15abfc1c7a63617117e8e29e2c028a1e8186 Mon Sep 17 00:00:00 2001
From: Zhenhua Zhang <zhenhua.zhang@intel.com>
Date: Wed, 4 Nov 2009 21:12:32 +0800
Subject: [PATCH 4/4] Fix: Fill in the phone number info for outgoing call

There're two cases of outgoing call: dial from HF or dial from
phone.

In the first case, some phones may not support enhanced call status
(AT+CLCC) to query outgoing number. So we need to pass struct
atd_cb_data to fill in the number and type. Later, we invoke
AT+CLCC to query phone number and overwrite ours if we are wrong.

In the second case, the phone is dialing from phone and we know
nothing. So we have to query it through AT+CLCC when callsetup=2.
If phone does not support AT+CLCC, we fake a new call for it.

Update: change algorithm in sync_dialing_cb to handle multi calls
situation.
---
 drivers/hfpmodem/voicecall.c |  211 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 176 insertions(+), 35 deletions(-)

diff --git a/drivers/hfpmodem/voicecall.c b/drivers/hfpmodem/voicecall.c
index dee7787..830bdbb 100644
--- a/drivers/hfpmodem/voicecall.c
+++ b/drivers/hfpmodem/voicecall.c
@@ -49,6 +49,7 @@
 
 static const char *none_prefix[] = { NULL };
 static const char *chld_prefix[] = { "+CHLD:", NULL };
+static const char *clcc_prefix[] = { "+CLCC:", NULL };
 
 struct voicecall_data {
 	GAtChat *chat;
@@ -76,6 +77,13 @@ struct change_state_req {
 	int affected_types;
 };
 
+struct atd_cb_data {
+	void *cb;
+	void *data;
+	void *user;
+	struct ofono_phone_number ph;
+};
+
 static struct ofono_call *create_call(struct voicecall_data *d, int type,
 					int direction, int status,
 					const char *num, int num_type, int clip)
@@ -108,6 +116,73 @@ static struct ofono_call *create_call(struct voicecall_data *d, int type,
 	return call;
 }
 
+static void new_call_notify(struct ofono_voicecall *vc, int type,
+					int direction, int status,
+					const char *num, int num_type, int clip)
+{
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_call *c;
+
+	c = create_call(vd, type, direction, status, num, num_type, clip);
+
+	ofono_voicecall_notify(vc, c);
+}
+
+static GSList *parse_clcc(GAtResult *result)
+{
+	GAtResultIter iter;
+	GSList *l = NULL;
+	int id, dir, status, type;
+	struct ofono_call *call;
+
+	g_at_result_iter_init(&iter, result);
+
+	while (g_at_result_iter_next(&iter, "+CLCC:")) {
+		const char *str = "";
+		int number_type = 129;
+
+		if (!g_at_result_iter_next_number(&iter, &id))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &dir))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &status))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &type))
+			continue;
+
+		if (!g_at_result_iter_skip_next(&iter))
+			continue;
+
+		if (g_at_result_iter_next_string(&iter, &str))
+			g_at_result_iter_next_number(&iter, &number_type);
+
+		call = g_try_new0(struct ofono_call, 1);
+
+		if (!call)
+			break;
+
+		call->id = id;
+		call->direction = dir;
+		call->status = status;
+		call->type = type;
+		strncpy(call->phone_number.number, str,
+				OFONO_MAX_PHONE_NUMBER_LENGTH);
+		call->phone_number.type = number_type;
+
+		if (strlen(call->phone_number.number) > 0)
+			call->clip_validity = 0;
+		else
+			call->clip_validity = 2;
+
+		l = g_slist_insert_sorted(l, call, at_util_call_compare);
+	}
+
+	return l;
+}
+
 static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct change_state_req *req = user_data;
@@ -134,12 +209,11 @@ static void generic_cb(gboolean ok, GAtResult *result, gpointer user_data)
 
 static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
-	struct cb_data *cbd = user_data;
+	struct atd_cb_data *cbd = user_data;
 	struct ofono_voicecall *vc = cbd->user;
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
 	ofono_voicecall_cb_t cb = cbd->cb;
-	int type = 128;
-	int validity = 2;
+	struct ofono_phone_number ph = cbd->ph;
 	struct ofono_error error;
 	struct ofono_call *call;
 
@@ -150,7 +224,8 @@ static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	if (!ok)
 		goto out;
 
-	call = create_call(vd, 0, 0, CALL_STATUS_DIALING, NULL, type, validity);
+	call = create_call(vd, 0, 0, CALL_STATUS_DIALING,
+					ph.number, ph.type, 0);
 
 	if (!call) {
 		ofono_error("Unable to allocate call, "
@@ -168,13 +243,20 @@ static void hfp_dial(struct ofono_voicecall *vc,
 			ofono_voicecall_cb_t cb, void *data)
 {
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
-	struct cb_data *cbd = cb_data_new(cb, data);
+	struct atd_cb_data *cbd;
 	char buf[256];
 
+	cbd = g_try_new0(struct atd_cb_data, 1);
+
 	if (!cbd)
 		goto error;
 
+	cbd->cb = cb;
+	cbd->data = data;
 	cbd->user = vc;
+
+	memcpy(&cbd->ph, ph, sizeof(struct ofono_phone_number));
+
 	if (ph->type == 145)
 		sprintf(buf, "ATD+%s", ph->number);
 	else
@@ -351,23 +433,71 @@ static void ciev_call_notify(struct ofono_voicecall *vc,
 {
 	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			release_call(vc, call);
-			break;
-		case 1:
-			call->status = CALL_STATUS_ACTIVE;
-			ofono_voicecall_notify(vc, call);
-			break;
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		release_call(vc, call);
+		break;
+	case 1:
+		call->status = CALL_STATUS_ACTIVE;
+		ofono_voicecall_notify(vc, call);
+		break;
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALL] = value;
 }
 
+static void sync_dialing_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_voicecall *vc = user_data;
+	struct voicecall_data *vd = ofono_voicecall_get_data(vc);
+	struct ofono_error error;
+	GSList *calls = NULL;
+	GSList *l = NULL;
+	struct ofono_call *nc = NULL;
+	struct ofono_call *oc = vd->call;
+
+	dump_response("sync_dialing_cb", ok, result);
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok)
+		return;
+
+	calls = parse_clcc(result);
+
+	if (calls == NULL)
+		return;
+
+	while (calls) {
+		nc = calls->data;
+
+		if (vd->calls)
+			l = g_slist_find_custom(vd->calls, nc,
+						at_util_call_compare);
+
+		if (l) {
+			oc = l->data;
+
+			if (memcmp(nc, oc, sizeof(struct ofono_call))) {
+				ofono_voicecall_notify(vc, nc);
+
+				memcpy(oc, nc, sizeof(struct ofono_call));
+			}
+
+		} else
+			new_call_notify(vc, nc->type, nc->direction, nc->status,
+						nc->phone_number.number,
+						nc->phone_number.type,
+						nc->clip_validity);
+
+		calls = calls->next;
+	}
+
+	g_slist_foreach(calls, (GFunc) g_free, NULL);
+	g_slist_free(calls);
+}
+
 static void ciev_callsetup_notify(struct ofono_voicecall *vc,
 					struct ofono_call *call,
 					unsigned int value)
@@ -376,24 +506,35 @@ static void ciev_callsetup_notify(struct ofono_voicecall *vc,
 	unsigned int ciev_callsetup = vd->cind_val[HFP_INDICATOR_CALLSETUP];
 	unsigned int ciev_call = vd->cind_val[HFP_INDICATOR_CALL];
 
-	if (g_slist_length(vd->calls) == 1) {
-		switch (value) {
-		case 0:
-			/* call=0 and callsetup=1: reject an incoming call
-			 * call=0 and callsetup=2,3: interrupt an outgoing call
-			 */
-			if ((ciev_call == 0) && (ciev_callsetup > 0))
-				release_call(vc, call);
-			break;
-		case 1:
-		case 2:
-			break;
-		case 3:
-			call->status = CALL_STATUS_ALERTING;
-			ofono_voicecall_notify(vc, call);
-		default:
-			break;
-		}
+	switch (value) {
+	case 0:
+		/* call=0 and callsetup=1: reject an incoming call
+		 * call=0 and callsetup=2,3: interrupt an outgoing call
+		 */
+		if ((ciev_call == 0) && (ciev_callsetup > 0))
+			release_call(vc, call);
+		break;
+	case 1:
+		break;
+	case 2:
+		/* two cases of outgoing call: dial from HF or AG.
+		 * from HF: query and sync the phone number.
+		 * from AG: query and create call.
+		 * if phone does not support CLLC, we guess the call.
+		 */
+		if (vd->ag_features & AG_FEATURE_ENHANCED_CALL_STATUS)
+			g_at_chat_send(vd->chat, "AT+CLCC", clcc_prefix,
+					sync_dialing_cb,
+					vc, NULL);
+		else if (!vd->call)
+			new_call_notify(vc, 0, 0, CALL_STATUS_DIALING,
+					NULL, 128, 2);
+		break;
+	case 3:
+		call->status = CALL_STATUS_ALERTING;
+		ofono_voicecall_notify(vc, call);
+	default:
+		break;
 	}
 
 	vd->cind_val[HFP_INDICATOR_CALLSETUP] = value;
-- 
1.6.2.5


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2009-11-12  9:25 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <1257545952-2776-1-git-send-email-zhenhua.zhang@intel.com>
2009-11-09  1:03 ` [PATCH 4/4] Fix: Fill in the phone number info for outgoing call Zhang, Zhenhua
2009-11-07  7:15 Zhenhua Zhang
2009-11-11 22:23 ` Denis Kenzior
2009-11-12  2:34   ` Zhang, Zhenhua
2009-11-12  9:25   ` Zhang, Zhenhua
     [not found] <1257337416-8647-1-git-send-email-zhenhua.zhang@intel.com>
2009-11-05 13:57 ` Zhang, Zhenhua
2009-11-06 14:02   ` Zhang, Zhenhua

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.