All of lore.kernel.org
 help / color / mirror / Atom feed
* Add support for Send USSD proactive command handling
@ 2010-09-09 12:31 Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 01/12] atutil changes for parsing cscs query and cscs support Jeevaka Badrappan
                   ` (12 more replies)
  0 siblings, 13 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

Hi all,

  Following patches adds the support for Send USSD proactive command.
This also includes support for setting the character set using CSCS.
USSD driver API changed to accept dcs, binary data and length. USSD
atom drivers changed to reflect the API change.

Find the change statistics information as follows

 drivers/atmodem/atutil.c |   78 ++++++++++++++++++++
 drivers/atmodem/atutil.h |   26 +++++++
 drivers/atmodem/ussd.c   |   99 +++++++++++++++-----------
 drivers/isimodem/ussd.c  |   44 ++++--------
 include/types.h          |    1 +
 include/ussd.h           |    8 ++-
 plugins/atgen.c          |   59 +++++++++++++++
 plugins/phonesim.c       |   54 ++++++++++++++
 src/call-barring.c       |    5 ++
 src/call-forwarding.c    |    5 ++
 src/call-settings.c      |    5 ++
 src/ofono.h              |   26 +++++++
 src/stk.c                |  141 ++++++++++++++++++++++++++++++++++++-
 src/stkutil.c            |   35 +++++++++
 src/stkutil.h            |   13 ++++
 src/ussd.c               |  179 +++++++++++++++++++++++++++++++++++++++++-----
 16 files changed, 683 insertions(+), 95 deletions(-)

Regards,
jeevaka

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 01/12] atutil changes for parsing cscs query and cscs support
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 14:45   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 02/12] atgen changes for setting TE character set Jeevaka Badrappan
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/atutil.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/atmodem/atutil.h |   26 +++++++++++++++
 2 files changed, 104 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/atutil.c b/drivers/atmodem/atutil.c
index f566237..ffbcb6c 100644
--- a/drivers/atmodem/atutil.c
+++ b/drivers/atmodem/atutil.c
@@ -341,3 +341,81 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
 
 	return TRUE;
 }
+
+gboolean at_util_charset_string_to_charset(const char *str,
+					enum at_util_charset *charset)
+{
+	if (!g_strcmp0(str, "GSM"))
+		*charset = AT_UTIL_CHARSET_GSM;
+	else if (!g_strcmp0(str, "HEX"))
+		*charset = AT_UTIL_CHARSET_HEX;
+	else if (!g_strcmp0(str, "IRA"))
+		*charset = AT_UTIL_CHARSET_IRA;
+	else if (!g_strcmp0(str, "PCCP437"))
+		*charset = AT_UTIL_CHARSET_PCCP437;
+	else if (!g_strcmp0(str, "PCDN"))
+		*charset = AT_UTIL_CHARSET_PCDN;
+	else if (!g_strcmp0(str, "UCS2"))
+		*charset = AT_UTIL_CHARSET_UCS2;
+	else if (!g_strcmp0(str, "UTF-8"))
+		*charset = AT_UTIL_CHARSET_UTF8;
+	else if (!g_strcmp0(str, "8859-1"))
+		*charset = AT_UTIL_CHARSET_8859_1;
+	else if (!g_strcmp0(str, "8859-2"))
+		*charset = AT_UTIL_CHARSET_8859_2;
+	else if (!g_strcmp0(str, "8859-3"))
+		*charset = AT_UTIL_CHARSET_8859_3;
+	else if (!g_strcmp0(str, "8859-4"))
+		*charset = AT_UTIL_CHARSET_8859_4;
+	else if (!g_strcmp0(str, "8859-5"))
+		*charset = AT_UTIL_CHARSET_8859_5;
+	else if (!g_strcmp0(str, "8859-6"))
+		*charset = AT_UTIL_CHARSET_8859_6;
+	else if (!g_strcmp0(str, "8859-C"))
+		*charset = AT_UTIL_CHARSET_8859_C;
+	else if (!g_strcmp0(str, "8859-A"))
+		*charset = AT_UTIL_CHARSET_8859_A;
+	else if (!g_strcmp0(str, "8859-G"))
+		*charset = AT_UTIL_CHARSET_8859_G;
+	else if (!g_strcmp0(str, "8859-H"))
+		*charset = AT_UTIL_CHARSET_8859_H;
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported)
+{
+	GAtResultIter iter;
+	const char *str;
+	enum at_util_charset charset;
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CSCS:"))
+		return FALSE;
+
+	/* Some modems don't report CSCS in a proper list */
+	g_at_result_iter_open_list(&iter);
+
+	while (g_at_result_iter_next_string(&iter, &str)) {
+		if (at_util_charset_string_to_charset(str, &charset))
+			*supported |= charset;
+	}
+
+	g_at_result_iter_close_list(&iter);
+
+	return TRUE;
+}
+
+gboolean at_util_parse_cscs_query(GAtResult *result, const char **charset)
+{
+	GAtResultIter iter;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CSCS:"))
+		return FALSE;
+
+	return g_at_result_iter_next_string(&iter, charset);
+}
diff --git a/drivers/atmodem/atutil.h b/drivers/atmodem/atutil.h
index 9e0a84b..845d8de 100644
--- a/drivers/atmodem/atutil.h
+++ b/drivers/atmodem/atutil.h
@@ -27,6 +27,27 @@ enum at_util_sms_store {
 	AT_UTIL_SMS_STORE_BM =	4,
 };
 
+/* 3GPP TS 27.007 Release 8 Section 5.5 */
+enum at_util_charset {
+	AT_UTIL_CHARSET_GSM     = 1,
+	AT_UTIL_CHARSET_HEX     = 2,
+	AT_UTIL_CHARSET_IRA     = 3,
+	AT_UTIL_CHARSET_PCCP437 = 4,
+	AT_UTIL_CHARSET_PCDN    = 5,
+	AT_UTIL_CHARSET_UCS2    = 6,
+	AT_UTIL_CHARSET_UTF8    = 7,
+	AT_UTIL_CHARSET_8859_1  = 8,
+	AT_UTIL_CHARSET_8859_2  = 9,
+	AT_UTIL_CHARSET_8859_3  = 10,
+	AT_UTIL_CHARSET_8859_4  = 11,
+	AT_UTIL_CHARSET_8859_5  = 12,
+	AT_UTIL_CHARSET_8859_6  = 13,
+	AT_UTIL_CHARSET_8859_C  = 14,
+	AT_UTIL_CHARSET_8859_A  = 15,
+	AT_UTIL_CHARSET_8859_G  = 16,
+	AT_UTIL_CHARSET_8859_H  = 17,
+};
+
 void decode_at_error(struct ofono_error *error, const char *final);
 gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b);
 gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
@@ -46,6 +67,11 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
 						enum at_util_sms_store *store,
 						int *index);
 
+gboolean at_util_charset_string_to_charset(const char *str,
+						enum at_util_charset *charset);
+gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported);
+gboolean at_util_parse_cscs_query(GAtResult *result, const char **charset);
+
 struct cb_data {
 	void *cb;
 	void *data;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 02/12] atgen changes for setting TE character set
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 01/12] atutil changes for parsing cscs query and cscs support Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 14:50   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 03/12] phonesim " Jeevaka Badrappan
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 plugins/atgen.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/plugins/atgen.c b/plugins/atgen.c
index 1ce2467..a8ca177 100644
--- a/plugins/atgen.c
+++ b/plugins/atgen.c
@@ -25,6 +25,8 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
 
 #include <glib.h>
 #include <gatchat.h>
@@ -55,6 +57,9 @@
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
 
+static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
+
 static const char *tty_opts[] = {
 	"Baud",
 	"Read",
@@ -67,6 +72,58 @@ static const char *tty_opts[] = {
 	NULL,
 };
 
+static const char *best_charset(int supported)
+{
+	const char *charset = "Invalid";
+
+	if (supported & AT_UTIL_CHARSET_GSM)
+		charset = "GSM";
+
+	if (supported & AT_UTIL_CHARSET_UTF8)
+		charset = "UTF-8";
+
+	return charset;
+}
+
+static void set_charset_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	if (!ok)
+		ofono_error("Setting character set failed");
+}
+
+static void list_charsets_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	GAtChat *chat = ofono_modem_get_data(modem);
+	const char *charset;
+	int supported = 0;
+	char buf[32];
+
+	if (!ok)
+		return;
+
+	if (!at_util_parse_cscs_supported(result, &supported))
+		return;
+
+	charset = best_charset(supported);
+	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
+
+	if (!g_at_chat_send(chat, buf, none_prefix, set_charset_cb, modem,
+			NULL))
+		ofono_error("AT+CSCS=%s request failed", charset);
+}
+
+static void list_charsets(struct ofono_modem *modem)
+{
+	GAtChat *chat = ofono_modem_get_data(modem);
+
+	if (!g_at_chat_send(chat, "AT+CSCS=?", cscs_prefix,
+			list_charsets_cb, modem, NULL))
+		ofono_error("AT+CSCS=? request failed");
+}
+
 static int atgen_probe(struct ofono_modem *modem)
 {
 	return 0;
@@ -207,6 +264,8 @@ static void atgen_pre_sim(struct ofono_modem *modem)
 
 	if (sim)
 		ofono_sim_inserted_notify(sim, TRUE);
+
+	list_charsets(modem);
 }
 
 static void atgen_post_sim(struct ofono_modem *modem)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 03/12] phonesim changes for setting TE character set
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 01/12] atutil changes for parsing cscs query and cscs support Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 02/12] atgen changes for setting TE character set Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 19:01   ` [PATCH 03/13] " Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 04/12] USSD atom driver changes to read current character setting Jeevaka Badrappan
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 plugins/phonesim.c |   54 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)

diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index d3caa20..521e8ae 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -64,6 +64,7 @@
 #include <drivers/atmodem/atutil.h>
 
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct phonesim_data {
 	GAtMux *mux;
@@ -72,6 +73,57 @@ struct phonesim_data {
 	gboolean use_mux;
 };
 
+static const char *best_charset(int supported)
+{
+	const char *charset = "Invalid";
+
+	if (supported & AT_UTIL_CHARSET_UCS2)
+		charset = "UCS2";
+
+	if (supported & AT_UTIL_CHARSET_GSM)
+		charset = "GSM";
+
+	return charset;
+}
+
+static void set_charset_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	if (!ok)
+		ofono_error("Setting character set failed");
+}
+
+static void list_charsets_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+	const char *charset;
+	int supported = 0;
+	char buf[32];
+
+	if (!ok)
+		return;
+
+	if (!at_util_parse_cscs_supported(result, &supported))
+		return;
+
+	charset = best_charset(supported);
+	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
+
+	if (!g_at_chat_send(data->chat, buf, none_prefix, set_charset_cb, 
+			modem, NULL))
+		ofono_error("Setting charset: %s failed", charset);
+}
+
+static void list_charsets(struct ofono_modem *modem)
+{
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+	if (!g_at_chat_send(data->chat, "AT+CSCS=?", cscs_prefix,
+			list_charsets_cb, modem, NULL))
+		ofono_error("AT+CSCS=? request failed");
+}
+
 static int phonesim_probe(struct ofono_modem *modem)
 {
 	struct phonesim_data *data;
@@ -321,6 +373,8 @@ static void phonesim_pre_sim(struct ofono_modem *modem)
 
 	if (sim)
 		ofono_sim_inserted_notify(sim, TRUE);
+
+	list_charsets(modem);
 }
 
 static void phonesim_post_sim(struct ofono_modem *modem)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 04/12] USSD atom driver changes to read current character setting
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (2 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 03/12] phonesim " Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 19:02   ` [PATCH 04/13] " Jeevaka Badrappan
  2010-09-09 12:31 ` [PATCH 05/12] Add internal api __ofono_call_barring_is_busy Jeevaka Badrappan
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 1e1fc25..cb1515f 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -44,12 +44,27 @@
 
 static const char *cusd_prefix[] = { "+CUSD:", NULL };
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct ussd_data {
 	GAtChat *chat;
 	unsigned int vendor;
+	enum at_util_charset charset;
 };
 
+static void read_charset_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ussd_data *data = user_data;
+	const char *str = NULL;
+
+	if (!ok)
+		return;
+
+	if (at_util_parse_cscs_query(result, &str))
+		at_util_charset_string_to_charset(str, &data->charset);
+}
+
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
 	GAtResultIter iter;
@@ -247,6 +262,9 @@ static int at_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,
 
 	ofono_ussd_set_data(ussd, data);
 
+	g_at_chat_send(chat, "AT+CSCS?", cscs_prefix, read_charset_cb, data,
+			NULL);
+
 	g_at_chat_send(chat, "AT+CUSD=1", NULL, at_ussd_register, ussd, NULL);
 
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 05/12] Add internal api __ofono_call_barring_is_busy
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (3 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 04/12] USSD atom driver changes to read current character setting Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:06   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy Jeevaka Badrappan
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/call-barring.c |    5 +++++
 src/ofono.h        |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/call-barring.c b/src/call-barring.c
index 7607f3f..a0ac689 100644
--- a/src/call-barring.c
+++ b/src/call-barring.c
@@ -580,6 +580,11 @@ static void cb_unregister_ss_controls(struct ofono_call_barring *cb)
 	__ofono_ussd_passwd_unregister(cb->ussd, "353");
 }
 
+gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb)
+{
+	return cb->pending ? TRUE : FALSE;
+}
+
 static inline void cb_append_property(struct ofono_call_barring *cb,
 					DBusMessageIter *dict, int start,
 					int end, int cls, const char *property)
diff --git a/src/ofono.h b/src/ofono.h
index d95f2f2..41ba115 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -163,6 +163,9 @@ gboolean __ofono_modem_remove_atom_watch(struct ofono_modem *modem,
 void __ofono_atom_free(struct ofono_atom *atom);
 
 #include <ofono/call-barring.h>
+
+gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb);
+
 #include <ofono/call-forwarding.h>
 #include <ofono/call-meter.h>
 #include <ofono/call-settings.h>
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (4 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 05/12] Add internal api __ofono_call_barring_is_busy Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:07   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 07/12] Add internal api __ofono_call_settings_is_busy Jeevaka Badrappan
                   ` (6 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/call-forwarding.c |    5 +++++
 src/ofono.h           |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index 4e77144..3e9265b 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -1092,6 +1092,11 @@ static void cf_unregister_ss_controls(struct ofono_call_forwarding *cf)
 	__ofono_ussd_ssc_unregister(cf->ussd, "004");
 }
 
+gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
+{
+	return cf->pending ? TRUE : FALSE;
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
diff --git a/src/ofono.h b/src/ofono.h
index 41ba115..c3329a6 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -167,6 +167,9 @@ void __ofono_atom_free(struct ofono_atom *atom);
 gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb);
 
 #include <ofono/call-forwarding.h>
+
+gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf);
+
 #include <ofono/call-meter.h>
 #include <ofono/call-settings.h>
 #include <ofono/cbs.h>
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 07/12] Add internal api __ofono_call_settings_is_busy
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (5 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:07   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 08/12] Add Send USSD command specific result codes Jeevaka Badrappan
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/call-settings.c |    5 +++++
 src/ofono.h         |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/src/call-settings.c b/src/call-settings.c
index ab20062..9c536e9 100644
--- a/src/call-settings.c
+++ b/src/call-settings.c
@@ -778,6 +778,11 @@ static void cs_unregister_ss_controls(struct ofono_call_settings *cs)
 		__ofono_ussd_ssc_unregister(cs->ussd, "77");
 }
 
+gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs)
+{
+	return cs->pending ? TRUE : FALSE;
+}
+
 static DBusMessage *generate_get_properties_reply(struct ofono_call_settings *cs,
 							DBusMessage *msg)
 {
diff --git a/src/ofono.h b/src/ofono.h
index c3329a6..9b8d938 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -172,6 +172,9 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf);
 
 #include <ofono/call-meter.h>
 #include <ofono/call-settings.h>
+
+gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs);
+
 #include <ofono/cbs.h>
 #include <ofono/devinfo.h>
 #include <ofono/phonebook.h>
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 08/12] Add Send USSD command specific result codes
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (6 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 07/12] Add internal api __ofono_call_settings_is_busy Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:09   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 09/12] Add Send USSD terminal response data structures Jeevaka Badrappan
                   ` (4 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.h b/src/stkutil.h
index 44d167a..00cb264 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -237,6 +237,7 @@ enum stk_result_type {
 	STK_RESULT_TYPE_GO_BACK =			0x11,
 	STK_RESULT_TYPE_NO_RESPONSE =			0x12,
 	STK_RESULT_TYPE_HELP_REQUESTED =		0x13,
+	STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION =	0x14,
 
 	/* 0x20 to 0x2F are used to indicate that SIM should retry */
 	STK_RESULT_TYPE_TERMINAL_BUSY =			0x20,
@@ -254,6 +255,7 @@ enum stk_result_type {
 	STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD =		0x32,
 	STK_RESULT_TYPE_COMMAND_ID_UNKNOWN =		0x33,
 	STK_RESULT_TYPE_MINIMUM_NOT_MET =		0x36,
+	STK_RESULT_TYPE_USSD_RETURN_ERROR =		0x37,
 	STK_RESULT_TYPE_CALL_CONTROL_PERMANENT =	0x39,
 	STK_RESULT_TYPE_BIP_ERROR =			0x3A,
 	STK_RESULT_TYPE_ACCESS_TECHNOLOGY_ERROR =	0x3B,
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 09/12] Add Send USSD terminal response data structures
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (7 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 08/12] Add Send USSD command specific result codes Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:20   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling Jeevaka Badrappan
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.h |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.h b/src/stkutil.h
index 00cb264..c7665e3 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -1376,6 +1376,12 @@ struct stk_answer_text {
 	 */
 };
 
+struct stk_ussd_text {
+	const unsigned char *text;
+	int dcs;
+	int len;
+};
+
 struct stk_response_get_inkey {
 	struct stk_answer_text text;
 	struct stk_duration duration;
@@ -1447,6 +1453,10 @@ struct stk_response_run_at_command {
 	const char *at_response;
 };
 
+struct stk_response_send_ussd {
+	struct stk_ussd_text text;
+};
+
 struct stk_response {
 	unsigned char number;
 	unsigned char type;
@@ -1476,6 +1486,7 @@ struct stk_response {
 		struct stk_response_generic send_dtmf;
 		struct stk_response_generic language_notification;
 		struct stk_response_generic launch_browser;
+		struct stk_response_send_ussd send_ussd;
 	};
 
 	void (*destructor)(struct stk_response *response);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (8 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 09/12] Add Send USSD terminal response data structures Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:31   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command Jeevaka Badrappan
                   ` (2 subsequent siblings)
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index ae4cc32..e953ead 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4170,6 +4170,34 @@ static gboolean build_dataobj_text(struct stk_tlv_builder *tlv,
 	return stk_tlv_builder_close_container(tlv);
 }
 
+/* Defined in TS 102.223 Section 8.15 - USSD specific case*/
+static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
+					const void *data, gboolean cr)
+{
+	const struct stk_ussd_text *text = data;
+	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
+	gboolean ret;
+
+	if (!text->text || !text->len)
+		return TRUE;
+
+	if (stk_tlv_builder_open_container(tlv, cr, tag, TRUE) != TRUE)
+		return FALSE;
+
+	if (text->dcs != -1) {
+		if (stk_tlv_builder_append_byte(tlv, text->dcs) != TRUE)
+			return FALSE;
+		
+		ret = stk_tlv_builder_append_bytes(tlv, text->text, text->len);
+	} else
+		ret = stk_tlv_builder_append_text(tlv, -1, (const char *) text->text);
+
+	if (ret != TRUE)
+		return ret;
+
+	return stk_tlv_builder_close_container(tlv);
+}
+
 /* Described in TS 131.111 Section 8.17 */
 static gboolean build_dataobj_ussd_string(struct stk_tlv_builder *tlv,
 					const void *data, gboolean cr)
@@ -5459,6 +5487,13 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
 	case STK_COMMAND_TYPE_LANGUAGE_NOTIFICATION:
 	case STK_COMMAND_TYPE_LAUNCH_BROWSER:
 		break;
+	case STK_COMMAND_TYPE_SEND_USSD:
+		ok = build_dataobj(&builder,
+					build_dataobj_ussd_text,
+					DATAOBJ_FLAG_CR,
+					&response->send_ussd.text,
+					NULL);
+		break;
 	default:
 		return NULL;
 	};
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (9 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:59   ` Denis Kenzior
  2010-09-09 12:31 ` [PATCH 12/12] Handling of Send USSD proactive command Jeevaka Badrappan
  2010-09-13 23:00 ` Added UCS2 handling and review comments incorporated Jeevaka Badrappan
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c  |   81 ++++++++++-----------
 drivers/isimodem/ussd.c |   44 ++++--------
 include/types.h         |    1 +
 include/ussd.h          |    8 ++-
 src/ofono.h             |   17 +++++
 src/ussd.c              |  179 ++++++++++++++++++++++++++++++++++++++++++-----
 6 files changed, 236 insertions(+), 94 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index cb1515f..573417a 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -67,15 +67,14 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
 
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
+	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	GAtResultIter iter;
 	int status;
 	int dcs;
 	const char *content;
-	char *converted = NULL;
-	gboolean udhi;
 	enum sms_charset charset;
-	gboolean compressed;
-	gboolean iso639;
+	unsigned char msg[182];
+	long msg_len = 0;
 
 	g_at_result_iter_init(&iter, result);
 
@@ -89,33 +88,27 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 		goto out;
 
 	if (g_at_result_iter_next_number(&iter, &dcs)) {
-		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
-					&compressed, NULL, &iso639))
-			goto out;
-
-		if (udhi || compressed || iso639)
+		if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
 			goto out;
 	} else
 		charset = SMS_CHARSET_7BIT;
 
-	if (charset == SMS_CHARSET_7BIT)
-		converted = convert_gsm_to_utf8((const guint8 *) content,
-						strlen(content), NULL, NULL, 0);
-
-	else if (charset == SMS_CHARSET_8BIT) {
-		/* TODO: Figure out what to do with 8 bit data */
-		ofono_error("8-bit coded USSD response received");
-		status = 4; /* Not supported */
-	} else {
+	if (charset == SMS_CHARSET_7BIT) {
+		if (data->charset == AT_UTIL_CHARSET_GSM)
+			pack_7bit_own_buf((const guint8 *) content, 
+					strlen(content), 0, TRUE,
+					&msg_len, 0, msg);
+	} else if (charset == SMS_CHARSET_8BIT)
+		decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+	else {
 		/* No other encoding is mentioned in TS27007 7.15 */
 		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
 		status = 4; /* Not supported */
 	}
 
 out:
-	ofono_ussd_notify(ussd, status, converted);
-
-	g_free(converted);
+	ofono_ussd_notify(ussd, status, dcs, msg, (int) msg_len);
 }
 
 static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -132,45 +125,50 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	cusd_parse(result, ussd);
 }
 
-static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
+static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *binary_data,
+				int binary_data_len,
 				ofono_ussd_cb_t cb, void *user_data)
 {
 	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	struct cb_data *cbd = cb_data_new(cb, user_data);
-	unsigned char *converted = NULL;
-	int dcs;
-	int max_len;
-	long written;
 	char buf[256];
+	long max_chars = 182;
+	unsigned char *unpacked_buf = NULL;
+	long written;
+	enum sms_charset charset;
 
 	if (!cbd)
 		goto error;
 
 	cbd->user = ussd;
+        
+	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
+		charset = SMS_CHARSET_7BIT;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-
-	if (!converted)
-		goto error;
-	else {
-		dcs = 15;
-		max_len = 182;
-	}
+	if (charset == SMS_CHARSET_7BIT) {
+		unpacked_buf = unpack_7bit(binary_data, binary_data_len, 0,
+						TRUE, max_chars, &written, 0);
 
-	if (written > max_len)
-		goto error;
+		if ( !unpacked_buf || written <= 0)
+			goto error;
 
-	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
-			(int) written, converted, dcs);
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				(int) written, unpacked_buf, dcs);
 
-	g_free(converted);
-	converted = NULL;
+		g_free(unpacked_buf);
+		unpacked_buf = NULL;
+	} else 
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				binary_data_len, binary_data, dcs);
 
 	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
 		/* Ensure that the modem is using GSM character set. It
 		 * seems it defaults to IRA and then umlauts are not
 		 * properly encoded. The modem returns some weird from
-		 * of Latin-1, but it is not really Latin-1 either. */
+		 * of Latin-1, but it is not really Latin-1 either.
+		 */
 		g_at_chat_send(data->chat, "AT+CSCS=\"GSM\"", none_prefix,
 							NULL, NULL, NULL);
 	}
@@ -181,7 +179,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
 
 error:
 	g_free(cbd);
-	g_free(converted);
 
 	CALLBACK_WITH_FAILURE(cb, user_data);
 }
diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
index 330a141..6ac945b 100644
--- a/drivers/isimodem/ussd.c
+++ b/drivers/isimodem/ussd.c
@@ -74,7 +74,9 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 {
 	const unsigned char *msg = data;
 	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
-	char *converted = NULL;
+	int msg_len = 0;
+	int dcs = -1;
+	unsigned char *coded_msg = NULL;
 
 	if (!msg || len < 4)
 		goto out;
@@ -84,14 +86,11 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
 		goto out;
 
-	converted = ussd_decode(msg[1], msg[3], msg + 4);
-
-	if (converted)
-		status = OFONO_USSD_STATUS_NOTIFY;
-
+	dcs = msg[1];
+	msg_len = msg[3];
+	coded_msg = (guint8 *) msg+4;
 out:
-	ofono_ussd_notify(ussd, status, converted);
-	g_free(converted);
+	ofono_ussd_notify(ussd, status, dcs, coded_msg, msg_len);
 }
 
 
@@ -129,7 +128,7 @@ error:
 }
 
 static GIsiRequest *ussd_send(GIsiClient *client,
-				uint8_t *str, size_t len,
+				int dcs, uint8_t *str, size_t len,
 				void *data, GDestroyNotify notify)
 {
 	const uint8_t msg[] = {
@@ -138,7 +137,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 		0x01,		/* subblock count */
 		SS_GSM_USSD_STRING,
 		4 + len + 3,	/* subblock length */
-		0x0f,		/* DCS */
+		dcs,		/* DCS */
 		len,		/* string length */
 		/* USSD string goes here */
 	};
@@ -152,33 +151,18 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 				ussd_send_resp_cb, data, notify);
 }
 
-static void isi_request(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t cb, void *data)
+static void isi_request(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *binary_data, int binary_data_len,
+			ofono_ussd_cb_t cb, void *data)
 {
 	struct ussd_data *ud = ofono_ussd_get_data(ussd);
 	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
-	unsigned char buf[256];
-	unsigned char *packed = NULL;
-	unsigned char *converted = NULL;
-	long num_packed;
-	long written;
 
 	if (!cbd)
 		goto error;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-	if (!converted)
-		goto error;
-
-	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
-					&num_packed, 0, buf);
-
-	g_free(converted);
-
-	if (written > SS_MAX_USSD_LENGTH)
-		goto error;
-
-	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
+	if (ussd_send(ud->client, dcs, (guint8 *) binary_data,
+			binary_data_len, cbd, g_free))
 		return;
 
 error:
diff --git a/include/types.h b/include/types.h
index 6098cba..fbd3c6a 100644
--- a/include/types.h
+++ b/include/types.h
@@ -77,6 +77,7 @@ struct ofono_error {
 };
 
 #define OFONO_MAX_PHONE_NUMBER_LENGTH 20
+#define OFONO_MAX_USSD_LENGTH 160
 
 struct ofono_phone_number {
 	char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 1];
diff --git a/include/ussd.h b/include/ussd.h
index 96e04cb..08dfc40 100644
--- a/include/ussd.h
+++ b/include/ussd.h
@@ -45,13 +45,15 @@ struct ofono_ussd_driver {
 	const char *name;
 	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
 	void (*remove)(struct ofono_ussd *ussd);
-	void (*request)(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t, void *data);
+	void (*request)(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *binary_data, int binary_data_len,
+			ofono_ussd_cb_t, void *data);
 	void (*cancel)(struct ofono_ussd *ussd,
 				ofono_ussd_cb_t cb, void *data);
 };
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len);
 
 int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
 void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
diff --git a/src/ofono.h b/src/ofono.h
index 9b8d938..bc67c73 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -244,6 +244,13 @@ gboolean __ofono_ssn_mt_watch_remove(struct ofono_ssn *ssn, int id);
 
 #include <ofono/ussd.h>
 
+enum ofono_ussd_failure {
+	OFONO_USSD_FAILURE_NONE,
+	OFONO_USSD_FAILURE_USER_TERMINATED,
+	OFONO_USSD_FAILURE_RETURN_ERROR,
+	OFONO_USSD_FAILURE_TIMED_OUT,
+};
+
 typedef gboolean (*ofono_ussd_ssc_cb_t)(int type,
 					const char *sc,
 					const char *sia, const char *sib,
@@ -254,6 +261,10 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
 					const char *old, const char *new,
 					DBusMessage *msg, void *data);
 
+typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
+					const unsigned char *str,
+					int str_len, void *data);
+
 gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
 					ofono_ussd_ssc_cb_t cb, void *data,
 					ofono_destroy_func destroy);
@@ -264,6 +275,12 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
 					ofono_destroy_func destroy);
 void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
 
+gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *binary_data, int binary_data_len,
+			ofono_ussd_request_cb_t cb, void *user_data);
+
 #include <ofono/netreg.h>
 
 typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
diff --git a/src/ussd.c b/src/ussd.c
index 825d560..c58bd7c 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -34,6 +34,8 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "smsutil.h"
+#include "util.h"
 
 #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
 
@@ -46,6 +48,15 @@ enum ussd_state {
 	USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+	struct ofono_ussd *ussd;
+	int dcs;
+	unsigned char *str;
+	int str_len;
+	ofono_ussd_request_cb_t cb;
+	void *user_data;
+};
+
 struct ofono_ussd {
 	int state;
 	DBusMessage *pending;
@@ -56,6 +67,7 @@ struct ofono_ussd {
 	const struct ofono_ussd_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -306,15 +318,56 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+				const unsigned char *str, int str_len)
+{
+	struct ussd_request *req = ussd->req;
+
+	if (req && req->cb) {
+		req->cb(error, dcs, str, str_len, req->user_data);
+		g_free(req->str);
+		g_free(req);
+		ussd->req = NULL;
+	}
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+	switch (status) {
+	case OFONO_USSD_STATUS_TIMED_OUT:
+		return OFONO_USSD_FAILURE_TIMED_OUT;
+	case OFONO_USSD_STATUS_NOT_SUPPORTED:
+		return OFONO_USSD_FAILURE_RETURN_ERROR;
+	}
+
+	return OFONO_USSD_FAILURE_NONE;
+}
+
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *ussdstr = "USSD";
+	char *utf8_str = NULL;
+	gboolean utf8_str_valid = FALSE;
 	const char sig[] = { DBUS_TYPE_STRING, 0 };
 	DBusMessage *reply;
 	DBusMessageIter iter;
 	DBusMessageIter variant;
 
+	if (ussd->req &&
+		(status == OFONO_USSD_STATUS_NOTIFY ||
+		status == OFONO_USSD_STATUS_TERMINATED ||
+		status == OFONO_USSD_STATUS_TIMED_OUT ||
+		status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
+
+		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
+					dcs, data, data_len);
+
+		ussd_change_state(ussd, USSD_STATE_IDLE);
+		return;
+	}
+
 	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
 		ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -334,15 +387,21 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 		reply = __ofono_error_timed_out(ussd->pending);
 		goto out;
 	}
+	
+	if (data && data_len > 0)
+		utf8_str = ussd_decode(dcs, data_len, data);
+
+	if (!utf8_str) {
+		utf8_str = "";
+		status = OFONO_USSD_STATUS_NOTIFY;
+	} else
+		utf8_str_valid = TRUE;
 
 	/* TODO: Rework this in the Agent framework */
 	if (ussd->state == USSD_STATE_ACTIVE) {
 
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
 		dbus_message_iter_init_append(reply, &iter);
 
 		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
@@ -352,7 +411,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 							&variant);
 
 		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
-						&str);
+						&utf8_str);
 
 		dbus_message_iter_close_container(&iter, &variant);
 
@@ -364,10 +423,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
-		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
 						DBUS_TYPE_INVALID);
 
 		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
@@ -387,20 +443,17 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 			signal_name = "NotificationReceived";
 		}
 
-		if (!str)
-			str = "";
-
 		g_dbus_emit_signal(conn, path,
 				SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
-				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
+				DBUS_TYPE_STRING, &utf8_str, DBUS_TYPE_INVALID);
 
 		ussd_change_state(ussd, new_state);
-		return;
+		goto free;
 	} else {
 		ofono_error("Received an unsolicited USSD but can't handle.");
-		DBG("USSD is: status: %d, %s", status, str);
+		DBG("USSD is: status: %d, %s", status, utf8_str);
 
-		return;
+		goto free;
 	}
 
 out:
@@ -408,6 +461,10 @@ out:
 
 	dbus_message_unref(ussd->pending);
 	ussd->pending = NULL;
+
+free:
+	if (utf8_str_valid)
+		g_free(utf8_str);
 }
 
 static void ussd_callback(const struct ofono_error *error, void *data)
@@ -436,6 +493,12 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[256];
+	unsigned char *converted;
+	unsigned char *packed = NULL;
+	long num_packed;
+	long written;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -458,14 +521,27 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 	if (!valid_ussd_string(str))
 		return __ofono_error_invalid_format(msg);
 
-	DBG("OK, running USSD request");
+	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
+	if (!converted)
+		return __ofono_error_invalid_format(msg);
+
+	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
+					&num_packed, 0, buf);
+
+	g_free(converted);
+
+	if (num_packed > OFONO_MAX_USSD_LENGTH)
+		return __ofono_error_invalid_format(msg);
 
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
+	DBG("OK, running USSD request");
+
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_callback, ussd);
+	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
+				ussd_callback, ussd);
 
 	return NULL;
 }
@@ -496,6 +572,12 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[256];
+	unsigned char *converted;
+	unsigned char *packed = NULL;
+	long num_packed;
+	long written;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -510,12 +592,25 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 	if (strlen(str) == 0)
 		return __ofono_error_invalid_format(msg);
 
+	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
+	if (!converted)
+		return __ofono_error_invalid_format(msg);
+
+	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
+					&num_packed, 0, buf);
+
+	g_free(converted);
+
+	if (num_packed > OFONO_MAX_USSD_LENGTH)
+		return __ofono_error_invalid_args(msg);
+
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
+	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
+				ussd_response_callback, ussd);
 
 	return NULL;
 }
@@ -543,6 +638,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
 	reply = dbus_message_new_method_return(ussd->cancel);
 	__ofono_dbus_pending_reply(&ussd->cancel, reply);
 
+	if (ussd->req)
+		ussd_request_finish(ussd, -1, USSD_STATE_USER_ACTION, NULL, -1);
+
 	ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
@@ -741,3 +839,46 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 {
 	return ussd->driver_data;
 }
+
+static void ussd_request_callback(const struct ofono_error *error, void *data)
+{
+	struct ofono_ussd *ussd = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		ussd_request_finish(ussd, OFONO_USSD_FAILURE_RETURN_ERROR, -1, NULL, -1);
+	else
+		ussd_change_state(ussd,USSD_STATE_ACTIVE);
+}
+
+gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
+{
+	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
+		return TRUE;
+
+	return FALSE;
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *binary_data,
+				int binary_data_len,
+				ofono_ussd_request_cb_t cb, void *user_data)
+{
+	struct ussd_request *req;
+
+	if (!ussd->driver->request)
+		return -ENOSYS;
+
+	req = g_try_new0(struct ussd_request, 1);
+	req->dcs = dcs;
+	req->str = g_memdup(binary_data, binary_data_len);
+	req->str_len = binary_data_len;
+	req->cb = cb;
+	req->user_data = user_data;
+
+	ussd->req = req;
+
+	ussd->driver->request(ussd, dcs, binary_data, binary_data_len,
+				ussd_request_callback, ussd);
+
+	return 0;
+}
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 12/12] Handling of Send USSD proactive command
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (10 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command Jeevaka Badrappan
@ 2010-09-09 12:31 ` Jeevaka Badrappan
  2010-09-09 15:37   ` Denis Kenzior
  2010-09-13 23:00 ` Added UCS2 handling and review comments incorporated Jeevaka Badrappan
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 12:31 UTC (permalink / raw)
  To: ofono

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

---
 src/stk.c |  141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 140 insertions(+), 1 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 3fda2af..ff194f1 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -1590,6 +1590,142 @@ static gboolean handle_command_set_up_call(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static void send_ussd_callback(int error, int dcs, const unsigned char *msg,
+				int msg_len, void *userdata)
+{
+	struct ofono_stk *stk = userdata;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	struct stk_response rsp;
+	enum sms_charset charset;
+	
+	if (stk->pending_cmd->send_ussd.alpha_id &&
+			stk->pending_cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_unset(stk);
+
+	switch (error) {
+	case OFONO_USSD_FAILURE_NONE:
+		memset(&rsp, 0, sizeof(rsp));
+
+		rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+		if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL)) {
+			if (charset == SMS_CHARSET_7BIT)
+				rsp.send_ussd.text.dcs = 0x00;
+			else if (charset == SMS_CHARSET_8BIT)
+				rsp.send_ussd.text.dcs = 0x04;
+			else if (charset == SMS_CHARSET_UCS2)
+				rsp.send_ussd.text.dcs = 0x08;
+		} else
+			rsp.send_ussd.text.dcs = -1;
+
+		rsp.send_ussd.text.text = msg;
+		rsp.send_ussd.text.len = msg_len;
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	case OFONO_USSD_FAILURE_USER_TERMINATED:
+		send_simple_response(stk, 
+				STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION);
+		break;
+	case OFONO_USSD_FAILURE_TIMED_OUT:
+		send_simple_response(stk, STK_RESULT_TYPE_NETWORK_UNAVAILABLE);
+		break;
+	case OFONO_USSD_FAILURE_RETURN_ERROR:
+		send_simple_response(stk, STK_RESULT_TYPE_USSD_RETURN_ERROR);
+		break;
+	}
+}
+
+static gboolean handle_command_send_ussd(const struct stk_command *cmd,
+					struct stk_response *rsp,
+					struct ofono_stk *stk)
+{
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	static unsigned char busy_on_ss_result[] = { 0x03 };
+	static unsigned char busy_on_ussd_result[] = { 0x08 };
+	int err;
+
+	struct ofono_atom *cf_atom;
+	struct ofono_atom *cb_atom;
+	struct ofono_atom *cs_atom;
+	struct ofono_atom *ussd_atom;
+
+	struct ofono_call_forwarding *cf;
+	struct ofono_call_barring *cb;
+	struct ofono_call_settings *cs;
+	struct ofono_ussd *ussd;
+
+	cf_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
+	cb_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_BARRING);
+	cs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS);
+	ussd_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
+
+	if (cf_atom && __ofono_atom_get_registered(cf_atom)) {
+		cf = __ofono_atom_get_data(cf_atom);
+		if (__ofono_call_forwarding_is_busy(cf)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	if (cb_atom && __ofono_atom_get_registered(cb_atom)) {
+		cb = __ofono_atom_get_data(cb_atom);
+		if (__ofono_call_barring_is_busy(cb)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	if (cs_atom && __ofono_atom_get_registered(cs_atom)) {
+		cs = __ofono_atom_get_data(cs_atom);
+		if (__ofono_call_settings_is_busy(cs)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	if (!ussd_atom || !__ofono_atom_get_registered(ussd_atom)) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	ussd = __ofono_atom_get_data(ussd_atom);
+
+	if (__ofono_ussd_is_busy(ussd)) {
+		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+		rsp->result.additional_len = sizeof(busy_on_ussd_result);
+		rsp->result.additional = busy_on_ussd_result;
+		return TRUE;
+	}
+
+	err = __ofono_ussd_initiate(ussd, cmd->send_ussd.ussd_string.dcs,
+					cmd->send_ussd.ussd_string.string,
+					cmd->send_ussd.ussd_string.len,
+					send_ussd_callback, stk);
+
+	if (err >= 0) 
+		return FALSE;
+
+	if (err == -ENOSYS) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	if (cmd->send_ussd.alpha_id && cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_set(stk, cmd->send_ussd.alpha_id);
+
+	return FALSE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -1740,7 +1876,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 		respond = handle_command_set_up_call(stk->pending_cmd,
 							&rsp, stk);
 		break;
-
+	case STK_COMMAND_TYPE_SEND_USSD:
+		respond = handle_command_send_ussd(stk->pending_cmd,
+							&rsp, stk);
+		break;
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 01/12] atutil changes for parsing cscs query and cscs support
  2010-09-09 12:31 ` [PATCH 01/12] atutil changes for parsing cscs query and cscs support Jeevaka Badrappan
@ 2010-09-09 14:45   ` Denis Kenzior
  2010-09-09 18:56     ` Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 14:45 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/atutil.c |   78 ++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/atmodem/atutil.h |   26 +++++++++++++++
>  2 files changed, 104 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/atmodem/atutil.c b/drivers/atmodem/atutil.c
> index f566237..ffbcb6c 100644
> --- a/drivers/atmodem/atutil.c
> +++ b/drivers/atmodem/atutil.c
> @@ -341,3 +341,81 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
>  
>  	return TRUE;
>  }
> +
> +gboolean at_util_charset_string_to_charset(const char *str,
> +					enum at_util_charset *charset)
> +{
> +	if (!g_strcmp0(str, "GSM"))
> +		*charset = AT_UTIL_CHARSET_GSM;
> +	else if (!g_strcmp0(str, "HEX"))
> +		*charset = AT_UTIL_CHARSET_HEX;
> +	else if (!g_strcmp0(str, "IRA"))
> +		*charset = AT_UTIL_CHARSET_IRA;
> +	else if (!g_strcmp0(str, "PCCP437"))
> +		*charset = AT_UTIL_CHARSET_PCCP437;
> +	else if (!g_strcmp0(str, "PCDN"))
> +		*charset = AT_UTIL_CHARSET_PCDN;
> +	else if (!g_strcmp0(str, "UCS2"))
> +		*charset = AT_UTIL_CHARSET_UCS2;
> +	else if (!g_strcmp0(str, "UTF-8"))
> +		*charset = AT_UTIL_CHARSET_UTF8;
> +	else if (!g_strcmp0(str, "8859-1"))
> +		*charset = AT_UTIL_CHARSET_8859_1;
> +	else if (!g_strcmp0(str, "8859-2"))
> +		*charset = AT_UTIL_CHARSET_8859_2;
> +	else if (!g_strcmp0(str, "8859-3"))
> +		*charset = AT_UTIL_CHARSET_8859_3;
> +	else if (!g_strcmp0(str, "8859-4"))
> +		*charset = AT_UTIL_CHARSET_8859_4;
> +	else if (!g_strcmp0(str, "8859-5"))
> +		*charset = AT_UTIL_CHARSET_8859_5;
> +	else if (!g_strcmp0(str, "8859-6"))
> +		*charset = AT_UTIL_CHARSET_8859_6;
> +	else if (!g_strcmp0(str, "8859-C"))
> +		*charset = AT_UTIL_CHARSET_8859_C;
> +	else if (!g_strcmp0(str, "8859-A"))
> +		*charset = AT_UTIL_CHARSET_8859_A;
> +	else if (!g_strcmp0(str, "8859-G"))
> +		*charset = AT_UTIL_CHARSET_8859_G;
> +	else if (!g_strcmp0(str, "8859-H"))
> +		*charset = AT_UTIL_CHARSET_8859_H;
> +	else
> +		return FALSE;
> +
> +	return TRUE;
> +}
> +
> +gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported)
> +{
> +	GAtResultIter iter;
> +	const char *str;
> +	enum at_util_charset charset;
> +	g_at_result_iter_init(&iter, result);
> +
> +	if (!g_at_result_iter_next(&iter, "+CSCS:"))
> +		return FALSE;
> +
> +	/* Some modems don't report CSCS in a proper list */
> +	g_at_result_iter_open_list(&iter);
> +
> +	while (g_at_result_iter_next_string(&iter, &str)) {
> +		if (at_util_charset_string_to_charset(str, &charset))
> +			*supported |= charset;

If you're going to do this, then you better make sure that the enum
values are setup for ORing.  Right now a modem supporting
AT_UTIL_CHARSET_8859_A will test positive to supporting UTF8, GSM, HEX,
PCCDN to name a few.

> +	}
> +
> +	g_at_result_iter_close_list(&iter);
> +
> +	return TRUE;
> +}
> +
> +gboolean at_util_parse_cscs_query(GAtResult *result, const char **charset)

I suggest you do the conversion of string to the enum here and perhaps
make at_util_charset_string_to_charset static.

> +{
> +	GAtResultIter iter;
> +
> +	g_at_result_iter_init(&iter, result);
> +
> +	if (!g_at_result_iter_next(&iter, "+CSCS:"))
> +		return FALSE;
> +
> +	return g_at_result_iter_next_string(&iter, charset);
> +}
> diff --git a/drivers/atmodem/atutil.h b/drivers/atmodem/atutil.h
> index 9e0a84b..845d8de 100644
> --- a/drivers/atmodem/atutil.h
> +++ b/drivers/atmodem/atutil.h
> @@ -27,6 +27,27 @@ enum at_util_sms_store {
>  	AT_UTIL_SMS_STORE_BM =	4,
>  };
>  
> +/* 3GPP TS 27.007 Release 8 Section 5.5 */
> +enum at_util_charset {
> +	AT_UTIL_CHARSET_GSM     = 1,
> +	AT_UTIL_CHARSET_HEX     = 2,
> +	AT_UTIL_CHARSET_IRA     = 3,
> +	AT_UTIL_CHARSET_PCCP437 = 4,
> +	AT_UTIL_CHARSET_PCDN    = 5,
> +	AT_UTIL_CHARSET_UCS2    = 6,
> +	AT_UTIL_CHARSET_UTF8    = 7,
> +	AT_UTIL_CHARSET_8859_1  = 8,
> +	AT_UTIL_CHARSET_8859_2  = 9,
> +	AT_UTIL_CHARSET_8859_3  = 10,
> +	AT_UTIL_CHARSET_8859_4  = 11,
> +	AT_UTIL_CHARSET_8859_5  = 12,
> +	AT_UTIL_CHARSET_8859_6  = 13,
> +	AT_UTIL_CHARSET_8859_C  = 14,
> +	AT_UTIL_CHARSET_8859_A  = 15,
> +	AT_UTIL_CHARSET_8859_G  = 16,
> +	AT_UTIL_CHARSET_8859_H  = 17,
> +};

Please refer to doc/coding-style.txt Section M11 on the preferred coding
style.  Namely, use a single space after the enum name and before the
'=' and several tabs to align the enum value.  There should be plenty of
examples in stkutil.h...

> +
>  void decode_at_error(struct ofono_error *error, const char *final);
>  gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b);
>  gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
> @@ -46,6 +67,11 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
>  						enum at_util_sms_store *store,
>  						int *index);
>  
> +gboolean at_util_charset_string_to_charset(const char *str,
> +						enum at_util_charset *charset);
> +gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported);
> +gboolean at_util_parse_cscs_query(GAtResult *result, const char **charset);
> +
>  struct cb_data {
>  	void *cb;
>  	void *data;

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 02/12] atgen changes for setting TE character set
  2010-09-09 12:31 ` [PATCH 02/12] atgen changes for setting TE character set Jeevaka Badrappan
@ 2010-09-09 14:50   ` Denis Kenzior
  2010-09-09 19:00     ` [PATCH 02/13] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 14:50 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  plugins/atgen.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 59 insertions(+), 0 deletions(-)
> 
> diff --git a/plugins/atgen.c b/plugins/atgen.c
> index 1ce2467..a8ca177 100644
> --- a/plugins/atgen.c
> +++ b/plugins/atgen.c
> @@ -25,6 +25,8 @@
>  
>  #include <errno.h>
>  #include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
>  
>  #include <glib.h>
>  #include <gatchat.h>
> @@ -55,6 +57,9 @@
>  #include <ofono/gprs.h>
>  #include <ofono/gprs-context.h>
>  
> +static const char *none_prefix[] = { NULL };
> +static const char *cscs_prefix[] = { "+CSCS:", NULL };
> +
>  static const char *tty_opts[] = {
>  	"Baud",
>  	"Read",
> @@ -67,6 +72,58 @@ static const char *tty_opts[] = {
>  	NULL,
>  };
>  
> +static const char *best_charset(int supported)
> +{
> +	const char *charset = "Invalid";
> +
> +	if (supported & AT_UTIL_CHARSET_GSM)
> +		charset = "GSM";
> +
> +	if (supported & AT_UTIL_CHARSET_UTF8)
> +		charset = "UTF-8";
> +
> +	return charset;
> +}
> +
> +static void set_charset_cb(gboolean ok, GAtResult *result,
> +				gpointer user_data)
> +{
> +	if (!ok)
> +		ofono_error("Setting character set failed");

Use of functions that do nothing is discouraged.  If CSCS fails, it can
be easily seen from the AT command trace.

> +}
> +
> +static void list_charsets_cb(gboolean ok, GAtResult *result,
> +				gpointer user_data)
> +{
> +	struct ofono_modem *modem = user_data;
> +	GAtChat *chat = ofono_modem_get_data(modem);
> +	const char *charset;
> +	int supported = 0;
> +	char buf[32];
> +
> +	if (!ok)
> +		return;
> +
> +	if (!at_util_parse_cscs_supported(result, &supported))
> +		return;
> +
> +	charset = best_charset(supported);
> +	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
> +
> +	if (!g_at_chat_send(chat, buf, none_prefix, set_charset_cb, modem,
> +			NULL))
> +		ofono_error("AT+CSCS=%s request failed", charset);

In general oFono plugins do not check for errors on g_at_chat_send.

There are two reasons:
- There's nothing that can be done anyway, and printing the error is not
really helpful
- The plugin just setup the device, so any errors are most likely
programmer errors.

> +}
> +
> +static void list_charsets(struct ofono_modem *modem)
> +{
> +	GAtChat *chat = ofono_modem_get_data(modem);
> +
> +	if (!g_at_chat_send(chat, "AT+CSCS=?", cscs_prefix,
> +			list_charsets_cb, modem, NULL))
> +		ofono_error("AT+CSCS=? request failed");

Same comment as above..

> +}
> +
>  static int atgen_probe(struct ofono_modem *modem)
>  {
>  	return 0;
> @@ -207,6 +264,8 @@ static void atgen_pre_sim(struct ofono_modem *modem)
>  
>  	if (sim)
>  		ofono_sim_inserted_notify(sim, TRUE);
> +
> +	list_charsets(modem);
>  }
>  
>  static void atgen_post_sim(struct ofono_modem *modem)

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 05/12] Add internal api __ofono_call_barring_is_busy
  2010-09-09 12:31 ` [PATCH 05/12] Add internal api __ofono_call_barring_is_busy Jeevaka Badrappan
@ 2010-09-09 15:06   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:06 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/call-barring.c |    5 +++++
>  src/ofono.h        |    3 +++
>  2 files changed, 8 insertions(+), 0 deletions(-)

Patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy
  2010-09-09 12:31 ` [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy Jeevaka Badrappan
@ 2010-09-09 15:07   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:07 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/call-forwarding.c |    5 +++++
>  src/ofono.h           |    3 +++
>  2 files changed, 8 insertions(+), 0 deletions(-)
> 
Patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 07/12] Add internal api __ofono_call_settings_is_busy
  2010-09-09 12:31 ` [PATCH 07/12] Add internal api __ofono_call_settings_is_busy Jeevaka Badrappan
@ 2010-09-09 15:07   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:07 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/call-settings.c |    5 +++++
>  src/ofono.h         |    3 +++
>  2 files changed, 8 insertions(+), 0 deletions(-)
> 
Patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 08/12] Add Send USSD command specific result codes
  2010-09-09 12:31 ` [PATCH 08/12] Add Send USSD command specific result codes Jeevaka Badrappan
@ 2010-09-09 15:09   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:09 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/stkutil.h |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/src/stkutil.h b/src/stkutil.h
> index 44d167a..00cb264 100644
> --- a/src/stkutil.h
> +++ b/src/stkutil.h
> @@ -237,6 +237,7 @@ enum stk_result_type {
>  	STK_RESULT_TYPE_GO_BACK =			0x11,
>  	STK_RESULT_TYPE_NO_RESPONSE =			0x12,
>  	STK_RESULT_TYPE_HELP_REQUESTED =		0x13,
> +	STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION =	0x14,
>  
>  	/* 0x20 to 0x2F are used to indicate that SIM should retry */
>  	STK_RESULT_TYPE_TERMINAL_BUSY =			0x20,
> @@ -254,6 +255,7 @@ enum stk_result_type {
>  	STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD =		0x32,
>  	STK_RESULT_TYPE_COMMAND_ID_UNKNOWN =		0x33,
>  	STK_RESULT_TYPE_MINIMUM_NOT_MET =		0x36,
> +	STK_RESULT_TYPE_USSD_RETURN_ERROR =		0x37,
>  	STK_RESULT_TYPE_CALL_CONTROL_PERMANENT =	0x39,
>  	STK_RESULT_TYPE_BIP_ERROR =			0x3A,
>  	STK_RESULT_TYPE_ACCESS_TECHNOLOGY_ERROR =	0x3B,

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 09/12] Add Send USSD terminal response data structures
  2010-09-09 12:31 ` [PATCH 09/12] Add Send USSD terminal response data structures Jeevaka Badrappan
@ 2010-09-09 15:20   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:20 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/stkutil.h |   11 +++++++++++
>  1 files changed, 11 insertions(+), 0 deletions(-)
> 

This patch has been applied, but I reworded the commit message somewhat.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-09 12:31 ` [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling Jeevaka Badrappan
@ 2010-09-09 15:31   ` Denis Kenzior
  2010-09-09 19:06     ` [PATCH 10/13] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:31 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/stkutil.c |   35 +++++++++++++++++++++++++++++++++++
>  1 files changed, 35 insertions(+), 0 deletions(-)
> 
> diff --git a/src/stkutil.c b/src/stkutil.c
> index ae4cc32..e953ead 100644
> --- a/src/stkutil.c
> +++ b/src/stkutil.c
> @@ -4170,6 +4170,34 @@ static gboolean build_dataobj_text(struct stk_tlv_builder *tlv,
>  	return stk_tlv_builder_close_container(tlv);
>  }
>  
> +/* Defined in TS 102.223 Section 8.15 - USSD specific case*/
> +static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
> +					const void *data, gboolean cr)
> +{
> +	const struct stk_ussd_text *text = data;
> +	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
> +	gboolean ret;
> +
> +	if (!text->text || !text->len)
> +		return TRUE;

You have to be a bit careful here.  Text does support the notion of
NULL/empty strings.  E.g. the CTLV is present, and the length is set to
0.  Refer to ETSI 102.223 Section 8.15.

> +
> +	if (stk_tlv_builder_open_container(tlv, cr, tag, TRUE) != TRUE)
> +		return FALSE;
> +
> +	if (text->dcs != -1) {
> +		if (stk_tlv_builder_append_byte(tlv, text->dcs) != TRUE)
> +			return FALSE;
> +		
> +		ret = stk_tlv_builder_append_bytes(tlv, text->text, text->len);
> +	} else
> +		ret = stk_tlv_builder_append_text(tlv, -1, (const char *) text->text);

I prefer that we assume dcs will always be 0x00, 0x04 or 0x08.

> +
> +	if (ret != TRUE)
> +		return ret;
> +
> +	return stk_tlv_builder_close_container(tlv);
> +}
> +
>  /* Described in TS 131.111 Section 8.17 */
>  static gboolean build_dataobj_ussd_string(struct stk_tlv_builder *tlv,
>  					const void *data, gboolean cr)
> @@ -5459,6 +5487,13 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
>  	case STK_COMMAND_TYPE_LANGUAGE_NOTIFICATION:
>  	case STK_COMMAND_TYPE_LAUNCH_BROWSER:
>  		break;
> +	case STK_COMMAND_TYPE_SEND_USSD:
> +		ok = build_dataobj(&builder,
> +					build_dataobj_ussd_text,
> +					DATAOBJ_FLAG_CR,
> +					&response->send_ussd.text,
> +					NULL);
> +		break;
>  	default:
>  		return NULL;
>  	};

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 12/12] Handling of Send USSD proactive command
  2010-09-09 12:31 ` [PATCH 12/12] Handling of Send USSD proactive command Jeevaka Badrappan
@ 2010-09-09 15:37   ` Denis Kenzior
  2010-09-09 19:42     ` [PATCH 8/8] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:37 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  src/stk.c |  141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 140 insertions(+), 1 deletions(-)
> 
> diff --git a/src/stk.c b/src/stk.c
> index 3fda2af..ff194f1 100644
> --- a/src/stk.c
> +++ b/src/stk.c
> @@ -1590,6 +1590,142 @@ static gboolean handle_command_set_up_call(const struct stk_command *cmd,
>  	return FALSE;
>  }
>  
> +static void send_ussd_callback(int error, int dcs, const unsigned char *msg,
> +				int msg_len, void *userdata)
> +{
> +	struct ofono_stk *stk = userdata;
> +	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
> +	struct stk_response rsp;
> +	enum sms_charset charset;
> +	
> +	if (stk->pending_cmd->send_ussd.alpha_id &&
> +			stk->pending_cmd->send_ussd.alpha_id[0])
> +		stk_alpha_id_unset(stk);
> +
> +	switch (error) {
> +	case OFONO_USSD_FAILURE_NONE:
> +		memset(&rsp, 0, sizeof(rsp));
> +
> +		rsp.result.type = STK_RESULT_TYPE_SUCCESS;
> +
> +		if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
> +					NULL, NULL, NULL)) {
> +			if (charset == SMS_CHARSET_7BIT)
> +				rsp.send_ussd.text.dcs = 0x00;
> +			else if (charset == SMS_CHARSET_8BIT)
> +				rsp.send_ussd.text.dcs = 0x04;
> +			else if (charset == SMS_CHARSET_UCS2)
> +				rsp.send_ussd.text.dcs = 0x08;
> +		} else
> +			rsp.send_ussd.text.dcs = -1;

As mentioned before, let us not bother with dcs == -1.  If the DCS
cannot be parsed, then simply fail.

> +
> +		rsp.send_ussd.text.text = msg;
> +		rsp.send_ussd.text.len = msg_len;
> +
> +		if (stk_respond(stk, &rsp, stk_command_cb))
> +			stk_command_cb(&failure, stk);
> +
> +		break;
> +	case OFONO_USSD_FAILURE_USER_TERMINATED:
> +		send_simple_response(stk, 
> +				STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION);
> +		break;
> +	case OFONO_USSD_FAILURE_TIMED_OUT:
> +		send_simple_response(stk, STK_RESULT_TYPE_NETWORK_UNAVAILABLE);
> +		break;
> +	case OFONO_USSD_FAILURE_RETURN_ERROR:
> +		send_simple_response(stk, STK_RESULT_TYPE_USSD_RETURN_ERROR);
> +		break;
> +	}
> +}
> +
> +static gboolean handle_command_send_ussd(const struct stk_command *cmd,
> +					struct stk_response *rsp,
> +					struct ofono_stk *stk)
> +{
> +	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
> +	static unsigned char busy_on_ss_result[] = { 0x03 };
> +	static unsigned char busy_on_ussd_result[] = { 0x08 };
> +	int err;
> +
> +	struct ofono_atom *cf_atom;
> +	struct ofono_atom *cb_atom;
> +	struct ofono_atom *cs_atom;
> +	struct ofono_atom *ussd_atom;
> +
> +	struct ofono_call_forwarding *cf;
> +	struct ofono_call_barring *cb;
> +	struct ofono_call_settings *cs;
> +	struct ofono_ussd *ussd;
> +
> +	cf_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
> +	cb_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_BARRING);
> +	cs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS);
> +	ussd_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
> +
> +	if (cf_atom && __ofono_atom_get_registered(cf_atom)) {
> +		cf = __ofono_atom_get_data(cf_atom);
> +		if (__ofono_call_forwarding_is_busy(cf)) {
> +			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +			rsp->result.additional_len = sizeof(busy_on_ss_result);
> +			rsp->result.additional = busy_on_ss_result;
> +			return TRUE;
> +		}
> +	}

Actually I prefer something like:

struct ofono_atom *atom;
struct ofono_ussd *ussd;

atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
if (atom && __ofono_atom_get_registered(atom)) {
	struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
	....
}

> +
> +	if (cb_atom && __ofono_atom_get_registered(cb_atom)) {
> +		cb = __ofono_atom_get_data(cb_atom);
> +		if (__ofono_call_barring_is_busy(cb)) {
> +			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +			rsp->result.additional_len = sizeof(busy_on_ss_result);
> +			rsp->result.additional = busy_on_ss_result;
> +			return TRUE;
> +		}
> +	}
> +
> +	if (cs_atom && __ofono_atom_get_registered(cs_atom)) {
> +		cs = __ofono_atom_get_data(cs_atom);
> +		if (__ofono_call_settings_is_busy(cs)) {
> +			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +			rsp->result.additional_len = sizeof(busy_on_ss_result);
> +			rsp->result.additional = busy_on_ss_result;
> +			return TRUE;
> +		}
> +	}
> +
> +	if (!ussd_atom || !__ofono_atom_get_registered(ussd_atom)) {
> +		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +		return TRUE;
> +	}
> +
> +	ussd = __ofono_atom_get_data(ussd_atom);
> +
> +	if (__ofono_ussd_is_busy(ussd)) {
> +		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
> +		rsp->result.additional_len = sizeof(busy_on_ussd_result);
> +		rsp->result.additional = busy_on_ussd_result;
> +		return TRUE;
> +	}
> +
> +	err = __ofono_ussd_initiate(ussd, cmd->send_ussd.ussd_string.dcs,
> +					cmd->send_ussd.ussd_string.string,
> +					cmd->send_ussd.ussd_string.len,
> +					send_ussd_callback, stk);
> +
> +	if (err >= 0) 
> +		return FALSE;
> +
> +	if (err == -ENOSYS) {
> +		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +		return TRUE;
> +	}
> +
> +	if (cmd->send_ussd.alpha_id && cmd->send_ussd.alpha_id[0])
> +		stk_alpha_id_set(stk, cmd->send_ussd.alpha_id);
> +
> +	return FALSE;
> +}
> +
>  static void stk_proactive_command_cancel(struct ofono_stk *stk)
>  {
>  	if (stk->immediate_response)
> @@ -1740,7 +1876,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
>  		respond = handle_command_set_up_call(stk->pending_cmd,
>  							&rsp, stk);
>  		break;
> -
> +	case STK_COMMAND_TYPE_SEND_USSD:
> +		respond = handle_command_send_ussd(stk->pending_cmd,
> +							&rsp, stk);
> +		break;
>  	default:
>  		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
>  		break;

Rest is looking fine to me.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command
  2010-09-09 12:31 ` [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command Jeevaka Badrappan
@ 2010-09-09 15:59   ` Denis Kenzior
  2010-09-09 20:25     ` [PATCH 6/8] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-09 15:59 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 07:31 AM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/ussd.c  |   81 ++++++++++-----------
>  drivers/isimodem/ussd.c |   44 ++++--------
>  include/types.h         |    1 +
>  include/ussd.h          |    8 ++-
>  src/ofono.h             |   17 +++++
>  src/ussd.c              |  179 ++++++++++++++++++++++++++++++++++++++++++-----
>  6 files changed, 236 insertions(+), 94 deletions(-)

Please break this patch up into two.  One with the core driver changes
and one for implementing __ofono_ussd_initiate

> 
> diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
> index cb1515f..573417a 100644
> --- a/drivers/atmodem/ussd.c
> +++ b/drivers/atmodem/ussd.c
> @@ -67,15 +67,14 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
>  
>  static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
>  {
> +	struct ussd_data *data = ofono_ussd_get_data(ussd);
>  	GAtResultIter iter;
>  	int status;
>  	int dcs;
>  	const char *content;
> -	char *converted = NULL;
> -	gboolean udhi;
>  	enum sms_charset charset;
> -	gboolean compressed;
> -	gboolean iso639;
> +	unsigned char msg[182];

The buffer should be 160 bytes no?

> +	long msg_len = 0;
>  
>  	g_at_result_iter_init(&iter, result);
>  
> @@ -89,33 +88,27 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
>  		goto out;
>  
>  	if (g_at_result_iter_next_number(&iter, &dcs)) {
> -		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
> -					&compressed, NULL, &iso639))
> -			goto out;
> -
> -		if (udhi || compressed || iso639)
> +		if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
> +					NULL, NULL, NULL))
>  			goto out;
>  	} else
>  		charset = SMS_CHARSET_7BIT;
>  
> -	if (charset == SMS_CHARSET_7BIT)
> -		converted = convert_gsm_to_utf8((const guint8 *) content,
> -						strlen(content), NULL, NULL, 0);
> -
> -	else if (charset == SMS_CHARSET_8BIT) {
> -		/* TODO: Figure out what to do with 8 bit data */
> -		ofono_error("8-bit coded USSD response received");
> -		status = 4; /* Not supported */
> -	} else {
> +	if (charset == SMS_CHARSET_7BIT) {
> +		if (data->charset == AT_UTIL_CHARSET_GSM)
> +			pack_7bit_own_buf((const guint8 *) content, 
> +					strlen(content), 0, TRUE,
> +					&msg_len, 0, msg);
> +	} else if (charset == SMS_CHARSET_8BIT)
> +		decode_hex_own_buf(content, -1, &msg_len, 0, msg);
> +	else {
>  		/* No other encoding is mentioned in TS27007 7.15 */
>  		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
>  		status = 4; /* Not supported */
>  	}
>  
>  out:
> -	ofono_ussd_notify(ussd, status, converted);
> -
> -	g_free(converted);
> +	ofono_ussd_notify(ussd, status, dcs, msg, (int) msg_len);

I don't think you need the cast here

>  }
>  
>  static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
> @@ -132,45 +125,50 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
>  	cusd_parse(result, ussd);
>  }
>  
> -static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
> +static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
> +				const unsigned char *binary_data,
> +				int binary_data_len,
>  				ofono_ussd_cb_t cb, void *user_data)
>  {
>  	struct ussd_data *data = ofono_ussd_get_data(ussd);
>  	struct cb_data *cbd = cb_data_new(cb, user_data);
> -	unsigned char *converted = NULL;
> -	int dcs;
> -	int max_len;
> -	long written;
>  	char buf[256];
> +	long max_chars = 182;
> +	unsigned char *unpacked_buf = NULL;
> +	long written;
> +	enum sms_charset charset;
>  
>  	if (!cbd)
>  		goto error;
>  
>  	cbd->user = ussd;
> +        
> +	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
> +					NULL, NULL, NULL))
> +		charset = SMS_CHARSET_7BIT;

Failing is fine here.  As a general rule, it is better to fail early.

>  
> -	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> -
> -	if (!converted)
> -		goto error;
> -	else {
> -		dcs = 15;
> -		max_len = 182;
> -	}
> +	if (charset == SMS_CHARSET_7BIT) {
> +		unpacked_buf = unpack_7bit(binary_data, binary_data_len, 0,
> +						TRUE, max_chars, &written, 0);
>  
> -	if (written > max_len)
> -		goto error;
> +		if ( !unpacked_buf || written <= 0)
> +			goto error;
>  
> -	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> -			(int) written, converted, dcs);
> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				(int) written, unpacked_buf, dcs);
>  
> -	g_free(converted);
> -	converted = NULL;
> +		g_free(unpacked_buf);
> +		unpacked_buf = NULL;
> +	} else 
> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				binary_data_len, binary_data, dcs);

This should be hex encoded

>  
>  	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
>  		/* Ensure that the modem is using GSM character set. It
>  		 * seems it defaults to IRA and then umlauts are not
>  		 * properly encoded. The modem returns some weird from
> -		 * of Latin-1, but it is not really Latin-1 either. */
> +		 * of Latin-1, but it is not really Latin-1 either.
> +		 */

Please send this as a separate cleanup patch

>  		g_at_chat_send(data->chat, "AT+CSCS=\"GSM\"", none_prefix,
>  							NULL, NULL, NULL);
>  	}
> @@ -181,7 +179,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
>  
>  error:
>  	g_free(cbd);
> -	g_free(converted);
>  
>  	CALLBACK_WITH_FAILURE(cb, user_data);
>  }
> diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
> index 330a141..6ac945b 100644
> --- a/drivers/isimodem/ussd.c
> +++ b/drivers/isimodem/ussd.c
> @@ -74,7 +74,9 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
>  {
>  	const unsigned char *msg = data;
>  	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
> -	char *converted = NULL;
> +	int msg_len = 0;
> +	int dcs = -1;
> +	unsigned char *coded_msg = NULL;
>  
>  	if (!msg || len < 4)
>  		goto out;
> @@ -84,14 +86,11 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
>  	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
>  		goto out;
>  
> -	converted = ussd_decode(msg[1], msg[3], msg + 4);
> -
> -	if (converted)
> -		status = OFONO_USSD_STATUS_NOTIFY;
> -
> +	dcs = msg[1];
> +	msg_len = msg[3];
> +	coded_msg = (guint8 *) msg+4;
>  out:
> -	ofono_ussd_notify(ussd, status, converted);
> -	g_free(converted);
> +	ofono_ussd_notify(ussd, status, dcs, coded_msg, msg_len);
>  }
>  
>  
> @@ -129,7 +128,7 @@ error:
>  }
>  
>  static GIsiRequest *ussd_send(GIsiClient *client,
> -				uint8_t *str, size_t len,
> +				int dcs, uint8_t *str, size_t len,
>  				void *data, GDestroyNotify notify)
>  {
>  	const uint8_t msg[] = {
> @@ -138,7 +137,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
>  		0x01,		/* subblock count */
>  		SS_GSM_USSD_STRING,
>  		4 + len + 3,	/* subblock length */
> -		0x0f,		/* DCS */
> +		dcs,		/* DCS */
>  		len,		/* string length */
>  		/* USSD string goes here */
>  	};
> @@ -152,33 +151,18 @@ static GIsiRequest *ussd_send(GIsiClient *client,
>  				ussd_send_resp_cb, data, notify);
>  }
>  
> -static void isi_request(struct ofono_ussd *ussd, const char *str,
> -				ofono_ussd_cb_t cb, void *data)
> +static void isi_request(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *binary_data, int binary_data_len,
> +			ofono_ussd_cb_t cb, void *data)
>  {
>  	struct ussd_data *ud = ofono_ussd_get_data(ussd);
>  	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
> -	unsigned char buf[256];
> -	unsigned char *packed = NULL;
> -	unsigned char *converted = NULL;
> -	long num_packed;
> -	long written;
>  
>  	if (!cbd)
>  		goto error;
>  
> -	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> -	if (!converted)
> -		goto error;
> -
> -	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
> -					&num_packed, 0, buf);
> -
> -	g_free(converted);
> -
> -	if (written > SS_MAX_USSD_LENGTH)
> -		goto error;
> -
> -	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
> +	if (ussd_send(ud->client, dcs, (guint8 *) binary_data,
> +			binary_data_len, cbd, g_free))
>  		return;
>  

This looks fine to me

>  error:
> diff --git a/include/types.h b/include/types.h
> index 6098cba..fbd3c6a 100644
> --- a/include/types.h
> +++ b/include/types.h
> @@ -77,6 +77,7 @@ struct ofono_error {
>  };
>  
>  #define OFONO_MAX_PHONE_NUMBER_LENGTH 20
> +#define OFONO_MAX_USSD_LENGTH 160

This define is only being used by ussd.c.  If so, please move it out to
ussd.c and don't give it the OFONO_ prefix.

>  
>  struct ofono_phone_number {
>  	char number[OFONO_MAX_PHONE_NUMBER_LENGTH + 1];
> diff --git a/include/ussd.h b/include/ussd.h
> index 96e04cb..08dfc40 100644
> --- a/include/ussd.h
> +++ b/include/ussd.h
> @@ -45,13 +45,15 @@ struct ofono_ussd_driver {
>  	const char *name;
>  	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
>  	void (*remove)(struct ofono_ussd *ussd);
> -	void (*request)(struct ofono_ussd *ussd, const char *str,
> -				ofono_ussd_cb_t, void *data);
> +	void (*request)(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *binary_data, int binary_data_len,
> +			ofono_ussd_cb_t, void *data);
>  	void (*cancel)(struct ofono_ussd *ussd,
>  				ofono_ussd_cb_t cb, void *data);
>  };
>  
> -void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
> +void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
> +			const unsigned char *data, int data_len);
>  
>  int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
>  void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
> diff --git a/src/ofono.h b/src/ofono.h
> index 9b8d938..bc67c73 100644
> --- a/src/ofono.h
> +++ b/src/ofono.h
> @@ -244,6 +244,13 @@ gboolean __ofono_ssn_mt_watch_remove(struct ofono_ssn *ssn, int id);
>  
>  #include <ofono/ussd.h>
>  
> +enum ofono_ussd_failure {
> +	OFONO_USSD_FAILURE_NONE,
> +	OFONO_USSD_FAILURE_USER_TERMINATED,
> +	OFONO_USSD_FAILURE_RETURN_ERROR,
> +	OFONO_USSD_FAILURE_TIMED_OUT,
> +};
> +
>  typedef gboolean (*ofono_ussd_ssc_cb_t)(int type,
>  					const char *sc,
>  					const char *sia, const char *sib,
> @@ -254,6 +261,10 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
>  					const char *old, const char *new,
>  					DBusMessage *msg, void *data);
>  
> +typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
> +					const unsigned char *str,
> +					int str_len, void *data);
> +
>  gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
>  					ofono_ussd_ssc_cb_t cb, void *data,
>  					ofono_destroy_func destroy);
> @@ -264,6 +275,12 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
>  					ofono_destroy_func destroy);
>  void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
>  
> +gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
> +
> +int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *binary_data, int binary_data_len,

naming these data or pdu and len is good enough

> +			ofono_ussd_request_cb_t cb, void *user_data);
> +
>  #include <ofono/netreg.h>
>  
>  typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
> diff --git a/src/ussd.c b/src/ussd.c
> index 825d560..c58bd7c 100644
> --- a/src/ussd.c
> +++ b/src/ussd.c
> @@ -34,6 +34,8 @@
>  #include "ofono.h"
>  
>  #include "common.h"
> +#include "smsutil.h"
> +#include "util.h"
>  
>  #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
>  
> @@ -46,6 +48,15 @@ enum ussd_state {
>  	USSD_STATE_RESPONSE_SENT,
>  };
>  
> +struct ussd_request {
> +	struct ofono_ussd *ussd;
> +	int dcs;
> +	unsigned char *str;
> +	int str_len;
> +	ofono_ussd_request_cb_t cb;
> +	void *user_data;
> +};
> +
>  struct ofono_ussd {
>  	int state;
>  	DBusMessage *pending;
> @@ -56,6 +67,7 @@ struct ofono_ussd {
>  	const struct ofono_ussd_driver *driver;
>  	void *driver_data;
>  	struct ofono_atom *atom;
> +	struct ussd_request *req;
>  };
>  
>  struct ssc_entry {
> @@ -306,15 +318,56 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
>  			"State", DBUS_TYPE_STRING, &value);
>  }
>  
> -void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
> +static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
> +				const unsigned char *str, int str_len)
> +{
> +	struct ussd_request *req = ussd->req;
> +
> +	if (req && req->cb) {
> +		req->cb(error, dcs, str, str_len, req->user_data);
> +		g_free(req->str);
> +		g_free(req);
> +		ussd->req = NULL;
> +	}
> +}
> +
> +static int ussd_status_to_failure_code(int status)
> +{
> +	switch (status) {
> +	case OFONO_USSD_STATUS_TIMED_OUT:
> +		return OFONO_USSD_FAILURE_TIMED_OUT;
> +	case OFONO_USSD_STATUS_NOT_SUPPORTED:
> +		return OFONO_USSD_FAILURE_RETURN_ERROR;
> +	}
> +
> +	return OFONO_USSD_FAILURE_NONE;
> +}
> +
> +void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
> +			const unsigned char *data, int data_len)
>  {
>  	DBusConnection *conn = ofono_dbus_get_connection();
>  	const char *ussdstr = "USSD";
> +	char *utf8_str = NULL;
> +	gboolean utf8_str_valid = FALSE;
>  	const char sig[] = { DBUS_TYPE_STRING, 0 };
>  	DBusMessage *reply;
>  	DBusMessageIter iter;
>  	DBusMessageIter variant;
>  
> +	if (ussd->req &&
> +		(status == OFONO_USSD_STATUS_NOTIFY ||
> +		status == OFONO_USSD_STATUS_TERMINATED ||
> +		status == OFONO_USSD_STATUS_TIMED_OUT ||
> +		status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
> +
> +		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
> +					dcs, data, data_len);
> +
> +		ussd_change_state(ussd, USSD_STATE_IDLE);
> +		return;
> +	}
> +
>  	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
>  		ussd_change_state(ussd, USSD_STATE_IDLE);
>  
> @@ -334,15 +387,21 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  		reply = __ofono_error_timed_out(ussd->pending);
>  		goto out;
>  	}
> +	
> +	if (data && data_len > 0)
> +		utf8_str = ussd_decode(dcs, data_len, data);
> +
> +	if (!utf8_str) {
> +		utf8_str = "";
> +		status = OFONO_USSD_STATUS_NOTIFY;
> +	} else
> +		utf8_str_valid = TRUE;
>  
>  	/* TODO: Rework this in the Agent framework */
>  	if (ussd->state == USSD_STATE_ACTIVE) {
>  
>  		reply = dbus_message_new_method_return(ussd->pending);
>  
> -		if (!str)
> -			str = "";
> -
>  		dbus_message_iter_init_append(reply, &iter);
>  
>  		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
> @@ -352,7 +411,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  							&variant);
>  
>  		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
> -						&str);
> +						&utf8_str);
>  
>  		dbus_message_iter_close_container(&iter, &variant);
>  
> @@ -364,10 +423,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
>  		reply = dbus_message_new_method_return(ussd->pending);
>  
> -		if (!str)
> -			str = "";
> -
> -		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
> +		dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
>  						DBUS_TYPE_INVALID);
>  
>  		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
> @@ -387,20 +443,17 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  			signal_name = "NotificationReceived";
>  		}
>  
> -		if (!str)
> -			str = "";
> -
>  		g_dbus_emit_signal(conn, path,
>  				SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
> -				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
> +				DBUS_TYPE_STRING, &utf8_str, DBUS_TYPE_INVALID);
>  
>  		ussd_change_state(ussd, new_state);
> -		return;
> +		goto free;
>  	} else {
>  		ofono_error("Received an unsolicited USSD but can't handle.");
> -		DBG("USSD is: status: %d, %s", status, str);
> +		DBG("USSD is: status: %d, %s", status, utf8_str);
>  
> -		return;
> +		goto free;
>  	}
>  
>  out:
> @@ -408,6 +461,10 @@ out:
>  
>  	dbus_message_unref(ussd->pending);
>  	ussd->pending = NULL;
> +
> +free:
> +	if (utf8_str_valid)
> +		g_free(utf8_str);
>  }
>  
>  static void ussd_callback(const struct ofono_error *error, void *data)
> @@ -436,6 +493,12 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
>  {
>  	struct ofono_ussd *ussd = data;
>  	const char *str;
> +	int dcs = 0x0f;
> +	unsigned char buf[256];
> +	unsigned char *converted;
> +	unsigned char *packed = NULL;
> +	long num_packed;
> +	long written;
>  
>  	if (ussd->pending)
>  		return __ofono_error_busy(msg);
> @@ -458,14 +521,27 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
>  	if (!valid_ussd_string(str))
>  		return __ofono_error_invalid_format(msg);
>  
> -	DBG("OK, running USSD request");
> +	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> +	if (!converted)
> +		return __ofono_error_invalid_format(msg);
> +
> +	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
> +					&num_packed, 0, buf);
> +
> +	g_free(converted);
> +
> +	if (num_packed > OFONO_MAX_USSD_LENGTH)
> +		return __ofono_error_invalid_format(msg);
>  
>  	if (!ussd->driver->request)
>  		return __ofono_error_not_implemented(msg);
>  
> +	DBG("OK, running USSD request");
> +
>  	ussd->pending = dbus_message_ref(msg);
>  
> -	ussd->driver->request(ussd, str, ussd_callback, ussd);
> +	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
> +				ussd_callback, ussd);
>  
>  	return NULL;
>  }
> @@ -496,6 +572,12 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
>  {
>  	struct ofono_ussd *ussd = data;
>  	const char *str;
> +	int dcs = 0x0f;
> +	unsigned char buf[256];
> +	unsigned char *converted;
> +	unsigned char *packed = NULL;
> +	long num_packed;
> +	long written;
>  
>  	if (ussd->pending)
>  		return __ofono_error_busy(msg);
> @@ -510,12 +592,25 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
>  	if (strlen(str) == 0)
>  		return __ofono_error_invalid_format(msg);
>  
> +	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> +	if (!converted)
> +		return __ofono_error_invalid_format(msg);
> +
> +	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
> +					&num_packed, 0, buf);
> +
> +	g_free(converted);
> +
> +	if (num_packed > OFONO_MAX_USSD_LENGTH)
> +		return __ofono_error_invalid_args(msg);
> +
>  	if (!ussd->driver->request)
>  		return __ofono_error_not_implemented(msg);
>  
>  	ussd->pending = dbus_message_ref(msg);
>  
> -	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
> +	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
> +				ussd_response_callback, ussd);
>  
>  	return NULL;
>  }
> @@ -543,6 +638,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
>  	reply = dbus_message_new_method_return(ussd->cancel);
>  	__ofono_dbus_pending_reply(&ussd->cancel, reply);
>  
> +	if (ussd->req)
> +		ussd_request_finish(ussd, -1, USSD_STATE_USER_ACTION, NULL, -1);
> +
>  	ussd_change_state(ussd, USSD_STATE_IDLE);
>  }
>  
> @@ -741,3 +839,46 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
>  {
>  	return ussd->driver_data;
>  }
> +
> +static void ussd_request_callback(const struct ofono_error *error, void *data)
> +{
> +	struct ofono_ussd *ussd = data;
> +
> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
> +		ussd_request_finish(ussd, OFONO_USSD_FAILURE_RETURN_ERROR, -1, NULL, -1);
> +	else
> +		ussd_change_state(ussd,USSD_STATE_ACTIVE);
> +}
> +
> +gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
> +{
> +	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
> +		return TRUE;
> +
> +	return FALSE;
> +}
> +
> +int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
> +				const unsigned char *binary_data,
> +				int binary_data_len,
> +				ofono_ussd_request_cb_t cb, void *user_data)
> +{
> +	struct ussd_request *req;
> +
> +	if (!ussd->driver->request)
> +		return -ENOSYS;
> +
> +	req = g_try_new0(struct ussd_request, 1);
> +	req->dcs = dcs;
> +	req->str = g_memdup(binary_data, binary_data_len);
> +	req->str_len = binary_data_len;
> +	req->cb = cb;
> +	req->user_data = user_data;
> +
> +	ussd->req = req;
> +
> +	ussd->driver->request(ussd, dcs, binary_data, binary_data_len,
> +				ussd_request_callback, ussd);
> +
> +	return 0;
> +}

Otherwise it looks fine, but I'll have to perform another round of
reviews once you separate out the driver changes from
ofono_ussd_initiate changes.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 01/12] atutil changes for parsing cscs query and cscs support
  2010-09-09 14:45   ` Denis Kenzior
@ 2010-09-09 18:56     ` Jeevaka Badrappan
  2010-09-09 18:56       ` [PATCH 01/13] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 18:56 UTC (permalink / raw)
  To: ofono

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


Hi Denis,

 I have incorporated your review comments.

Thanks and Regards,
jeevaka

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 01/13] atutil changes for parsing cscs query and cscs support
  2010-09-09 18:56     ` Jeevaka Badrappan
@ 2010-09-09 18:56       ` Jeevaka Badrappan
  2010-09-10 17:27         ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 18:56 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/atutil.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/atmodem/atutil.h |   25 ++++++++++++++
 2 files changed, 108 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/atutil.c b/drivers/atmodem/atutil.c
index f566237..7a8d04d 100644
--- a/drivers/atmodem/atutil.c
+++ b/drivers/atmodem/atutil.c
@@ -341,3 +341,86 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
 
 	return TRUE;
 }
+
+static gboolean at_util_charset_string_to_charset(const char *str,
+					enum at_util_charset *charset)
+{
+	if (!g_strcmp0(str, "GSM"))
+		*charset = AT_UTIL_CHARSET_GSM;
+	else if (!g_strcmp0(str, "HEX"))
+		*charset = AT_UTIL_CHARSET_HEX;
+	else if (!g_strcmp0(str, "IRA"))
+		*charset = AT_UTIL_CHARSET_IRA;
+	else if (!g_strcmp0(str, "PCCP437"))
+		*charset = AT_UTIL_CHARSET_PCCP437;
+	else if (!g_strcmp0(str, "PCDN"))
+		*charset = AT_UTIL_CHARSET_PCDN;
+	else if (!g_strcmp0(str, "UCS2"))
+		*charset = AT_UTIL_CHARSET_UCS2;
+	else if (!g_strcmp0(str, "UTF-8"))
+		*charset = AT_UTIL_CHARSET_UTF8;
+	else if (!g_strcmp0(str, "8859-1"))
+		*charset = AT_UTIL_CHARSET_8859_1;
+	else if (!g_strcmp0(str, "8859-2"))
+		*charset = AT_UTIL_CHARSET_8859_2;
+	else if (!g_strcmp0(str, "8859-3"))
+		*charset = AT_UTIL_CHARSET_8859_3;
+	else if (!g_strcmp0(str, "8859-4"))
+		*charset = AT_UTIL_CHARSET_8859_4;
+	else if (!g_strcmp0(str, "8859-5"))
+		*charset = AT_UTIL_CHARSET_8859_5;
+	else if (!g_strcmp0(str, "8859-6"))
+		*charset = AT_UTIL_CHARSET_8859_6;
+	else if (!g_strcmp0(str, "8859-C"))
+		*charset = AT_UTIL_CHARSET_8859_C;
+	else if (!g_strcmp0(str, "8859-A"))
+		*charset = AT_UTIL_CHARSET_8859_A;
+	else if (!g_strcmp0(str, "8859-G"))
+		*charset = AT_UTIL_CHARSET_8859_G;
+	else if (!g_strcmp0(str, "8859-H"))
+		*charset = AT_UTIL_CHARSET_8859_H;
+	else
+		return FALSE;
+
+	return TRUE;
+}
+
+gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported)
+{
+	GAtResultIter iter;
+	const char *str;
+	enum at_util_charset charset;
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CSCS:"))
+		return FALSE;
+
+	/* Some modems don't report CSCS in a proper list */
+	g_at_result_iter_open_list(&iter);
+
+	while (g_at_result_iter_next_string(&iter, &str)) {
+		if (at_util_charset_string_to_charset(str, &charset))
+			*supported |= charset;
+	}
+
+	g_at_result_iter_close_list(&iter);
+
+	return TRUE;
+}
+
+gboolean at_util_parse_cscs_query(GAtResult *result,
+				enum at_util_charset *charset)
+{
+	GAtResultIter iter;
+	const char *str;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CSCS:"))
+		return FALSE;
+
+	if (g_at_result_iter_next_string(&iter, &str))
+		return at_util_charset_string_to_charset(str, charset);		
+
+	return FALSE;
+}
diff --git a/drivers/atmodem/atutil.h b/drivers/atmodem/atutil.h
index 9e0a84b..7dbb8a6 100644
--- a/drivers/atmodem/atutil.h
+++ b/drivers/atmodem/atutil.h
@@ -27,6 +27,27 @@ enum at_util_sms_store {
 	AT_UTIL_SMS_STORE_BM =	4,
 };
 
+/* 3GPP TS 27.007 Release 8 Section 5.5 */
+enum at_util_charset {
+	AT_UTIL_CHARSET_GSM =		0x1,
+	AT_UTIL_CHARSET_HEX =		0x2,
+	AT_UTIL_CHARSET_IRA =		0x4,
+	AT_UTIL_CHARSET_PCCP437 =	0x8,
+	AT_UTIL_CHARSET_PCDN =		0x10,
+	AT_UTIL_CHARSET_UCS2 =		0x20,
+	AT_UTIL_CHARSET_UTF8 =		0x40,
+	AT_UTIL_CHARSET_8859_1 =	0x80,
+	AT_UTIL_CHARSET_8859_2 =	0x100,
+	AT_UTIL_CHARSET_8859_3 =	0x200,
+	AT_UTIL_CHARSET_8859_4 =	0x400,
+	AT_UTIL_CHARSET_8859_5 =	0x800,
+	AT_UTIL_CHARSET_8859_6 =	0x1000,
+	AT_UTIL_CHARSET_8859_C =	0x2000,
+	AT_UTIL_CHARSET_8859_A =	0x4000,
+	AT_UTIL_CHARSET_8859_G =	0x8000,
+	AT_UTIL_CHARSET_8859_H =	0x10000,
+};
+
 void decode_at_error(struct ofono_error *error, const char *final);
 gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b);
 gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b);
@@ -46,6 +67,10 @@ gboolean at_util_parse_sms_index_delivery(GAtResult *result, const char *prefix,
 						enum at_util_sms_store *store,
 						int *index);
 
+gboolean at_util_parse_cscs_supported(GAtResult *result, int *supported);
+gboolean at_util_parse_cscs_query(GAtResult *result,
+				enum at_util_charset *charset);
+
 struct cb_data {
 	void *cb;
 	void *data;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 02/13] atgen changes for setting TE character set
  2010-09-09 14:50   ` Denis Kenzior
@ 2010-09-09 19:00     ` Jeevaka Badrappan
  0 siblings, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 19:00 UTC (permalink / raw)
  To: ofono

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

---
 plugins/atgen.c |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 49 insertions(+), 0 deletions(-)

diff --git a/plugins/atgen.c b/plugins/atgen.c
index 1ce2467..1b898b7 100644
--- a/plugins/atgen.c
+++ b/plugins/atgen.c
@@ -25,6 +25,8 @@
 
 #include <errno.h>
 #include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
 
 #include <glib.h>
 #include <gatchat.h>
@@ -55,6 +57,9 @@
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
 
+static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
+
 static const char *tty_opts[] = {
 	"Baud",
 	"Read",
@@ -67,6 +72,48 @@ static const char *tty_opts[] = {
 	NULL,
 };
 
+static const char *best_charset(int supported)
+{
+	const char *charset = "Invalid";
+
+	if (supported & AT_UTIL_CHARSET_GSM)
+		charset = "GSM";
+
+	if (supported & AT_UTIL_CHARSET_UTF8)
+		charset = "UTF-8";
+
+	return charset;
+}
+
+static void list_charsets_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	GAtChat *chat = ofono_modem_get_data(modem);
+	const char *charset;
+	int supported = 0;
+	char buf[32];
+
+	if (!ok)
+		return;
+
+	if (!at_util_parse_cscs_supported(result, &supported))
+		return;
+
+	charset = best_charset(supported);
+	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
+
+	g_at_chat_send(chat, buf, none_prefix, NULL, NULL, NULL);
+}
+
+static void list_charsets(struct ofono_modem *modem)
+{
+	GAtChat *chat = ofono_modem_get_data(modem);
+
+	g_at_chat_send(chat, "AT+CSCS=?", cscs_prefix,
+			list_charsets_cb, modem, NULL);
+}
+
 static int atgen_probe(struct ofono_modem *modem)
 {
 	return 0;
@@ -207,6 +254,8 @@ static void atgen_pre_sim(struct ofono_modem *modem)
 
 	if (sim)
 		ofono_sim_inserted_notify(sim, TRUE);
+
+	list_charsets(modem);
 }
 
 static void atgen_post_sim(struct ofono_modem *modem)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 03/13] phonesim changes for setting TE character set
  2010-09-09 12:31 ` [PATCH 03/12] phonesim " Jeevaka Badrappan
@ 2010-09-09 19:01   ` Jeevaka Badrappan
  2010-09-10 17:07     ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 19:01 UTC (permalink / raw)
  To: ofono

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

---
 plugins/phonesim.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index d3caa20..288baf6 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -64,6 +64,7 @@
 #include <drivers/atmodem/atutil.h>
 
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct phonesim_data {
 	GAtMux *mux;
@@ -72,6 +73,48 @@ struct phonesim_data {
 	gboolean use_mux;
 };
 
+static const char *best_charset(int supported)
+{
+	const char *charset = "Invalid";
+
+	if (supported & AT_UTIL_CHARSET_UCS2)
+		charset = "UCS2";
+
+	if (supported & AT_UTIL_CHARSET_GSM)
+		charset = "GSM";
+
+	return charset;
+}
+
+static void list_charsets_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+	const char *charset;
+	int supported = 0;
+	char buf[32];
+
+	if (!ok)
+		return;
+
+	if (!at_util_parse_cscs_supported(result, &supported))
+		return;
+
+	charset = best_charset(supported);
+	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
+
+	g_at_chat_send(data->chat, buf, none_prefix, NULL, NULL, NULL);
+}
+
+static void list_charsets(struct ofono_modem *modem)
+{
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+	
+	g_at_chat_send(data->chat, "AT+CSCS=?", cscs_prefix,
+			list_charsets_cb, modem, NULL);
+}
+
 static int phonesim_probe(struct ofono_modem *modem)
 {
 	struct phonesim_data *data;
@@ -321,6 +364,8 @@ static void phonesim_pre_sim(struct ofono_modem *modem)
 
 	if (sim)
 		ofono_sim_inserted_notify(sim, TRUE);
+
+	list_charsets(modem);
 }
 
 static void phonesim_post_sim(struct ofono_modem *modem)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 04/13] USSD atom driver changes to read current character setting
  2010-09-09 12:31 ` [PATCH 04/12] USSD atom driver changes to read current character setting Jeevaka Badrappan
@ 2010-09-09 19:02   ` Jeevaka Badrappan
  0 siblings, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 19:02 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 1e1fc25..30145ad 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -44,12 +44,25 @@
 
 static const char *cusd_prefix[] = { "+CUSD:", NULL };
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct ussd_data {
 	GAtChat *chat;
 	unsigned int vendor;
+	enum at_util_charset charset;
 };
 
+static void read_charset_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ussd_data *data = user_data;
+
+	if (!ok)
+		return;
+
+	at_util_parse_cscs_query(result, &data->charset);
+}
+
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
 	GAtResultIter iter;
@@ -247,6 +260,9 @@ static int at_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,
 
 	ofono_ussd_set_data(ussd, data);
 
+	g_at_chat_send(chat, "AT+CSCS?", cscs_prefix, read_charset_cb, data,
+			NULL);
+
 	g_at_chat_send(chat, "AT+CUSD=1", NULL, at_ussd_register, ussd, NULL);
 
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 10/13] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-09 15:31   ` Denis Kenzior
@ 2010-09-09 19:06     ` Jeevaka Badrappan
  2010-09-10 17:29       ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 19:06 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index ae4cc32..c69ebba 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4170,6 +4170,22 @@ static gboolean build_dataobj_text(struct stk_tlv_builder *tlv,
 	return stk_tlv_builder_close_container(tlv);
 }
 
+/* Defined in TS 102.223 Section 8.15 - USSD specific case*/
+static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
+					const void *data, gboolean cr)
+{
+	const struct stk_ussd_text *text = data;
+	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
+
+	if (!text->text)
+		return TRUE;
+
+	return stk_tlv_builder_open_container(tlv, cr, tag, TRUE) &&
+		stk_tlv_builder_append_byte(tlv, text->dcs) &&
+		stk_tlv_builder_append_bytes(tlv, text->text, text->len) &&
+		stk_tlv_builder_close_container(tlv);
+}
+
 /* Described in TS 131.111 Section 8.17 */
 static gboolean build_dataobj_ussd_string(struct stk_tlv_builder *tlv,
 					const void *data, gboolean cr)
@@ -5459,6 +5475,13 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
 	case STK_COMMAND_TYPE_LANGUAGE_NOTIFICATION:
 	case STK_COMMAND_TYPE_LAUNCH_BROWSER:
 		break;
+	case STK_COMMAND_TYPE_SEND_USSD:
+		ok = build_dataobj(&builder,
+					build_dataobj_ussd_text,
+					DATAOBJ_FLAG_CR,
+					&response->send_ussd.text,
+					NULL);
+		break;
 	default:
 		return NULL;
 	};
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 8/8] Handling of Send USSD proactive command
  2010-09-09 15:37   ` Denis Kenzior
@ 2010-09-09 19:42     ` Jeevaka Badrappan
  0 siblings, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 19:42 UTC (permalink / raw)
  To: ofono

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

---
 src/stk.c |  136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 135 insertions(+), 1 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 3fda2af..76ffdf5 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -1590,6 +1590,137 @@ static gboolean handle_command_set_up_call(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static void send_ussd_callback(int error, int dcs, const unsigned char *msg,
+				int msg_len, void *userdata)
+{
+	struct ofono_stk *stk = userdata;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	struct stk_response rsp;
+	enum sms_charset charset;
+	
+	if (stk->pending_cmd->send_ussd.alpha_id &&
+			stk->pending_cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_unset(stk);
+
+	switch (error) {
+	case OFONO_USSD_FAILURE_NONE:
+		if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL)) {
+			if (charset == SMS_CHARSET_7BIT)
+				rsp.send_ussd.text.dcs = 0x00;
+			else if (charset == SMS_CHARSET_8BIT)
+				rsp.send_ussd.text.dcs = 0x04;
+			else if (charset == SMS_CHARSET_UCS2)
+				rsp.send_ussd.text.dcs = 0x08;
+		} else {
+			send_simple_response(stk,
+					STK_RESULT_TYPE_USSD_RETURN_ERROR);
+			return;
+		}
+
+		memset(&rsp, 0, sizeof(rsp));
+
+		rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+		rsp.send_ussd.text.text = msg;
+		rsp.send_ussd.text.len = msg_len;
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	case OFONO_USSD_FAILURE_USER_TERMINATED:
+		send_simple_response(stk, 
+				STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION);
+		break;
+	case OFONO_USSD_FAILURE_TIMED_OUT:
+		send_simple_response(stk, STK_RESULT_TYPE_NETWORK_UNAVAILABLE);
+		break;
+	case OFONO_USSD_FAILURE_RETURN_ERROR:
+		send_simple_response(stk, STK_RESULT_TYPE_USSD_RETURN_ERROR);
+		break;
+	}
+}
+
+static gboolean handle_command_send_ussd(const struct stk_command *cmd,
+					struct stk_response *rsp,
+					struct ofono_stk *stk)
+{
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	static unsigned char busy_on_ss_result[] = { 0x03 };
+	static unsigned char busy_on_ussd_result[] = { 0x08 };
+	struct ofono_atom *atom;
+	struct ofono_ussd *ussd;
+	int err;
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
+		
+		if (__ofono_call_forwarding_is_busy(cf)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_BARRING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_barring *cb = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_barring_is_busy(cb)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
+		
+		if (__ofono_call_settings_is_busy(cs)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
+	if (!atom || !__ofono_atom_get_registered(atom)) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	ussd = __ofono_atom_get_data(atom);
+	if (__ofono_ussd_is_busy(ussd)) {
+		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+		rsp->result.additional_len = sizeof(busy_on_ussd_result);
+		rsp->result.additional = busy_on_ussd_result;
+		return TRUE;
+	}
+
+	err = __ofono_ussd_initiate(ussd, cmd->send_ussd.ussd_string.dcs,
+					cmd->send_ussd.ussd_string.string,
+					cmd->send_ussd.ussd_string.len,
+					send_ussd_callback, stk);
+
+	if (err >= 0) 
+		return FALSE;
+
+	if (err == -ENOSYS) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	if (cmd->send_ussd.alpha_id && cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_set(stk, cmd->send_ussd.alpha_id);
+
+	return FALSE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -1740,7 +1871,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 		respond = handle_command_set_up_call(stk->pending_cmd,
 							&rsp, stk);
 		break;
-
+	case STK_COMMAND_TYPE_SEND_USSD:
+		respond = handle_command_send_ussd(stk->pending_cmd,
+							&rsp, stk);
+		break;
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 6/8] Internal and Driver api changes for Send USSD proactive command
  2010-09-09 15:59   ` Denis Kenzior
@ 2010-09-09 20:25     ` Jeevaka Badrappan
  2010-09-09 20:25       ` [PATCH 7/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 20:25 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c  |   86 +++++++++++++++++++++++++---------------------
 drivers/isimodem/ussd.c |   44 +++++++----------------
 include/ussd.h          |    8 +++--
 src/ussd.c              |   87 ++++++++++++++++++++++++++++++++++++----------
 4 files changed, 133 insertions(+), 92 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 30145ad..ac99f0e 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -65,15 +65,15 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
 
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
+	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	GAtResultIter iter;
 	int status;
 	int dcs;
 	const char *content;
-	char *converted = NULL;
-	gboolean udhi;
 	enum sms_charset charset;
-	gboolean compressed;
-	gboolean iso639;
+	unsigned char msg[160];
+	long msg_len = 0;
+	unsigned char *msg_ptr = NULL;
 
 	g_at_result_iter_init(&iter, result);
 
@@ -87,33 +87,27 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 		goto out;
 
 	if (g_at_result_iter_next_number(&iter, &dcs)) {
-		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
-					&compressed, NULL, &iso639))
-			goto out;
-
-		if (udhi || compressed || iso639)
+		if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
 			goto out;
 	} else
 		charset = SMS_CHARSET_7BIT;
 
-	if (charset == SMS_CHARSET_7BIT)
-		converted = convert_gsm_to_utf8((const guint8 *) content,
-						strlen(content), NULL, NULL, 0);
-
-	else if (charset == SMS_CHARSET_8BIT) {
-		/* TODO: Figure out what to do with 8 bit data */
-		ofono_error("8-bit coded USSD response received");
-		status = 4; /* Not supported */
-	} else {
+	if (charset == SMS_CHARSET_7BIT) {
+		if (data->charset == AT_UTIL_CHARSET_GSM)
+			msg_ptr = pack_7bit_own_buf((const guint8 *) content,
+					strlen(content), 0, TRUE,
+					&msg_len, 0, msg);
+	} else if (charset == SMS_CHARSET_8BIT)
+		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+	else {
 		/* No other encoding is mentioned in TS27007 7.15 */
 		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
 		status = 4; /* Not supported */
 	}
 
 out:
-	ofono_ussd_notify(ussd, status, converted);
-
-	g_free(converted);
+	ofono_ussd_notify(ussd, status, dcs, msg_ptr, msg_len);
 }
 
 static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -130,39 +124,52 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	cusd_parse(result, ussd);
 }
 
-static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
+static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
 				ofono_ussd_cb_t cb, void *user_data)
 {
 	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	struct cb_data *cbd = cb_data_new(cb, user_data);
-	unsigned char *converted = NULL;
-	int dcs;
-	int max_len;
-	long written;
 	char buf[256];
+	long max_chars = 182;
+	unsigned char *unpacked_buf = NULL;
+	char *converted = NULL;
+	long written;
+	enum sms_charset charset;
 
 	if (!cbd)
 		goto error;
 
 	cbd->user = ussd;
+        
+	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
+		goto error;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
+	if (charset == SMS_CHARSET_7BIT) {
+		unpacked_buf = unpack_7bit(pdu, len, 0, TRUE, max_chars,
+						&written, 0);
 
-	if (!converted)
-		goto error;
-	else {
-		dcs = 15;
-		max_len = 182;
-	}
+		if ( !unpacked_buf || written <= 0)
+			goto error;
 
-	if (written > max_len)
-		goto error;
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				(int) written, unpacked_buf, dcs);
+
+		g_free(unpacked_buf);
+		unpacked_buf = NULL;
+	} else {
+		converted = encode_hex(pdu, len, 0);
 
-	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
-			(int) written, converted, dcs);
+		if (!converted)
+			goto error;
 
-	g_free(converted);
-	converted = NULL;
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				strlen(converted), converted, dcs);
+
+		g_free(converted);
+		converted = NULL;
+	}
 
 	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
 		/* Ensure that the modem is using GSM character set. It
@@ -179,7 +186,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
 
 error:
 	g_free(cbd);
-	g_free(converted);
 
 	CALLBACK_WITH_FAILURE(cb, user_data);
 }
diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
index 330a141..6ac945b 100644
--- a/drivers/isimodem/ussd.c
+++ b/drivers/isimodem/ussd.c
@@ -74,7 +74,9 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 {
 	const unsigned char *msg = data;
 	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
-	char *converted = NULL;
+	int msg_len = 0;
+	int dcs = -1;
+	unsigned char *coded_msg = NULL;
 
 	if (!msg || len < 4)
 		goto out;
@@ -84,14 +86,11 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
 		goto out;
 
-	converted = ussd_decode(msg[1], msg[3], msg + 4);
-
-	if (converted)
-		status = OFONO_USSD_STATUS_NOTIFY;
-
+	dcs = msg[1];
+	msg_len = msg[3];
+	coded_msg = (guint8 *) msg+4;
 out:
-	ofono_ussd_notify(ussd, status, converted);
-	g_free(converted);
+	ofono_ussd_notify(ussd, status, dcs, coded_msg, msg_len);
 }
 
 
@@ -129,7 +128,7 @@ error:
 }
 
 static GIsiRequest *ussd_send(GIsiClient *client,
-				uint8_t *str, size_t len,
+				int dcs, uint8_t *str, size_t len,
 				void *data, GDestroyNotify notify)
 {
 	const uint8_t msg[] = {
@@ -138,7 +137,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 		0x01,		/* subblock count */
 		SS_GSM_USSD_STRING,
 		4 + len + 3,	/* subblock length */
-		0x0f,		/* DCS */
+		dcs,		/* DCS */
 		len,		/* string length */
 		/* USSD string goes here */
 	};
@@ -152,33 +151,18 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 				ussd_send_resp_cb, data, notify);
 }
 
-static void isi_request(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t cb, void *data)
+static void isi_request(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *binary_data, int binary_data_len,
+			ofono_ussd_cb_t cb, void *data)
 {
 	struct ussd_data *ud = ofono_ussd_get_data(ussd);
 	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
-	unsigned char buf[256];
-	unsigned char *packed = NULL;
-	unsigned char *converted = NULL;
-	long num_packed;
-	long written;
 
 	if (!cbd)
 		goto error;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-	if (!converted)
-		goto error;
-
-	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
-					&num_packed, 0, buf);
-
-	g_free(converted);
-
-	if (written > SS_MAX_USSD_LENGTH)
-		goto error;
-
-	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
+	if (ussd_send(ud->client, dcs, (guint8 *) binary_data,
+			binary_data_len, cbd, g_free))
 		return;
 
 error:
diff --git a/include/ussd.h b/include/ussd.h
index 96e04cb..360ef00 100644
--- a/include/ussd.h
+++ b/include/ussd.h
@@ -45,13 +45,15 @@ struct ofono_ussd_driver {
 	const char *name;
 	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
 	void (*remove)(struct ofono_ussd *ussd);
-	void (*request)(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t, void *data);
+	void (*request)(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_cb_t, void *data);
 	void (*cancel)(struct ofono_ussd *ussd,
 				ofono_ussd_cb_t cb, void *data);
 };
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len);
 
 int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
 void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
diff --git a/src/ussd.c b/src/ussd.c
index fbb07d2..a2e9e72 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -34,8 +34,11 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "smsutil.h"
+#include "util.h"
 
 #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
+#define MAX_USSD_LENGTH 160
 
 static GSList *g_drivers = NULL;
 
@@ -317,10 +320,13 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *ussdstr = "USSD";
+	char *utf8_str = NULL;
+	gboolean utf8_str_valid = FALSE;
 	const char sig[] = { DBUS_TYPE_STRING, 0 };
 	DBusMessage *reply;
 	DBusMessageIter iter;
@@ -345,15 +351,21 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 		reply = __ofono_error_timed_out(ussd->pending);
 		goto out;
 	}
+	
+	if (data && data_len > 0)
+		utf8_str = ussd_decode(dcs, data_len, data);
+
+	if (!utf8_str) {
+		utf8_str = "";
+		status = OFONO_USSD_STATUS_NOTIFY;
+	} else
+		utf8_str_valid = TRUE;
 
 	/* TODO: Rework this in the Agent framework */
 	if (ussd->state == USSD_STATE_ACTIVE) {
 
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
 		dbus_message_iter_init_append(reply, &iter);
 
 		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
@@ -363,7 +375,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 							&variant);
 
 		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
-						&str);
+						&utf8_str);
 
 		dbus_message_iter_close_container(&iter, &variant);
 
@@ -375,10 +387,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
-		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
 						DBUS_TYPE_INVALID);
 
 		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
@@ -398,20 +407,17 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 			signal_name = "NotificationReceived";
 		}
 
-		if (!str)
-			str = "";
-
 		g_dbus_emit_signal(conn, path,
 				SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
-				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
+				DBUS_TYPE_STRING, &utf8_str, DBUS_TYPE_INVALID);
 
 		ussd_change_state(ussd, new_state);
-		return;
+		goto free;
 	} else {
 		ofono_error("Received an unsolicited USSD but can't handle.");
-		DBG("USSD is: status: %d, %s", status, str);
+		DBG("USSD is: status: %d, %s", status, utf8_str);
 
-		return;
+		goto free;
 	}
 
 out:
@@ -419,6 +425,10 @@ out:
 
 	dbus_message_unref(ussd->pending);
 	ussd->pending = NULL;
+
+free:
+	if (utf8_str_valid)
+		g_free(utf8_str);
 }
 
 static void ussd_callback(const struct ofono_error *error, void *data)
@@ -447,6 +457,12 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[256];
+	unsigned char *converted;
+	unsigned char *packed = NULL;
+	long num_packed;
+	long written;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -469,14 +485,27 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 	if (!valid_ussd_string(str))
 		return __ofono_error_invalid_format(msg);
 
-	DBG("OK, running USSD request");
+	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
+	if (!converted)
+		return __ofono_error_invalid_format(msg);
+
+	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
+					&num_packed, 0, buf);
+
+	g_free(converted);
+
+	if (num_packed > MAX_USSD_LENGTH)
+		return __ofono_error_invalid_format(msg);
 
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
+	DBG("OK, running USSD request");
+
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_callback, ussd);
+	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
+				ussd_callback, ussd);
 
 	return NULL;
 }
@@ -507,6 +536,12 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[256];
+	unsigned char *converted;
+	unsigned char *packed = NULL;
+	long num_packed;
+	long written;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -521,12 +556,25 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 	if (strlen(str) == 0)
 		return __ofono_error_invalid_format(msg);
 
+	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
+	if (!converted)
+		return __ofono_error_invalid_format(msg);
+
+	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
+					&num_packed, 0, buf);
+
+	g_free(converted);
+
+	if (num_packed > MAX_USSD_LENGTH)
+		return __ofono_error_invalid_args(msg);
+
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
+	ussd->driver->request(ussd, dcs, packed, (int) num_packed,
+				ussd_response_callback, ussd);
 
 	return NULL;
 }
@@ -752,3 +800,4 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 {
 	return ussd->driver_data;
 }
+
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 7/8] Add __ofono_ussd_initiate internal api for Sending USSD
  2010-09-09 20:25     ` [PATCH 6/8] " Jeevaka Badrappan
@ 2010-09-09 20:25       ` Jeevaka Badrappan
  0 siblings, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-09 20:25 UTC (permalink / raw)
  To: ofono

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

---
 src/ofono.h |   14 +++++++++
 src/ussd.c  |   85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 98 insertions(+), 1 deletions(-)

diff --git a/src/ofono.h b/src/ofono.h
index 7e814c9..9786829 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -244,6 +244,13 @@ gboolean __ofono_ssn_mt_watch_remove(struct ofono_ssn *ssn, int id);
 
 #include <ofono/ussd.h>
 
+enum ofono_ussd_failure {
+	OFONO_USSD_FAILURE_NONE,
+	OFONO_USSD_FAILURE_USER_TERMINATED,
+	OFONO_USSD_FAILURE_RETURN_ERROR,
+	OFONO_USSD_FAILURE_TIMED_OUT,
+};
+
 typedef gboolean (*ofono_ussd_ssc_cb_t)(int type,
 					const char *sc,
 					const char *sia, const char *sib,
@@ -254,6 +261,9 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
 					const char *old, const char *new,
 					DBusMessage *msg, void *data);
 
+typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
+					const unsigned char *pdu, int len, void *data);
+
 gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
 					ofono_ussd_ssc_cb_t cb, void *data,
 					ofono_destroy_func destroy);
@@ -265,6 +275,10 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
 void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
 gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
 
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_request_cb_t cb, void *user_data);
+
 #include <ofono/netreg.h>
 
 typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
diff --git a/src/ussd.c b/src/ussd.c
index a2e9e72..4db3bce 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -49,6 +49,15 @@ enum ussd_state {
 	USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+	struct ofono_ussd *ussd;
+	int dcs;
+	unsigned char *pdu;
+	int len;
+	ofono_ussd_request_cb_t cb;
+	void *user_data;
+};
+
 struct ofono_ussd {
 	int state;
 	DBusMessage *pending;
@@ -59,6 +68,7 @@ struct ofono_ussd {
 	const struct ofono_ussd_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -73,7 +83,7 @@ gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
 	if (!ussd)
 		return FALSE;
 
-	if (ussd->pending || ussd->state != USSD_STATE_IDLE)
+	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
 		return TRUE;
 
 	return FALSE;
@@ -320,6 +330,31 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+				const unsigned char *pdu, int len)
+{
+	struct ussd_request *req = ussd->req;
+
+	if (req && req->cb) {
+		req->cb(error, dcs, pdu, len, req->user_data);
+		g_free(req->pdu);
+		g_free(req);
+		ussd->req = NULL;
+	}
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+	switch (status) {
+	case OFONO_USSD_STATUS_TIMED_OUT:
+		return OFONO_USSD_FAILURE_TIMED_OUT;
+	case OFONO_USSD_STATUS_NOT_SUPPORTED:
+		return OFONO_USSD_FAILURE_RETURN_ERROR;
+	}
+
+	return OFONO_USSD_FAILURE_NONE;
+}
+
 void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 			const unsigned char *data, int data_len)
 {
@@ -332,6 +367,19 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 	DBusMessageIter iter;
 	DBusMessageIter variant;
 
+	if (ussd->req &&
+		(status == OFONO_USSD_STATUS_NOTIFY ||
+		status == OFONO_USSD_STATUS_TERMINATED ||
+		status == OFONO_USSD_STATUS_TIMED_OUT ||
+		status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
+
+		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
+					dcs, data, data_len);
+
+		ussd_change_state(ussd, USSD_STATE_IDLE);
+		return;
+	}
+
 	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
 		ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -602,6 +650,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
 	reply = dbus_message_new_method_return(ussd->cancel);
 	__ofono_dbus_pending_reply(&ussd->cancel, reply);
 
+	if (ussd->req)
+		ussd_request_finish(ussd, -1, USSD_STATE_USER_ACTION, NULL, -1);
+
 	ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
@@ -801,3 +852,35 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 	return ussd->driver_data;
 }
 
+static void ussd_request_callback(const struct ofono_error *error, void *data)
+{
+	struct ofono_ussd *ussd = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		ussd_request_finish(ussd, OFONO_USSD_FAILURE_RETURN_ERROR, -1, NULL, -1);
+	else
+		ussd_change_state(ussd,USSD_STATE_ACTIVE);
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
+				ofono_ussd_request_cb_t cb, void *user_data)
+{
+	struct ussd_request *req;
+
+	if (!ussd->driver->request)
+		return -ENOSYS;
+
+	req = g_try_new0(struct ussd_request, 1);
+	req->dcs = dcs;
+	req->pdu = g_memdup(pdu, len);
+	req->len = len;
+	req->cb = cb;
+	req->user_data = user_data;
+
+	ussd->req = req;
+
+	ussd->driver->request(ussd, dcs, pdu, len, ussd_request_callback, ussd);
+
+	return 0;
+}
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/13] phonesim changes for setting TE character set
  2010-09-09 19:01   ` [PATCH 03/13] " Jeevaka Badrappan
@ 2010-09-10 17:07     ` Denis Kenzior
  2010-09-10 20:29       ` [PATCH 2/7] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-10 17:07 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 02:01 PM, Jeevaka Badrappan wrote:
> ---
>  plugins/phonesim.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 45 insertions(+), 0 deletions(-)
> 

We use pretty strict git settings, your patch does not apply due to
whitespace corruption:

Applying: phonesim changes for setting TE character set
/home/denkenz/ofono-master/.git/rebase-apply/patch:58: trailing whitespace.
	
fatal: 1 line adds whitespace errors.
Patch failed at 0001 phonesim changes for setting TE character set
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 01/13] atutil changes for parsing cscs query and cscs support
  2010-09-09 18:56       ` [PATCH 01/13] " Jeevaka Badrappan
@ 2010-09-10 17:27         ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-10 17:27 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 01:56 PM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/atutil.c |   83 ++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/atmodem/atutil.h |   25 ++++++++++++++
>  2 files changed, 108 insertions(+), 0 deletions(-)

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/13] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-09 19:06     ` [PATCH 10/13] " Jeevaka Badrappan
@ 2010-09-10 17:29       ` Denis Kenzior
  2010-09-10 20:19         ` [PATCH 4/7] " Jeevaka Badrappan
  0 siblings, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-10 17:29 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/09/2010 02:06 PM, Jeevaka Badrappan wrote:
> ---
>  src/stkutil.c |   23 +++++++++++++++++++++++
>  1 files changed, 23 insertions(+), 0 deletions(-)
> 
> diff --git a/src/stkutil.c b/src/stkutil.c
> index ae4cc32..c69ebba 100644
> --- a/src/stkutil.c
> +++ b/src/stkutil.c
> @@ -4170,6 +4170,22 @@ static gboolean build_dataobj_text(struct stk_tlv_builder *tlv,
>  	return stk_tlv_builder_close_container(tlv);
>  }
>  
> +/* Defined in TS 102.223 Section 8.15 - USSD specific case*/
> +static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
> +					const void *data, gboolean cr)
> +{
> +	const struct stk_ussd_text *text = data;
> +	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
> +
> +	if (!text->text)
> +		return TRUE;

This still does not handle empty data.  We should do something like:

open_container()

if (text->len > 0) {
	append_byte(dcs);
	append_bytes(text);
}

close_container()

> +
> +	return stk_tlv_builder_open_container(tlv, cr, tag, TRUE) &&
> +		stk_tlv_builder_append_byte(tlv, text->dcs) &&
> +		stk_tlv_builder_append_bytes(tlv, text->text, text->len) &&
> +		stk_tlv_builder_close_container(tlv);
> +}
> +

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 4/7] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-10 17:29       ` Denis Kenzior
@ 2010-09-10 20:19         ` Jeevaka Badrappan
  2010-09-10 20:22           ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-10 20:19 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.c |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index 056f2e7..3cfe06a 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4170,6 +4170,23 @@ static gboolean build_dataobj_text(struct stk_tlv_builder *tlv,
 	return stk_tlv_builder_close_container(tlv);
 }
 
+/* Defined in TS 102.223 Section 8.15 - USSD specific case*/
+static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
+					const void *data, gboolean cr)
+{
+	const struct stk_ussd_text *text = data;
+	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
+
+	stk_tlv_builder_open_container(tlv, cr, tag, TRUE);
+
+	if (text->len > 0) {
+		stk_tlv_builder_append_byte(tlv, text->dcs);
+		stk_tlv_builder_append_bytes(tlv, text->text, text->len);
+	}
+
+	return stk_tlv_builder_close_container(tlv);
+}
+
 /* Described in TS 131.111 Section 8.17 */
 static gboolean build_dataobj_ussd_string(struct stk_tlv_builder *tlv,
 					const void *data, gboolean cr)
@@ -5457,6 +5474,13 @@ const unsigned char *stk_pdu_from_response(const struct stk_response *response,
 	case STK_COMMAND_TYPE_LANGUAGE_NOTIFICATION:
 	case STK_COMMAND_TYPE_LAUNCH_BROWSER:
 		break;
+	case STK_COMMAND_TYPE_SEND_USSD:
+		ok = build_dataobj(&builder,
+					build_dataobj_ussd_text,
+					DATAOBJ_FLAG_CR,
+					&response->send_ussd.text,
+					NULL);
+		break;
 	default:
 		return NULL;
 	};
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 4/7] Add build_dataobj_ussd_text for ussd specific text string handling
  2010-09-10 20:19         ` [PATCH 4/7] " Jeevaka Badrappan
@ 2010-09-10 20:22           ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-10 20:22 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/10/2010 03:19 PM, Jeevaka Badrappan wrote:
> ---
>  src/stkutil.c |   24 ++++++++++++++++++++++++
>  1 files changed, 24 insertions(+), 0 deletions(-)
> 

Patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 2/7] phonesim changes for setting TE character set
  2010-09-10 17:07     ` Denis Kenzior
@ 2010-09-10 20:29       ` Jeevaka Badrappan
  0 siblings, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-10 20:29 UTC (permalink / raw)
  To: ofono

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

---
 plugins/phonesim.c |   45 +++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index d3caa20..24b68bf 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -64,6 +64,7 @@
 #include <drivers/atmodem/atutil.h>
 
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct phonesim_data {
 	GAtMux *mux;
@@ -72,6 +73,48 @@ struct phonesim_data {
 	gboolean use_mux;
 };
 
+static const char *best_charset(int supported)
+{
+	const char *charset = "Invalid";
+
+	if (supported & AT_UTIL_CHARSET_UCS2)
+		charset = "UCS2";
+
+	if (supported & AT_UTIL_CHARSET_GSM)
+		charset = "GSM";
+
+	return charset;
+}
+
+static void list_charsets_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+	const char *charset;
+	int supported = 0;
+	char buf[32];
+
+	if (!ok)
+		return;
+
+	if (!at_util_parse_cscs_supported(result, &supported))
+		return;
+
+	charset = best_charset(supported);
+	snprintf(buf, sizeof(buf), "AT+CSCS=\"%s\"", charset);
+
+	g_at_chat_send(data->chat, buf, none_prefix, NULL, NULL, NULL);
+}
+
+static void list_charsets(struct ofono_modem *modem)
+{
+	struct phonesim_data *data = ofono_modem_get_data(modem);
+
+	g_at_chat_send(data->chat, "AT+CSCS=?", cscs_prefix,
+			list_charsets_cb, modem, NULL);
+}
+
 static int phonesim_probe(struct ofono_modem *modem)
 {
 	struct phonesim_data *data;
@@ -321,6 +364,8 @@ static void phonesim_pre_sim(struct ofono_modem *modem)
 
 	if (sim)
 		ofono_sim_inserted_notify(sim, TRUE);
+
+	list_charsets(modem);
 }
 
 static void phonesim_post_sim(struct ofono_modem *modem)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Added UCS2 handling and review comments incorporated
  2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
                   ` (11 preceding siblings ...)
  2010-09-09 12:31 ` [PATCH 12/12] Handling of Send USSD proactive command Jeevaka Badrappan
@ 2010-09-13 23:00 ` Jeevaka Badrappan
  2010-09-13 23:00   ` [PATCH 1/8] smsutil: Add USSD encoding function Jeevaka Badrappan
  12 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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


Hi all,

   Following patches adds the missing UCS2 handling for received USSD data, 
Denis's review comments incorporated and also test added for testing the 
newly added utility functions. All the changes are done for adding support 
for the Send USSD proactive command

Thanks and Regards,
jeevaka

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 1/8] smsutil: Add USSD encoding function
  2010-09-13 23:00 ` Added UCS2 handling and review comments incorporated Jeevaka Badrappan
@ 2010-09-13 23:00   ` Jeevaka Badrappan
  2010-09-13 23:00     ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Jeevaka Badrappan
  2010-09-14 16:58     ` [PATCH 1/8] smsutil: Add USSD encoding function Denis Kenzior
  0 siblings, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 src/smsutil.c |   29 +++++++++++++++++++++++++++++
 src/smsutil.h |    1 +
 2 files changed, 30 insertions(+), 0 deletions(-)

diff --git a/src/smsutil.c b/src/smsutil.c
index 26c7951..0d68d33 100644
--- a/src/smsutil.c
+++ b/src/smsutil.c
@@ -4179,3 +4179,32 @@ char *ussd_decode(int dcs, int len, const unsigned char *data)
 
 	return utf8;
 }
+
+gboolean ussd_encode(const char *str, long *items_written, unsigned char *pdu)
+{
+	unsigned char *converted = NULL;
+	long written;
+	long num_packed;
+
+	if (!pdu)
+		return FALSE;
+
+	converted = convert_utf8_to_gsm(str, -1, NULL, &written, 0);
+	if (!converted || written > 182)
+		goto error;
+
+	pack_7bit_own_buf(converted, written, 0, TRUE, &num_packed, 0, pdu);
+
+	g_free(converted);
+
+	if (num_packed < 1)
+		return FALSE;
+
+	if (items_written)
+		*items_written = num_packed;
+
+	return TRUE;
+error:
+	g_free(converted);
+	return FALSE;
+}
diff --git a/src/smsutil.h b/src/smsutil.h
index 0e0ddf4..a81fd6d 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -544,3 +544,4 @@ GSList *cbs_optimize_ranges(GSList *ranges);
 gboolean cbs_topic_in_range(unsigned int topic, GSList *ranges);
 
 char *ussd_decode(int dcs, int len, const unsigned char *data);
+gboolean ussd_encode(const char *str, long *items_written, unsigned char *pdu);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function
  2010-09-13 23:00   ` [PATCH 1/8] smsutil: Add USSD encoding function Jeevaka Badrappan
@ 2010-09-13 23:00     ` Jeevaka Badrappan
  2010-09-13 23:00       ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Jeevaka Badrappan
  2010-09-14 17:01       ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Denis Kenzior
  2010-09-14 16:58     ` [PATCH 1/8] smsutil: Add USSD encoding function Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 src/util.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/util.h |   10 +++++
 2 files changed, 118 insertions(+), 0 deletions(-)

diff --git a/src/util.c b/src/util.c
index bb90f6c..b2a9321 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1261,3 +1261,111 @@ unsigned char *utf8_to_sim_string(const char *utf,
 
 	return result;
 }
+
+/*!
+ * Converts UCS2 encoded text to GSM alphabet. The result is unpacked,
+ * with the 7th bit always 0. If terminator is not 0, a terminator character
+ * is appended to the result.
+ *
+ * Returns the encoded data or NULL if the data could not be encoded. The
+ * data must be freed by the caller. If items_read is not NULL, it contains
+ * the actual number of bytes read. If items_written is not NULL, contains
+ * the number of bytes written.
+ */
+unsigned char *convert_ucs2_to_gsm_with_lang(const unsigned char *text,
+					long len, long *items_read,
+					long *items_written,
+					unsigned char terminator,
+					enum gsm_dialect locking_lang,
+					enum gsm_dialect single_lang)
+{
+	long nchars = 0;
+	const unsigned char *in;
+	unsigned char *out;
+	unsigned char *res = NULL;
+	long res_len;
+	long i;
+
+	if (locking_lang >= GSM_DIALECT_INVALID)
+		return NULL;
+
+	if (single_lang >= GSM_DIALECT_INVALID)
+		return NULL;
+
+	if (len < 1 || len % 2)
+		return NULL;
+
+	in = text;
+	res_len = 0;
+
+	for (i = 0; i < len; i+=2) {
+		gunichar c = (in[i] << 8) | in[i+1];
+		unsigned short converted = GUND;
+
+		if (c > 0xffff)
+			goto err_out;
+
+		converted = unicode_locking_shift_lookup(c, locking_lang);
+
+		if (converted == GUND)
+			converted = unicode_single_shift_lookup(c, single_lang);
+
+		if (converted == GUND)
+			goto err_out;
+
+		if (converted & 0x1b00)
+			res_len += 2;
+		else
+			res_len += 1;
+
+		nchars += 1;
+	}
+
+	res = g_try_malloc(res_len + (terminator ? 1 : 0));
+	if (!res)
+		goto err_out;
+
+	in = text;
+	out = res;
+
+	for (i = 0; i < len; i+=2) {
+		gunichar c = (in[i] << 8) | in[i+1];
+		unsigned short converted = GUND;
+
+		converted = unicode_locking_shift_lookup(c, locking_lang);
+
+		if (converted == GUND)
+			converted = unicode_single_shift_lookup(c, single_lang);
+
+		if (converted & 0x1b00) {
+			*out = 0x1b;
+			++out;
+		}
+
+		*out = converted;
+		++out;
+	}
+
+	if (terminator)
+		*out = terminator;
+
+	if (items_written)
+		*items_written = out - res;
+
+err_out:
+	if (items_read)
+		*items_read = nchars;
+
+	return res;
+}
+
+unsigned char *convert_ucs2_to_gsm(const unsigned char *text, long len,
+				long *items_read, long *items_written,
+				unsigned char terminator)
+{
+	return convert_ucs2_to_gsm_with_lang(text, len, items_read,
+						items_written,
+						terminator,
+						GSM_DIALECT_DEFAULT,
+						GSM_DIALECT_DEFAULT);
+}
diff --git a/src/util.h b/src/util.h
index 9da81aa..76498ad 100644
--- a/src/util.h
+++ b/src/util.h
@@ -80,3 +80,13 @@ char *sim_string_to_utf8(const unsigned char *buffer, int length);
 
 unsigned char *utf8_to_sim_string(const char *utf,
 					int max_length, int *out_length);
+
+unsigned char *convert_ucs2_to_gsm_with_lang(const unsigned char *text, long len,
+					long *items_read, long *items_written,
+					unsigned char terminator,
+					enum gsm_dialect locking_lang,
+					enum gsm_dialect single_lang);
+
+unsigned char *convert_ucs2_to_gsm(const unsigned char *text, long len,
+				long *items_read, long *items_written,
+				unsigned char terminator);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion
  2010-09-13 23:00     ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Jeevaka Badrappan
@ 2010-09-13 23:00       ` Jeevaka Badrappan
  2010-09-13 23:00         ` [PATCH 4/8] USSD atom driver changes to read current character setting Jeevaka Badrappan
  2010-09-14 17:01         ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Denis Kenzior
  2010-09-14 17:01       ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 unit/test-util.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/unit/test-util.c b/unit/test-util.c
index de62848..9df61dd 100644
--- a/unit/test-util.c
+++ b/unit/test-util.c
@@ -38,6 +38,10 @@ const unsigned char invalid_gsm_extended_len[] = {
 	0x1b, 0x28, 0x1b
 };
 
+const unsigned char invalid_ucs2[] = {
+	0x03, 0x93, 0x00, 0x00
+};
+
 unsigned short gsm_to_unicode_map[] =
 {
 0x00,	0x0040,
@@ -342,6 +346,7 @@ static void test_invalid()
 	long nwritten;
 	long nread;
 	char *res;
+	unsigned char *gsm;
 
 	res = convert_gsm_to_utf8(invalid_gsm_extended, 0, &nread, &nwritten,
 					0);
@@ -362,6 +367,19 @@ static void test_invalid()
 					&nread, &nwritten, 0);
 	g_assert(res == NULL);
 	g_assert(nread == 3);
+
+	gsm = convert_ucs2_to_gsm(invalid_ucs2,
+					sizeof(invalid_ucs2),
+					&nread, &nwritten, 0);
+	g_assert(gsm == NULL);
+	g_assert(nread == 1);
+
+	nread = 0;
+	gsm = convert_ucs2_to_gsm(invalid_ucs2,
+					sizeof(invalid_ucs2) - 1,
+					&nread, &nwritten, 0);
+	g_assert(gsm == NULL);
+	g_assert(nread == 0);
 }
 
 static void test_valid()
@@ -905,6 +923,67 @@ static void test_sim()
 	g_assert(utf8 == NULL);
 }
 
+static void test_unicode_to_gsm()
+{
+	long nwritten;
+	long nread;
+	int i;
+	unsigned char *res;
+	char *utf8;
+	unsigned char buf[2];
+	unsigned char *back;
+	gunichar2 verify;
+
+	static int map_size =
+		sizeof(gsm_to_unicode_map) / sizeof(unsigned short) / 2;
+
+	for (i = 0; i < map_size; i++) {
+		unsigned short c = gsm_to_unicode_map[i*2+1];
+
+		buf[0] = c >> 8;
+		buf[1] = c & 0xff;
+
+		res = convert_ucs2_to_gsm(buf, 2, &nread, &nwritten, 0);
+		g_assert(res);
+
+		if (g_test_verbose())
+			g_print("nread:%ld, nwritten:%ld, %s\n",
+				nread, nwritten, res);
+
+		if (res[0] == 0x1B)
+			g_assert(nwritten == 2);
+		else
+			g_assert(nwritten == 1);
+
+		utf8 = g_convert((const gchar *) buf, 2,
+				"UTF-8", "UCS-2BE",
+				NULL, NULL, NULL);
+		g_assert(utf8);
+
+		back = convert_utf8_to_gsm(utf8, strlen(utf8), &nread,
+						&nwritten, 0);
+		g_assert(back);
+
+		if (back[0] == 0x1B) {
+			g_assert(nwritten == 2);
+			verify = back[0] << 8 | back[1];
+		} else {
+			g_assert(nwritten == 1);
+			verify = back[0];
+		}
+
+		if (g_test_verbose())
+			g_print("nwritten:%ld, verify: 0x%x\n",
+				nwritten, verify);
+
+		g_assert(verify == gsm_to_unicode_map[i*2]);
+
+		g_free(res);
+		g_free(back);
+		g_free(utf8);
+	}
+}
+
 int main(int argc, char **argv)
 {
 	g_test_init(&argc, &argv, NULL);
@@ -918,6 +997,7 @@ int main(int argc, char **argv)
 	g_test_add_func("/testutil/SMS Handling", test_sms_handling);
 	g_test_add_func("/testutil/Offset Handling", test_offset_handling);
 	g_test_add_func("/testutil/SIM conversions", test_sim);
+	g_test_add_func("/testutil/Valid Unicode to GSM Conversion", test_unicode_to_gsm);
 
 	return g_test_run();
 }
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 4/8] USSD atom driver changes to read current character setting
  2010-09-13 23:00       ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Jeevaka Badrappan
@ 2010-09-13 23:00         ` Jeevaka Badrappan
  2010-09-13 23:00           ` [PATCH 5/8] Internal and Driver API changes for Send USSD Jeevaka Badrappan
  2010-09-14 17:01           ` [PATCH 4/8] USSD atom driver changes to read current character setting Denis Kenzior
  2010-09-14 17:01         ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 1e1fc25..30145ad 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -44,12 +44,25 @@
 
 static const char *cusd_prefix[] = { "+CUSD:", NULL };
 static const char *none_prefix[] = { NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
 
 struct ussd_data {
 	GAtChat *chat;
 	unsigned int vendor;
+	enum at_util_charset charset;
 };
 
+static void read_charset_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct ussd_data *data = user_data;
+
+	if (!ok)
+		return;
+
+	at_util_parse_cscs_query(result, &data->charset);
+}
+
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
 	GAtResultIter iter;
@@ -247,6 +260,9 @@ static int at_ussd_probe(struct ofono_ussd *ussd, unsigned int vendor,
 
 	ofono_ussd_set_data(ussd, data);
 
+	g_at_chat_send(chat, "AT+CSCS?", cscs_prefix, read_charset_cb, data,
+			NULL);
+
 	g_at_chat_send(chat, "AT+CUSD=1", NULL, at_ussd_register, ussd, NULL);
 
 	return 0;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 5/8] Internal and Driver API changes for Send USSD
  2010-09-13 23:00         ` [PATCH 4/8] USSD atom driver changes to read current character setting Jeevaka Badrappan
@ 2010-09-13 23:00           ` Jeevaka Badrappan
  2010-09-13 23:00             ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
  2010-09-14 17:24             ` [PATCH 5/8] Internal and Driver API changes for Send USSD Denis Kenzior
  2010-09-14 17:01           ` [PATCH 4/8] USSD atom driver changes to read current character setting Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c  |  112 +++++++++++++++++++++++++++--------------------
 drivers/isimodem/ussd.c |   42 +++--------------
 include/ussd.h          |    8 ++-
 src/ussd.c              |   61 +++++++++++++++++--------
 4 files changed, 120 insertions(+), 103 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 30145ad..bc5690d 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -65,15 +65,17 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
 
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
+	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	GAtResultIter iter;
 	int status;
 	int dcs;
-	const char *content;
-	char *converted = NULL;
-	gboolean udhi;
+	const char *content = NULL;
 	enum sms_charset charset;
-	gboolean compressed;
-	gboolean iso639;
+	unsigned char msg[160];
+	const unsigned char *msg_ptr = NULL;
+	unsigned char *converted = NULL;
+	long written;
+	long msg_len = 0;
 
 	g_at_result_iter_init(&iter, result);
 
@@ -86,34 +88,45 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 	if (!g_at_result_iter_next_string(&iter, &content))
 		goto out;
 
-	if (g_at_result_iter_next_number(&iter, &dcs)) {
-		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
-					&compressed, NULL, &iso639))
-			goto out;
-
-		if (udhi || compressed || iso639)
-			goto out;
-	} else
-		charset = SMS_CHARSET_7BIT;
-
-	if (charset == SMS_CHARSET_7BIT)
-		converted = convert_gsm_to_utf8((const guint8 *) content,
-						strlen(content), NULL, NULL, 0);
-
-	else if (charset == SMS_CHARSET_8BIT) {
-		/* TODO: Figure out what to do with 8 bit data */
-		ofono_error("8-bit coded USSD response received");
-		status = 4; /* Not supported */
-	} else {
-		/* No other encoding is mentioned in TS27007 7.15 */
+	if (!g_at_result_iter_next_number(&iter, &dcs))
+		dcs = 0;
+
+	cbs_dcs_decode(dcs, NULL, NULL, &charset, NULL, NULL, NULL);
+
+	if (charset == SMS_CHARSET_7BIT) {
+		if (data->charset == AT_UTIL_CHARSET_GSM)
+			msg_ptr = pack_7bit_own_buf((const guint8 *) content,
+					strlen(content), 0, TRUE, &msg_len, 0, msg);
+		else if (data->charset == AT_UTIL_CHARSET_UTF8)
+			ussd_encode(content, &msg_len, msg);
+		else if (data->charset == AT_UTIL_CHARSET_UCS2) {
+			msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+
+			converted = convert_ucs2_to_gsm(msg_ptr, msg_len, NULL,
+							&written, 0);
+			if (!converted) {
+				msg_ptr = NULL;
+				msg_len = 0;
+				goto out;
+			}
+
+			msg_ptr = pack_7bit_own_buf(converted,
+						written, 0, TRUE,
+						&msg_len, 0, msg);
+
+			g_free(converted);
+		}
+	} else if (charset == SMS_CHARSET_8BIT)
+		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+	else if (charset == SMS_CHARSET_UCS2)
+		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+	else {
 		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
 		status = 4; /* Not supported */
 	}
 
 out:
-	ofono_ussd_notify(ussd, status, converted);
-
-	g_free(converted);
+	ofono_ussd_notify(ussd, status, dcs, msg_ptr, msg_len);
 }
 
 static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -130,39 +143,45 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	cusd_parse(result, ussd);
 }
 
-static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
+static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
 				ofono_ussd_cb_t cb, void *user_data)
 {
 	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	struct cb_data *cbd = cb_data_new(cb, user_data);
-	unsigned char *converted = NULL;
-	int dcs;
-	int max_len;
-	long written;
 	char buf[256];
+	unsigned char unpacked_buf[182];
+	char coded_buf[160];
+	char *converted;
+	long written;
+	enum sms_charset charset;
 
 	if (!cbd)
 		goto error;
 
 	cbd->user = ussd;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-
-	if (!converted)
+	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
 		goto error;
-	else {
-		dcs = 15;
-		max_len = 182;
-	}
 
-	if (written > max_len)
-		goto error;
+	if (charset == SMS_CHARSET_7BIT) {
+		unpack_7bit_own_buf(pdu, len, 0, TRUE, sizeof(unpacked_buf),
+					&written, 0, unpacked_buf);
 
-	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
-			(int) written, converted, dcs);
+		if (written < 1)
+			goto error;
 
-	g_free(converted);
-	converted = NULL;
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				(int) written, unpacked_buf, dcs);
+	} else {
+		converted = encode_hex_own_buf(pdu, len, 0, coded_buf);
+		if (!converted)
+			goto error;
+
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				strlen(converted), converted, dcs);
+	}
 
 	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
 		/* Ensure that the modem is using GSM character set. It
@@ -179,7 +198,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
 
 error:
 	g_free(cbd);
-	g_free(converted);
 
 	CALLBACK_WITH_FAILURE(cb, user_data);
 }
diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
index 330a141..19ba30e 100644
--- a/drivers/isimodem/ussd.c
+++ b/drivers/isimodem/ussd.c
@@ -74,24 +74,14 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 {
 	const unsigned char *msg = data;
 	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
-	char *converted = NULL;
 
 	if (!msg || len < 4)
-		goto out;
+		ofono_ussd_notify(ussd, status, 0, NULL, 0);
 
 	status = isi_type_to_status(msg[2]);
 
 	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
-		goto out;
-
-	converted = ussd_decode(msg[1], msg[3], msg + 4);
-
-	if (converted)
-		status = OFONO_USSD_STATUS_NOTIFY;
-
-out:
-	ofono_ussd_notify(ussd, status, converted);
-	g_free(converted);
+		ofono_ussd_notify(ussd, status, msg[1], msg + 4, msg[3]);
 }
 
 
@@ -129,7 +119,7 @@ error:
 }
 
 static GIsiRequest *ussd_send(GIsiClient *client,
-				uint8_t *str, size_t len,
+				int dcs, uint8_t *str, size_t len,
 				void *data, GDestroyNotify notify)
 {
 	const uint8_t msg[] = {
@@ -138,7 +128,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 		0x01,		/* subblock count */
 		SS_GSM_USSD_STRING,
 		4 + len + 3,	/* subblock length */
-		0x0f,		/* DCS */
+		dcs,		/* DCS */
 		len,		/* string length */
 		/* USSD string goes here */
 	};
@@ -152,33 +142,17 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 				ussd_send_resp_cb, data, notify);
 }
 
-static void isi_request(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t cb, void *data)
+static void isi_request(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_cb_t cb, void *data)
 {
 	struct ussd_data *ud = ofono_ussd_get_data(ussd);
 	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
-	unsigned char buf[256];
-	unsigned char *packed = NULL;
-	unsigned char *converted = NULL;
-	long num_packed;
-	long written;
 
 	if (!cbd)
 		goto error;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-	if (!converted)
-		goto error;
-
-	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
-					&num_packed, 0, buf);
-
-	g_free(converted);
-
-	if (written > SS_MAX_USSD_LENGTH)
-		goto error;
-
-	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
+	if (ussd_send(ud->client, dcs, (guint8 *) pdu, len, cbd, g_free))
 		return;
 
 error:
diff --git a/include/ussd.h b/include/ussd.h
index 96e04cb..360ef00 100644
--- a/include/ussd.h
+++ b/include/ussd.h
@@ -45,13 +45,15 @@ struct ofono_ussd_driver {
 	const char *name;
 	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
 	void (*remove)(struct ofono_ussd *ussd);
-	void (*request)(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t, void *data);
+	void (*request)(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_cb_t, void *data);
 	void (*cancel)(struct ofono_ussd *ussd,
 				ofono_ussd_cb_t cb, void *data);
 };
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len);
 
 int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
 void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
diff --git a/src/ussd.c b/src/ussd.c
index fbb07d2..8d9c98d 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -34,8 +34,11 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "smsutil.h"
+#include "util.h"
 
 #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
+#define MAX_USSD_LENGTH 160
 
 static GSList *g_drivers = NULL;
 
@@ -317,10 +320,13 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *ussdstr = "USSD";
+	char *utf8_str = NULL;
+	gboolean utf8_str_valid = FALSE;
 	const char sig[] = { DBUS_TYPE_STRING, 0 };
 	DBusMessage *reply;
 	DBusMessageIter iter;
@@ -346,14 +352,20 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 		goto out;
 	}
 
+	if (data && data_len > 0)
+		utf8_str = ussd_decode(dcs, data_len, data);
+
+	if (!utf8_str) {
+		utf8_str = "";
+		status = OFONO_USSD_STATUS_NOTIFY;
+	} else
+		utf8_str_valid = TRUE;
+
 	/* TODO: Rework this in the Agent framework */
 	if (ussd->state == USSD_STATE_ACTIVE) {
 
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
 		dbus_message_iter_init_append(reply, &iter);
 
 		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
@@ -363,7 +375,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 							&variant);
 
 		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
-						&str);
+						&utf8_str);
 
 		dbus_message_iter_close_container(&iter, &variant);
 
@@ -375,10 +387,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
 		reply = dbus_message_new_method_return(ussd->pending);
 
-		if (!str)
-			str = "";
-
-		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
+		dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
 						DBUS_TYPE_INVALID);
 
 		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
@@ -398,20 +407,17 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 			signal_name = "NotificationReceived";
 		}
 
-		if (!str)
-			str = "";
-
 		g_dbus_emit_signal(conn, path,
 				SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
-				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
+				DBUS_TYPE_STRING, &utf8_str, DBUS_TYPE_INVALID);
 
 		ussd_change_state(ussd, new_state);
-		return;
+		goto free;
 	} else {
 		ofono_error("Received an unsolicited USSD but can't handle.");
-		DBG("USSD is: status: %d, %s", status, str);
+		DBG("USSD is: status: %d, %s", status, utf8_str);
 
-		return;
+		goto free;
 	}
 
 out:
@@ -419,6 +425,10 @@ out:
 
 	dbus_message_unref(ussd->pending);
 	ussd->pending = NULL;
+
+free:
+	if (utf8_str_valid)
+		g_free(utf8_str);
 }
 
 static void ussd_callback(const struct ofono_error *error, void *data)
@@ -447,6 +457,9 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[160];
+	long num_packed;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -469,14 +482,17 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 	if (!valid_ussd_string(str))
 		return __ofono_error_invalid_format(msg);
 
-	DBG("OK, running USSD request");
+	if (!ussd_encode(str, &num_packed, buf))
+		return __ofono_error_invalid_format(msg);
 
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
+	DBG("OK, running USSD request");
+
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_callback, ussd);
+	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_callback, ussd);
 
 	return NULL;
 }
@@ -507,6 +523,9 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[160];
+	long num_packed;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -521,12 +540,16 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 	if (strlen(str) == 0)
 		return __ofono_error_invalid_format(msg);
 
+	if (!ussd_encode(str, &num_packed, buf))
+		return __ofono_error_invalid_format(msg);
+
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
+	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_response_callback,
+				ussd);
 
 	return NULL;
 }
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD
  2010-09-13 23:00           ` [PATCH 5/8] Internal and Driver API changes for Send USSD Jeevaka Badrappan
@ 2010-09-13 23:00             ` Jeevaka Badrappan
  2010-09-13 23:00               ` [PATCH 7/8] stk: Handling of Send USSD proactive command Jeevaka Badrappan
  2010-09-14 17:45               ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Denis Kenzior
  2010-09-14 17:24             ` [PATCH 5/8] Internal and Driver API changes for Send USSD Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 src/ofono.h |    7 +++++
 src/ussd.c  |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 92 insertions(+), 1 deletions(-)

diff --git a/src/ofono.h b/src/ofono.h
index f1c0973..8ab6a2e 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -258,6 +258,9 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
 					const char *old, const char *new,
 					DBusMessage *msg, void *data);
 
+typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
+					const unsigned char *pdu, int len, void *data);
+
 gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
 					ofono_ussd_ssc_cb_t cb, void *data,
 					ofono_destroy_func destroy);
@@ -269,6 +272,10 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
 void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
 gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
 
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_request_cb_t cb, void *user_data);
+
 #include <ofono/netreg.h>
 
 typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
diff --git a/src/ussd.c b/src/ussd.c
index 8d9c98d..af0aae1 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -49,6 +49,15 @@ enum ussd_state {
 	USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+	struct ofono_ussd *ussd;
+	int dcs;
+	unsigned char *pdu;
+	int len;
+	ofono_ussd_request_cb_t cb;
+	void *user_data;
+};
+
 struct ofono_ussd {
 	int state;
 	DBusMessage *pending;
@@ -59,6 +68,7 @@ struct ofono_ussd {
 	const struct ofono_ussd_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -73,7 +83,7 @@ gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
 	if (!ussd)
 		return FALSE;
 
-	if (ussd->pending || ussd->state != USSD_STATE_IDLE)
+	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
 		return TRUE;
 
 	return FALSE;
@@ -320,6 +330,31 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+				const unsigned char *pdu, int len)
+{
+	struct ussd_request *req = ussd->req;
+
+	if (req && req->cb) {
+		req->cb(error, dcs, pdu, len, req->user_data);
+		g_free(req->pdu);
+		g_free(req);
+		ussd->req = NULL;
+	}
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+	switch (status) {
+	case OFONO_USSD_STATUS_TIMED_OUT:
+		return -ETIMEDOUT;
+	case OFONO_USSD_STATUS_NOT_SUPPORTED:
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
 void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 			const unsigned char *data, int data_len)
 {
@@ -332,6 +367,19 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 	DBusMessageIter iter;
 	DBusMessageIter variant;
 
+	if (ussd->req &&
+		(status == OFONO_USSD_STATUS_NOTIFY ||
+		status == OFONO_USSD_STATUS_TERMINATED ||
+		status == OFONO_USSD_STATUS_TIMED_OUT ||
+		status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
+
+		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
+					dcs, data, data_len);
+
+		ussd_change_state(ussd, USSD_STATE_IDLE);
+		return;
+	}
+
 	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
 		ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -577,6 +625,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
 	reply = dbus_message_new_method_return(ussd->cancel);
 	__ofono_dbus_pending_reply(&ussd->cancel, reply);
 
+	if (ussd->req)
+		ussd_request_finish(ussd, -1, -ECANCELED, NULL, -1);
+
 	ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
@@ -775,3 +826,36 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 {
 	return ussd->driver_data;
 }
+
+static void ussd_request_callback(const struct ofono_error *error, void *data)
+{
+	struct ofono_ussd *ussd = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		ussd_request_finish(ussd, error->error, -1, NULL, -1);
+	else
+		ussd_change_state(ussd,USSD_STATE_ACTIVE);
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
+				ofono_ussd_request_cb_t cb, void *user_data)
+{
+	struct ussd_request *req;
+
+	if (!ussd->driver->request)
+		return -ENOSYS;
+
+	req = g_try_new0(struct ussd_request, 1);
+	req->dcs = dcs;
+	req->pdu = g_memdup(pdu, len);
+	req->len = len;
+	req->cb = cb;
+	req->user_data = user_data;
+
+	ussd->req = req;
+
+	ussd->driver->request(ussd, dcs, pdu, len, ussd_request_callback, ussd);
+
+	return 0;
+}
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 7/8] stk: Handling of Send USSD proactive command
  2010-09-13 23:00             ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
@ 2010-09-13 23:00               ` Jeevaka Badrappan
  2010-09-13 23:00                 ` [PATCH 8/8] stkutil: Add handling of error case scenario in build USSD data object Jeevaka Badrappan
  2010-09-14 21:49                 ` [PATCH 3/4] stk: Handling of Send USSD proactive command Jeevaka Badrappan
  2010-09-14 17:45               ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Denis Kenzior
  1 sibling, 2 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 src/stk.c |  144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 143 insertions(+), 1 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 04bfc65..e9e42be 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -1590,6 +1590,145 @@ static gboolean handle_command_set_up_call(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static void send_ussd_callback(int error, int dcs, const unsigned char *msg,
+				int msg_len, void *userdata)
+{
+	struct ofono_stk *stk = userdata;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	struct stk_response rsp;
+	enum sms_charset charset;
+
+	if (stk->pending_cmd->send_ussd.alpha_id &&
+			stk->pending_cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_unset(stk);
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	switch (error) {
+	case 0:
+		if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL)) {
+			if (charset == SMS_CHARSET_7BIT)
+				rsp.send_ussd.text.dcs = 0x00;
+			else if (charset == SMS_CHARSET_8BIT)
+				rsp.send_ussd.text.dcs = 0x04;
+			else if (charset == SMS_CHARSET_UCS2)
+				rsp.send_ussd.text.dcs = 0x08;
+
+			rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+			rsp.send_ussd.text.text = msg;
+			rsp.send_ussd.text.len = msg_len;
+		} else {
+			rsp.result.type = STK_RESULT_TYPE_USSD_RETURN_ERROR;
+			rsp.result.additional = (unsigned char *) &error;
+			rsp.result.additional_len = 1;
+			rsp.send_ussd.text.dcs = -1;
+		}
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	case -ECANCELED:
+		send_simple_response(stk,
+				STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION);
+		break;
+	case -ETIMEDOUT:
+		send_simple_response(stk, STK_RESULT_TYPE_NETWORK_UNAVAILABLE);
+		break;
+	default:
+		rsp.result.type = STK_RESULT_TYPE_USSD_RETURN_ERROR;
+		rsp.result.additional = (unsigned char *) &error;
+		rsp.result.additional_len = 1;
+		rsp.send_ussd.text.dcs = -1;
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	}
+}
+
+static gboolean handle_command_send_ussd(const struct stk_command *cmd,
+					struct stk_response *rsp,
+					struct ofono_stk *stk)
+{
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	static unsigned char busy_on_ss_result[] = { 0x03 };
+	static unsigned char busy_on_ussd_result[] = { 0x08 };
+	struct ofono_atom *atom;
+	struct ofono_ussd *ussd;
+	int err;
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_forwarding_is_busy(cf)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_BARRING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_barring *cb = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_barring_is_busy(cb)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_settings_is_busy(cs)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
+	if (!atom || !__ofono_atom_get_registered(atom)) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	ussd = __ofono_atom_get_data(atom);
+	if (__ofono_ussd_is_busy(ussd)) {
+		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+		rsp->result.additional_len = sizeof(busy_on_ussd_result);
+		rsp->result.additional = busy_on_ussd_result;
+		return TRUE;
+	}
+
+	err = __ofono_ussd_initiate(ussd, cmd->send_ussd.ussd_string.dcs,
+					cmd->send_ussd.ussd_string.string,
+					cmd->send_ussd.ussd_string.len,
+					send_ussd_callback, stk);
+
+	if (err >= 0)
+		return FALSE;
+
+	if (err == -ENOSYS) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	if (cmd->send_ussd.alpha_id && cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_set(stk, cmd->send_ussd.alpha_id);
+
+	return FALSE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -1740,7 +1879,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 		respond = handle_command_set_up_call(stk->pending_cmd,
 							&rsp, stk);
 		break;
-
+	case STK_COMMAND_TYPE_SEND_USSD:
+		respond = handle_command_send_ussd(stk->pending_cmd,
+							&rsp, stk);
+		break;
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 8/8] stkutil: Add handling of error case scenario in build USSD data object
  2010-09-13 23:00               ` [PATCH 7/8] stk: Handling of Send USSD proactive command Jeevaka Badrappan
@ 2010-09-13 23:00                 ` Jeevaka Badrappan
  2010-09-14 21:49                 ` [PATCH 3/4] stk: Handling of Send USSD proactive command Jeevaka Badrappan
  1 sibling, 0 replies; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-13 23:00 UTC (permalink / raw)
  To: ofono

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

---
 src/stkutil.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/src/stkutil.c b/src/stkutil.c
index 3cfe06a..95d2f9b 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -4177,6 +4177,9 @@ static gboolean build_dataobj_ussd_text(struct stk_tlv_builder *tlv,
 	const struct stk_ussd_text *text = data;
 	unsigned char tag = STK_DATA_OBJECT_TYPE_TEXT;
 
+	if (text->dcs == -1)
+		return TRUE;
+
 	stk_tlv_builder_open_container(tlv, cr, tag, TRUE);
 
 	if (text->len > 0) {
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 1/8] smsutil: Add USSD encoding function
  2010-09-13 23:00   ` [PATCH 1/8] smsutil: Add USSD encoding function Jeevaka Badrappan
  2010-09-13 23:00     ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Jeevaka Badrappan
@ 2010-09-14 16:58     ` Denis Kenzior
  1 sibling, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 16:58 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  src/smsutil.c |   29 +++++++++++++++++++++++++++++
>  src/smsutil.h |    1 +
>  2 files changed, 30 insertions(+), 0 deletions(-)

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function
  2010-09-13 23:00     ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Jeevaka Badrappan
  2010-09-13 23:00       ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Jeevaka Badrappan
@ 2010-09-14 17:01       ` Denis Kenzior
  1 sibling, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 17:01 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  src/util.c |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/util.h |   10 +++++
>  2 files changed, 118 insertions(+), 0 deletions(-)

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion
  2010-09-13 23:00       ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Jeevaka Badrappan
  2010-09-13 23:00         ` [PATCH 4/8] USSD atom driver changes to read current character setting Jeevaka Badrappan
@ 2010-09-14 17:01         ` Denis Kenzior
  1 sibling, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 17:01 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  unit/test-util.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 80 insertions(+), 0 deletions(-)

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 4/8] USSD atom driver changes to read current character setting
  2010-09-13 23:00         ` [PATCH 4/8] USSD atom driver changes to read current character setting Jeevaka Badrappan
  2010-09-13 23:00           ` [PATCH 5/8] Internal and Driver API changes for Send USSD Jeevaka Badrappan
@ 2010-09-14 17:01           ` Denis Kenzior
  1 sibling, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 17:01 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/ussd.c |   16 ++++++++++++++++
>  1 files changed, 16 insertions(+), 0 deletions(-)

This patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 5/8] Internal and Driver API changes for Send USSD
  2010-09-13 23:00           ` [PATCH 5/8] Internal and Driver API changes for Send USSD Jeevaka Badrappan
  2010-09-13 23:00             ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
@ 2010-09-14 17:24             ` Denis Kenzior
  2010-09-14 21:23               ` [PATCH 1/4] " Jeevaka Badrappan
  1 sibling, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 17:24 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/ussd.c  |  112 +++++++++++++++++++++++++++--------------------
>  drivers/isimodem/ussd.c |   42 +++--------------
>  include/ussd.h          |    8 ++-
>  src/ussd.c              |   61 +++++++++++++++++--------
>  4 files changed, 120 insertions(+), 103 deletions(-)
> 
> diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
> index 30145ad..bc5690d 100644
> --- a/drivers/atmodem/ussd.c
> +++ b/drivers/atmodem/ussd.c
> @@ -65,15 +65,17 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
>  
>  static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
>  {
> +	struct ussd_data *data = ofono_ussd_get_data(ussd);
>  	GAtResultIter iter;
>  	int status;
>  	int dcs;
> -	const char *content;
> -	char *converted = NULL;
> -	gboolean udhi;
> +	const char *content = NULL;
>  	enum sms_charset charset;
> -	gboolean compressed;
> -	gboolean iso639;
> +	unsigned char msg[160];
> +	const unsigned char *msg_ptr = NULL;
> +	unsigned char *converted = NULL;
> +	long written;
> +	long msg_len = 0;
>  
>  	g_at_result_iter_init(&iter, result);
>  
> @@ -86,34 +88,45 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
>  	if (!g_at_result_iter_next_string(&iter, &content))
>  		goto out;
>  
> -	if (g_at_result_iter_next_number(&iter, &dcs)) {
> -		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
> -					&compressed, NULL, &iso639))
> -			goto out;
> -
> -		if (udhi || compressed || iso639)
> -			goto out;
> -	} else
> -		charset = SMS_CHARSET_7BIT;
> -
> -	if (charset == SMS_CHARSET_7BIT)
> -		converted = convert_gsm_to_utf8((const guint8 *) content,
> -						strlen(content), NULL, NULL, 0);
> -
> -	else if (charset == SMS_CHARSET_8BIT) {
> -		/* TODO: Figure out what to do with 8 bit data */
> -		ofono_error("8-bit coded USSD response received");
> -		status = 4; /* Not supported */
> -	} else {
> -		/* No other encoding is mentioned in TS27007 7.15 */
> +	if (!g_at_result_iter_next_number(&iter, &dcs))
> +		dcs = 0;
> +
> +	cbs_dcs_decode(dcs, NULL, NULL, &charset, NULL, NULL, NULL);
> +
> +	if (charset == SMS_CHARSET_7BIT) {
> +		if (data->charset == AT_UTIL_CHARSET_GSM)
> +			msg_ptr = pack_7bit_own_buf((const guint8 *) content,
> +					strlen(content), 0, TRUE, &msg_len, 0, msg);
> +		else if (data->charset == AT_UTIL_CHARSET_UTF8)
> +			ussd_encode(content, &msg_len, msg);
> +		else if (data->charset == AT_UTIL_CHARSET_UCS2) {
> +			msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
> +
> +			converted = convert_ucs2_to_gsm(msg_ptr, msg_len, NULL,
> +							&written, 0);
> +			if (!converted) {
> +				msg_ptr = NULL;
> +				msg_len = 0;
> +				goto out;
> +			}
> +
> +			msg_ptr = pack_7bit_own_buf(converted,
> +						written, 0, TRUE,
> +						&msg_len, 0, msg);
> +
> +			g_free(converted);
> +		}
> +	} else if (charset == SMS_CHARSET_8BIT)
> +		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
> +	else if (charset == SMS_CHARSET_UCS2)
> +		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
> +	else {
>  		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
>  		status = 4; /* Not supported */
>  	}

Can you do me a favor and convert this if statement to a switch/case?
Move the contents of the else clause to the if that checks the DCS.  e.g.

if (cbs_dcs_decode() == FALSE) {
	....
}

switch (charset)
case SMS_CHARSET_7BIT:
	....
case SMS_CHARSET_8BIT:
case SMS_CHARSET_UCS2:
	....

>  
>  out:
> -	ofono_ussd_notify(ussd, status, converted);
> -
> -	g_free(converted);
> +	ofono_ussd_notify(ussd, status, dcs, msg_ptr, msg_len);
>  }
>  
>  static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
> @@ -130,39 +143,45 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
>  	cusd_parse(result, ussd);
>  }
>  
> -static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
> +static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
> +				const unsigned char *pdu, int len,
>  				ofono_ussd_cb_t cb, void *user_data)
>  {
>  	struct ussd_data *data = ofono_ussd_get_data(ussd);
>  	struct cb_data *cbd = cb_data_new(cb, user_data);
> -	unsigned char *converted = NULL;
> -	int dcs;
> -	int max_len;
> -	long written;
>  	char buf[256];
> +	unsigned char unpacked_buf[182];
> +	char coded_buf[160];
> +	char *converted;
> +	long written;
> +	enum sms_charset charset;
>  
>  	if (!cbd)
>  		goto error;
>  
>  	cbd->user = ussd;
>  
> -	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> -
> -	if (!converted)
> +	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
> +					NULL, NULL, NULL))
>  		goto error;
> -	else {
> -		dcs = 15;
> -		max_len = 182;
> -	}
>  
> -	if (written > max_len)
> -		goto error;
> +	if (charset == SMS_CHARSET_7BIT) {
> +		unpack_7bit_own_buf(pdu, len, 0, TRUE, sizeof(unpacked_buf),
> +					&written, 0, unpacked_buf);
>  
> -	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> -			(int) written, converted, dcs);
> +		if (written < 1)
> +			goto error;
>  
> -	g_free(converted);
> -	converted = NULL;
> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				(int) written, unpacked_buf, dcs);
> +	} else {
> +		converted = encode_hex_own_buf(pdu, len, 0, coded_buf);
> +		if (!converted)
> +			goto error;
> +
> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				strlen(converted), converted, dcs);
> +	}
>  
>  	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
>  		/* Ensure that the modem is using GSM character set. It
> @@ -179,7 +198,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
>  
>  error:
>  	g_free(cbd);
> -	g_free(converted);
>  
>  	CALLBACK_WITH_FAILURE(cb, user_data);
>  }
> diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
> index 330a141..19ba30e 100644
> --- a/drivers/isimodem/ussd.c
> +++ b/drivers/isimodem/ussd.c
> @@ -74,24 +74,14 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
>  {
>  	const unsigned char *msg = data;
>  	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
> -	char *converted = NULL;
>  
>  	if (!msg || len < 4)
> -		goto out;
> +		ofono_ussd_notify(ussd, status, 0, NULL, 0);
>  
>  	status = isi_type_to_status(msg[2]);
>  
>  	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
> -		goto out;
> -
> -	converted = ussd_decode(msg[1], msg[3], msg + 4);
> -
> -	if (converted)
> -		status = OFONO_USSD_STATUS_NOTIFY;
> -
> -out:
> -	ofono_ussd_notify(ussd, status, converted);
> -	g_free(converted);
> +		ofono_ussd_notify(ussd, status, msg[1], msg + 4, msg[3]);
>  }
>  
>  
> @@ -129,7 +119,7 @@ error:
>  }
>  
>  static GIsiRequest *ussd_send(GIsiClient *client,
> -				uint8_t *str, size_t len,
> +				int dcs, uint8_t *str, size_t len,
>  				void *data, GDestroyNotify notify)
>  {
>  	const uint8_t msg[] = {
> @@ -138,7 +128,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
>  		0x01,		/* subblock count */
>  		SS_GSM_USSD_STRING,
>  		4 + len + 3,	/* subblock length */
> -		0x0f,		/* DCS */
> +		dcs,		/* DCS */
>  		len,		/* string length */
>  		/* USSD string goes here */
>  	};
> @@ -152,33 +142,17 @@ static GIsiRequest *ussd_send(GIsiClient *client,
>  				ussd_send_resp_cb, data, notify);
>  }
>  
> -static void isi_request(struct ofono_ussd *ussd, const char *str,
> -				ofono_ussd_cb_t cb, void *data)
> +static void isi_request(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *pdu, int len,
> +			ofono_ussd_cb_t cb, void *data)
>  {
>  	struct ussd_data *ud = ofono_ussd_get_data(ussd);
>  	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
> -	unsigned char buf[256];
> -	unsigned char *packed = NULL;
> -	unsigned char *converted = NULL;
> -	long num_packed;
> -	long written;
>  
>  	if (!cbd)
>  		goto error;
>  
> -	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
> -	if (!converted)
> -		goto error;
> -
> -	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
> -					&num_packed, 0, buf);
> -
> -	g_free(converted);
> -
> -	if (written > SS_MAX_USSD_LENGTH)
> -		goto error;
> -
> -	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
> +	if (ussd_send(ud->client, dcs, (guint8 *) pdu, len, cbd, g_free))
>  		return;
>  
>  error:
> diff --git a/include/ussd.h b/include/ussd.h
> index 96e04cb..360ef00 100644
> --- a/include/ussd.h
> +++ b/include/ussd.h
> @@ -45,13 +45,15 @@ struct ofono_ussd_driver {
>  	const char *name;
>  	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
>  	void (*remove)(struct ofono_ussd *ussd);
> -	void (*request)(struct ofono_ussd *ussd, const char *str,
> -				ofono_ussd_cb_t, void *data);
> +	void (*request)(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *pdu, int len,
> +			ofono_ussd_cb_t, void *data);
>  	void (*cancel)(struct ofono_ussd *ussd,
>  				ofono_ussd_cb_t cb, void *data);
>  };
>  
> -void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
> +void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
> +			const unsigned char *data, int data_len);
>  
>  int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
>  void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
> diff --git a/src/ussd.c b/src/ussd.c
> index fbb07d2..8d9c98d 100644
> --- a/src/ussd.c
> +++ b/src/ussd.c
> @@ -34,8 +34,11 @@
>  #include "ofono.h"
>  
>  #include "common.h"
> +#include "smsutil.h"
> +#include "util.h"
>  
>  #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
> +#define MAX_USSD_LENGTH 160
>  
>  static GSList *g_drivers = NULL;
>  
> @@ -317,10 +320,13 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
>  			"State", DBUS_TYPE_STRING, &value);
>  }
>  
> -void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
> +void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
> +			const unsigned char *data, int data_len)
>  {
>  	DBusConnection *conn = ofono_dbus_get_connection();
>  	const char *ussdstr = "USSD";
> +	char *utf8_str = NULL;
> +	gboolean utf8_str_valid = FALSE;

Please do something like:
char *utf8;
const char *str;

and drop the utf8_str_valid variable

>  	const char sig[] = { DBUS_TYPE_STRING, 0 };
>  	DBusMessage *reply;
>  	DBusMessageIter iter;
> @@ -346,14 +352,20 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  		goto out;
>  	}
>  
> +	if (data && data_len > 0)
> +		utf8_str = ussd_decode(dcs, data_len, data);
> +

str = utf8;

> +	if (!utf8_str) {
> +		utf8_str = "";
> +		status = OFONO_USSD_STATUS_NOTIFY;

Sorry, I'm not following.  Can you explain what is this trying to do?

> +	} else
> +		utf8_str_valid = TRUE;
> +
>  	/* TODO: Rework this in the Agent framework */
>  	if (ussd->state == USSD_STATE_ACTIVE) {
>  
>  		reply = dbus_message_new_method_return(ussd->pending);
>  
> -		if (!str)
> -			str = "";
> -

Leave this in

>  		dbus_message_iter_init_append(reply, &iter);
>  
>  		dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
> @@ -363,7 +375,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  							&variant);
>  
>  		dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
> -						&str);
> +						&utf8_str);
>  
>  		dbus_message_iter_close_container(&iter, &variant);
>  
> @@ -375,10 +387,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  	} else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
>  		reply = dbus_message_new_method_return(ussd->pending);
>  
> -		if (!str)
> -			str = "";
> -
> -		dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
> +		dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
>  						DBUS_TYPE_INVALID);

And this

>  
>  		if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
> @@ -398,20 +407,17 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
>  			signal_name = "NotificationReceived";
>  		}
>  
> -		if (!str)
> -			str = "";
> -
>  		g_dbus_emit_signal(conn, path,
>  				SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
> -				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
> +				DBUS_TYPE_STRING, &utf8_str, DBUS_TYPE_INVALID);

And this

>  
>  		ussd_change_state(ussd, new_state);
> -		return;
> +		goto free;
>  	} else {
>  		ofono_error("Received an unsolicited USSD but can't handle.");
> -		DBG("USSD is: status: %d, %s", status, str);
> +		DBG("USSD is: status: %d, %s", status, utf8_str);
>  
> -		return;
> +		goto free;
>  	}
>  
>  out:
> @@ -419,6 +425,10 @@ out:
>  
>  	dbus_message_unref(ussd->pending);
>  	ussd->pending = NULL;
> +
> +free:
> +	if (utf8_str_valid)
> +		g_free(utf8_str);
>  }
>  
>  static void ussd_callback(const struct ofono_error *error, void *data)
> @@ -447,6 +457,9 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
>  {
>  	struct ofono_ussd *ussd = data;
>  	const char *str;
> +	int dcs = 0x0f;
> +	unsigned char buf[160];
> +	long num_packed;
>  
>  	if (ussd->pending)
>  		return __ofono_error_busy(msg);
> @@ -469,14 +482,17 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
>  	if (!valid_ussd_string(str))
>  		return __ofono_error_invalid_format(msg);
>  
> -	DBG("OK, running USSD request");
> +	if (!ussd_encode(str, &num_packed, buf))
> +		return __ofono_error_invalid_format(msg);
>  
>  	if (!ussd->driver->request)
>  		return __ofono_error_not_implemented(msg);
>  
> +	DBG("OK, running USSD request");
> +
>  	ussd->pending = dbus_message_ref(msg);
>  
> -	ussd->driver->request(ussd, str, ussd_callback, ussd);
> +	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_callback, ussd);
>  
>  	return NULL;
>  }
> @@ -507,6 +523,9 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
>  {
>  	struct ofono_ussd *ussd = data;
>  	const char *str;
> +	int dcs = 0x0f;
> +	unsigned char buf[160];
> +	long num_packed;
>  
>  	if (ussd->pending)
>  		return __ofono_error_busy(msg);
> @@ -521,12 +540,16 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
>  	if (strlen(str) == 0)
>  		return __ofono_error_invalid_format(msg);
>  
> +	if (!ussd_encode(str, &num_packed, buf))
> +		return __ofono_error_invalid_format(msg);
> +
>  	if (!ussd->driver->request)
>  		return __ofono_error_not_implemented(msg);
>  
>  	ussd->pending = dbus_message_ref(msg);
>  
> -	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
> +	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_response_callback,
> +				ussd);
>  
>  	return NULL;
>  }

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD
  2010-09-13 23:00             ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
  2010-09-13 23:00               ` [PATCH 7/8] stk: Handling of Send USSD proactive command Jeevaka Badrappan
@ 2010-09-14 17:45               ` Denis Kenzior
  2010-09-14 21:31                 ` [PATCH 2/4] " Jeevaka Badrappan
  1 sibling, 1 reply; 59+ messages in thread
From: Denis Kenzior @ 2010-09-14 17:45 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/13/2010 06:00 PM, Jeevaka Badrappan wrote:
> ---
>  src/ofono.h |    7 +++++
>  src/ussd.c  |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  2 files changed, 92 insertions(+), 1 deletions(-)
> 
> diff --git a/src/ofono.h b/src/ofono.h
> index f1c0973..8ab6a2e 100644
> --- a/src/ofono.h
> +++ b/src/ofono.h
> @@ -258,6 +258,9 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
>  					const char *old, const char *new,
>  					DBusMessage *msg, void *data);
>  
> +typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
> +					const unsigned char *pdu, int len, void *data);
> +
>  gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
>  					ofono_ussd_ssc_cb_t cb, void *data,
>  					ofono_destroy_func destroy);
> @@ -269,6 +272,10 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
>  void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
>  gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
>  
> +int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
> +			const unsigned char *pdu, int len,
> +			ofono_ussd_request_cb_t cb, void *user_data);
> +

Do we need a cancel here as well?  In case the SIM cancels the session.

>  #include <ofono/netreg.h>
>  
>  typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
> diff --git a/src/ussd.c b/src/ussd.c
> index 8d9c98d..af0aae1 100644
> --- a/src/ussd.c
> +++ b/src/ussd.c
> @@ -49,6 +49,15 @@ enum ussd_state {
>  	USSD_STATE_RESPONSE_SENT,
>  };
>  
> +struct ussd_request {
> +	struct ofono_ussd *ussd;
> +	int dcs;
> +	unsigned char *pdu;
> +	int len;
> +	ofono_ussd_request_cb_t cb;
> +	void *user_data;
> +};
> +
>  struct ofono_ussd {
>  	int state;
>  	DBusMessage *pending;
> @@ -59,6 +68,7 @@ struct ofono_ussd {
>  	const struct ofono_ussd_driver *driver;
>  	void *driver_data;
>  	struct ofono_atom *atom;
> +	struct ussd_request *req;
>  };
>  
>  struct ssc_entry {
> @@ -73,7 +83,7 @@ gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
>  	if (!ussd)
>  		return FALSE;
>  
> -	if (ussd->pending || ussd->state != USSD_STATE_IDLE)
> +	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
>  		return TRUE;

You might also want to make sure that initiate / respond / cancel cannot
interfere with the SIM request.

>  
>  	return FALSE;
> @@ -320,6 +330,31 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
>  			"State", DBUS_TYPE_STRING, &value);
>  }
>  
> +static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
> +				const unsigned char *pdu, int len)
> +{
> +	struct ussd_request *req = ussd->req;
> +
> +	if (req && req->cb) {
> +		req->cb(error, dcs, pdu, len, req->user_data);

> +		g_free(req->pdu);
> +		g_free(req);
> +		ussd->req = NULL;

What if req->cb is NULL?

> +	}
> +}
> +
> +static int ussd_status_to_failure_code(int status)
> +{
> +	switch (status) {
> +	case OFONO_USSD_STATUS_TIMED_OUT:
> +		return -ETIMEDOUT;
> +	case OFONO_USSD_STATUS_NOT_SUPPORTED:
> +		return -ENOSYS;
> +	}
> +
> +	return 0;
> +}
> +
>  void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
>  			const unsigned char *data, int data_len)
>  {
> @@ -332,6 +367,19 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
>  	DBusMessageIter iter;
>  	DBusMessageIter variant;
>  
> +	if (ussd->req &&
> +		(status == OFONO_USSD_STATUS_NOTIFY ||
> +		status == OFONO_USSD_STATUS_TERMINATED ||
> +		status == OFONO_USSD_STATUS_TIMED_OUT ||
> +		status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
> +

Please check coding style section M4

So what happens if the network sends a ACTION_REQUIRED as a response to
the STK ussd?

> +		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
> +					dcs, data, data_len);
> +
> +		ussd_change_state(ussd, USSD_STATE_IDLE);
> +		return;
> +	}
> +
>  	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
>  		ussd_change_state(ussd, USSD_STATE_IDLE);
>  
> @@ -577,6 +625,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
>  	reply = dbus_message_new_method_return(ussd->cancel);
>  	__ofono_dbus_pending_reply(&ussd->cancel, reply);
>  
> +	if (ussd->req)
> +		ussd_request_finish(ussd, -1, -ECANCELED, NULL, -1);
> +
>  	ussd_change_state(ussd, USSD_STATE_IDLE);
>  }
>  
> @@ -775,3 +826,36 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
>  {
>  	return ussd->driver_data;
>  }
> +
> +static void ussd_request_callback(const struct ofono_error *error, void *data)
> +{
> +	struct ofono_ussd *ussd = data;
> +
> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
> +		ussd_request_finish(ussd, error->error, -1, NULL, -1);
> +	else
> +		ussd_change_state(ussd,USSD_STATE_ACTIVE);

Missing space after the comma

> +}
> +
> +int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
> +				const unsigned char *pdu, int len,
> +				ofono_ussd_request_cb_t cb, void *user_data)
> +{
> +	struct ussd_request *req;
> +

You might want to check the busy condition here as well, just to be
pedantic.  This is what voicecall_dial does...

> +	if (!ussd->driver->request)
> +		return -ENOSYS;
> +
> +	req = g_try_new0(struct ussd_request, 1);
> +	req->dcs = dcs;
> +	req->pdu = g_memdup(pdu, len);
> +	req->len = len;
> +	req->cb = cb;
> +	req->user_data = user_data;
> +
> +	ussd->req = req;
> +
> +	ussd->driver->request(ussd, dcs, pdu, len, ussd_request_callback, ussd);
> +
> +	return 0;
> +}

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 1/4] Internal and Driver API changes for Send USSD
  2010-09-14 17:24             ` [PATCH 5/8] Internal and Driver API changes for Send USSD Denis Kenzior
@ 2010-09-14 21:23               ` Jeevaka Badrappan
  2010-09-15 17:13                 ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-14 21:23 UTC (permalink / raw)
  To: ofono

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

---
 drivers/atmodem/ussd.c  |  115 ++++++++++++++++++++++++++++-------------------
 drivers/isimodem/ussd.c |   42 +++--------------
 include/ussd.h          |    8 ++-
 src/ussd.c              |   39 +++++++++++++---
 4 files changed, 115 insertions(+), 89 deletions(-)

diff --git a/drivers/atmodem/ussd.c b/drivers/atmodem/ussd.c
index 30145ad..685bc9b 100644
--- a/drivers/atmodem/ussd.c
+++ b/drivers/atmodem/ussd.c
@@ -65,15 +65,17 @@ static void read_charset_cb(gboolean ok, GAtResult *result,
 
 static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 {
+	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	GAtResultIter iter;
 	int status;
 	int dcs;
-	const char *content;
-	char *converted = NULL;
-	gboolean udhi;
+	const char *content = NULL;
 	enum sms_charset charset;
-	gboolean compressed;
-	gboolean iso639;
+	unsigned char msg[160];
+	const unsigned char *msg_ptr = NULL;
+	unsigned char *converted = NULL;
+	long written;
+	long msg_len = 0;
 
 	g_at_result_iter_init(&iter, result);
 
@@ -86,34 +88,50 @@ static void cusd_parse(GAtResult *result, struct ofono_ussd *ussd)
 	if (!g_at_result_iter_next_string(&iter, &content))
 		goto out;
 
-	if (g_at_result_iter_next_number(&iter, &dcs)) {
-		if (!cbs_dcs_decode(dcs, &udhi, NULL, &charset,
-					&compressed, NULL, &iso639))
-			goto out;
+	if (!g_at_result_iter_next_number(&iter, &dcs))
+		dcs = 0;
 
-		if (udhi || compressed || iso639)
-			goto out;
-	} else
-		charset = SMS_CHARSET_7BIT;
-
-	if (charset == SMS_CHARSET_7BIT)
-		converted = convert_gsm_to_utf8((const guint8 *) content,
-						strlen(content), NULL, NULL, 0);
-
-	else if (charset == SMS_CHARSET_8BIT) {
-		/* TODO: Figure out what to do with 8 bit data */
-		ofono_error("8-bit coded USSD response received");
-		status = 4; /* Not supported */
-	} else {
-		/* No other encoding is mentioned in TS27007 7.15 */
+	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset, NULL, NULL, NULL)) {
 		ofono_error("Unsupported USSD data coding scheme (%02x)", dcs);
 		status = 4; /* Not supported */
+		goto out;
 	}
 
-out:
-	ofono_ussd_notify(ussd, status, converted);
+	switch (charset) {
+	case SMS_CHARSET_7BIT:
+		if (data->charset == AT_UTIL_CHARSET_GSM)
+			msg_ptr = pack_7bit_own_buf((const guint8 *) content,
+					strlen(content), 0, TRUE, &msg_len, 0, msg);
+		else if (data->charset == AT_UTIL_CHARSET_UTF8)
+			ussd_encode(content, &msg_len, msg);
+		else if (data->charset == AT_UTIL_CHARSET_UCS2) {
+			msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+
+			converted = convert_ucs2_to_gsm(msg_ptr, msg_len, NULL,
+							&written, 0);
+			if (!converted) {
+				msg_ptr = NULL;
+				msg_len = 0;
+				goto out;
+			}
+
+			msg_ptr = pack_7bit_own_buf(converted,
+						written, 0, TRUE,
+						&msg_len, 0, msg);
+
+			g_free(converted);
+		}
+		break;
+	case SMS_CHARSET_8BIT:
+		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+		break;
+	case SMS_CHARSET_UCS2:
+		msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);
+		break;
+	}
 
-	g_free(converted);
+out:
+	ofono_ussd_notify(ussd, status, dcs, msg_ptr, msg_len);
 }
 
 static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
@@ -130,39 +148,45 @@ static void cusd_request_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	cusd_parse(result, ussd);
 }
 
-static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
+static void at_ussd_request(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
 				ofono_ussd_cb_t cb, void *user_data)
 {
 	struct ussd_data *data = ofono_ussd_get_data(ussd);
 	struct cb_data *cbd = cb_data_new(cb, user_data);
-	unsigned char *converted = NULL;
-	int dcs;
-	int max_len;
-	long written;
 	char buf[256];
+	unsigned char unpacked_buf[182];
+	char coded_buf[160];
+	char *converted;
+	long written;
+	enum sms_charset charset;
 
 	if (!cbd)
 		goto error;
 
 	cbd->user = ussd;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-
-	if (!converted)
+	if (!cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL))
 		goto error;
-	else {
-		dcs = 15;
-		max_len = 182;
-	}
 
-	if (written > max_len)
-		goto error;
+	if (charset == SMS_CHARSET_7BIT) {
+		unpack_7bit_own_buf(pdu, len, 0, TRUE, sizeof(unpacked_buf),
+					&written, 0, unpacked_buf);
 
-	snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
-			(int) written, converted, dcs);
+		if (written < 1)
+			goto error;
 
-	g_free(converted);
-	converted = NULL;
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				(int) written, unpacked_buf, dcs);
+	} else {
+		converted = encode_hex_own_buf(pdu, len, 0, coded_buf);
+		if (!converted)
+			goto error;
+
+		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
+				strlen(converted), converted, dcs);
+	}
 
 	if (data->vendor == OFONO_VENDOR_QUALCOMM_MSM) {
 		/* Ensure that the modem is using GSM character set. It
@@ -179,7 +203,6 @@ static void at_ussd_request(struct ofono_ussd *ussd, const char *str,
 
 error:
 	g_free(cbd);
-	g_free(converted);
 
 	CALLBACK_WITH_FAILURE(cb, user_data);
 }
diff --git a/drivers/isimodem/ussd.c b/drivers/isimodem/ussd.c
index 330a141..19ba30e 100644
--- a/drivers/isimodem/ussd.c
+++ b/drivers/isimodem/ussd.c
@@ -74,24 +74,14 @@ static void ussd_parse(struct ofono_ussd *ussd, const void *restrict data,
 {
 	const unsigned char *msg = data;
 	int status = OFONO_USSD_STATUS_NOT_SUPPORTED;
-	char *converted = NULL;
 
 	if (!msg || len < 4)
-		goto out;
+		ofono_ussd_notify(ussd, status, 0, NULL, 0);
 
 	status = isi_type_to_status(msg[2]);
 
 	if (msg[3] == 0 || (size_t)(msg[3] + 4) > len)
-		goto out;
-
-	converted = ussd_decode(msg[1], msg[3], msg + 4);
-
-	if (converted)
-		status = OFONO_USSD_STATUS_NOTIFY;
-
-out:
-	ofono_ussd_notify(ussd, status, converted);
-	g_free(converted);
+		ofono_ussd_notify(ussd, status, msg[1], msg + 4, msg[3]);
 }
 
 
@@ -129,7 +119,7 @@ error:
 }
 
 static GIsiRequest *ussd_send(GIsiClient *client,
-				uint8_t *str, size_t len,
+				int dcs, uint8_t *str, size_t len,
 				void *data, GDestroyNotify notify)
 {
 	const uint8_t msg[] = {
@@ -138,7 +128,7 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 		0x01,		/* subblock count */
 		SS_GSM_USSD_STRING,
 		4 + len + 3,	/* subblock length */
-		0x0f,		/* DCS */
+		dcs,		/* DCS */
 		len,		/* string length */
 		/* USSD string goes here */
 	};
@@ -152,33 +142,17 @@ static GIsiRequest *ussd_send(GIsiClient *client,
 				ussd_send_resp_cb, data, notify);
 }
 
-static void isi_request(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t cb, void *data)
+static void isi_request(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_cb_t cb, void *data)
 {
 	struct ussd_data *ud = ofono_ussd_get_data(ussd);
 	struct isi_cb_data *cbd = isi_cb_data_new(ussd, cb, data);
-	unsigned char buf[256];
-	unsigned char *packed = NULL;
-	unsigned char *converted = NULL;
-	long num_packed;
-	long written;
 
 	if (!cbd)
 		goto error;
 
-	converted = convert_utf8_to_gsm(str, strlen(str), NULL, &written, 0);
-	if (!converted)
-		goto error;
-
-	packed = pack_7bit_own_buf(converted, written, 0, TRUE,
-					&num_packed, 0, buf);
-
-	g_free(converted);
-
-	if (written > SS_MAX_USSD_LENGTH)
-		goto error;
-
-	if (ussd_send(ud->client, packed, num_packed, cbd, g_free))
+	if (ussd_send(ud->client, dcs, (guint8 *) pdu, len, cbd, g_free))
 		return;
 
 error:
diff --git a/include/ussd.h b/include/ussd.h
index 96e04cb..360ef00 100644
--- a/include/ussd.h
+++ b/include/ussd.h
@@ -45,13 +45,15 @@ struct ofono_ussd_driver {
 	const char *name;
 	int (*probe)(struct ofono_ussd *ussd, unsigned int vendor, void *data);
 	void (*remove)(struct ofono_ussd *ussd);
-	void (*request)(struct ofono_ussd *ussd, const char *str,
-				ofono_ussd_cb_t, void *data);
+	void (*request)(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_cb_t, void *data);
 	void (*cancel)(struct ofono_ussd *ussd,
 				ofono_ussd_cb_t cb, void *data);
 };
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str);
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len);
 
 int ofono_ussd_driver_register(const struct ofono_ussd_driver *d);
 void ofono_ussd_driver_unregister(const struct ofono_ussd_driver *d);
diff --git a/src/ussd.c b/src/ussd.c
index fbb07d2..f89345a 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -34,8 +34,11 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "smsutil.h"
+#include "util.h"
 
 #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
+#define MAX_USSD_LENGTH 160
 
 static GSList *g_drivers = NULL;
 
@@ -317,10 +320,13 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+			const unsigned char *data, int data_len)
 {
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *ussdstr = "USSD";
+	char *utf8_str = NULL;
+	const char *str;
 	const char sig[] = { DBUS_TYPE_STRING, 0 };
 	DBusMessage *reply;
 	DBusMessageIter iter;
@@ -346,6 +352,11 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 		goto out;
 	}
 
+	if (data && data_len > 0)
+		utf8_str = ussd_decode(dcs, data_len, data);
+
+	str = utf8_str;
+
 	/* TODO: Rework this in the Agent framework */
 	if (ussd->state == USSD_STATE_ACTIVE) {
 
@@ -406,12 +417,12 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
 				DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
 
 		ussd_change_state(ussd, new_state);
-		return;
+		goto free;
 	} else {
 		ofono_error("Received an unsolicited USSD but can't handle.");
 		DBG("USSD is: status: %d, %s", status, str);
 
-		return;
+		goto free;
 	}
 
 out:
@@ -419,6 +430,9 @@ out:
 
 	dbus_message_unref(ussd->pending);
 	ussd->pending = NULL;
+
+free:
+	g_free(utf8_str);
 }
 
 static void ussd_callback(const struct ofono_error *error, void *data)
@@ -447,6 +461,9 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[160];
+	long num_packed;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -469,14 +486,17 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 	if (!valid_ussd_string(str))
 		return __ofono_error_invalid_format(msg);
 
-	DBG("OK, running USSD request");
+	if (!ussd_encode(str, &num_packed, buf))
+		return __ofono_error_invalid_format(msg);
 
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
+	DBG("OK, running USSD request");
+
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_callback, ussd);
+	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_callback, ussd);
 
 	return NULL;
 }
@@ -507,6 +527,9 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_ussd *ussd = data;
 	const char *str;
+	int dcs = 0x0f;
+	unsigned char buf[160];
+	long num_packed;
 
 	if (ussd->pending)
 		return __ofono_error_busy(msg);
@@ -521,12 +544,16 @@ static DBusMessage *ussd_respond(DBusConnection *conn, DBusMessage *msg,
 	if (strlen(str) == 0)
 		return __ofono_error_invalid_format(msg);
 
+	if (!ussd_encode(str, &num_packed, buf))
+		return __ofono_error_invalid_format(msg);
+
 	if (!ussd->driver->request)
 		return __ofono_error_not_implemented(msg);
 
 	ussd->pending = dbus_message_ref(msg);
 
-	ussd->driver->request(ussd, str, ussd_response_callback, ussd);
+	ussd->driver->request(ussd, dcs, buf, num_packed, ussd_response_callback,
+				ussd);
 
 	return NULL;
 }
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 2/4] Add __ofono_ussd_initiate internal api for Sending USSD
  2010-09-14 17:45               ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Denis Kenzior
@ 2010-09-14 21:31                 ` Jeevaka Badrappan
  2010-09-15 17:13                   ` Denis Kenzior
  0 siblings, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-14 21:31 UTC (permalink / raw)
  To: ofono

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

---
 src/ofono.h |    8 +++++
 src/ussd.c  |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 104 insertions(+), 5 deletions(-)

diff --git a/src/ofono.h b/src/ofono.h
index f1c0973..f64f149 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -258,6 +258,9 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
 					const char *old, const char *new,
 					DBusMessage *msg, void *data);
 
+typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
+					const unsigned char *pdu, int len, void *data);
+
 gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
 					ofono_ussd_ssc_cb_t cb, void *data,
 					ofono_destroy_func destroy);
@@ -269,6 +272,11 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
 void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
 gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
 
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+			const unsigned char *pdu, int len,
+			ofono_ussd_request_cb_t cb, void *user_data);
+void __ofono_ussd_initiate_cancel(struct ofono_ussd *ussd);
+
 #include <ofono/netreg.h>
 
 typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
diff --git a/src/ussd.c b/src/ussd.c
index f89345a..cb1d2e1 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -49,6 +49,15 @@ enum ussd_state {
 	USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+	struct ofono_ussd *ussd;
+	int dcs;
+	unsigned char *pdu;
+	int len;
+	ofono_ussd_request_cb_t cb;
+	void *user_data;
+};
+
 struct ofono_ussd {
 	int state;
 	DBusMessage *pending;
@@ -59,6 +68,7 @@ struct ofono_ussd {
 	const struct ofono_ussd_driver *driver;
 	void *driver_data;
 	struct ofono_atom *atom;
+	struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -73,7 +83,7 @@ gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
 	if (!ussd)
 		return FALSE;
 
-	if (ussd->pending || ussd->state != USSD_STATE_IDLE)
+	if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
 		return TRUE;
 
 	return FALSE;
@@ -320,6 +330,31 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
 			"State", DBUS_TYPE_STRING, &value);
 }
 
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+				const unsigned char *pdu, int len)
+{
+	struct ussd_request *req = ussd->req;
+
+	if (req && req->cb)
+		req->cb(error, dcs, pdu, len, req->user_data);
+
+	g_free(req->pdu);
+	g_free(req);
+	ussd->req = NULL;
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+	switch (status) {
+	case OFONO_USSD_STATUS_TIMED_OUT:
+		return -ETIMEDOUT;
+	case OFONO_USSD_STATUS_NOT_SUPPORTED:
+		return -ENOSYS;
+	}
+
+	return 0;
+}
+
 void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 			const unsigned char *data, int data_len)
 {
@@ -332,6 +367,18 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
 	DBusMessageIter iter;
 	DBusMessageIter variant;
 
+	if (ussd->req &&
+			(status == OFONO_USSD_STATUS_NOTIFY ||
+			status == OFONO_USSD_STATUS_TERMINATED ||
+			status == OFONO_USSD_STATUS_TIMED_OUT ||
+			status == OFONO_USSD_STATUS_NOT_SUPPORTED)) {
+		ussd_request_finish(ussd, ussd_status_to_failure_code(status),
+					dcs, data, data_len);
+
+		ussd_change_state(ussd, USSD_STATE_IDLE);
+		return;
+	}
+
 	if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
 		ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -465,10 +512,7 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
 	unsigned char buf[160];
 	long num_packed;
 
-	if (ussd->pending)
-		return __ofono_error_busy(msg);
-
-	if (ussd->state != USSD_STATE_IDLE)
+	if (__ofono_ussd_is_busy(ussd))
 		return __ofono_error_busy(msg);
 
 	if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
@@ -581,6 +625,9 @@ static void ussd_cancel_callback(const struct ofono_error *error, void *data)
 	reply = dbus_message_new_method_return(ussd->cancel);
 	__ofono_dbus_pending_reply(&ussd->cancel, reply);
 
+	if (ussd->req)
+		ussd_request_finish(ussd, -1, -ECANCELED, NULL, -1);
+
 	ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
@@ -779,3 +826,47 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 {
 	return ussd->driver_data;
 }
+
+static void ussd_request_callback(const struct ofono_error *error, void *data)
+{
+	struct ofono_ussd *ussd = data;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+		ussd_request_finish(ussd, error->error, -1, NULL, -1);
+	else
+		ussd_change_state(ussd, USSD_STATE_ACTIVE);
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+				const unsigned char *pdu, int len,
+				ofono_ussd_request_cb_t cb, void *user_data)
+{
+	struct ussd_request *req;
+
+	if (!ussd->driver->request)
+		return -ENOSYS;
+
+	if (__ofono_ussd_is_busy(ussd))
+		return -EBUSY;
+
+	req = g_try_new0(struct ussd_request, 1);
+	req->dcs = dcs;
+	req->pdu = g_memdup(pdu, len);
+	req->len = len;
+	req->cb = cb;
+	req->user_data = user_data;
+
+	ussd->req = req;
+
+	ussd->driver->request(ussd, dcs, pdu, len, ussd_request_callback, ussd);
+
+	return 0;
+}
+
+void __ofono_ussd_initiate_cancel(struct ofono_ussd *ussd)
+{
+	if (!ussd->req || !ussd->req->cb)
+		return;
+
+	ussd->req->cb = NULL;
+}
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 3/4] stk: Handling of Send USSD proactive command
  2010-09-13 23:00               ` [PATCH 7/8] stk: Handling of Send USSD proactive command Jeevaka Badrappan
  2010-09-13 23:00                 ` [PATCH 8/8] stkutil: Add handling of error case scenario in build USSD data object Jeevaka Badrappan
@ 2010-09-14 21:49                 ` Jeevaka Badrappan
  2010-09-15 17:15                   ` Denis Kenzior
  1 sibling, 1 reply; 59+ messages in thread
From: Jeevaka Badrappan @ 2010-09-14 21:49 UTC (permalink / raw)
  To: ofono

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

---
 src/stk.c |  173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 172 insertions(+), 1 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 04bfc65..f94643f 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -1590,6 +1590,174 @@ static gboolean handle_command_set_up_call(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static void send_ussd_cancel(struct ofono_stk *stk)
+{
+	struct ofono_ussd *ussd;
+	struct ofono_atom *atom;
+
+	atom = __ofono_modem_find_atom(__ofono_atom_get_modem(stk->atom),
+						OFONO_ATOM_TYPE_USSD);
+	if (!atom)
+		return;
+
+	ussd = __ofono_atom_get_data(atom);
+	if (ussd)
+		__ofono_ussd_initiate_cancel(ussd);
+
+	if (stk->pending_cmd->send_ussd.alpha_id &&
+			stk->pending_cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_unset(stk);
+}
+
+static void send_ussd_callback(int error, int dcs, const unsigned char *msg,
+				int msg_len, void *userdata)
+{
+	struct ofono_stk *stk = userdata;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	struct stk_response rsp;
+	enum sms_charset charset;
+
+	if (stk->pending_cmd->send_ussd.alpha_id &&
+			stk->pending_cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_unset(stk);
+
+	memset(&rsp, 0, sizeof(rsp));
+
+	switch (error) {
+	case 0:
+		if (cbs_dcs_decode(dcs, NULL, NULL, &charset,
+					NULL, NULL, NULL)) {
+			if (charset == SMS_CHARSET_7BIT)
+				rsp.send_ussd.text.dcs = 0x00;
+			else if (charset == SMS_CHARSET_8BIT)
+				rsp.send_ussd.text.dcs = 0x04;
+			else if (charset == SMS_CHARSET_UCS2)
+				rsp.send_ussd.text.dcs = 0x08;
+
+			rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+			rsp.send_ussd.text.text = msg;
+			rsp.send_ussd.text.len = msg_len;
+		} else {
+			rsp.result.type = STK_RESULT_TYPE_USSD_RETURN_ERROR;
+			rsp.result.additional = (unsigned char *) &error;
+			rsp.result.additional_len = 1;
+			rsp.send_ussd.text.dcs = -1;
+		}
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	case -ECANCELED:
+		send_simple_response(stk,
+				STK_RESULT_TYPE_USSD_OR_SS_USER_TERMINATION);
+		break;
+	case -ETIMEDOUT:
+		send_simple_response(stk, STK_RESULT_TYPE_NETWORK_UNAVAILABLE);
+		break;
+	default:
+		rsp.result.type = STK_RESULT_TYPE_USSD_RETURN_ERROR;
+		rsp.result.additional = (unsigned char *) &error;
+		rsp.result.additional_len = 1;
+		rsp.send_ussd.text.dcs = -1;
+
+		if (stk_respond(stk, &rsp, stk_command_cb))
+			stk_command_cb(&failure, stk);
+
+		break;
+	}
+}
+
+static gboolean handle_command_send_ussd(const struct stk_command *cmd,
+					struct stk_response *rsp,
+					struct ofono_stk *stk)
+{
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	static unsigned char busy_on_ss_result[] = { 0x03 };
+	static unsigned char busy_on_ussd_result[] = { 0x08 };
+	struct ofono_atom *atom;
+	struct ofono_ussd *ussd;
+	int err;
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_FORWARDING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_forwarding_is_busy(cf)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_BARRING);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_barring *cb = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_barring_is_busy(cb)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS);
+	if (atom && __ofono_atom_get_registered(atom)) {
+		struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
+
+		if (__ofono_call_settings_is_busy(cs)) {
+			rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+			rsp->result.additional_len = sizeof(busy_on_ss_result);
+			rsp->result.additional = busy_on_ss_result;
+			return TRUE;
+		}
+	}
+
+	atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
+	if (!atom || !__ofono_atom_get_registered(atom)) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	ussd = __ofono_atom_get_data(atom);
+	if (__ofono_ussd_is_busy(ussd)) {
+		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+		rsp->result.additional_len = sizeof(busy_on_ussd_result);
+		rsp->result.additional = busy_on_ussd_result;
+		return TRUE;
+	}
+
+	err = __ofono_ussd_initiate(ussd, cmd->send_ussd.ussd_string.dcs,
+					cmd->send_ussd.ussd_string.string,
+					cmd->send_ussd.ussd_string.len,
+					send_ussd_callback, stk);
+
+	if (err >= 0) {
+		stk->cancel_cmd = send_ussd_cancel;
+
+		return FALSE;
+	}
+
+	if (err == -ENOSYS) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	if (err == -EBUSY) {
+		rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+		rsp->result.additional_len = sizeof(busy_on_ussd_result);
+		rsp->result.additional = busy_on_ussd_result;
+		return TRUE;
+	}
+
+	if (cmd->send_ussd.alpha_id && cmd->send_ussd.alpha_id[0])
+		stk_alpha_id_set(stk, cmd->send_ussd.alpha_id);
+
+	return FALSE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -1740,7 +1908,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 		respond = handle_command_set_up_call(stk->pending_cmd,
 							&rsp, stk);
 		break;
-
+	case STK_COMMAND_TYPE_SEND_USSD:
+		respond = handle_command_send_ussd(stk->pending_cmd,
+							&rsp, stk);
+		break;
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 1/4] Internal and Driver API changes for Send USSD
  2010-09-14 21:23               ` [PATCH 1/4] " Jeevaka Badrappan
@ 2010-09-15 17:13                 ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-15 17:13 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/14/2010 04:23 PM, Jeevaka Badrappan wrote:
> ---
>  drivers/atmodem/ussd.c  |  115 ++++++++++++++++++++++++++++-------------------
>  drivers/isimodem/ussd.c |   42 +++--------------
>  include/ussd.h          |    8 ++-
>  src/ussd.c              |   39 +++++++++++++---
>  4 files changed, 115 insertions(+), 89 deletions(-)
> 

This patch has been applied, but refactored heavily afterward.

> +	struct ussd_data *data = ofono_ussd_get_data(ussd);
>  	GAtResultIter iter;
>  	int status;
>  	int dcs;
> -	const char *content;
> -	char *converted = NULL;
> -	gboolean udhi;
> +	const char *content = NULL;
>  	enum sms_charset charset;
> -	gboolean compressed;
> -	gboolean iso639;
> +	unsigned char msg[160];
> +	const unsigned char *msg_ptr = NULL;
> +	unsigned char *converted = NULL;
> +	long written;
> +	long msg_len = 0;

Please avoid initializing variables unless absolutely necessary.  This
actually hid some serious issues in the code which I had to fix.  In the
future I will not be so nice and simply reject such patches.

> +	switch (charset) {
> +	case SMS_CHARSET_7BIT:
> +		if (data->charset == AT_UTIL_CHARSET_GSM)
> +			msg_ptr = pack_7bit_own_buf((const guint8 *) content,
> +					strlen(content), 0, TRUE, &msg_len, 0, msg);
> +		else if (data->charset == AT_UTIL_CHARSET_UTF8)
> +			ussd_encode(content, &msg_len, msg);
> +		else if (data->charset == AT_UTIL_CHARSET_UCS2) {
> +			msg_ptr = decode_hex_own_buf(content, -1, &msg_len, 0, msg);

Please watch out for buffer overflows and make sure to run valgrind and
test all your code.  msg in this case was too small to contain the
decoded UCS2 information (up to 182 * 2 characters)

> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				(int) written, unpacked_buf, dcs);
> +	} else {
> +		converted = encode_hex_own_buf(pdu, len, 0, coded_buf);

Same thing here, you were overflowing the coded_buf

> +		if (!converted)
> +			goto error;
> +
> +		snprintf(buf, sizeof(buf), "AT+CUSD=1,\"%.*s\",%d",
> +				strlen(converted), converted, dcs);

and overflowing buf as well

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 2/4] Add __ofono_ussd_initiate internal api for Sending USSD
  2010-09-14 21:31                 ` [PATCH 2/4] " Jeevaka Badrappan
@ 2010-09-15 17:13                   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-15 17:13 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/14/2010 04:31 PM, Jeevaka Badrappan wrote:
> ---
>  src/ofono.h |    8 +++++
>  src/ussd.c  |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 104 insertions(+), 5 deletions(-)

This patch has been applied, but simplified a bit afterward.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 3/4] stk: Handling of Send USSD proactive command
  2010-09-14 21:49                 ` [PATCH 3/4] stk: Handling of Send USSD proactive command Jeevaka Badrappan
@ 2010-09-15 17:15                   ` Denis Kenzior
  0 siblings, 0 replies; 59+ messages in thread
From: Denis Kenzior @ 2010-09-15 17:15 UTC (permalink / raw)
  To: ofono

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

Hi Jeevaka,

On 09/14/2010 04:49 PM, Jeevaka Badrappan wrote:
> ---
>  src/stk.c |  173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 172 insertions(+), 1 deletions(-)
>

This patch has been applied, but refactored afterward.

> +			rsp.result.type = STK_RESULT_TYPE_USSD_RETURN_ERROR;
> +			rsp.result.additional = (unsigned char *) &error;
> +			rsp.result.additional_len = 1;

This part made no sense to me, why are we sending our internal error
enum to the SIM?

Regards,
-Denis

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2010-09-15 17:15 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-09 12:31 Add support for Send USSD proactive command handling Jeevaka Badrappan
2010-09-09 12:31 ` [PATCH 01/12] atutil changes for parsing cscs query and cscs support Jeevaka Badrappan
2010-09-09 14:45   ` Denis Kenzior
2010-09-09 18:56     ` Jeevaka Badrappan
2010-09-09 18:56       ` [PATCH 01/13] " Jeevaka Badrappan
2010-09-10 17:27         ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 02/12] atgen changes for setting TE character set Jeevaka Badrappan
2010-09-09 14:50   ` Denis Kenzior
2010-09-09 19:00     ` [PATCH 02/13] " Jeevaka Badrappan
2010-09-09 12:31 ` [PATCH 03/12] phonesim " Jeevaka Badrappan
2010-09-09 19:01   ` [PATCH 03/13] " Jeevaka Badrappan
2010-09-10 17:07     ` Denis Kenzior
2010-09-10 20:29       ` [PATCH 2/7] " Jeevaka Badrappan
2010-09-09 12:31 ` [PATCH 04/12] USSD atom driver changes to read current character setting Jeevaka Badrappan
2010-09-09 19:02   ` [PATCH 04/13] " Jeevaka Badrappan
2010-09-09 12:31 ` [PATCH 05/12] Add internal api __ofono_call_barring_is_busy Jeevaka Badrappan
2010-09-09 15:06   ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 06/12] Add internal api __ofono_call_forwarding_is_busy Jeevaka Badrappan
2010-09-09 15:07   ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 07/12] Add internal api __ofono_call_settings_is_busy Jeevaka Badrappan
2010-09-09 15:07   ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 08/12] Add Send USSD command specific result codes Jeevaka Badrappan
2010-09-09 15:09   ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 09/12] Add Send USSD terminal response data structures Jeevaka Badrappan
2010-09-09 15:20   ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 10/12] Add build_dataobj_ussd_text for ussd specific text string handling Jeevaka Badrappan
2010-09-09 15:31   ` Denis Kenzior
2010-09-09 19:06     ` [PATCH 10/13] " Jeevaka Badrappan
2010-09-10 17:29       ` Denis Kenzior
2010-09-10 20:19         ` [PATCH 4/7] " Jeevaka Badrappan
2010-09-10 20:22           ` Denis Kenzior
2010-09-09 12:31 ` [PATCH 11/12] Internal and Driver api changes for Send USSD proactive command Jeevaka Badrappan
2010-09-09 15:59   ` Denis Kenzior
2010-09-09 20:25     ` [PATCH 6/8] " Jeevaka Badrappan
2010-09-09 20:25       ` [PATCH 7/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
2010-09-09 12:31 ` [PATCH 12/12] Handling of Send USSD proactive command Jeevaka Badrappan
2010-09-09 15:37   ` Denis Kenzior
2010-09-09 19:42     ` [PATCH 8/8] " Jeevaka Badrappan
2010-09-13 23:00 ` Added UCS2 handling and review comments incorporated Jeevaka Badrappan
2010-09-13 23:00   ` [PATCH 1/8] smsutil: Add USSD encoding function Jeevaka Badrappan
2010-09-13 23:00     ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Jeevaka Badrappan
2010-09-13 23:00       ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Jeevaka Badrappan
2010-09-13 23:00         ` [PATCH 4/8] USSD atom driver changes to read current character setting Jeevaka Badrappan
2010-09-13 23:00           ` [PATCH 5/8] Internal and Driver API changes for Send USSD Jeevaka Badrappan
2010-09-13 23:00             ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Jeevaka Badrappan
2010-09-13 23:00               ` [PATCH 7/8] stk: Handling of Send USSD proactive command Jeevaka Badrappan
2010-09-13 23:00                 ` [PATCH 8/8] stkutil: Add handling of error case scenario in build USSD data object Jeevaka Badrappan
2010-09-14 21:49                 ` [PATCH 3/4] stk: Handling of Send USSD proactive command Jeevaka Badrappan
2010-09-15 17:15                   ` Denis Kenzior
2010-09-14 17:45               ` [PATCH 6/8] Add __ofono_ussd_initiate internal api for Sending USSD Denis Kenzior
2010-09-14 21:31                 ` [PATCH 2/4] " Jeevaka Badrappan
2010-09-15 17:13                   ` Denis Kenzior
2010-09-14 17:24             ` [PATCH 5/8] Internal and Driver API changes for Send USSD Denis Kenzior
2010-09-14 21:23               ` [PATCH 1/4] " Jeevaka Badrappan
2010-09-15 17:13                 ` Denis Kenzior
2010-09-14 17:01           ` [PATCH 4/8] USSD atom driver changes to read current character setting Denis Kenzior
2010-09-14 17:01         ` [PATCH 3/8] test-util: Add function for validating UCS2 to GSM bit conversion Denis Kenzior
2010-09-14 17:01       ` [PATCH 2/8] util: Add UCS2 to GSM 7bit converion function Denis Kenzior
2010-09-14 16:58     ` [PATCH 1/8] smsutil: Add USSD encoding function Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.