Open Source Telephony
 help / color / mirror / Atom feed
From: Andrzej Zaborowski <andrew.zaborowski@intel.com>
To: ofono@ofono.org
Subject: [PATCH 02/13] stk: Handle the Send DTMF proactive command.
Date: Wed, 13 Oct 2010 15:54:05 +0200	[thread overview]
Message-ID: <1286978056-16600-2-git-send-email-andrew.zaborowski@intel.com> (raw)
In-Reply-To: <1286978056-16600-1-git-send-email-andrew.zaborowski@intel.com>

[-- Attachment #1: Type: text/plain, Size: 7933 bytes --]

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.
---
 src/stk.c |  177 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 168 insertions(+), 9 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 80b4d23..3792d2f 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;
 };
@@ -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);
 	}
@@ -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])
@@ -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;
@@ -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)
@@ -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;
 	}
@@ -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) {
+		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*#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);
+
+	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;
-- 
1.7.1.86.g0e460.dirty


  reply	other threads:[~2010-10-13 13:54 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-13 13:54 [PATCH 01/13] voicecall: __ofono_voicecall_send_tone internal api Andrzej Zaborowski
2010-10-13 13:54 ` Andrzej Zaborowski [this message]
2010-10-14  8:55   ` [PATCH 02/13] stk: Handle the Send DTMF proactive command Denis Kenzior
2010-10-13 13:54 ` [PATCH 03/13] atmodem: Handle pauses in DTMF string Andrzej Zaborowski
2010-10-13 13:54 ` [PATCH 04/13] doc: Update property name to match code Andrzej Zaborowski
2010-10-14  5:56   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 05/13] doc: Add STK properties relevant for icons Andrzej Zaborowski
2010-10-14  8:08   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 06/13] stk: Pass icon IDs in stk agent request parameters Andrzej Zaborowski
2010-10-14  8:09   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 07/13] stk: Add icon ID information in stk_menu Andrzej Zaborowski
2010-10-14  8:09   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 08/13] stk: IdleModeIcon and MainMenuIcon properties Andrzej Zaborowski
2010-10-14  8:10   ` Denis Kenzior
2010-10-14  8:31     ` list-modems patch Alexander A Khryukin
2010-10-14  8:45       ` Marcel Holtmann
2010-10-14  9:17         ` Alexander A Khryukin
2010-10-14  9:34         ` Alexander A Khryukin
2010-10-14 10:13           ` Marcel Holtmann
2010-10-14 10:36             ` Alexander A Khryukin
2010-10-15  6:17               ` Marcel Holtmann
2010-10-13 13:54 ` [PATCH 09/13] stk: Simplify and add icon to alphaId api Andrzej Zaborowski
2010-10-14  8:56   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 10/13] stk: Apply STK text attributes as html Andrzej Zaborowski
2010-10-14  8:57   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 11/13] stkagent: Add PlayTone and LoopTone requests Andrzej Zaborowski
2010-10-14  9:02   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 12/13] stk: Handle the Play Tone proactive command Andrzej Zaborowski
2010-10-14  9:11   ` Denis Kenzior
2010-10-13 13:54 ` [PATCH 13/13] [RfC] API for STK driver to signal executed commands Andrzej Zaborowski
2010-10-14  9:17   ` Denis Kenzior
2010-10-14  8:47 ` [PATCH 01/13] voicecall: __ofono_voicecall_send_tone internal api Denis Kenzior
2010-10-19 14:10   ` Andrzej Zaborowski
2010-10-19 14:58     ` Denis Kenzior
2010-10-19 15:34       ` Andrzej Zaborowski
2010-10-19 15:59         ` Denis Kenzior

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1286978056-16600-2-git-send-email-andrew.zaborowski@intel.com \
    --to=andrew.zaborowski@intel.com \
    --cc=ofono@ofono.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox