All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Add BIP command support
@ 2011-06-28 17:16 Philippe Nunes
  2011-06-28 17:16 ` [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts Philippe Nunes
                   ` (10 more replies)
  0 siblings, 11 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

This new set of patches is introducing the support of the BIP commands in oFono (stk class 'e'):
As agreed, this patch set is:	
	- not exposing STK contexts over D-Bus 	
	- only using the kernel buffer.
	- using blocking sockets after the connect phase.
	- oriented to support TCP/IP first (for UDP Rx, the packet boundaries are currently not preserved).

Philippe Nunes (11):
  gprs: Add private APIs to activate/deactivate private contexts
  stk: Add support for the proactive command 'Open channel'
  stk: Add support for the proactive command 'Get channel status'
  stk: Add support for the proactive command 'Close channel'
  stk: Add 'ofono_stk_activate_cb' definition
  stk: Add 'ofono_stk_deactivate_context_cb' definition
  stk: Add support for the proactive command 'Receive data'
  stk: Add support for the proactive command 'Send data'
  stk: Add support of the Setup event list proactive command
  stk: Add host route to route the traffic through the stk interface
  gprs: Add API to set a 'detach'notification callback

 src/gprs.c  |  248 +++++++++++++++++
 src/ofono.h |   23 ++
 src/stk.c   |  882 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1153 insertions(+), 0 deletions(-)


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

* [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-29 22:22   ` Denis Kenzior
  2011-06-28 17:16 ` [PATCH 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

---
 src/gprs.c  |  211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ofono.h |   17 +++++
 2 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index acbfa56..b3e6869 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -59,6 +59,7 @@
 
 static GSList *g_drivers = NULL;
 static GSList *g_context_drivers = NULL;
+static GSList *g_private_contexts = NULL;
 
 /* 27.007 Section 7.29 */
 enum packet_bearer {
@@ -149,6 +150,13 @@ struct pri_context {
 	struct ofono_gprs *gprs;
 };
 
+struct gprs_private_context {
+	unsigned int cid;
+	struct ofono_gprs_context *context_driver;
+	void *notify;
+	void *notify_data;
+};
+
 static void gprs_netreg_update(struct ofono_gprs *gprs);
 static void gprs_deactivate_next(struct ofono_gprs *gprs);
 
@@ -346,6 +354,20 @@ static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
 	return NULL;
 }
 
+static struct pri_context *gprs_get_default_context(struct ofono_gprs *gprs)
+{
+	GSList *l;
+
+	for (l = gprs->contexts; l; l = l->next) {
+		struct pri_context *ctx = l->data;
+
+		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
+			return ctx;
+	}
+
+	return NULL;
+}
+
 static void context_settings_free(struct context_settings *settings)
 {
 	if (settings->ipv4) {
@@ -872,6 +894,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
 				dbus_message_new_method_return(ctx->pending));
 
 	if (gc->settings->interface != NULL) {
+		DBG("Interface %s", gc->settings->interface);
+
 		pri_ifupdown(gc->settings->interface, TRUE);
 
 		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
@@ -3012,3 +3036,190 @@ void *ofono_gprs_get_data(struct ofono_gprs *gprs)
 {
 	return gprs->driver_data;
 }
+
+static struct gprs_private_context *gprs_private_context_by_id(unsigned int id)
+{
+	GSList *l;
+
+	for (l = g_private_contexts; l; l = l->next) {
+		struct gprs_private_context *ctx = l->data;
+
+		if (ctx->cid == id)
+			return ctx;
+	}
+
+	return NULL;
+}
+
+static void activate_request_callback(const struct ofono_error *error,
+					void *data)
+{
+	struct gprs_private_context *ctx = data;
+	struct context_settings *settings = ctx->context_driver->settings;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		DBG("Activating context failed with error: %s",
+				telephony_error_to_str(error));
+		context_settings_free(settings);
+		gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
+		ctx->context_driver->inuse = FALSE;
+
+		if (ctx->notify)
+			((__ofono_gprs_activate_context_cb_t) ctx->notify)
+				(-ENOSYS, NULL, NULL, ctx->notify_data);
+
+		g_private_contexts = g_slist_remove(g_private_contexts, ctx);
+		return;
+	}
+
+	if (settings->interface != NULL) {
+		pri_ifupdown(settings->interface, TRUE);
+
+		if (settings->ipv4)
+			pri_set_ipv4_addr(settings->interface,
+							settings->ipv4->ip);
+	}
+
+	if (ctx->notify && settings->ipv4)
+		((__ofono_gprs_activate_context_cb_t) ctx->notify)
+					(0, settings->interface,
+						settings->ipv4->ip,
+						ctx->notify_data);
+}
+
+int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
+				struct ofono_gprs_primary_context *context,
+				__ofono_gprs_activate_context_cb_t cb,
+				void *data)
+{
+	struct gprs_private_context *private_ctx;
+	struct pri_context *default_ctx = NULL;
+	struct ofono_gprs_context *gc = NULL;
+	struct idmap *cidmap = gprs->cid_map;
+	GSList *l;
+
+	if (context->apn[0] == '\0' || (context->username[0] == '\0' &&
+			context->password[0] == '\0')) {
+		/* take the default primary internet context */
+		default_ctx = gprs_get_default_context(gprs);
+
+		if (default_ctx == NULL && context->apn[0] == '\0')
+			return -ENOENT;
+	}
+
+	if (context->apn[0] != '\0' && is_valid_apn(context->apn) == FALSE)
+		return EINVAL;
+
+	if (context->proto != OFONO_GPRS_PROTO_IPV4V6 &&
+			context->proto != OFONO_GPRS_PROTO_IP)
+		return -ENOSYS;
+
+	if (cidmap == NULL)
+		return -ENOSYS;
+
+	if (context->apn[0] == '\0') {
+		strcpy(context->apn, default_ctx->context.apn);
+		strcpy(context->username, default_ctx->context.username);
+		strcpy(context->password, default_ctx->context.password);
+	}
+
+	private_ctx = g_try_new0(struct gprs_private_context, 1);
+	if (private_ctx == NULL)
+		return -ENOMEM;
+
+	private_ctx->cid = gprs_cid_alloc(gprs);
+	if (private_ctx->cid == 0) {
+		g_free(private_ctx);
+		return -EBUSY;
+	}
+
+	context->cid = private_ctx->cid;
+
+	for (l = gprs->context_drivers; l; l = l->next) {
+		gc = l->data;
+
+		if (gc->inuse == TRUE)
+			continue;
+
+		if (gc->driver == NULL)
+			continue;
+
+		if (gc->driver->activate_primary == NULL ||
+				gc->driver->deactivate_primary == NULL)
+			continue;
+
+		if (gc->type != OFONO_GPRS_CONTEXT_TYPE_ANY &&
+				gc->type != OFONO_GPRS_CONTEXT_TYPE_INTERNET)
+			continue;
+
+		break;
+	}
+
+	if (gc == NULL) {
+		g_free(private_ctx);
+		return -EBUSY;
+	}
+
+	gc->inuse = TRUE;
+	gc->settings->ipv4 = g_new0(struct ipv4_settings, 1);
+	private_ctx->context_driver = gc;
+	private_ctx->notify = cb;
+	private_ctx->notify_data = data;
+
+	g_private_contexts = g_slist_append(g_private_contexts, private_ctx);
+
+	gc->driver->activate_primary(gc, context, activate_request_callback,
+					private_ctx);
+	return 0;
+}
+
+static void deactivate_request_callback(const struct ofono_error *error,
+					void *data)
+{
+	struct gprs_private_context *ctx = data;
+	struct context_settings *settings = ctx->context_driver->settings;
+	int err = 0;
+
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+		DBG("Deactivating context failed with error: %s",
+				telephony_error_to_str(error));
+		err = -ENOSYS;
+	}
+
+	pri_set_ipv4_addr(settings->interface, NULL);
+	pri_ifupdown(settings->interface, FALSE);
+	context_settings_free(settings);
+
+	DBG("Release Context cid %d", ctx->cid);
+
+	gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
+	ctx->context_driver->inuse = FALSE;
+
+	if (ctx->notify)
+		((__ofono_gprs_deactivate_context_cb_t) ctx->notify)
+				(err, ctx->notify_data);
+
+	g_private_contexts = g_slist_remove(g_private_contexts, ctx);
+}
+
+int __ofono_gprs_deactivate_context(unsigned int id,
+					__ofono_gprs_deactivate_context_cb_t cb,
+					void *data)
+{
+	struct gprs_private_context *private_ctx;
+	struct ofono_gprs_context *gc;
+
+	DBG("Deactivate context with cid %d", id);
+
+	private_ctx = gprs_private_context_by_id(id);
+	if (private_ctx == NULL)
+		return -EINVAL;
+
+	private_ctx->notify = cb;
+	private_ctx->notify_data = data;
+
+	gc = private_ctx->context_driver;
+	gc->driver->deactivate_primary(gc, private_ctx->cid,
+				deactivate_request_callback, private_ctx);
+	return 0;
+}
diff --git a/src/ofono.h b/src/ofono.h
index 6524806..6b72816 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -240,6 +240,23 @@ gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs);
 #include <ofono/phonebook.h>
 #include <ofono/gprs.h>
 #include <ofono/gprs-context.h>
+
+typedef void (*__ofono_gprs_activate_context_cb_t)(int error,
+						const char *interface,
+						const char *ip,
+						void *data);
+
+typedef void (*__ofono_gprs_deactivate_context_cb_t)(int error, void *data);
+
+int __ofono_gprs_deactivate_context(unsigned int id,
+					__ofono_gprs_deactivate_context_cb_t cb,
+					void *data);
+
+int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
+				struct ofono_gprs_primary_context *context,
+				__ofono_gprs_activate_context_cb_t cb,
+				void *data);
+
 #include <ofono/radio-settings.h>
 #include <ofono/audio-settings.h>
 #include <ofono/ctm.h>
-- 
1.7.1


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

* [PATCH 02/11] stk: Add support for the proactive command 'Open channel'
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
  2011-06-28 17:16 ` [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-29 22:38   ` Denis Kenzior
  2011-06-28 17:16 ` [PATCH 03/11] stk: Add support for the proactive command 'Get channel status' Philippe Nunes
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

stk: add modifications
---
 src/stk.c |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 221 insertions(+), 0 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index 9575f0e..4bf6a08 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -41,6 +41,7 @@
 #include "smsutil.h"
 #include "stkutil.h"
 #include "stkagent.h"
+#include "gprs.h"
 #include "util.h"
 
 static GSList *g_drivers = NULL;
@@ -79,6 +80,13 @@ struct ofono_stk {
 
 	__ofono_sms_sim_download_cb_t sms_pp_cb;
 	void *sms_pp_userdata;
+	struct stk_channel channel;
+	struct ofono_gprs_primary_context context;
+	gsize tx_avail;
+	gboolean link_on_demand;
+	struct ofono_gprs *gprs;
+	struct stk_bearer_description bearer_desc;
+	enum stk_transport_protocol_type protocol;
 };
 
 struct envelope_op {
@@ -104,6 +112,12 @@ static void timers_update(struct ofono_stk *stk);
 		result.additional_len = sizeof(addn_info);	\
 		result.additional = addn_info;			\
 
+/*
+ * Channel identifier is attributed by default to 1 since only one channel
+ * is open per time
+ */
+#define DEFAULT_CHANNEL_ID 1
+
 static int stk_respond(struct ofono_stk *stk, struct stk_response *rsp,
 			ofono_stk_generic_cb_t cb)
 {
@@ -532,6 +546,113 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
 	stk_agent_request_cancel(stk->current_agent);
 }
 
+static void ofono_stk_activate_context_cb(int error, const char *interface,
+						const char *ip,
+						void *data)
+{
+}
+
+static void stk_open_channel(struct ofono_stk *stk)
+{
+	const struct stk_command_open_channel *oc;
+	struct stk_response rsp;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	int err;
+
+	if (stk->pending_cmd == NULL ||
+			stk->pending_cmd->type != STK_COMMAND_TYPE_OPEN_CHANNEL)
+		return;
+
+	oc = &stk->pending_cmd->open_channel;
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+	if (oc->data_dest_addr.type == STK_ADDRESS_IPV6) {
+		/*
+		 * For now, only the bearer type "GPRS / UTRAN packet service /
+		 * E-UTRAN" is supported.
+		 * For such bearer, according 3GPP TS 31.111, the packet data
+		 * protocol type is IP, so only IPv4 addresses are considered.
+		 */
+		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		goto out;
+	}
+
+	stk->channel.id = DEFAULT_CHANNEL_ID;
+	stk->tx_avail = oc->buf_size;
+
+	memset(&stk->context, 0, sizeof(stk->context));
+	stk->context.proto = OFONO_GPRS_PROTO_IP;
+
+	if (oc->apn) {
+		if (strlen(oc->apn) > OFONO_GPRS_MAX_APN_LENGTH) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+		strcpy(stk->context.apn, oc->apn);
+	}
+
+	if (oc->text_usr) {
+		if (strlen(oc->text_usr) > OFONO_GPRS_MAX_APN_LENGTH) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+		strcpy(stk->context.username, oc->text_usr);
+	}
+
+	if (oc->text_passwd) {
+		if (strlen(oc->text_passwd) > OFONO_GPRS_MAX_APN_LENGTH) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+		strcpy(stk->context.password, oc->text_passwd);
+	}
+
+	memcpy(&stk->bearer_desc, &oc->bearer_desc,
+					sizeof(struct stk_bearer_description));
+	stk->protocol = oc->uti.protocol;
+	stk->link_on_demand = (stk->pending_cmd->qualifier &
+				STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
+
+	if (stk->link_on_demand) {
+		rsp.open_channel.channel.id = stk->channel.id;
+		rsp.open_channel.channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+		rsp.open_channel.buf_size = oc->buf_size;
+		goto out;
+	}
+
+	err = __ofono_gprs_activate_context(stk->gprs, &stk->context,
+					ofono_stk_activate_context_cb, stk);
+
+	if (err == -EBUSY) {
+		rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+		goto out;
+	} else if (err < 0) {
+		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		goto out;
+	}
+
+	/* In background mode, send the terminal response now */
+	if (stk->pending_cmd->qualifier & STK_OPEN_CHANNEL_FLAG_BACKGROUND) {
+		rsp.open_channel.channel.id = stk->channel.id;
+		rsp.open_channel.channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+		rsp.open_channel.buf_size = oc->buf_size;
+		goto out;
+	}
+
+	/* wait for the PDP context activation to send the Terminal Response */
+	return;
+
+out:
+	if (stk_respond(stk, &rsp, stk_command_cb))
+		stk_command_cb(&failure, stk);
+
+}
+
+
 static int duration_to_msecs(const struct stk_duration *duration)
 {
 	int msecs = duration->interval;
@@ -2601,6 +2722,101 @@ static gboolean handle_command_launch_browser(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static void confirm_open_channel_cb(enum stk_agent_result result,
+					gboolean confirm,
+					void *user_data)
+{
+	struct ofono_stk *stk = user_data;
+
+	switch (result) {
+	case STK_AGENT_RESULT_TIMEOUT:
+		confirm = FALSE;
+		/* Fall through */
+
+	case STK_AGENT_RESULT_OK:
+		if (confirm)
+			break;
+
+		send_simple_response(stk, STK_RESULT_TYPE_USER_REJECT);
+		return;
+
+	case STK_AGENT_RESULT_TERMINATE:
+	default:
+		send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
+		return;
+	}
+
+	stk_open_channel(stk);
+}
+
+static gboolean handle_command_open_channel(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	const struct stk_command_open_channel *oc = &cmd->open_channel;
+	struct ofono_atom *gprs_atom;
+	int err;
+
+	/* Check first if channel is available */
+	if (stk->channel.id) {
+		unsigned char addnl_info[1];
+
+		addnl_info[0] = STK_RESULT_ADDNL_BIP_PB_NO_CHANNEL_AVAIL;
+		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
+				addnl_info);
+		return TRUE;
+	}
+
+	gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+	if (gprs_atom == NULL || !__ofono_atom_get_registered(gprs_atom)) {
+		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		return TRUE;
+	}
+
+	stk->gprs = __ofono_atom_get_data(gprs_atom);
+	stk->respond_on_exit = TRUE;
+	stk->cancel_cmd = stk_request_cancel;
+
+	/*
+	 * Don't ask for user confirmation if AID is a null data object
+	 * or is not provided
+	 */
+	if (oc->alpha_id && oc->alpha_id[0] != '\0') {
+		char *alpha_id;
+
+		alpha_id = dbus_apply_text_attributes(oc->alpha_id,
+								&oc->text_attr);
+		if (alpha_id == NULL) {
+			rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+			return TRUE;
+		}
+
+		err = stk_agent_confirm_open_channel(stk->current_agent,
+							alpha_id,
+							&oc->icon_id,
+							confirm_open_channel_cb,
+							stk, NULL,
+							stk->timeout * 1000);
+		g_free(alpha_id);
+
+		if (err < 0) {
+			unsigned char no_cause_result[] = { 0x00 };
+
+			ADD_ERROR_RESULT(rsp->result,
+						STK_RESULT_TYPE_TERMINAL_BUSY,
+						no_cause_result);
+			return TRUE;
+		}
+
+		return FALSE;
+	}
+
+	stk_open_channel(stk);
+
+	return FALSE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -2794,6 +3010,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_OPEN_CHANNEL:
+		respond = handle_command_open_channel(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.1


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

* [PATCH 03/11] stk: Add support for the proactive command 'Get channel status'
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
  2011-06-28 17:16 ` [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts Philippe Nunes
  2011-06-28 17:16 ` [PATCH 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 04/11] stk: Add support for the proactive command 'Close channel' Philippe Nunes
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 4bf6a08..835922f 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -2817,6 +2817,16 @@ static gboolean handle_command_open_channel(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static gboolean handle_command_get_channel_status(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	rsp->result.type = STK_RESULT_TYPE_SUCCESS;
+	rsp->channel_status.channel.id = stk->channel.id;
+	rsp->channel_status.channel.status = stk->channel.status;
+	return TRUE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -3015,6 +3025,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_GET_CHANNEL_STATUS:
+		respond = handle_command_get_channel_status(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.1


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

* [PATCH 04/11] stk: Add support for the proactive command 'Close channel'
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (2 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 03/11] stk: Add support for the proactive command 'Get channel status' Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 05/11] stk: Add 'ofono_stk_activate_cb' definition Philippe Nunes
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 835922f..8426af7 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -502,6 +502,28 @@ static void cancel_pending_dtmf(struct ofono_stk *stk)
 		__ofono_voicecall_tone_cancel(vc, stk->dtmf_id);
 }
 
+static void ofono_stk_deactivate_context_cb(int error, void *data)
+{
+}
+
+static void stk_close_channel(struct ofono_stk *stk)
+{
+	int err;
+
+	err = __ofono_gprs_deactivate_context(stk->context.cid,
+			ofono_stk_deactivate_context_cb, stk);
+
+	if (err < 0) {
+		stk->channel.id = 0;
+		stk->channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+
+		if (stk->pending_cmd && stk->pending_cmd->type ==
+				STK_COMMAND_TYPE_CLOSE_CHANNEL)
+			send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
+	}
+}
+
 static void user_termination_cb(enum stk_agent_result result, void *user_data)
 {
 	struct ofono_stk *stk = user_data;
@@ -516,6 +538,9 @@ static void user_termination_cb(enum stk_agent_result result, void *user_data)
 	}
 
 	send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
+
+	if (stk->channel.id)
+		stk_close_channel(stk);
 }
 
 static void stk_alpha_id_set(struct ofono_stk *stk,
@@ -650,6 +675,8 @@ out:
 	if (stk_respond(stk, &rsp, stk_command_cb))
 		stk_command_cb(&failure, stk);
 
+	if (rsp.result.type != STK_RESULT_TYPE_SUCCESS)
+		stk_close_channel(stk);
 }
 
 
@@ -2817,6 +2844,38 @@ static gboolean handle_command_open_channel(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static gboolean handle_command_close_channel(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	const struct stk_command_close_channel *cc = &cmd->close_channel;
+
+	/* Check if channel identifier is valid */
+	if (cmd->dst != (stk->channel.id | 0x20)) {
+		unsigned char addnl_info[1];
+
+		addnl_info[1] = STK_RESULT_ADDNL_BIP_PB_CHANNEL_ID_NOT_VALID;
+		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
+					addnl_info);
+		return TRUE;
+	}
+
+	/*
+	 * Don't inform the user about the link closing phase if AID is
+	 * a null data object or is not provided
+	 */
+	if (cc->alpha_id && cc->alpha_id[0] != '\0')
+		stk_alpha_id_set(stk, cc->alpha_id, &cc->text_attr,
+							&cc->icon_id);
+
+	stk->respond_on_exit = TRUE;
+	stk->cancel_cmd = stk_request_cancel;
+
+	stk_close_channel(stk);
+
+	return FALSE;
+}
+
 static gboolean handle_command_get_channel_status(const struct stk_command *cmd,
 						struct stk_response *rsp,
 						struct ofono_stk *stk)
@@ -3025,6 +3084,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_CLOSE_CHANNEL:
+		respond = handle_command_close_channel(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	case STK_COMMAND_TYPE_GET_CHANNEL_STATUS:
 		respond = handle_command_get_channel_status(stk->pending_cmd,
 							&rsp, stk);
-- 
1.7.1


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

* [PATCH 05/11] stk: Add 'ofono_stk_activate_cb' definition
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (3 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 04/11] stk: Add support for the proactive command 'Close channel' Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 06/11] stk: Add 'ofono_stk_deactivate_context_cb' definition Philippe Nunes
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 8426af7..1db45eb 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -28,6 +28,9 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <unistd.h>
 
 #include <glib.h>
 #include <gdbus.h>
@@ -87,6 +90,9 @@ struct ofono_stk {
 	struct ofono_gprs *gprs;
 	struct stk_bearer_description bearer_desc;
 	enum stk_transport_protocol_type protocol;
+	struct sockaddr_in dest_addr;
+	GIOChannel *io;
+	guint read_watch;
 };
 
 struct envelope_op {
@@ -571,10 +577,150 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
 	stk_agent_request_cancel(stk->current_agent);
 }
 
+static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
+				gpointer userdata)
+{
+	return TRUE;
+}
+
 static void ofono_stk_activate_context_cb(int error, const char *interface,
 						const char *ip,
 						void *data)
 {
+	struct ofono_stk *stk = data;
+	struct stk_response rsp;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	GIOChannel *io;
+	int sk;
+
+	DBG("");
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+	if (error < 0) {
+		ofono_error("Failed to connect gprs context");
+
+		if (stk->pending_cmd == NULL ||
+				(stk->pending_cmd->type !=
+				STK_COMMAND_TYPE_OPEN_CHANNEL &&
+				stk->pending_cmd->type !=
+				STK_COMMAND_TYPE_SEND_DATA)) {
+			/* TODO send channel status event */
+			return;
+		} else {
+			rsp.result.type = STK_RESULT_TYPE_NETWORK_UNAVAILABLE;
+			goto out;
+		}
+	} else {
+		DBG("Interface %s, IP = %s", interface, ip);
+		stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
+	}
+
+	if (stk->protocol == STK_TRANSPORT_PROTOCOL_TCP_CLIENT_REMOTE) {
+		sk = socket(AF_INET, SOCK_STREAM, 0);
+		if (sk < 0) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+
+		error = connect(sk, (struct sockaddr *) &stk->dest_addr,
+						sizeof(stk->dest_addr));
+
+		if (error < 0) {
+			close(sk);
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+	} else if (stk->protocol == STK_TRANSPORT_PROTOCOL_UDP_CLIENT_REMOTE) {
+		struct sockaddr_in addr;
+
+		sk = socket(AF_INET, SOCK_DGRAM, 0);
+		if (sk < 0) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+
+		memset(&addr, 0, sizeof(addr));
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = htonl(INADDR_ANY);
+		addr.sin_port = htons(0);
+
+		error = bind(sk, (struct sockaddr *) &addr, sizeof(addr));
+		if (error < 0) {
+			close(sk);
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+	} else {
+		/* raw IP */
+		sk = socket(AF_INET, SOCK_RAW, 0);
+		if (sk < 0) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+
+		/* Bind socket to specified interface */
+		if (interface) {
+			struct ifreq ifreq;
+
+			memset(&ifreq, 0, sizeof(ifreq));
+			strcpy(ifreq.ifr_name, interface);
+			error = setsockopt(sk, SOL_SOCKET,
+					SO_BINDTODEVICE, &ifreq, sizeof(ifreq));
+			if (error < 0) {
+				ofono_error("Failed to bind socket "
+						"to interface");
+				close(sk);
+				rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+				goto out;
+			}
+		}
+	}
+
+	io = g_io_channel_unix_new(sk);
+	if (io == NULL) {
+		close(sk);
+		error = -ENOMEM;
+		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+		goto out;
+	}
+
+	g_io_channel_set_close_on_unref(io, TRUE);
+	g_io_channel_set_flags(io, 0, NULL);
+	g_io_channel_set_encoding(io, NULL, NULL);
+	g_io_channel_set_buffered(io, FALSE);
+
+	stk->read_watch = g_io_add_watch_full(io, G_PRIORITY_DEFAULT,
+				G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
+				receive_callback, stk, NULL);
+	stk->io = io;
+	g_io_channel_unref(io);
+
+	if (stk->pending_cmd == NULL) {
+		/* TODO send channel status event */
+		return;
+	} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_OPEN_CHANNEL) {
+		rsp.open_channel.channel.id = stk->channel.id;
+		rsp.open_channel.channel.status = stk->channel.status;
+		rsp.open_channel.buf_size = stk->tx_avail;
+		memcpy(&rsp.open_channel.bearer_desc, &stk->bearer_desc,
+				sizeof(struct stk_bearer_description));
+	} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_SEND_DATA &&
+			stk->link_on_demand) {
+		/* TODO send data */
+		rsp.send_data.tx_avail = stk->tx_avail;
+	} else {
+		/* TODO send channel status event */
+		return;
+	}
+
+out:
+	if (stk_respond(stk, &rsp, stk_command_cb))
+		stk_command_cb(&failure, stk);
+
+	if (rsp.result.type != STK_RESULT_TYPE_SUCCESS)
+		stk_close_channel(stk);
 }
 
 static void stk_open_channel(struct ofono_stk *stk)
@@ -602,6 +748,11 @@ static void stk_open_channel(struct ofono_stk *stk)
 		 */
 		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
 		goto out;
+	} else if (oc->data_dest_addr.type == STK_ADDRESS_IPV4) {
+		memset(&stk->dest_addr, 0, sizeof(stk->dest_addr));
+		stk->dest_addr.sin_family = AF_INET;
+		stk->dest_addr.sin_port = htons(oc->uti.port);
+		stk->dest_addr.sin_addr.s_addr = oc->data_dest_addr.addr.ipv4;
 	}
 
 	stk->channel.id = DEFAULT_CHANNEL_ID;
-- 
1.7.1


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

* [PATCH 06/11] stk: Add 'ofono_stk_deactivate_context_cb' definition
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (4 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 05/11] stk: Add 'ofono_stk_activate_cb' definition Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 07/11] stk: Add support for the proactive command 'Receive data' Philippe Nunes
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 1db45eb..9739e4b 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -510,6 +510,24 @@ static void cancel_pending_dtmf(struct ofono_stk *stk)
 
 static void ofono_stk_deactivate_context_cb(int error, void *data)
 {
+	struct ofono_stk *stk = data;
+
+	DBG("");
+
+	if (stk->pending_cmd && stk->pending_cmd->type ==
+			STK_COMMAND_TYPE_CLOSE_CHANNEL) {
+		stk->channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+
+		if (error < 0)
+			send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
+		else
+			send_simple_response(stk, STK_RESULT_TYPE_SUCCESS);
+	} else {
+		/* TODO send channel status event */
+	}
+
+	stk->channel.id = 0;
 }
 
 static void stk_close_channel(struct ofono_stk *stk)
-- 
1.7.1


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

* [PATCH 07/11] stk: Add support for the proactive command 'Receive data'
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (5 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 06/11] stk: Add 'ofono_stk_deactivate_context_cb' definition Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 08/11] stk: Add support for the proactive command 'Send data' Philippe Nunes
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 9739e4b..5abc27c 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -31,6 +31,7 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <unistd.h>
+#include <sys/ioctl.h>
 
 #include <glib.h>
 #include <gdbus.h>
@@ -85,6 +86,7 @@ struct ofono_stk {
 	void *sms_pp_userdata;
 	struct stk_channel channel;
 	struct ofono_gprs_primary_context context;
+	gsize rx_remaining;
 	gsize tx_avail;
 	gboolean link_on_demand;
 	struct ofono_gprs *gprs;
@@ -124,6 +126,14 @@ static void timers_update(struct ofono_stk *stk);
  */
 #define DEFAULT_CHANNEL_ID 1
 
+/*
+ * According the structure and coding of the Terminal response defined in
+ * TS 102 223 section 6.8, the maximum number of bytes possible for the channel
+ * data object is 243
+ */
+#define CHANNEL_DATA_OBJECT_MAX_LENGTH 243
+
+
 static int stk_respond(struct ofono_stk *stk, struct stk_response *rsp,
 			ofono_stk_generic_cb_t cb)
 {
@@ -534,6 +544,11 @@ static void stk_close_channel(struct ofono_stk *stk)
 {
 	int err;
 
+	if (stk->read_watch > 0)
+		g_source_remove(stk->read_watch);
+	else if (stk->io)
+		g_io_channel_unref(stk->io);
+
 	err = __ofono_gprs_deactivate_context(stk->context.cid,
 			ofono_stk_deactivate_context_cb, stk);
 
@@ -598,6 +613,31 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
 static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
 				gpointer userdata)
 {
+	struct ofono_stk *stk = (struct ofono_stk *) userdata;
+
+	if (cond & (G_IO_NVAL | G_IO_ERR | G_IO_HUP))
+		return FALSE;
+
+	if (cond & G_IO_IN) {
+		int fd = g_io_channel_unix_get_fd(channel);
+		int len = 0;
+
+		ioctl(fd, FIONREAD, &len);
+		DBG("%zd bytes to read", len);
+
+		/*
+		 * TODO
+		 * send data available event if the buffer is empty
+		 * when new data arrives in it
+		 */
+
+		stk->rx_remaining = len;
+
+		/* Disable the read watch until the SIM requests all bytes */
+		g_io_channel_ref(channel);
+		g_source_remove(stk->read_watch);
+		stk->read_watch = 0;
+	}
 	return TRUE;
 }
 
@@ -775,6 +815,7 @@ static void stk_open_channel(struct ofono_stk *stk)
 
 	stk->channel.id = DEFAULT_CHANNEL_ID;
 	stk->tx_avail = oc->buf_size;
+	stk->io = NULL;
 
 	memset(&stk->context, 0, sizeof(stk->context));
 	stk->context.proto = OFONO_GPRS_PROTO_IP;
@@ -848,6 +889,61 @@ out:
 		stk_close_channel(stk);
 }
 
+static void stk_receive_data(struct ofono_stk *stk, unsigned char toread)
+{
+	struct stk_response rsp;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	gsize bytes_read;
+	unsigned char buf[CHANNEL_DATA_OBJECT_MAX_LENGTH];
+	GIOStatus status;
+	int fd;
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+	/* update bytes_to_read */
+	fd = g_io_channel_unix_get_fd(stk->io);
+	ioctl(fd, FIONREAD, &stk->rx_remaining);
+	DBG("%zd bytes to read", stk->rx_remaining);
+
+	if (stk->rx_remaining == 0) {
+		rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+		goto out;
+	}
+
+	if (toread > stk->rx_remaining) {
+		rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+		toread = stk->rx_remaining;
+	}
+
+	if (toread > CHANNEL_DATA_OBJECT_MAX_LENGTH)
+		toread = CHANNEL_DATA_OBJECT_MAX_LENGTH;
+
+	status = g_io_channel_read_chars(stk->io, (gchar *)buf, toread,
+						&bytes_read, NULL);
+
+	if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
+		rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+		goto out;
+	}
+
+	rsp.receive_data.rx_data.len = bytes_read;
+	rsp.receive_data.rx_data.array = buf;
+	stk->rx_remaining -= bytes_read;
+	rsp.receive_data.rx_remaining = stk->rx_remaining;
+
+	if (stk->rx_remaining == 0) {
+		stk->read_watch = g_io_add_watch_full(stk->io,
+					G_PRIORITY_DEFAULT,
+					G_IO_IN | G_IO_HUP | G_IO_ERR |
+					G_IO_NVAL, receive_callback, stk, NULL);
+		g_io_channel_unref(stk->io);
+	}
+
+out:
+	if (stk_respond(stk, &rsp, stk_command_cb))
+		stk_command_cb(&failure, stk);
+}
 
 static int duration_to_msecs(const struct stk_duration *duration)
 {
@@ -3045,6 +3141,38 @@ static gboolean handle_command_close_channel(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static gboolean handle_command_receive_data(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	const struct stk_command_receive_data *rd = &cmd->receive_data;
+
+	/* Check if channel identifier is valid or already closed */
+	if (cmd->dst != (stk->channel.id | 0x20)) {
+		unsigned char addnl_info[1];
+
+		addnl_info[1] = STK_RESULT_ADDNL_BIP_PB_CHANNEL_ID_NOT_VALID;
+		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
+					addnl_info);
+		return TRUE;
+	}
+
+	/*
+	 * Don't inform the user during data transfer if AID is
+	 * a null data object or is not provided
+	 */
+	if (rd->alpha_id && rd->alpha_id[0] != '\0')
+		stk_alpha_id_set(stk, rd->alpha_id, &rd->text_attr,
+					&rd->icon_id);
+
+	stk->respond_on_exit = TRUE;
+	stk->cancel_cmd = stk_request_cancel;
+
+	stk_receive_data(stk, rd->data_len);
+
+	return FALSE;
+}
+
 static gboolean handle_command_get_channel_status(const struct stk_command *cmd,
 						struct stk_response *rsp,
 						struct ofono_stk *stk)
@@ -3258,6 +3386,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_RECEIVE_DATA:
+		respond = handle_command_receive_data(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	case STK_COMMAND_TYPE_GET_CHANNEL_STATUS:
 		respond = handle_command_get_channel_status(stk->pending_cmd,
 							&rsp, stk);
-- 
1.7.1


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

* [PATCH 08/11] stk: Add support for the proactive command 'Send data'
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (6 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 07/11] stk: Add support for the proactive command 'Receive data' Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 09/11] stk: Add support of the Setup event list proactive command Philippe Nunes
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 5abc27c..bb17b00 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -610,6 +610,42 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
 	stk_agent_request_cancel(stk->current_agent);
 }
 
+static gsize stk_channel_data_write(struct ofono_stk *stk, gboolean package,
+					const unsigned char *data, gsize len)
+{
+	GIOStatus status;
+	gssize bytes_written;
+	int flags = 0;
+
+	if (stk->protocol == STK_TRANSPORT_PROTOCOL_UDP_CLIENT_REMOTE) {
+		if (package == TRUE)
+			flags = MSG_MORE;
+
+		bytes_written = sendto(g_io_channel_unix_get_fd(stk->io), data,
+				len, flags, (struct sockaddr *) &stk->dest_addr,
+				sizeof(stk->dest_addr));
+
+		if (bytes_written == -1 && stk->read_watch > 0) {
+			g_source_remove(stk->read_watch);
+			return 0;
+		}
+	} else {
+		status = g_io_channel_write_chars(stk->io, (gchar *)data,
+					len, (gsize *) &bytes_written, NULL);
+
+		if (status != G_IO_STATUS_NORMAL && stk->read_watch > 0) {
+			g_source_remove(stk->read_watch);
+			return 0;
+		}
+	}
+
+	DBG("Send %zd bytes", bytes_written);
+
+	stk->tx_avail += bytes_written;
+
+	return bytes_written;
+}
+
 static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
 				gpointer userdata)
 {
@@ -766,7 +802,17 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 				sizeof(struct stk_bearer_description));
 	} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_SEND_DATA &&
 			stk->link_on_demand) {
-		/* TODO send data */
+		const struct stk_command_send_data *sd =
+						&stk->pending_cmd->send_data;
+		gboolean package = (stk->pending_cmd->qualifier ==
+				STK_SEND_DATA_STORE_DATA) ? TRUE : FALSE;
+
+		if (stk_channel_data_write(stk, package, sd->data.array,
+						sd->data.len) == 0) {
+				ofono_error("Failed to send data");
+				rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+				goto out;
+		}
 		rsp.send_data.tx_avail = stk->tx_avail;
 	} else {
 		/* TODO send channel status event */
@@ -889,6 +935,57 @@ out:
 		stk_close_channel(stk);
 }
 
+static void stk_send_data(struct ofono_stk *stk,
+				struct stk_common_byte_array data,
+				unsigned char qualifier)
+{
+	struct stk_response rsp;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+
+
+	memset(&rsp, 0, sizeof(rsp));
+	rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+	if (data.len > stk->tx_avail) {
+		rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+		goto out;
+	}
+
+	if (stk->channel.status == STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED
+			&& stk->link_on_demand == TRUE) {
+		int err;
+
+		err = __ofono_gprs_activate_context(stk->gprs, &stk->context,
+					ofono_stk_activate_context_cb, stk);
+
+		if (err == -EBUSY) {
+			rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+			goto out;
+		} else if (err < 0) {
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+
+		return;
+	} else {
+		gboolean package = (qualifier == STK_SEND_DATA_STORE_DATA) ?
+						TRUE : FALSE;
+
+		if (stk_channel_data_write(stk, package, data.array,
+						data.len) == 0) {
+				ofono_error("Failed to send data");
+				rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+				goto out;
+		}
+		stk->tx_avail -= data.len;
+		rsp.send_data.tx_avail = stk->tx_avail;
+	}
+
+out:
+	if (stk_respond(stk, &rsp, stk_command_cb))
+		stk_command_cb(&failure, stk);
+}
+
 static void stk_receive_data(struct ofono_stk *stk, unsigned char toread)
 {
 	struct stk_response rsp;
@@ -3173,6 +3270,45 @@ static gboolean handle_command_receive_data(const struct stk_command *cmd,
 	return FALSE;
 }
 
+static gboolean handle_command_send_data(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	const struct stk_command_send_data *sd = &cmd->send_data;
+	unsigned char addnl_info[1];
+
+	/* Check if channel identifier is valid or already closed */
+	if (cmd->dst != (stk->channel.id | 0x20)) {
+		addnl_info[1] = STK_RESULT_ADDNL_BIP_PB_CHANNEL_ID_NOT_VALID;
+		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
+					addnl_info);
+		return TRUE;
+	}
+
+	/* Check if the link was dropped */
+	if (stk->channel.status == STK_CHANNEL_LINK_DROPPED) {
+		addnl_info[1] = STK_RESULT_ADDNL_BIP_PB_CHANNEL_CLOSED;
+		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
+					addnl_info);
+		return TRUE;
+	}
+
+	/*
+	 * Don't inform the user during data transfer if AID is
+	 * a null data object or is not provided
+	 */
+	if (sd->alpha_id && sd->alpha_id[0] != '\0')
+		stk_alpha_id_set(stk, sd->alpha_id, &sd->text_attr,
+							&sd->icon_id);
+
+	stk->respond_on_exit = TRUE;
+	stk->cancel_cmd = stk_request_cancel;
+
+	stk_send_data(stk, sd->data, cmd->qualifier);
+
+	return FALSE;
+}
+
 static gboolean handle_command_get_channel_status(const struct stk_command *cmd,
 						struct stk_response *rsp,
 						struct ofono_stk *stk)
@@ -3391,6 +3527,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_SEND_DATA:
+		respond = handle_command_send_data(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	case STK_COMMAND_TYPE_GET_CHANNEL_STATUS:
 		respond = handle_command_get_channel_status(stk->pending_cmd,
 							&rsp, stk);
-- 
1.7.1


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

* [PATCH 09/11] stk: Add support of the Setup event list proactive command
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (7 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 08/11] stk: Add support for the proactive command 'Send data' Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 10/11] stk: Add host route to route the traffic through the stk interface Philippe Nunes
  2011-06-28 17:16 ` [PATCH 11/11] gprs: Add API to set a 'detach'notification callback Philippe Nunes
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

---
 src/stk.c |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 108 insertions(+), 10 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index bb17b00..9eecee3 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -89,6 +89,8 @@ struct ofono_stk {
 	gsize rx_remaining;
 	gsize tx_avail;
 	gboolean link_on_demand;
+	gboolean report_data_available;
+	gboolean report_channel_status;
 	struct ofono_gprs *gprs;
 	struct stk_bearer_description bearer_desc;
 	enum stk_transport_protocol_type protocol;
@@ -518,6 +520,58 @@ static void cancel_pending_dtmf(struct ofono_stk *stk)
 		__ofono_voicecall_tone_cancel(vc, stk->dtmf_id);
 }
 
+static void event_download_envelope_cb(struct ofono_stk *stk, gboolean ok,
+				const unsigned char *data, int len)
+{
+	if (!ok) {
+		ofono_error("Event download to UICC failed");
+		return;
+	}
+
+	if (len)
+		ofono_error("Event download returned %i bytes of data",
+				len);
+
+	DBG("Event download  to UICC reported no error");
+}
+
+static void stk_send_channel_status_event(struct ofono_stk *stk)
+{
+	struct stk_envelope e;
+
+	memset(&e, 0, sizeof(e));
+	e.type = STK_ENVELOPE_TYPE_EVENT_DOWNLOAD;
+	e.src = STK_DEVICE_IDENTITY_TYPE_TERMINAL;
+	e.event_download.type = STK_EVENT_TYPE_CHANNEL_STATUS;
+	e.event_download.channel_status.channel.id = stk->channel.id;
+	e.event_download.channel_status.channel.status = stk->channel.status;
+
+	if (stk->channel.status == STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED)
+		memcpy(&e.event_download.channel_status.bearer_desc,
+				&stk->bearer_desc,
+				sizeof(struct stk_bearer_description));
+
+	if (stk_send_envelope(stk, &e, event_download_envelope_cb, 0))
+		event_download_envelope_cb(stk, FALSE, NULL, -1);
+}
+
+static void stk_send_data_available_event(struct ofono_stk *stk,
+						unsigned short data_available)
+{
+	struct stk_envelope e;
+
+	memset(&e, 0, sizeof(e));
+	e.type = STK_ENVELOPE_TYPE_EVENT_DOWNLOAD;
+	e.src = STK_DEVICE_IDENTITY_TYPE_TERMINAL;
+	e.event_download.type = STK_EVENT_TYPE_DATA_AVAILABLE;
+	e.event_download.data_available.channel.id = stk->channel.id;
+	e.event_download.data_available.channel.status = stk->channel.status;
+	e.event_download.data_available.channel_data_len = data_available;
+
+	if (stk_send_envelope(stk, &e, event_download_envelope_cb, 0))
+		event_download_envelope_cb(stk, FALSE, NULL, -1);
+}
+
 static void ofono_stk_deactivate_context_cb(int error, void *data)
 {
 	struct ofono_stk *stk = data;
@@ -533,8 +587,10 @@ static void ofono_stk_deactivate_context_cb(int error, void *data)
 			send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
 		else
 			send_simple_response(stk, STK_RESULT_TYPE_SUCCESS);
-	} else {
-		/* TODO send channel status event */
+	} else if (stk->report_channel_status) {
+		/* user cancellation */
+		stk->channel.status = STK_CHANNEL_LINK_DROPPED;
+		stk_send_channel_status_event(stk);
 	}
 
 	stk->channel.id = 0;
@@ -661,11 +717,10 @@ static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
 		ioctl(fd, FIONREAD, &len);
 		DBG("%zd bytes to read", len);
 
-		/*
-		 * TODO
-		 * send data available event if the buffer is empty
-		 * when new data arrives in it
-		 */
+		if (len > 0 && stk->rx_remaining == 0 &&
+				stk->report_data_available) {
+			stk_send_data_available_event(stk, len);
+		}
 
 		stk->rx_remaining = len;
 
@@ -700,7 +755,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 				STK_COMMAND_TYPE_OPEN_CHANNEL &&
 				stk->pending_cmd->type !=
 				STK_COMMAND_TYPE_SEND_DATA)) {
-			/* TODO send channel status event */
+			if (stk->report_channel_status)
+				stk_send_channel_status_event(stk);
 			return;
 		} else {
 			rsp.result.type = STK_RESULT_TYPE_NETWORK_UNAVAILABLE;
@@ -792,7 +848,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 	g_io_channel_unref(io);
 
 	if (stk->pending_cmd == NULL) {
-		/* TODO send channel status event */
+		if (stk->report_channel_status)
+			stk_send_channel_status_event(stk);
 		return;
 	} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_OPEN_CHANNEL) {
 		rsp.open_channel.channel.id = stk->channel.id;
@@ -815,7 +872,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 		}
 		rsp.send_data.tx_avail = stk->tx_avail;
 	} else {
-		/* TODO send channel status event */
+		if (stk->report_channel_status)
+			stk_send_channel_status_event(stk);
 		return;
 	}
 
@@ -2710,6 +2768,8 @@ static gboolean handle_command_refresh(const struct stk_command *cmd,
 		case 5:
 		case 6:
 			free_idle_mode_text(stk);
+			stk->report_data_available = FALSE;
+			stk->report_channel_status = FALSE;
 			__ofono_sim_refresh(sim, file_list, FALSE, TRUE);
 			break;
 		}
@@ -3319,6 +3379,39 @@ static gboolean handle_command_get_channel_status(const struct stk_command *cmd,
 	return TRUE;
 }
 
+
+static gboolean handle_command_setup_event_list(const struct stk_command *cmd,
+						struct stk_response *rsp,
+						struct ofono_stk *stk)
+{
+	const struct stk_command_setup_event_list *sel = &cmd->setup_event_list;
+	unsigned int i;
+
+	stk->report_data_available = FALSE;
+	stk->report_channel_status = FALSE;
+
+	for (i = 0; i < sel->event_list.len; i++) {
+		switch (sel->event_list.list[i]) {
+		case STK_EVENT_TYPE_DATA_AVAILABLE:
+			DBG("Enable data available event");
+			stk->report_data_available = TRUE;
+			break;
+		case STK_EVENT_TYPE_CHANNEL_STATUS:
+			DBG("Enable channel status event");
+			stk->report_channel_status = TRUE;
+			break;
+		default:
+			DBG("Event type (%d) not supported",
+						sel->event_list.list[i]);
+			rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			return TRUE;
+		}
+	}
+
+	rsp->result.type = STK_RESULT_TYPE_SUCCESS;
+	return TRUE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -3537,6 +3630,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
 							&rsp, stk);
 		break;
 
