--- src/stk.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 160 insertions(+), 8 deletions(-)
diff --git a/src/stk.c b/src/stk.c index 80b4d23..84a22c9 100644 --- a/src/stk.c +++ b/src/stk.c @@ -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; }; @@ -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; }; @@ -660,7 +660,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]) @@ -671,7 +671,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; @@ -697,6 +697,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) @@ -715,15 +721,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; } @@ -1824,6 +1829,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) { + 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) { + 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*#,*#,"; + 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); + + 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 +2143,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; -- 1.7.1.86.g0e460.dirty _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono