Hi Andrew,

On 10/13/2010 08:54 AM, Andrzej Zaborowski wrote:
> In this version 'p' is used as the pause character in DTMF strings as
> it seems in more widespread use than comma.  ISImodem already
> understands 'p'.  atmodem support comes in the next patch.
> ---

I cannibalized this patch a little bit, see comments below:

> @@ -70,7 +70,7 @@ struct ofono_stk {
>       gboolean respond_on_exit;
>       ofono_bool_t immediate_response;
>       guint remove_agent_source;
> -     struct sms_submit_req *sms_submit_req;
> +     struct extern_req *extern_req;
>       char *idle_mode_text;
>       struct timeval get_inkey_start_ts;
>  };

This chunk was applied

> @@ -83,7 +83,7 @@ struct envelope_op {
>                       const unsigned char *data, int length);
>  };
>  
> -struct sms_submit_req {
> +struct extern_req {
>       struct ofono_stk *stk;
>       gboolean cancelled;
>  };

This chunk was applied

> @@ -435,8 +435,12 @@ static void default_agent_notify(gpointer user_data)
>  {
>       struct ofono_stk *stk = user_data;
>  
> -     if (stk->current_agent == stk->default_agent && stk->respond_on_exit)
> +     if (stk->current_agent == stk->default_agent && stk->respond_on_exit) {
> +             if (stk->pending_cmd)
> +                     stk->cancel_cmd(stk);
> +
>               send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
> +     }
>  
>       stk->default_agent = NULL;
>       stk->current_agent = stk->session_agent;
> @@ -450,6 +454,9 @@ static void session_agent_notify(gpointer user_data)
>       DBG("Session Agent removed");
>  
>       if (stk->current_agent == stk->session_agent && stk->respond_on_exit) {
> +             if (stk->pending_cmd)
> +                     stk->cancel_cmd(stk);
> +
>               DBG("Sending Terminate response for session agent");
>               send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
>       }

Can you explain a bit more what these two chunks are doing?

> @@ -660,7 +667,7 @@ static gboolean handle_command_more_time(const struct 
> stk_command *cmd,
>  
>  static void send_sms_cancel(struct ofono_stk *stk)
>  {
> -     stk->sms_submit_req->cancelled = TRUE;
> +     stk->extern_req->cancelled = TRUE;
>  
>       if (!stk->pending_cmd->send_sms.alpha_id ||
>                       !stk->pending_cmd->send_sms.alpha_id[0])

This chunk has been applied

> @@ -671,7 +678,7 @@ static void send_sms_cancel(struct ofono_stk *stk)
>  
>  static void send_sms_submit_cb(gboolean ok, void *data)
>  {
> -     struct sms_submit_req *req = data;
> +     struct extern_req *req = data;
>       struct ofono_stk *stk = req->stk;
>       struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
>       struct stk_response rsp;

This chunk has been applied

> @@ -697,6 +704,12 @@ static void send_sms_submit_cb(gboolean ok, void *data)
>               stk_command_cb(&failure, stk);
>  }
>  
> +static void extern_req_start(struct ofono_stk *stk)
> +{
> +     stk->extern_req = g_new0(struct extern_req, 1);
> +     stk->extern_req->stk = stk;
> +}
> +
>  static gboolean handle_command_send_sms(const struct stk_command *cmd,
>                                       struct stk_response *rsp,
>                                       struct ofono_stk *stk)

This chunk has been applied

> @@ -715,15 +728,14 @@ static gboolean handle_command_send_sms(const struct 
> stk_command *cmd,
>  
>       sms = __ofono_atom_get_data(sms_atom);
>  
> -     stk->sms_submit_req = g_new0(struct sms_submit_req, 1);
> -     stk->sms_submit_req->stk = stk;
> +     extern_req_start(stk);
>  
>       msg_list.data = (void *) &cmd->send_sms.gsm_sms;
>       msg_list.next = NULL;
>  
>       if (__ofono_sms_txq_submit(sms, &msg_list, 0, NULL, send_sms_submit_cb,
> -                             stk->sms_submit_req, g_free) < 0) {
> -             g_free(stk->sms_submit_req);
> +                             stk->extern_req, g_free) < 0) {
> +             g_free(stk->extern_req);
>               rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
>               return TRUE;
>       }

This chunk has been applied

> @@ -1824,6 +1836,148 @@ static gboolean handle_command_refresh(const struct 
> stk_command *cmd,
>       return TRUE;
>  }
>  
> +static void send_dtmf_cancel(struct ofono_stk *stk)
> +{
> +     stk->respond_on_exit = FALSE;
> +     stk->extern_req->cancelled = TRUE;
> +
> +     if (stk->pending_cmd->send_dtmf.alpha_id &&
> +                     stk->pending_cmd->send_dtmf.alpha_id[0])
> +             stk_alpha_id_unset(stk);
> +}
> +
> +static void dtmf_sent_cb(const struct ofono_error *error, void *user_data)
> +{
> +     struct extern_req *req = user_data;
> +     struct ofono_stk *stk = req->stk;
> +     gboolean cancelled = req->cancelled;
> +
> +     g_free(req);
> +
> +     if (cancelled) {
> +             DBG("Received a DTMF Sent callback after the "
> +                             "proactive command was cancelled");
> +             return;
> +     }
> +
> +     stk->respond_on_exit = FALSE;
> +
> +     if (stk->pending_cmd->send_dtmf.alpha_id &&
> +                     stk->pending_cmd->send_dtmf.alpha_id[0])
> +             stk_alpha_id_unset(stk);
> +
> +     if (error->type == OFONO_ERROR_TYPE_FAILURE &&
> +                     error->error == ENOENT) {

I don't see how this if can be triggered from reviewing the previous
patch.  Should the error be -ENOENT?

> +             struct stk_response rsp;
> +             static unsigned char not_in_speech_call_result[] = { 0x07 };
> +             static struct ofono_error failure =
> +                     { .type = OFONO_ERROR_TYPE_FAILURE };
> +
> +             memset(&rsp, 0, sizeof(rsp));
> +
> +             rsp.result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +             rsp.result.additional_len = sizeof(not_in_speech_call_result);
> +             rsp.result.additional = not_in_speech_call_result;
> +
> +             if (stk_respond(stk, &rsp, stk_command_cb))
> +                     stk_command_cb(&failure, stk);
> +
> +             return;
> +     }
> +
> +     if (error->type == OFONO_ERROR_TYPE_FAILURE &&
> +                     error->error == ENOENT) {

And now we're repeating the if condition above? Have you tested this part?

> +             send_simple_response(stk, STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD);
> +             return;
> +     }
> +
> +     if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
> +             send_simple_response(stk, STK_RESULT_TYPE_SUCCESS);
> +     else
> +             send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
> +}
> +
> +static gboolean handle_command_send_dtmf(const struct stk_command *cmd,
> +                                             struct stk_response *rsp,
> +                                             struct ofono_stk *stk)
> +{
> +     static unsigned char not_in_speech_call_result[] = { 0x07 };
> +     struct ofono_voicecall *vc = NULL;
> +     struct ofono_atom *vc_atom;
> +     char dtmf[256], *digit;
> +     char *dtmf_from = "01234567890abcABC";
> +     char *dtmf_to = "01234567890*#p*#p";
> +     int err, pos;
> +
> +     vc_atom = __ofono_modem_find_atom(__ofono_atom_get_modem(stk->atom),
> +                                             OFONO_ATOM_TYPE_VOICECALL);
> +     if (vc_atom)
> +             vc = __ofono_atom_get_data(vc_atom);
> +
> +     if (!vc) {
> +             rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +             return TRUE;
> +     }
> +
> +     /* Convert the DTMF string to phone number format */
> +     for (pos = 0; cmd->send_dtmf.dtmf[pos] != 0; pos++) {
> +             digit = strchr(dtmf_from, cmd->send_dtmf.dtmf[pos]);
> +             if (!digit) {
> +                     rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
> +                     return TRUE;
> +             }
> +
> +             dtmf[pos] = dtmf_to[digit - dtmf_from];
> +     }
> +     dtmf[pos] = 0;
> +
> +     extern_req_start(stk);

I'm not sure that modeling this after the Send SMS implementation is a
good idea.  Send SMS uses the SMS submit queue, which does not support
cancellation.  Wouldn't the Setup Call implementation be a better
template? E.g. a voicecall_send_tone and voicecall_send_tone_cancel?

> +
> +     err = __ofono_voicecall_send_tone(vc, dtmf,
> +                                             dtmf_sent_cb, stk->extern_req);
> +     if (err < 0)
> +             g_free(stk->extern_req);
> +
> +     if (err == -EBUSY) {
> +             rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +             return TRUE;
> +     }
> +
> +     if (err == -ENOSYS) {
> +             rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +             return TRUE;
> +     }
> +
> +     if (err == -ENOENT) {
> +             rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +             rsp->result.additional_len = sizeof(not_in_speech_call_result);
> +             rsp->result.additional = not_in_speech_call_result;
> +             return TRUE;
> +     }
> +
> +     if (err < 0) {
> +             /*
> +              * We most likely got an out of memory error, tell SIM
> +              * to retry
> +              */
> +             rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +             return TRUE;
> +     }
> +
> +     if (cmd->send_dtmf.alpha_id && cmd->send_dtmf.alpha_id[0])
> +             stk_alpha_id_set(stk, cmd->send_dtmf.alpha_id);
> +
> +     /*
> +      * Note that we don't strictly require an agent to be connected,
> +      * but to comply with 6.4.24 we need to send a End Session when
> +      * the user decides so.
> +      */
> +     stk->respond_on_exit = TRUE;
> +     stk->cancel_cmd = send_dtmf_cancel;
> +
> +     return FALSE;
> +}
> +
>  static void stk_proactive_command_cancel(struct ofono_stk *stk)
>  {
>       if (stk->immediate_response)
> @@ -1996,6 +2150,11 @@ void ofono_stk_proactive_command_notify(struct 
> ofono_stk *stk,
>                                                       &rsp, stk);
>               break;
>  
> +     case STK_COMMAND_TYPE_SEND_DTMF:
> +             respond = handle_command_send_dtmf(stk->pending_cmd,
> +                                                     &rsp, stk);
> +             break;
> +
>       default:
>               rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
>               break;

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

Reply via email to