+	case STK_COMMAND_TYPE_SETUP_EVENT_LIST:
+		respond = handle_command_setup_event_list(stk->pending_cmd,
+							&rsp, stk);
+		break;
+
 	default:
 		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
 		break;
-- 
1.7.1


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

* [PATCH 10/11] stk: Add host route to route the traffic through the stk interface
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (8 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 09/11] stk: Add support of the Setup event list proactive command Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-28 17:16 ` [PATCH 11/11] gprs: Add API to set a 'detach'notification callback Philippe Nunes
  10 siblings, 0 replies; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/stk.c b/src/stk.c
index 9eecee3..58b58df 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -31,6 +31,7 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 #include <unistd.h>
+#include <net/route.h>
 #include <sys/ioctl.h>
 
 #include <glib.h>
@@ -666,6 +667,44 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
 	stk_agent_request_cancel(stk->current_agent);
 }
 
+static void stk_add_host_route(struct ofono_stk *stk, const char *interface)
+{
+	struct rtentry rt;
+	struct sockaddr_in addr;
+	int sk;
+
+	if (interface == NULL)
+		return;
+
+	sk = socket(PF_INET, SOCK_DGRAM, 0);
+	if (sk < 0)
+		return;
+
+	memset(&rt, 0, sizeof(rt));
+	rt.rt_flags = RTF_UP | RTF_HOST;
+	rt.rt_dev = (char *) interface;
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = stk->dest_addr.sin_addr.s_addr;
+	memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+	addr.sin_addr.s_addr = INADDR_ANY;
+	memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+
+	if (ioctl(sk, SIOCADDRT, &rt) < 0)
+		ofono_error("Failed to add host route");
+
+	close(sk);
+}
+
 static gsize stk_channel_data_write(struct ofono_stk *stk, gboolean package,
 					const unsigned char *data, gsize len)
 {
@@ -767,6 +806,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 		stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
 	}
 
+	stk_add_host_route(stk, interface);
+
 	if (stk->protocol == STK_TRANSPORT_PROTOCOL_TCP_CLIENT_REMOTE) {
 		sk = socket(AF_INET, SOCK_STREAM, 0);
 		if (sk < 0) {
-- 
1.7.1


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

* [PATCH 11/11] gprs: Add API to set a 'detach'notification callback
  2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
                   ` (9 preceding siblings ...)
  2011-06-28 17:16 ` [PATCH 10/11] stk: Add host route to route the traffic through the stk interface Philippe Nunes
@ 2011-06-28 17:16 ` Philippe Nunes
  2011-06-29 22:46   ` Denis Kenzior
  10 siblings, 1 reply; 17+ messages in thread
From: Philippe Nunes @ 2011-06-28 17:16 UTC (permalink / raw)
  To: ofono

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

---
 src/gprs.c  |   37 +++++++++++++++++++++++++++++++++++++
 src/ofono.h |    6 ++++++
 2 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index b3e6869..0166e70 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -1495,6 +1495,28 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
 					"Active", DBUS_TYPE_BOOLEAN, &value);
 		}
 
+		for (l = g_private_contexts; l; l = l->next) {
+			struct gprs_private_context *ctx = l->data;
+			struct context_settings *settings =
+						ctx->context_driver->settings;
+
+			pri_set_ipv4_addr(settings->interface, NULL);
+			pri_ifupdown(settings->interface, FALSE);
+			context_settings_free(settings);
+
+			DBG("Release private context cid %d", ctx->cid);
+
+			gprs_cid_release(gprs, ctx->cid);
+			ctx->context_driver->inuse = FALSE;
+
+			if (ctx->notify)
+				((__ofono_gprs_deactivated_on_detach_cb_t)
+						ctx->notify)(ctx->notify_data);
+
+			g_private_contexts = g_slist_remove(g_private_contexts,
+								ctx);
+		}
+
 		gprs->bearer = -1;
 	}
 
@@ -3223,3 +3245,18 @@ int __ofono_gprs_deactivate_context(unsigned int id,
 				deactivate_request_callback, private_ctx);
 	return 0;
 }
+
+int __ofono_gprs_set_deactivated_on_detach_notify(unsigned int id,
+				__ofono_gprs_deactivated_on_detach_cb_t cb,
+				void *data)
+{
+	struct gprs_private_context *private_ctx;
+
+	private_ctx = gprs_private_context_by_id(id);
+	if (private_ctx == NULL)
+		return -EINVAL;
+
+	private_ctx->notify = cb;
+	private_ctx->notify_data = data;
+	return 0;
+}
diff --git a/src/ofono.h b/src/ofono.h
index 6b72816..a1215e8 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -248,6 +248,8 @@ typedef void (*__ofono_gprs_activate_context_cb_t)(int error,
 
 typedef void (*__ofono_gprs_deactivate_context_cb_t)(int error, void *data);
 
+typedef void (*__ofono_gprs_deactivated_on_detach_cb_t)(void *data);
+
 int __ofono_gprs_deactivate_context(unsigned int id,
 					__ofono_gprs_deactivate_context_cb_t cb,
 					void *data);
@@ -257,6 +259,10 @@ int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
 				__ofono_gprs_activate_context_cb_t cb,
 				void *data);
 
+int __ofono_gprs_set_deactivated_on_detach_notify(unsigned int id,
+				__ofono_gprs_deactivated_on_detach_cb_t cb,
+				void *data);
+
 #include <ofono/radio-settings.h>
 #include <ofono/audio-settings.h>
 #include <ofono/ctm.h>
-- 
1.7.1


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

* Re: [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts
  2011-06-28 17:16 ` [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts Philippe Nunes
@ 2011-06-29 22:22   ` Denis Kenzior
  2011-06-30 16:24     ` Philippe Nunes
  0 siblings, 1 reply; 17+ messages in thread
From: Denis Kenzior @ 2011-06-29 22:22 UTC (permalink / raw)
  To: ofono

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

Hi Philippe,

On 06/28/2011 12:16 PM, Philippe Nunes wrote:
> ---
>  src/gprs.c  |  211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/ofono.h |   17 +++++
>  2 files changed, 228 insertions(+), 0 deletions(-)
> 
> diff --git a/src/gprs.c b/src/gprs.c
> index acbfa56..b3e6869 100644
> --- a/src/gprs.c
> +++ b/src/gprs.c
> @@ -59,6 +59,7 @@
>  
>  static GSList *g_drivers = NULL;
>  static GSList *g_context_drivers = NULL;
> +static GSList *g_private_contexts = NULL;

So this part is quite wrong ;)  What you have done here is to make stk
activated contexts shared across all gprs atoms, with potentially
duplicate ids.

>  
>  /* 27.007 Section 7.29 */
>  enum packet_bearer {
> @@ -149,6 +150,13 @@ struct pri_context {
>  	struct ofono_gprs *gprs;
>  };
>  
> +struct gprs_private_context {
> +	unsigned int cid;
> +	struct ofono_gprs_context *context_driver;
> +	void *notify;

I suggest you use a union so as to avoid casting all over the place.

e.g.

union {
	activate_cb act;
	deactivate_cb deact;
};

or something

> +	void *notify_data;
> +};
> +
>  static void gprs_netreg_update(struct ofono_gprs *gprs);
>  static void gprs_deactivate_next(struct ofono_gprs *gprs);
>  
> @@ -346,6 +354,20 @@ static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
>  	return NULL;
>  }
>  
> +static struct pri_context *gprs_get_default_context(struct ofono_gprs *gprs)
> +{
> +	GSList *l;
> +
> +	for (l = gprs->contexts; l; l = l->next) {
> +		struct pri_context *ctx = l->data;
> +
> +		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
> +			return ctx;
> +	}
> +
> +	return NULL;
> +}
> +
>  static void context_settings_free(struct context_settings *settings)
>  {
>  	if (settings->ipv4) {
> @@ -872,6 +894,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
>  				dbus_message_new_method_return(ctx->pending));
>  
>  	if (gc->settings->interface != NULL) {
> +		DBG("Interface %s", gc->settings->interface);
> +
>  		pri_ifupdown(gc->settings->interface, TRUE);
>  
>  		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS &&
> @@ -3012,3 +3036,190 @@ void *ofono_gprs_get_data(struct ofono_gprs *gprs)
>  {
>  	return gprs->driver_data;
>  }
> +
> +static struct gprs_private_context *gprs_private_context_by_id(unsigned int id)
> +{
> +	GSList *l;
> +
> +	for (l = g_private_contexts; l; l = l->next) {
> +		struct gprs_private_context *ctx = l->data;
> +
> +		if (ctx->cid == id)
> +			return ctx;
> +	}
> +
> +	return NULL;
> +}
> +
> +static void activate_request_callback(const struct ofono_error *error,
> +					void *data)
> +{
> +	struct gprs_private_context *ctx = data;
> +	struct context_settings *settings = ctx->context_driver->settings;
> +
> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
> +		DBG("Activating context failed with error: %s",
> +				telephony_error_to_str(error));
> +		context_settings_free(settings);
> +		gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
> +		ctx->context_driver->inuse = FALSE;
> +
> +		if (ctx->notify)
> +			((__ofono_gprs_activate_context_cb_t) ctx->notify)
> +				(-ENOSYS, NULL, NULL, ctx->notify_data);
> +
> +		g_private_contexts = g_slist_remove(g_private_contexts, ctx);
> +		return;
> +	}
> +
> +	if (settings->interface != NULL) {
> +		pri_ifupdown(settings->interface, TRUE);
> +
> +		if (settings->ipv4)
> +			pri_set_ipv4_addr(settings->interface,
> +							settings->ipv4->ip);
> +	}
> +
> +	if (ctx->notify && settings->ipv4)
> +		((__ofono_gprs_activate_context_cb_t) ctx->notify)
> +					(0, settings->interface,
> +						settings->ipv4->ip,
> +						ctx->notify_data);
> +}
> +
> +int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
> +				struct ofono_gprs_primary_context *context,
> +				__ofono_gprs_activate_context_cb_t cb,
> +				void *data)
> +{
> +	struct gprs_private_context *private_ctx;
> +	struct pri_context *default_ctx = NULL;
> +	struct ofono_gprs_context *gc = NULL;
> +	struct idmap *cidmap = gprs->cid_map;
> +	GSList *l;
> +
> +	if (context->apn[0] == '\0' || (context->username[0] == '\0' &&
> +			context->password[0] == '\0')) {
> +		/* take the default primary internet context */
> +		default_ctx = gprs_get_default_context(gprs);
> +
> +		if (default_ctx == NULL && context->apn[0] == '\0')
> +			return -ENOENT;
> +	}
> +
> +	if (context->apn[0] != '\0' && is_valid_apn(context->apn) == FALSE)
> +		return EINVAL;
> +
> +	if (context->proto != OFONO_GPRS_PROTO_IPV4V6 &&
> +			context->proto != OFONO_GPRS_PROTO_IP)
> +		return -ENOSYS;
> +
> +	if (cidmap == NULL)
> +		return -ENOSYS;
> +
> +	if (context->apn[0] == '\0') {
> +		strcpy(context->apn, default_ctx->context.apn);
> +		strcpy(context->username, default_ctx->context.username);
> +		strcpy(context->password, default_ctx->context.password);
> +	}
> +
> +	private_ctx = g_try_new0(struct gprs_private_context, 1);
> +	if (private_ctx == NULL)
> +		return -ENOMEM;
> +
> +	private_ctx->cid = gprs_cid_alloc(gprs);
> +	if (private_ctx->cid == 0) {
> +		g_free(private_ctx);
> +		return -EBUSY;
> +	}
> +
> +	context->cid = private_ctx->cid;
> +
> +	for (l = gprs->context_drivers; l; l = l->next) {
> +		gc = l->data;
> +
> +		if (gc->inuse == TRUE)
> +			continue;
> +
> +		if (gc->driver == NULL)
> +			continue;
> +
> +		if (gc->driver->activate_primary == NULL ||
> +				gc->driver->deactivate_primary == NULL)
> +			continue;
> +
> +		if (gc->type != OFONO_GPRS_CONTEXT_TYPE_ANY &&
> +				gc->type != OFONO_GPRS_CONTEXT_TYPE_INTERNET)
> +			continue;
> +
> +		break;
> +	}
> +
> +	if (gc == NULL) {
> +		g_free(private_ctx);
> +		return -EBUSY;
> +	}
> +
> +	gc->inuse = TRUE;
> +	gc->settings->ipv4 = g_new0(struct ipv4_settings, 1);
> +	private_ctx->context_driver = gc;
> +	private_ctx->notify = cb;
> +	private_ctx->notify_data = data;
> +
> +	g_private_contexts = g_slist_append(g_private_contexts, private_ctx);
> +
> +	gc->driver->activate_primary(gc, context, activate_request_callback,
> +					private_ctx);
> +	return 0;
> +}
> +
> +static void deactivate_request_callback(const struct ofono_error *error,
> +					void *data)
> +{
> +	struct gprs_private_context *ctx = data;
> +	struct context_settings *settings = ctx->context_driver->settings;
> +	int err = 0;
> +
> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
> +		DBG("Deactivating context failed with error: %s",
> +				telephony_error_to_str(error));
> +		err = -ENOSYS;
> +	}
> +
> +	pri_set_ipv4_addr(settings->interface, NULL);
> +	pri_ifupdown(settings->interface, FALSE);
> +	context_settings_free(settings);
> +
> +	DBG("Release Context cid %d", ctx->cid);
> +
> +	gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
> +	ctx->context_driver->inuse = FALSE;
> +
> +	if (ctx->notify)
> +		((__ofono_gprs_deactivate_context_cb_t) ctx->notify)
> +				(err, ctx->notify_data);
> +
> +	g_private_contexts = g_slist_remove(g_private_contexts, ctx);
> +}
> +
> +int __ofono_gprs_deactivate_context(unsigned int id,
> +					__ofono_gprs_deactivate_context_cb_t cb,
> +					void *data)
> +{
> +	struct gprs_private_context *private_ctx;
> +	struct ofono_gprs_context *gc;
> +
> +	DBG("Deactivate context with cid %d", id);
> +
> +	private_ctx = gprs_private_context_by_id(id);
> +	if (private_ctx == NULL)
> +		return -EINVAL;
> +
> +	private_ctx->notify = cb;
> +	private_ctx->notify_data = data;
> +
> +	gc = private_ctx->context_driver;
> +	gc->driver->deactivate_primary(gc, private_ctx->cid,
> +				deactivate_request_callback, private_ctx);
> +	return 0;
> +}
> diff --git a/src/ofono.h b/src/ofono.h
> index 6524806..6b72816 100644
> --- a/src/ofono.h
> +++ b/src/ofono.h
> @@ -240,6 +240,23 @@ gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs);
>  #include <ofono/phonebook.h>
>  #include <ofono/gprs.h>
>  #include <ofono/gprs-context.h>
> +
> +typedef void (*__ofono_gprs_activate_context_cb_t)(int error,
> +						const char *interface,
> +						const char *ip,
> +						void *data);
> +
> +typedef void (*__ofono_gprs_deactivate_context_cb_t)(int error, void *data);
> +
> +int __ofono_gprs_deactivate_context(unsigned int id,
> +					__ofono_gprs_deactivate_context_cb_t cb,
> +					void *data);
> +
> +int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
> +				struct ofono_gprs_primary_context *context,
> +				__ofono_gprs_activate_context_cb_t cb,
> +				void *data);
> +
>  #include <ofono/radio-settings.h>
>  #include <ofono/audio-settings.h>
>  #include <ofono/ctm.h>

Regards,
-Denis

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

* Re: [PATCH 02/11] stk: Add support for the proactive command 'Open channel'
  2011-06-28 17:16 ` [PATCH 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
@ 2011-06-29 22:38   ` Denis Kenzior
  0 siblings, 0 replies; 17+ messages in thread
From: Denis Kenzior @ 2011-06-29 22:38 UTC (permalink / raw)
  To: ofono

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

Hi Philippe,

On 06/28/2011 12:16 PM, Philippe Nunes wrote:
> stk: add modifications
> ---
>  src/stk.c |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 221 insertions(+), 0 deletions(-)
> 
> diff --git a/src/stk.c b/src/stk.c
> index 9575f0e..4bf6a08 100644
> --- a/src/stk.c
> +++ b/src/stk.c
> @@ -41,6 +41,7 @@
>  #include "smsutil.h"
>  #include "stkutil.h"
>  #include "stkagent.h"
> +#include "gprs.h"
>  #include "util.h"
>  
>  static GSList *g_drivers = NULL;
> @@ -79,6 +80,13 @@ struct ofono_stk {
>  
>  	__ofono_sms_sim_download_cb_t sms_pp_cb;
>  	void *sms_pp_userdata;
> +	struct stk_channel channel;
> +	struct ofono_gprs_primary_context context;
> +	gsize tx_avail;
> +	gboolean link_on_demand;
> +	struct ofono_gprs *gprs;
> +	struct stk_bearer_description bearer_desc;
> +	enum stk_transport_protocol_type protocol;

Since BIP related stuff has quite a bit of parameters, can we group this
all into an anonymous structure here?

e.g. something like
	...
	struct {
	..
	..
	} bip; or bip_data.

>  };
>  
>  struct envelope_op {
> @@ -104,6 +112,12 @@ static void timers_update(struct ofono_stk *stk);
>  		result.additional_len = sizeof(addn_info);	\
>  		result.additional = addn_info;			\
>  
> +/*
> + * Channel identifier is attributed by default to 1 since only one channel
> + * is open per time
> + */
> +#define DEFAULT_CHANNEL_ID 1
> +
>  static int stk_respond(struct ofono_stk *stk, struct stk_response *rsp,
>  			ofono_stk_generic_cb_t cb)
>  {
> @@ -532,6 +546,113 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
>  	stk_agent_request_cancel(stk->current_agent);
>  }
>  
> +static void ofono_stk_activate_context_cb(int error, const char *interface,
> +						const char *ip,
> +						void *data)
> +{
> +}
> +
> +static void stk_open_channel(struct ofono_stk *stk)
> +{
> +	const struct stk_command_open_channel *oc;
> +	struct stk_response rsp;
> +	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
> +	int err;
> +
> +	if (stk->pending_cmd == NULL ||
> +			stk->pending_cmd->type != STK_COMMAND_TYPE_OPEN_CHANNEL)
> +		return;

Why do you feel the need to check this? If the command is canceled, then
this function should never be called, right?

> +
> +	oc = &stk->pending_cmd->open_channel;
> +
> +	memset(&rsp, 0, sizeof(rsp));
> +	rsp.result.type = STK_RESULT_TYPE_SUCCESS;
> +
> +	if (oc->data_dest_addr.type == STK_ADDRESS_IPV6) {
> +		/*
> +		 * For now, only the bearer type "GPRS / UTRAN packet service /
> +		 * E-UTRAN" is supported.
> +		 * For such bearer, according 3GPP TS 31.111, the packet data
> +		 * protocol type is IP, so only IPv4 addresses are considered.
> +		 */
> +		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +		goto out;
> +	}
> +
> +	stk->channel.id = DEFAULT_CHANNEL_ID;
> +	stk->tx_avail = oc->buf_size;
> +
> +	memset(&stk->context, 0, sizeof(stk->context));
> +	stk->context.proto = OFONO_GPRS_PROTO_IP;
> +
> +	if (oc->apn) {
> +		if (strlen(oc->apn) > OFONO_GPRS_MAX_APN_LENGTH) {
> +			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +			goto out;
> +		}

doc/coding-style.txt item M1

> +		strcpy(stk->context.apn, oc->apn);
> +	}
> +
> +	if (oc->text_usr) {
> +		if (strlen(oc->text_usr) > OFONO_GPRS_MAX_APN_LENGTH) {
> +			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +			goto out;
> +		}

doc/coding-style.txt item M1

> +		strcpy(stk->context.username, oc->text_usr);
> +	}
> +
> +	if (oc->text_passwd) {
> +		if (strlen(oc->text_passwd) > OFONO_GPRS_MAX_APN_LENGTH) {
> +			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +			goto out;
> +		}

doc/coding-style.txt item M1

> +		strcpy(stk->context.password, oc->text_passwd);
> +	}
> +
> +	memcpy(&stk->bearer_desc, &oc->bearer_desc,
> +					sizeof(struct stk_bearer_description));
> +	stk->protocol = oc->uti.protocol;
> +	stk->link_on_demand = (stk->pending_cmd->qualifier &
> +				STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
> +
> +	if (stk->link_on_demand) {
> +		rsp.open_channel.channel.id = stk->channel.id;
> +		rsp.open_channel.channel.status =
> +				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
> +		rsp.open_channel.buf_size = oc->buf_size;
> +		goto out;
> +	}
> +
> +	err = __ofono_gprs_activate_context(stk->gprs, &stk->context,
> +					ofono_stk_activate_context_cb, stk);
> +
> +	if (err == -EBUSY) {
> +		rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
> +		goto out;
> +	} else if (err < 0) {
> +		rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +		goto out;
> +	}
> +
> +	/* In background mode, send the terminal response now */
> +	if (stk->pending_cmd->qualifier & STK_OPEN_CHANNEL_FLAG_BACKGROUND) {
> +		rsp.open_channel.channel.id = stk->channel.id;
> +		rsp.open_channel.channel.status =
> +				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
> +		rsp.open_channel.buf_size = oc->buf_size;
> +		goto out;
> +	}
> +
> +	/* wait for the PDP context activation to send the Terminal Response */
> +	return;
> +
> +out:
> +	if (stk_respond(stk, &rsp, stk_command_cb))
> +		stk_command_cb(&failure, stk);
> +
> +}
> +
> +

Why two empty lines?

>  static int duration_to_msecs(const struct stk_duration *duration)
>  {
>  	int msecs = duration->interval;
> @@ -2601,6 +2722,101 @@ static gboolean handle_command_launch_browser(const struct stk_command *cmd,
>  	return FALSE;
>  }
>  
> +static void confirm_open_channel_cb(enum stk_agent_result result,
> +					gboolean confirm,
> +					void *user_data)
> +{
> +	struct ofono_stk *stk = user_data;
> +
> +	switch (result) {
> +	case STK_AGENT_RESULT_TIMEOUT:
> +		confirm = FALSE;
> +		/* Fall through */
> +
> +	case STK_AGENT_RESULT_OK:
> +		if (confirm)
> +			break;
> +
> +		send_simple_response(stk, STK_RESULT_TYPE_USER_REJECT);
> +		return;
> +
> +	case STK_AGENT_RESULT_TERMINATE:
> +	default:
> +		send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
> +		return;
> +	}
> +
> +	stk_open_channel(stk);
> +}
> +
> +static gboolean handle_command_open_channel(const struct stk_command *cmd,
> +						struct stk_response *rsp,
> +						struct ofono_stk *stk)
> +{
> +	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
> +	const struct stk_command_open_channel *oc = &cmd->open_channel;
> +	struct ofono_atom *gprs_atom;
> +	int err;
> +
> +	/* Check first if channel is available */
> +	if (stk->channel.id) {
> +		unsigned char addnl_info[1];
> +
> +		addnl_info[0] = STK_RESULT_ADDNL_BIP_PB_NO_CHANNEL_AVAIL;
> +		ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_BIP_ERROR,
> +				addnl_info);
> +		return TRUE;
> +	}
> +
> +	gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
> +	if (gprs_atom == NULL || !__ofono_atom_get_registered(gprs_atom)) {
> +		rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> +		return TRUE;
> +	}
> +
> +	stk->gprs = __ofono_atom_get_data(gprs_atom);

I suggest using find_modem again, and not storing this value here.  In
general I'd like to keep the ofono_stk structure members to a minimum.
If you can obtain the info (easily) elsewhere, please do so.

> +	stk->respond_on_exit = TRUE;
> +	stk->cancel_cmd = stk_request_cancel;
> +
> +	/*
> +	 * Don't ask for user confirmation if AID is a null data object
> +	 * or is not provided
> +	 */
> +	if (oc->alpha_id && oc->alpha_id[0] != '\0') {
> +		char *alpha_id;
> +
> +		alpha_id = dbus_apply_text_attributes(oc->alpha_id,
> +								&oc->text_attr);
> +		if (alpha_id == NULL) {
> +			rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
> +			return TRUE;
> +		}
> +
> +		err = stk_agent_confirm_open_channel(stk->current_agent,
> +							alpha_id,
> +							&oc->icon_id,
> +							confirm_open_channel_cb,
> +							stk, NULL,
> +							stk->timeout * 1000);
> +		g_free(alpha_id);
> +
> +		if (err < 0) {
> +			unsigned char no_cause_result[] = { 0x00 };
> +
> +			ADD_ERROR_RESULT(rsp->result,
> +						STK_RESULT_TYPE_TERMINAL_BUSY,
> +						no_cause_result);
> +			return TRUE;
> +		}
> +
> +		return FALSE;
> +	}
> +
> +	stk_open_channel(stk);
> +
> +	return FALSE;
> +}
> +
>  static void stk_proactive_command_cancel(struct ofono_stk *stk)
>  {
>  	if (stk->immediate_response)
> @@ -2794,6 +3010,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
>  							&rsp, stk);
>  		break;
>  
> +	case STK_COMMAND_TYPE_OPEN_CHANNEL:
> +		respond = handle_command_open_channel(stk->pending_cmd,
> +							&rsp, stk);
> +		break;
> +
>  	default:
>  		rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
>  		break;

Regards,
-Denis

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

* Re: [PATCH 11/11] gprs: Add API to set a 'detach'notification callback
  2011-06-28 17:16 ` [PATCH 11/11] gprs: Add API to set a 'detach'notification callback Philippe Nunes
@ 2011-06-29 22:46   ` Denis Kenzior
  0 siblings, 0 replies; 17+ messages in thread
From: Denis Kenzior @ 2011-06-29 22:46 UTC (permalink / raw)
  To: ofono

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

Hi Philippe,

On 06/28/2011 12:16 PM, Philippe Nunes wrote:
> ---
>  src/gprs.c  |   37 +++++++++++++++++++++++++++++++++++++
>  src/ofono.h |    6 ++++++
>  2 files changed, 43 insertions(+), 0 deletions(-)
> 
> diff --git a/src/gprs.c b/src/gprs.c
> index b3e6869..0166e70 100644
> --- a/src/gprs.c
> +++ b/src/gprs.c
> @@ -1495,6 +1495,28 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
>  					"Active", DBUS_TYPE_BOOLEAN, &value);
>  		}
>  
> +		for (l = g_private_contexts; l; l = l->next) {
> +			struct gprs_private_context *ctx = l->data;
> +			struct context_settings *settings =
> +						ctx->context_driver->settings;
> +
> +			pri_set_ipv4_addr(settings->interface, NULL);
> +			pri_ifupdown(settings->interface, FALSE);
> +			context_settings_free(settings);
> +
> +			DBG("Release private context cid %d", ctx->cid);
> +
> +			gprs_cid_release(gprs, ctx->cid);
> +			ctx->context_driver->inuse = FALSE;
> +
> +			if (ctx->notify)
> +				((__ofono_gprs_deactivated_on_detach_cb_t)
> +						ctx->notify)(ctx->notify_data);
> +
> +			g_private_contexts = g_slist_remove(g_private_contexts,
> +								ctx);
> +		}
> +

