--- drivers/ifxmodem/voicecall.c | 197 +++++++++++++++++++----------------------- 1 files changed, 90 insertions(+), 107 deletions(-)
diff --git a/drivers/ifxmodem/voicecall.c b/drivers/ifxmodem/voicecall.c index f66815a..c6e3878 100644 --- a/drivers/ifxmodem/voicecall.c +++ b/drivers/ifxmodem/voicecall.c @@ -120,7 +120,8 @@ static void xcallstat_notify(GAtResult *result, gpointer user_data) int id; int status; GSList *l; - struct ofono_call *call; + struct ofono_call *new_call; + struct ofono_call *existing_call = NULL; g_at_result_iter_init(&iter, result); @@ -136,53 +137,70 @@ static void xcallstat_notify(GAtResult *result, gpointer user_data) l = g_slist_find_custom(vd->calls, GINT_TO_POINTER(id), at_util_call_compare_by_id); - if (l == NULL) { - /* - * We should only receive XCALLSTAT on waiting and incoming - * In the case of waiting, we will get the rest of the info - * from CCWA indication. - * In the case of incoming, we will get the info from CLIP - * indications. - */ - if (status != CALL_STATUS_INCOMING && - status != CALL_STATUS_WAITING) { - ofono_info("Received an XCALLSTAT for an untracked" - " call, this indicates a bug!"); - return; - } - + if (l == NULL && status != CALL_STATUS_INCOMING && + status != CALL_STATUS_WAITING) { + ofono_error("Received an XCALLSTAT for an untracked" + " call, this indicates a bug!"); return; } - call = l->data; + if (l) + existing_call = l->data; - /* Check if call has been disconnected */ - if (status == CALL_STATUS_DISCONNECTED) { - enum ofono_disconnect_reason r; + switch (status) { + case CALL_STATUS_DISCONNECTED: + { + enum ofono_disconnect_reason reason; - if (vd->local_release & (1 << call->id)) - r = OFONO_DISCONNECT_REASON_LOCAL_HANGUP; - else - r = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; + existing_call->status = status; - if (call->type == 0) - ofono_voicecall_disconnected(vc, call->id, r, NULL); + if (vd->local_release & (1 << existing_call->id)) + reason = OFONO_DISCONNECT_REASON_LOCAL_HANGUP; + else + reason = OFONO_DISCONNECT_REASON_REMOTE_HANGUP; - vd->local_release &= ~(1 << call->id); - vd->calls = g_slist_remove(vd->calls, call); - g_free(call); + ofono_voicecall_disconnected(vc, existing_call->id, + reason, NULL); - return; + 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; + + if (status == CALL_STATUS_DIALING) + direction = CALL_DIRECTION_MOBILE_ORIGINATED; + else + direction = CALL_DIRECTION_MOBILE_TERMINATED; - /* For connected status, simply reset back to active */ - if (status == 7) - status = 0; + new_call = create_call(vc, 0, direction, status, + NULL, 128, CLIP_VALIDITY_NOT_AVAILABLE); + if (new_call == NULL) { + ofono_error("Unable to malloc. " + "Call management is fubar"); + return; + } - call->status = status; + new_call->id = id; + break; + } + 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 = 0; - if (call->type == 0) - ofono_voicecall_notify(vc, call); + existing_call->status = status; + ofono_voicecall_notify(vc, existing_call); + break; + } } static void xem_notify(GAtResult *result, gpointer user_data) @@ -253,51 +271,12 @@ static void release_id_cb(gboolean ok, GAtResult *result, static void atd_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; - struct ofono_voicecall *vc = cbd->user; ofono_voicecall_cb_t cb = cbd->cb; - GAtResultIter iter; - const char *num; - int type = 128; - int validity = 2; struct ofono_error error; - struct ofono_call *call; decode_at_error(&error, g_at_result_final_response(result)); - if (!ok) { - cb(&error, cbd->data); - return; - } - - g_at_result_iter_init(&iter, result); - - if (g_at_result_iter_next(&iter, "+COLP:")) { - g_at_result_iter_next_string(&iter, &num); - g_at_result_iter_next_number(&iter, &type); - - if (strlen(num) > 0) - validity = 0; - else - validity = 2; - - DBG("colp_notify: %s %d %d", num, type, validity); - } - - /* Generate a voice call that was just dialed, we guess the ID */ - call = create_call(vc, 0, 0, CALL_STATUS_DIALING, num, type, validity); - if (call == NULL) { - ofono_error("Unable to malloc, call tracking will fail!"); - return; - } - - /* Let oFono core will generate a call with the dialed number - * inside its dial callback. - */ cb(&error, cbd->data); - - /* If we got COLP information, then notify the core */ - if (validity != 2) - ofono_voicecall_notify(vc, call); } static void ifx_dial(struct ofono_voicecall *vc, @@ -531,52 +510,56 @@ error: CALLBACK_WITH_FAILURE(cb, data); } -static void cring_notify(GAtResult *result, gpointer user_data) +static void xcolp_notify(GAtResult *result, gpointer user_data) { struct ofono_voicecall *vc = user_data; struct voicecall_data *vd = ofono_voicecall_get_data(vc); GAtResultIter iter; - const char *line; - int type; - - /* Handle the following situation: - * Active Call + Waiting Call. Active Call is Released. The Waiting - * call becomes Incoming and RING/CRING indications are signaled. - * Sometimes these arrive before we managed to poll CLCC to find about - * the stage change. If this happens, simply ignore the RING/CRING - * when a waiting call exists (cannot have waiting + incoming in GSM) - */ - if (g_slist_find_custom(vd->calls, - GINT_TO_POINTER(CALL_STATUS_WAITING), - at_util_call_compare_by_status)) - return; + const char *num; + int type, validity, call_id; + GSList *l; + struct ofono_call *call; - /* CRING can repeat, ignore if we already have an incoming call */ - if (g_slist_find_custom(vd->calls, - GINT_TO_POINTER(CALL_STATUS_INCOMING), - at_util_call_compare_by_status)) - return; + DBG(""); g_at_result_iter_init(&iter, result); - if (!g_at_result_iter_next(&iter, "+CRING:")) + if (!g_at_result_iter_next(&iter, "+XCOLP:")) + return; + + if (!g_at_result_iter_next_number(&iter, &call_id)) + return; + + if (!g_at_result_iter_next_string(&iter, &num)) return; - line = g_at_result_iter_raw_line(&iter); - if (line == NULL) + if (!g_at_result_iter_next_number(&iter, &type)) return; - /* Ignore everything that is not voice for now */ - if (!strcasecmp(line, "VOICE")) - type = 0; + if (strlen(num) > 0) + validity = 0; else - type = 9; + validity = 2; - /* Generate an incoming call */ - create_call(vc, type, 1, CALL_STATUS_INCOMING, NULL, 128, 2); + DBG("xcolp_notify: %d %s %d %d", call_id, num, type, validity); + + l = g_slist_find_custom(vd->calls, + GINT_TO_POINTER(call_id), + at_util_call_compare_by_id); + if (l == NULL) { + ofono_error("XCOLP for unknown call"); + return; + } + + call = l->data; + + strncpy(call->phone_number.number, num, + OFONO_MAX_PHONE_NUMBER_LENGTH); + call->phone_number.number[OFONO_MAX_PHONE_NUMBER_LENGTH] = '\0'; + call->phone_number.type = type; + call->clip_validity = validity; - /* Assume the CLIP always arrives, and we signal the call there */ - DBG("cring_notify"); + ofono_voicecall_notify(vc, call); } static void clip_notify(GAtResult *result, gpointer user_data) @@ -696,12 +679,12 @@ static void ifx_voicecall_initialized(gboolean ok, GAtResult *result, DBG("voicecall_init: registering to notifications"); - g_at_chat_register(vd->chat, "+CRING:", cring_notify, FALSE, vc, NULL); g_at_chat_register(vd->chat, "+CLIP:", clip_notify, FALSE, vc, NULL); g_at_chat_register(vd->chat, "+CCWA:", ccwa_notify, FALSE, vc, NULL); g_at_chat_register(vd->chat, "+XEM:", xem_notify, FALSE, vc, NULL); g_at_chat_register(vd->chat, "+XCALLSTAT:", xcallstat_notify, FALSE, vc, NULL); + g_at_chat_register(vd->chat, "+XCOLP:", xcolp_notify, FALSE, vc, NULL); ofono_voicecall_register(vc); } -- 1.7.0.4 _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono