ifxmodem: move call creation to xcallstat_notify

This commit is contained in:
Jeevaka Badrappan 2011-02-08 09:04:14 -08:00 committed by Denis Kenzior
parent a8f15c5cf3
commit 67f41014de
1 changed files with 101 additions and 77 deletions

View File

@ -79,7 +79,8 @@ static int class_to_call_type(int cls)
static struct ofono_call *create_call(struct ofono_voicecall *vc, int type, static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
int direction, int status, int direction, int status,
const char *num, int num_type, int clip) const char *num, int num_type,
int clip, int id)
{ {
struct voicecall_data *d = ofono_voicecall_get_data(vc); struct voicecall_data *d = ofono_voicecall_get_data(vc);
struct ofono_call *call; struct ofono_call *call;
@ -91,7 +92,7 @@ static struct ofono_call *create_call(struct ofono_voicecall *vc, int type,
ofono_call_init(call); ofono_call_init(call);
call->id = ofono_voicecall_get_next_callid(vc); call->id = id;
call->type = type; call->type = type;
call->direction = direction; call->direction = direction;
call->status = status; call->status = status;
@ -117,7 +118,8 @@ static void xcallstat_notify(GAtResult *result, gpointer user_data)
int id; int id;
int status; int status;
GSList *l; GSList *l;
struct ofono_call *call; struct ofono_call *new_call;
struct ofono_call *existing_call = NULL;
g_at_result_iter_init(&iter, result); g_at_result_iter_init(&iter, result);
@ -133,53 +135,83 @@ static void xcallstat_notify(GAtResult *result, gpointer user_data)
l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id), l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id),
at_util_call_compare_by_id); at_util_call_compare_by_id);
if (l == NULL) { if (l == NULL && status != CALL_STATUS_DIALING &&
/* status != CALL_STATUS_INCOMING &&
* We should only receive XCALLSTAT on waiting and incoming status != CALL_STATUS_WAITING) {
* In the case of waiting, we will get the rest of the info ofono_error("Received XCALLSTAT for an untracked"
* from CCWA indication. " call, this indicates a bug!");
* In the case of incoming, we will get the info from CLIP return;
* indications. }
if (l)
existing_call = l->data;
switch (status) {
case CALL_STATUS_DISCONNECTED:
{
enum ofono_disconnect_reason reason;
existing_call->status = status;
if (vd->local_release & (1 << existing_call->id))
reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
else
reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP;
ofono_voicecall_disconnected(vc, existing_call->id,
reason, NULL);
vd->local_release &= ~(1 << existing_call->id);
vd->calls = g_slist_remove(vd->calls, l->data);
g_free(existing_call);
break;
}
case CALL_STATUS_DIALING:
case CALL_STATUS_WAITING:
case CALL_STATUS_INCOMING:
{
int direction;
/* Handle the following situation:
* Active Call + Waiting Call. Active Call is Released.
* The Waiting call becomes Incoming. In this case, no
* need to create a new call. Call status change will be
* triggered from clip_notify.
*/ */
if (status != CALL_STATUS_INCOMING && if (existing_call) {
status != CALL_STATUS_WAITING) { existing_call->status = status;
ofono_info("Received an XCALLSTAT for an untracked"
" call, this indicates a bug!");
return; return;
} }
return; if (status == CALL_STATUS_DIALING)
} direction = CALL_DIRECTION_MOBILE_ORIGINATED;
call = l->data;
/* Check if call has been disconnected */
if (status == CALL_STATUS_DISCONNECTED) {
enum ofono_disconnect_reason r;
if (vd->local_release & (1 << call->id))
r = OFONO_DISCONNECT_REASON_LOCAL_HANGUP;
else else
r = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; direction = CALL_DIRECTION_MOBILE_TERMINATED;
if (call->type == 0) new_call = create_call(vc, 0, direction, status,
ofono_voicecall_disconnected(vc, call->id, r, NULL); NULL, 128,
CLIP_VALIDITY_NOT_AVAILABLE, id);
if (new_call == NULL) {
ofono_error("Unable to malloc. "
"Call management is fubar");
return;
}
vd->local_release &= ~(1 << call->id); new_call->id = id;
vd->calls = g_slist_remove(vd->calls, call); break;
g_free(call);
return;
} }
case CALL_STATUS_ALERTING:
case CALL_STATUS_ACTIVE:
case CALL_STATUS_HELD:
default:
/* For connected status, simply reset back to active */
if (status == 7)
status = CALL_STATUS_ACTIVE;
/* For connected status, simply reset back to active */ existing_call->status = status;
if (status == 7) ofono_voicecall_notify(vc, existing_call);
status = 0; break;
}
call->status = status;
if (call->type == 0)
ofono_voicecall_notify(vc, call);
} }
static void xem_notify(GAtResult *result, gpointer user_data) static void xem_notify(GAtResult *result, gpointer user_data)
@ -250,25 +282,11 @@ static void release_id_cb(gboolean ok, GAtResult *result,
static void atd_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 cb_data *cbd = user_data;
struct ofono_voicecall *vc = cbd->user;
ofono_voicecall_cb_t cb = cbd->cb; ofono_voicecall_cb_t cb = cbd->cb;
struct ofono_error error; struct ofono_error error;
struct ofono_call *call;
decode_at_error(&error, g_at_result_final_response(result)); decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
cb(&error, cbd->data);
return;
}
/* Generate a voice call that was just dialed, we guess the ID */
call = create_call(vc, 0, 0, CALL_STATUS_DIALING, NULL, 128, 2);
if (call == NULL) {
ofono_error("Unable to malloc, call tracking will fail!");
return;
}
/* Let oFono core will generate a call with the dialed number /* Let oFono core will generate a call with the dialed number
* inside its dial callback. * inside its dial callback.
*/ */
@ -512,25 +530,28 @@ static void cring_notify(GAtResult *result, gpointer user_data)
struct voicecall_data *vd = ofono_voicecall_get_data(vc); struct voicecall_data *vd = ofono_voicecall_get_data(vc);
GAtResultIter iter; GAtResultIter iter;
const char *line; const char *line;
int type; GSList *l;
struct ofono_call *call;
/* Handle the following situation: /* Handle the following situation:
* Active Call + Waiting Call. Active Call is Released. The Waiting * Active Call + Waiting Call. Active Call is Released. The Waiting
* call becomes Incoming and RING/CRING indications are signaled. * call becomes Incoming and CRING indications are signaled.
* Sometimes these arrive before we managed to poll CLCC to find about * Sometimes these arrive before the actual state change notification.
* the stage change. If this happens, simply ignore the RING/CRING * If this happens, simply ignore the CRING when a waiting call
* when a waiting call exists (cannot have waiting + incoming in GSM) * exists (cannot have waiting + incoming in GSM)
*/ */
if (g_slist_find_custom(vd->calls, if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING), GINT_TO_POINTER(CALL_STATUS_WAITING),
at_util_call_compare_by_status)) at_util_call_compare_by_status))
return; return;
/* CRING can repeat, ignore if we already have an incoming call */ l = g_slist_find_custom(vd->calls,
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_INCOMING), GINT_TO_POINTER(CALL_STATUS_INCOMING),
at_util_call_compare_by_status)) at_util_call_compare_by_status);
if (l == NULL) {
ofono_error("CRING received before XCALLSTAT!!!");
return; return;
}
g_at_result_iter_init(&iter, result); g_at_result_iter_init(&iter, result);
@ -541,14 +562,13 @@ static void cring_notify(GAtResult *result, gpointer user_data)
if (line == NULL) if (line == NULL)
return; return;
call = l->data;
/* Ignore everything that is not voice for now */ /* Ignore everything that is not voice for now */
if (!strcasecmp(line, "VOICE")) if (!strcasecmp(line, "VOICE"))
type = 0; call->type = 0;
else else
type = 9; call->type = 9;
/* Generate an incoming call */
create_call(vc, type, 1, CALL_STATUS_INCOMING, NULL, 128, 2);
/* Assume the CLIP always arrives, and we signal the call there */ /* Assume the CLIP always arrives, and we signal the call there */
DBG("cring_notify"); DBG("cring_notify");
@ -617,13 +637,16 @@ static void ccwa_notify(GAtResult *result, gpointer user_data)
GAtResultIter iter; GAtResultIter iter;
const char *num; const char *num;
int num_type, validity, cls; int num_type, validity, cls;
GSList *l;
struct ofono_call *call; struct ofono_call *call;
/* Some modems resend CCWA, ignore it the second time around */ l = g_slist_find_custom(vd->calls,
if (g_slist_find_custom(vd->calls,
GINT_TO_POINTER(CALL_STATUS_WAITING), GINT_TO_POINTER(CALL_STATUS_WAITING),
at_util_call_compare_by_status)) at_util_call_compare_by_status);
if (l == NULL) {
ofono_error("CCWA received before XCALLSTAT!!!");
return; return;
}
g_at_result_iter_init(&iter, result); g_at_result_iter_init(&iter, result);
@ -652,12 +675,13 @@ static void ccwa_notify(GAtResult *result, gpointer user_data)
DBG("ccwa_notify: %s %d %d %d", num, num_type, cls, validity); DBG("ccwa_notify: %s %d %d %d", num, num_type, cls, validity);
call = create_call(vc, class_to_call_type(cls), 1, CALL_STATUS_WAITING, call = l->data;
num, num_type, validity);
if (call == NULL) { call->type = class_to_call_type(cls);
ofono_error("Unable to malloc. Call management is fubar"); strncpy(call->phone_number.number, num, OFONO_MAX_PHONE_NUMBER_LENGTH);
return; call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0';
} call->phone_number.type = num_type;
call->clip_validity = validity;
if (call->type == 0) /* Only notify voice calls */ if (call->type == 0) /* Only notify voice calls */
ofono_voicecall_notify(vc, call); ofono_voicecall_notify(vc, call);