Doing this only here might not quite be enough.  The context can also be
deactivated due to gprs_context atom destruction or network forced detach.

>  		gprs->bearer = -1;
>  	}
>  
> @@ -3223,3 +3245,18 @@ int __ofono_gprs_deactivate_context(unsigned int id,
>  				deactivate_request_callback, private_ctx);
>  	return 0;
>  }
> +
> +int __ofono_gprs_set_deactivated_on_detach_notify(unsigned int id,
> +				__ofono_gprs_deactivated_on_detach_cb_t cb,
> +				void *data)

I'd prefer ofono_gprs_private_context_set_detached_notify

> +{
> +	struct gprs_private_context *private_ctx;
> +
> +	private_ctx = gprs_private_context_by_id(id);
> +	if (private_ctx == NULL)
> +		return -EINVAL;
> +
> +	private_ctx->notify = cb;
> +	private_ctx->notify_data = data;
> +	return 0;
> +}
> diff --git a/src/ofono.h b/src/ofono.h
> index 6b72816..a1215e8 100644
> --- a/src/ofono.h
> +++ b/src/ofono.h
> @@ -248,6 +248,8 @@ typedef void (*__ofono_gprs_activate_context_cb_t)(int error,
>  
>  typedef void (*__ofono_gprs_deactivate_context_cb_t)(int error, void *data);
>  
> +typedef void (*__ofono_gprs_deactivated_on_detach_cb_t)(void *data);
> +
>  int __ofono_gprs_deactivate_context(unsigned int id,
>  					__ofono_gprs_deactivate_context_cb_t cb,
>  					void *data);
> @@ -257,6 +259,10 @@ int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
>  				__ofono_gprs_activate_context_cb_t cb,
>  				void *data);
>  
> +int __ofono_gprs_set_deactivated_on_detach_notify(unsigned int id,
> +				__ofono_gprs_deactivated_on_detach_cb_t cb,
> +				void *data);
> +
>  #include <ofono/radio-settings.h>
>  #include <ofono/audio-settings.h>
>  #include <ofono/ctm.h>

Do we have some way of testing at least the channel open / close parts?
 Can we add this to phonesim to enable some basic sanity testing?

Regards,
-Denis

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

* Re: [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts
  2011-06-30 16:24     ` Philippe Nunes
@ 2011-06-30  6:11       ` Denis Kenzior
  0 siblings, 0 replies; 17+ messages in thread
From: Denis Kenzior @ 2011-06-30  6:11 UTC (permalink / raw)
  To: ofono

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

Hi Philippe,

>>>   static GSList *g_drivers = NULL;
>>>   static GSList *g_context_drivers = NULL;
>>> +static GSList *g_private_contexts = NULL;
>>
>> So this part is quite wrong ;)  What you have done here is to make stk
>> activated contexts shared across all gprs atoms, with potentially
>> duplicate ids.
>>
> 
> The gprs_private_contexts are linked to one specific gprs atom as for
> ofono_gprs_contexts. So, I don't understand your point.
> Also, could we think to have more than one gprs atom? In which condition?
> 

You are using a global variable, such that this list is shared across
all atoms.  Remember, oFono has multiple modem objects, each one having
a gprs atom.  The idmap for each gprs atom is independent, so your
gprs_private_context_by_id implementation will fall flat on its face as
soon as you have multiple STK enabled modems in the system ;)

> The idea of this list was to offer the possibility to active/deactivate
> a private context from any atom, not only STK. Hence, the private
> context is not specifically an STK context.
> If we consider that this is not really useful, I can handle only one
> static _gprs_private_context_ pointer.
> This way, it means also that we don't need to return a cid to the STK atom.
> 
> So, I presume, I should simplify and remove this list?
> 

This thought did come across my mind when I reviewed this patch.
Honestly I don't ever see a case where we would need to activate a
context outside of stk.  And I don't think stk is ever going to activate
multiple contexts...

Certainly this simplification will make the API and implementation a bit
cleaner without having any negative impact.

Regards,
-Denis

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

* Re: [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts
  2011-06-29 22:22   ` Denis Kenzior
@ 2011-06-30 16:24     ` Philippe Nunes
  2011-06-30  6:11       ` Denis Kenzior
  0 siblings, 1 reply; 17+ messages in thread
From: Philippe Nunes @ 2011-06-30 16:24 UTC (permalink / raw)
  To: ofono

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

On 06/30/2011 12:22 AM, Denis Kenzior wrote:
> Hi Philippe,
>
> On 06/28/2011 12:16 PM, Philippe Nunes wrote:
>> ---
>>   src/gprs.c  |  211 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   src/ofono.h |   17 +++++
>>   2 files changed, 228 insertions(+), 0 deletions(-)
>>
>> diff --git a/src/gprs.c b/src/gprs.c
>> index acbfa56..b3e6869 100644
>> --- a/src/gprs.c
>> +++ b/src/gprs.c
>> @@ -59,6 +59,7 @@
>>
>>   static GSList *g_drivers = NULL;
>>   static GSList *g_context_drivers = NULL;
>> +static GSList *g_private_contexts = NULL;
>
> So this part is quite wrong ;)  What you have done here is to make stk
> activated contexts shared across all gprs atoms, with potentially
> duplicate ids.
>

The gprs_private_contexts are linked to one specific gprs atom as for 
ofono_gprs_contexts. So, I don't understand your point.
Also, could we think to have more than one gprs atom? In which condition?

The idea of this list was to offer the possibility to active/deactivate 
a private context from any atom, not only STK. Hence, the private 
context is not specifically an STK context.
If we consider that this is not really useful, I can handle only one 
static _gprs_private_context_ pointer.
This way, it means also that we don't need to return a cid to the STK atom.

So, I presume, I should simplify and remove this list?

Regards,

Philippe.


>>
>>   /* 27.007 Section 7.29 */
>>   enum packet_bearer {
>> @@ -149,6 +150,13 @@ struct pri_context {
>>   	struct ofono_gprs *gprs;
>>   };
>>
>> +struct gprs_private_context {
>> +	unsigned int cid;
>> +	struct ofono_gprs_context *context_driver;
>> +	void *notify;
>
> I suggest you use a union so as to avoid casting all over the place.
>
> e.g.
>
> union {
> 	activate_cb act;
> 	deactivate_cb deact;
> };
>
> or something
>
>> +	void *notify_data;
>> +};
>> +
>>   static void gprs_netreg_update(struct ofono_gprs *gprs);
>>   static void gprs_deactivate_next(struct ofono_gprs *gprs);
>>
>> @@ -346,6 +354,20 @@ static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
>>   	return NULL;
>>   }
>>
>> +static struct pri_context *gprs_get_default_context(struct ofono_gprs *gprs)
>> +{
>> +	GSList *l;
>> +
>> +	for (l = gprs->contexts; l; l = l->next) {
>> +		struct pri_context *ctx = l->data;
>> +
>> +		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_INTERNET)
>> +			return ctx;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>>   static void context_settings_free(struct context_settings *settings)
>>   {
>>   	if (settings->ipv4) {
>> @@ -872,6 +894,8 @@ static void pri_activate_callback(const struct ofono_error *error, void *data)
>>   				dbus_message_new_method_return(ctx->pending));
>>
>>   	if (gc->settings->interface != NULL) {
>> +		DBG("Interface %s", gc->settings->interface);
>> +
>>   		pri_ifupdown(gc->settings->interface, TRUE);
>>
>>   		if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS&&
>> @@ -3012,3 +3036,190 @@ void *ofono_gprs_get_data(struct ofono_gprs *gprs)
>>   {
>>   	return gprs->driver_data;
>>   }
>> +
>> +static struct gprs_private_context *gprs_private_context_by_id(unsigned int id)
>> +{
>> +	GSList *l;
>> +
>> +	for (l = g_private_contexts; l; l = l->next) {
>> +		struct gprs_private_context *ctx = l->data;
>> +
>> +		if (ctx->cid == id)
>> +			return ctx;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +
>> +static void activate_request_callback(const struct ofono_error *error,
>> +					void *data)
>> +{
>> +	struct gprs_private_context *ctx = data;
>> +	struct context_settings *settings = ctx->context_driver->settings;
>> +
>> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
>> +		DBG("Activating context failed with error: %s",
>> +				telephony_error_to_str(error));
>> +		context_settings_free(settings);
>> +		gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
>> +		ctx->context_driver->inuse = FALSE;
>> +
>> +		if (ctx->notify)
>> +			((__ofono_gprs_activate_context_cb_t) ctx->notify)
>> +				(-ENOSYS, NULL, NULL, ctx->notify_data);
>> +
>> +		g_private_contexts = g_slist_remove(g_private_contexts, ctx);
>> +		return;
>> +	}
>> +
>> +	if (settings->interface != NULL) {
>> +		pri_ifupdown(settings->interface, TRUE);
>> +
>> +		if (settings->ipv4)
>> +			pri_set_ipv4_addr(settings->interface,
>> +							settings->ipv4->ip);
>> +	}
>> +
>> +	if (ctx->notify&&  settings->ipv4)
>> +		((__ofono_gprs_activate_context_cb_t) ctx->notify)
>> +					(0, settings->interface,
>> +						settings->ipv4->ip,
>> +						ctx->notify_data);
>> +}
>> +
>> +int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
>> +				struct ofono_gprs_primary_context *context,
>> +				__ofono_gprs_activate_context_cb_t cb,
>> +				void *data)
>> +{
>> +	struct gprs_private_context *private_ctx;
>> +	struct pri_context *default_ctx = NULL;
>> +	struct ofono_gprs_context *gc = NULL;
>> +	struct idmap *cidmap = gprs->cid_map;
>> +	GSList *l;
>> +
>> +	if (context->apn[0] == '\0' || (context->username[0] == '\0'&&
>> +			context->password[0] == '\0')) {
>> +		/* take the default primary internet context */
>> +		default_ctx = gprs_get_default_context(gprs);
>> +
>> +		if (default_ctx == NULL&&  context->apn[0] == '\0')
>> +			return -ENOENT;
>> +	}
>> +
>> +	if (context->apn[0] != '\0'&&  is_valid_apn(context->apn) == FALSE)
>> +		return EINVAL;
>> +
>> +	if (context->proto != OFONO_GPRS_PROTO_IPV4V6&&
>> +			context->proto != OFONO_GPRS_PROTO_IP)
>> +		return -ENOSYS;
>> +
>> +	if (cidmap == NULL)
>> +		return -ENOSYS;
>> +
>> +	if (context->apn[0] == '\0') {
>> +		strcpy(context->apn, default_ctx->context.apn);
>> +		strcpy(context->username, default_ctx->context.username);
>> +		strcpy(context->password, default_ctx->context.password);
>> +	}
>> +
>> +	private_ctx = g_try_new0(struct gprs_private_context, 1);
>> +	if (private_ctx == NULL)
>> +		return -ENOMEM;
>> +
>> +	private_ctx->cid = gprs_cid_alloc(gprs);
>> +	if (private_ctx->cid == 0) {
>> +		g_free(private_ctx);
>> +		return -EBUSY;
>> +	}
>> +
>> +	context->cid = private_ctx->cid;
>> +
>> +	for (l = gprs->context_drivers; l; l = l->next) {
>> +		gc = l->data;
>> +
>> +		if (gc->inuse == TRUE)
>> +			continue;
>> +
>> +		if (gc->driver == NULL)
>> +			continue;
>> +
>> +		if (gc->driver->activate_primary == NULL ||
>> +				gc->driver->deactivate_primary == NULL)
>> +			continue;
>> +
>> +		if (gc->type != OFONO_GPRS_CONTEXT_TYPE_ANY&&
>> +				gc->type != OFONO_GPRS_CONTEXT_TYPE_INTERNET)
>> +			continue;
>> +
>> +		break;
>> +	}
>> +
>> +	if (gc == NULL) {
>> +		g_free(private_ctx);
>> +		return -EBUSY;
>> +	}
>> +
>> +	gc->inuse = TRUE;
>> +	gc->settings->ipv4 = g_new0(struct ipv4_settings, 1);
>> +	private_ctx->context_driver = gc;
>> +	private_ctx->notify = cb;
>> +	private_ctx->notify_data = data;
>> +
>> +	g_private_contexts = g_slist_append(g_private_contexts, private_ctx);
>> +
>> +	gc->driver->activate_primary(gc, context, activate_request_callback,
>> +					private_ctx);
>> +	return 0;
>> +}
>> +
>> +static void deactivate_request_callback(const struct ofono_error *error,
>> +					void *data)
>> +{
>> +	struct gprs_private_context *ctx = data;
>> +	struct context_settings *settings = ctx->context_driver->settings;
>> +	int err = 0;
>> +
>> +	if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
>> +		DBG("Deactivating context failed with error: %s",
>> +				telephony_error_to_str(error));
>> +		err = -ENOSYS;
>> +	}
>> +
>> +	pri_set_ipv4_addr(settings->interface, NULL);
>> +	pri_ifupdown(settings->interface, FALSE);
>> +	context_settings_free(settings);
>> +
>> +	DBG("Release Context cid %d", ctx->cid);
>> +
>> +	gprs_cid_release(ctx->context_driver->gprs, ctx->cid);
>> +	ctx->context_driver->inuse = FALSE;
>> +
>> +	if (ctx->notify)
>> +		((__ofono_gprs_deactivate_context_cb_t) ctx->notify)
>> +				(err, ctx->notify_data);
>> +
>> +	g_private_contexts = g_slist_remove(g_private_contexts, ctx);
>> +}
>> +
>> +int __ofono_gprs_deactivate_context(unsigned int id,
>> +					__ofono_gprs_deactivate_context_cb_t cb,
>> +					void *data)
>> +{
>> +	struct gprs_private_context *private_ctx;
>> +	struct ofono_gprs_context *gc;
>> +
>> +	DBG("Deactivate context with cid %d", id);
>> +
>> +	private_ctx = gprs_private_context_by_id(id);
>> +	if (private_ctx == NULL)
>> +		return -EINVAL;
>> +
>> +	private_ctx->notify = cb;
>> +	private_ctx->notify_data = data;
>> +
>> +	gc = private_ctx->context_driver;
>> +	gc->driver->deactivate_primary(gc, private_ctx->cid,
>> +				deactivate_request_callback, private_ctx);
>> +	return 0;
>> +}
>> diff --git a/src/ofono.h b/src/ofono.h
>> index 6524806..6b72816 100644
>> --- a/src/ofono.h
>> +++ b/src/ofono.h
>> @@ -240,6 +240,23 @@ gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs);
>>   #include<ofono/phonebook.h>
>>   #include<ofono/gprs.h>
>>   #include<ofono/gprs-context.h>
>> +
>> +typedef void (*__ofono_gprs_activate_context_cb_t)(int error,
>> +						const char *interface,
>> +						const char *ip,
>> +						void *data);
>> +
>> +typedef void (*__ofono_gprs_deactivate_context_cb_t)(int error, void *data);
>> +
>> +int __ofono_gprs_deactivate_context(unsigned int id,
>> +					__ofono_gprs_deactivate_context_cb_t cb,
>> +					void *data);
>> +
>> +int __ofono_gprs_activate_context(struct ofono_gprs *gprs,
>> +				struct ofono_gprs_primary_context *context,
>> +				__ofono_gprs_activate_context_cb_t cb,
>> +				void *data);
>> +
>>   #include<ofono/radio-settings.h>
>>   #include<ofono/audio-settings.h>
>>   #include<ofono/ctm.h>
>
> Regards,
> -Denis
>


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

end of thread, other threads:[~2011-06-30 16:24 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-28 17:16 [PATCH 00/11] Add BIP command support Philippe Nunes
2011-06-28 17:16 ` [PATCH 01/11] gprs: Add private APIs to activate/deactivate private contexts Philippe Nunes
2011-06-29 22:22   ` Denis Kenzior
2011-06-30 16:24     ` Philippe Nunes
2011-06-30  6:11       ` Denis Kenzior
2011-06-28 17:16 ` [PATCH 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
2011-06-29 22:38   ` Denis Kenzior
2011-06-28 17:16 ` [PATCH 03/11] stk: Add support for the proactive command 'Get channel status' Philippe Nunes
2011-06-28 17:16 ` [PATCH 04/11] stk: Add support for the proactive command 'Close channel' Philippe Nunes
2011-06-28 17:16 ` [PATCH 05/11] stk: Add 'ofono_stk_activate_cb' definition Philippe Nunes
2011-06-28 17:16 ` [PATCH 06/11] stk: Add 'ofono_stk_deactivate_context_cb' definition Philippe Nunes
2011-06-28 17:16 ` [PATCH 07/11] stk: Add support for the proactive command 'Receive data' Philippe Nunes
2011-06-28 17:16 ` [PATCH 08/11] stk: Add support for the proactive command 'Send data' Philippe Nunes
2011-06-28 17:16 ` [PATCH 09/11] stk: Add support of the Setup event list proactive command Philippe Nunes
2011-06-28 17:16 ` [PATCH 10/11] stk: Add host route to route the traffic through the stk interface Philippe Nunes
2011-06-28 17:16 ` [PATCH 11/11] gprs: Add API to set a 'detach'notification callback Philippe Nunes
2011-06-29 22:46   ` 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.