Hi Jeevaka,

On 02/07/2011 03:07 PM, Jeevaka Badrappan wrote:
> ---
>  drivers/ifxmodem/voicecall.c |  170 ++++++++++++++++++++++++-----------------
>  1 files changed, 99 insertions(+), 71 deletions(-)
> 
> diff --git a/drivers/ifxmodem/voicecall.c b/drivers/ifxmodem/voicecall.c
> index 648f46b..c94698b 100644
> --- a/drivers/ifxmodem/voicecall.c
> +++ b/drivers/ifxmodem/voicecall.c
> @@ -117,7 +117,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);
>  
> @@ -133,53 +134,83 @@ 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_DIALING &&
> +                             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;
> +
> +             /* 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 (existing_call) {
> +                     existing_call->status = status;
> +                     return;
> +             }
>  
> -     /* For connected status, simply reset back to active */
> -     if (status == 7)
> -             status = 0;
> +             if (status == CALL_STATUS_DIALING)
> +                     direction = CALL_DIRECTION_MOBILE_ORIGINATED;
> +             else
> +                     direction = CALL_DIRECTION_MOBILE_TERMINATED;
> +
> +             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;

So if you really insist on creating the call with a particular id, you
might as well make that a parameter of the create_call function.
However, do note that you still have one potential problem.  If the ATD
callback returns before the call is signaled, then oFono synthesizes an
outgoing call and picks an ID for you (according to the rules I
outlined).  If the ID that oFono picked doesn't match the ID you have,
you're in trouble.  So I'm not sure if you still want to go through all
this trouble or not...

> +             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 = CALL_STATUS_ACTIVE;
>  
> -     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)
> @@ -250,25 +281,11 @@ 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;
>       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;
> -     }
> -
> -     /* 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
>        * inside its dial callback.
>        */
> @@ -512,25 +529,28 @@ static void cring_notify(GAtResult *result, gpointer 
> user_data)
>       struct voicecall_data *vd = ofono_voicecall_get_data(vc);
>       GAtResultIter iter;
>       const char *line;
> -     int type;
> +     GSList *l;
> +     struct ofono_call *call;
>  
>       /* 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)
> +      * call becomes Incoming and CRING indications are signaled.
> +      * Sometimes these arrive before the actual state change notification.
> +      * If this happens, simply ignore the 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;
>  
> -     /* CRING can repeat, ignore if we already have an incoming call */
> -     if (g_slist_find_custom(vd->calls,
> +     l = g_slist_find_custom(vd->calls,
>                               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;
> +     }
>  
>       g_at_result_iter_init(&iter, result);
>  
> @@ -541,14 +561,13 @@ static void cring_notify(GAtResult *result, gpointer 
> user_data)
>       if (line == NULL)
>               return;
>  
> +     call = l->data;
> +
>       /* Ignore everything that is not voice for now */
>       if (!strcasecmp(line, "VOICE"))
> -             type = 0;
> +             call->type = 0;
>       else
> -             type = 9;
> -
> -     /* Generate an incoming call */
> -     create_call(vc, type, 1, CALL_STATUS_INCOMING, NULL, 128, 2);
> +             call->type = 9;
>  
>       /* Assume the CLIP always arrives, and we signal the call there */
>       DBG("cring_notify");
> @@ -617,13 +636,16 @@ static void ccwa_notify(GAtResult *result, gpointer 
> user_data)
>       GAtResultIter iter;
>       const char *num;
>       int num_type, validity, cls;
> +     GSList *l;
>       struct ofono_call *call;
>  
> -     /* Some modems resend CCWA, ignore it the second time around */
> -     if (g_slist_find_custom(vd->calls,
> +     l = g_slist_find_custom(vd->calls,

Can CCWA repeat on IFX?

>                               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;
> +     }
>  
>       g_at_result_iter_init(&iter, result);
>  
> @@ -652,13 +674,19 @@ static void ccwa_notify(GAtResult *result, gpointer 
> user_data)
>  
>       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,
> -                             num, num_type, validity);
> -     if (call == NULL) {
> -             ofono_error("Unable to malloc. Call management is fubar");
> -             return;
> +     call = l->data;
> +
> +     call->type = class_to_call_type(cls);
> +
> +     if (validity != 2) {
> +             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 = num_type;
>       }
>  
> +     call->clip_validity = validity;
> +
>       if (call->type == 0) /* Only notify voice calls */
>               ofono_voicecall_notify(vc, call);
>  }

Regards,
-Denis
_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to