mirror of git://git.sysmocom.de/ofono
ifxmodem: move call creation to xcallstat_notify
This commit is contained in:
parent
a8f15c5cf3
commit
67f41014de
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue