Open Source Telephony
 help / color / mirror / Atom feed
* [PATCH v2 00/11] Add BIP commands support
@ 2011-07-04 16:06 Philippe Nunes
  2011-07-04 16:06 ` [PATCH v2 01/11] gprs: Add private APIs to activate/deactivate a private context for STK Philippe Nunes
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Philippe Nunes @ 2011-07-04 16:06 UTC (permalink / raw)
  To: ofono

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

 - Remove the list of private context as we don't expect to activate multiple contexts from STK  or to activate a context outside of STK.
 - Replace the context id argument in the GPRS private APIs by the GPRS atom data. This way, the global variable used to store the STK private context is checked against the solicited GPRS atom.
 It prevents concurrent access if we have multiple STK enabled modems in the system.
 - Introduce an anonymous structure in ofono_stk structure to group all the BIP parameters
 - Release the STK context when the associated GPRS context is unregistered or when the STK context is deactivated after a network forced detach.  

Philippe Nunes (11):
  gprs: Add private APIs to activate/deactivate a private context for
    STK
  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  |  256 +++++++++++++++++
 src/ofono.h |   23 ++
 src/stk.c   |  920 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1199 insertions(+), 0 deletions(-)


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

* [PATCH v2 01/11] gprs: Add private APIs to activate/deactivate a private context for STK
  2011-07-04 16:06 [PATCH v2 00/11] Add BIP commands support Philippe Nunes
@ 2011-07-04 16:06 ` Philippe Nunes
  2011-07-04 16:06 ` [PATCH v2 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Philippe Nunes @ 2011-07-04 16:06 UTC (permalink / raw)
  To: ofono

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

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

diff --git a/src/gprs.c b/src/gprs.c
index acbfa56..f6090ba 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -149,6 +149,19 @@ struct pri_context {
 	struct ofono_gprs *gprs;
 };
 
+struct gprs_private_context {
+	unsigned int cid;
+	struct ofono_gprs_context *context_driver;
+	union {
+		__ofono_gprs_private_context_activate_cb_t act;
+		__ofono_gprs_private_context_deactivate_cb_t deact;
+	};
+	void *cb_data;
+};
+
+static struct gprs_private_context *stk_context = NULL;
+
+static void gprs_private_context_release(struct gprs_private_context *ctx);
 static void gprs_netreg_update(struct ofono_gprs *gprs);
 static void gprs_deactivate_next(struct ofono_gprs *gprs);
 
@@ -346,6 +359,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 +899,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 &&
@@ -1471,6 +1500,12 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
 					"Active", DBUS_TYPE_BOOLEAN, &value);
 		}
 
+		if (stk_context) {
+			gprs_private_context_release(stk_context);
+			g_free(stk_context);
+			stk_context = NULL;
+		}
+
 		gprs->bearer = -1;
 	}
 
@@ -2173,6 +2208,12 @@ static void gprs_context_unregister(struct ofono_atom *atom)
 					"Active", DBUS_TYPE_BOOLEAN, &value);
 	}
 
+	if (stk_context && stk_context->context_driver == gc) {
+		gprs_private_context_release(stk_context);
+		g_free(stk_context);
+		stk_context = NULL;
+	}
+
 	gc->gprs->context_drivers = g_slist_remove(gc->gprs->context_drivers,
 							gc);
 	gc->gprs = NULL;
@@ -2243,6 +2284,12 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
 					OFONO_CONNECTION_CONTEXT_INTERFACE,
 					"Active", DBUS_TYPE_BOOLEAN, &value);
 	}
+
+	if (stk_context && stk_context->context_driver == gc) {
+		gprs_private_context_release(stk_context);
+		g_free(stk_context);
+		stk_context = NULL;
+	}
 }
 
 int ofono_gprs_context_driver_register(const struct ofono_gprs_context_driver *d)
@@ -3012,3 +3059,184 @@ void *ofono_gprs_get_data(struct ofono_gprs *gprs)
 {
 	return gprs->driver_data;
 }
+
+static void gprs_private_context_release(struct gprs_private_context *ctx)
+{
+	struct context_settings *settings = ctx->context_driver->settings;
+
+	if (settings->interface != NULL) {
+		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(ctx->context_driver->gprs, ctx->cid);
+	ctx->context_driver->inuse = FALSE;
+}
+
+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));
+		gprs_private_context_release(ctx);
+
+		if (ctx->act)
+			ctx->act(-ENOSYS, NULL, NULL, ctx->cb_data);
+
+		g_free(ctx);
+		stk_context = NULL;
+		return;
+	}
+
+	if (settings->interface != NULL) {
+		pri_ifupdown(settings->interface, TRUE);
+
+		if (settings->ipv4)
+			pri_set_ipv4_addr(settings->interface,
+							settings->ipv4->ip);
+	}
+
+	if (ctx->act && settings->ipv4)
+		ctx->act(0, settings->interface, settings->ipv4->ip,
+				ctx->cb_data);
+}
+
+int __ofono_gprs_private_context_activate(struct ofono_gprs *gprs,
+				struct ofono_gprs_primary_context *context,
+				__ofono_gprs_private_context_activate_cb_t cb,
+				void *data)
+{
+	struct pri_context *default_ctx = NULL;
+	struct ofono_gprs_context *gc = NULL;
+	struct idmap *cidmap = gprs->cid_map;
+	GSList *l;
+
+	if (stk_context)
+		return -EBUSY;
+
+	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);
+	}
+
+	stk_context = g_try_new0(struct gprs_private_context, 1);
+	if (stk_context == NULL)
+		return -ENOMEM;
+
+	stk_context->cid = gprs_cid_alloc(gprs);
+	if (stk_context->cid == 0) {
+		g_free(stk_context);
+		stk_context = NULL;
+		return -EBUSY;
+	}
+
+	context->cid = stk_context->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(stk_context);
+		stk_context = NULL;
+		return -EBUSY;
+	}
+
+	gc->inuse = TRUE;
+	gc->settings->ipv4 = g_new0(struct ipv4_settings, 1);
+	stk_context->context_driver = gc;
+	stk_context->act = cb;
+	stk_context->cb_data = data;
+
+	gc->driver->activate_primary(gc, context, activate_request_callback,
+					stk_context);
+	return 0;
+}
+
+static void deactivate_request_callback(const struct ofono_error *error,
+					void *data)
+{
+	struct gprs_private_context *ctx = data;
+	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;
+	}
+
+	gprs_private_context_release(ctx);
+
+	if (ctx->deact)
+		ctx->deact(err, ctx->cb_data);
+
+	g_free(ctx);
+	stk_context = NULL;
+}
+
+int __ofono_gprs_private_context_deactivate(struct ofono_gprs *gprs,
+				__ofono_gprs_private_context_deactivate_cb_t cb,
+				void *data)
+{
+	struct ofono_gprs_context *gc;
+
+	if (stk_context == NULL)
+		return -ENOENT;
+
+	if (stk_context->context_driver->gprs != gprs)
+		return -EINVAL;
+
+	DBG("Deactivate context with cid %d", stk_context->cid);
+
+	stk_context->deact = cb;
+	stk_context->cb_data = data;
+
+	gc = stk_context->context_driver;
+	gc->driver->deactivate_primary(gc, stk_context->cid,
+				deactivate_request_callback, stk_context);
+	return 0;
+}
diff --git a/src/ofono.h b/src/ofono.h
index 6524806..274912d 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -240,6 +240,24 @@ 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_private_context_deactivate_cb_t)(int error,
+								void *data);
+
+typedef void (*__ofono_gprs_private_context_activate_cb_t)(int error,
+						const char *interface,
+						const char *ip,
+						void *data);
+
+int __ofono_gprs_private_context_deactivate(struct ofono_gprs *gprs,
+				__ofono_gprs_private_context_deactivate_cb_t cb,
+				void *data);
+
+int __ofono_gprs_private_context_activate(struct ofono_gprs *gprs,
+				struct ofono_gprs_primary_context *context,
+				__ofono_gprs_private_context_activate_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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 9575f0e..cbbab4a 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,15 @@ struct ofono_stk {
 
 	__ofono_sms_sim_download_cb_t sms_pp_cb;
 	void *sms_pp_userdata;
+	struct {
+		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;
+	} bip;
 };
 
 struct envelope_op {
@@ -104,6 +114,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 +548,122 @@ 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 ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	struct ofono_atom *gprs_atom;
+	struct stk_response rsp;
+	struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+	int err;
+
+	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->bip.channel.id = DEFAULT_CHANNEL_ID;
+	stk->bip.tx_avail = oc->buf_size;
+
+	memset(&stk->bip.context, 0, sizeof(stk->bip.context));
+	stk->bip.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->bip.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->bip.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->bip.context.password, oc->text_passwd);
+	}
+
+	memcpy(&stk->bip.bearer_desc, &oc->bearer_desc,
+					sizeof(struct stk_bearer_description));
+	stk->bip.protocol = oc->uti.protocol;
+	stk->bip.link_on_demand = (stk->pending_cmd->qualifier &
+				STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
+
+	if (stk->bip.link_on_demand) {
+		rsp.open_channel.channel.id = stk->bip.channel.id;
+		rsp.open_channel.channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+		rsp.open_channel.buf_size = oc->buf_size;
+		goto out;
+	}
+
+	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;
+		goto out;
+	}
+
+	err = __ofono_gprs_private_context_activate(
+					__ofono_atom_get_data(gprs_atom),
+					&stk->bip.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->bip.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 +2733,100 @@ 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->bip.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->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 +3020,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index cbbab4a..64ef91a 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -2827,6 +2827,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->bip.channel.id;
+	rsp->channel_status.channel.status = stk->bip.channel.status;
+	return TRUE;
+}
+
 static void stk_proactive_command_cancel(struct ofono_stk *stk)
 {
 	if (stk->immediate_response)
@@ -3025,6 +3035,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 64ef91a..8d4f7c0 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -504,6 +504,37 @@ 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;
+	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+	struct ofono_atom *gprs_atom;
+
+	gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+	if (gprs_atom == NULL || !__ofono_atom_get_registered(gprs_atom))
+		goto out;
+
+	err = __ofono_gprs_private_context_deactivate(
+					__ofono_atom_get_data(gprs_atom),
+					ofono_stk_deactivate_context_cb,
+					stk);
+
+	if (err == 0)
+		return;
+
+out:
+	stk->bip.channel.id = 0;
+	stk->bip.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;
@@ -518,6 +549,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->bip.channel.id)
+		stk_close_channel(stk);
 }
 
 static void stk_alpha_id_set(struct ofono_stk *stk,
@@ -662,6 +696,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);
 }
 
 static int duration_to_msecs(const struct stk_duration *duration)
@@ -2827,6 +2863,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->bip.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)
@@ -3035,6 +3103,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 8d4f7c0..1e4d237 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>
@@ -88,6 +91,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;
 	} bip;
 };
 
@@ -582,10 +588,152 @@ 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->bip.channel.status =
+				STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
+	}
+
+	if (stk->bip.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->bip.dest_addr,
+						sizeof(stk->bip.dest_addr));
+
+		if (error < 0) {
+			close(sk);
+			rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+			goto out;
+		}
+	} else if (stk->bip.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->bip.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->bip.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->bip.channel.id;
+		rsp.open_channel.channel.status = stk->bip.channel.status;
+		rsp.open_channel.buf_size = stk->bip.tx_avail;
+		memcpy(&rsp.open_channel.bearer_desc, &stk->bip.bearer_desc,
+				sizeof(struct stk_bearer_description));
+	} else if (stk->pending_cmd->type == STK_COMMAND_TYPE_SEND_DATA &&
+			stk->bip.link_on_demand) {
+		/* TODO send data */
+		rsp.send_data.tx_avail = stk->bip.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)
@@ -611,6 +759,12 @@ 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->bip.dest_addr, 0, sizeof(stk->bip.dest_addr));
+		stk->bip.dest_addr.sin_family = AF_INET;
+		stk->bip.dest_addr.sin_port = htons(oc->uti.port);
+		stk->bip.dest_addr.sin_addr.s_addr
+						= oc->data_dest_addr.addr.ipv4;
 	}
 
 	stk->bip.channel.id = DEFAULT_CHANNEL_ID;
-- 
1.7.1


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

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 1e4d237..58fdbdf 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -512,6 +512,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->bip.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->bip.channel.id = 0;
 }
 
 static void stk_close_channel(struct ofono_stk *stk)
-- 
1.7.1


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

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 58fdbdf..612eafb 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>
@@ -86,6 +87,7 @@ struct ofono_stk {
 	struct {
 		struct stk_channel channel;
 		struct ofono_gprs_primary_context context;
+		gsize rx_remaining;
 		gsize tx_avail;
 		gboolean link_on_demand;
 		struct ofono_gprs *gprs;
@@ -126,6 +128,13 @@ 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)
 {
@@ -538,6 +547,11 @@ static void stk_close_channel(struct ofono_stk *stk)
 	struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
 	struct ofono_atom *gprs_atom;
 
+	if (stk->bip.read_watch > 0)
+		g_source_remove(stk->bip.read_watch);
+	else if (stk->bip.io)
+		g_io_channel_unref(stk->bip.io);
+
 	gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
 	if (gprs_atom == NULL || !__ofono_atom_get_registered(gprs_atom))
 		goto out;
@@ -609,6 +623,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->bip.rx_remaining = len;
+
+		/* Disable the read watch until the SIM requests all bytes */
+		g_io_channel_ref(channel);
+		g_source_remove(stk->bip.read_watch);
+		stk->bip.read_watch = 0;
+	}
 	return TRUE;
 }
 
@@ -787,6 +826,7 @@ static void stk_open_channel(struct ofono_stk *stk)
 
 	stk->bip.channel.id = DEFAULT_CHANNEL_ID;
 	stk->bip.tx_avail = oc->buf_size;
+	stk->bip.io = NULL;
 
 	memset(&stk->bip.context, 0, sizeof(stk->bip.context));
 	stk->bip.context.proto = OFONO_GPRS_PROTO_IP;
@@ -872,6 +912,62 @@ 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->bip.io);
+	ioctl(fd, FIONREAD, &stk->bip.rx_remaining);
+	DBG("%zd bytes to read", stk->bip.rx_remaining);
+
+	if (stk->bip.rx_remaining == 0) {
+		rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+		goto out;
+	}
+
+	if (toread > stk->bip.rx_remaining) {
+		rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+		toread = stk->bip.rx_remaining;
+	}
+
+	if (toread > CHANNEL_DATA_OBJECT_MAX_LENGTH)
+		toread = CHANNEL_DATA_OBJECT_MAX_LENGTH;
+
+	status = g_io_channel_read_chars(stk->bip.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->bip.rx_remaining -= bytes_read;
+	rsp.receive_data.rx_remaining = stk->bip.rx_remaining;
+
+	if (stk->bip.rx_remaining == 0) {
+		stk->bip.read_watch = g_io_add_watch_full(stk->bip.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->bip.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)
 {
 	int msecs = duration->interval;
@@ -3067,6 +3163,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->bip.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)
@@ -3280,6 +3408,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 612eafb..1e5869a 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -620,6 +620,43 @@ 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->bip.protocol == STK_TRANSPORT_PROTOCOL_UDP_CLIENT_REMOTE) {
+		if (package == TRUE)
+			flags = MSG_MORE;
+
+		bytes_written = sendto(g_io_channel_unix_get_fd(stk->bip.io),
+					data, len, flags,
+					(struct sockaddr *) &stk->bip.dest_addr,
+					sizeof(stk->bip.dest_addr));
+
+		if (bytes_written == -1 && stk->bip.read_watch > 0) {
+			g_source_remove(stk->bip.read_watch);
+			return 0;
+		}
+	} else {
+		status = g_io_channel_write_chars(stk->bip.io, (gchar *)data,
+					len, (gsize *) &bytes_written, NULL);
+
+		if (status != G_IO_STATUS_NORMAL && stk->bip.read_watch > 0) {
+			g_source_remove(stk->bip.read_watch);
+			return 0;
+		}
+	}
+
+	DBG("Send %zd bytes", bytes_written);
+
+	stk->bip.tx_avail += bytes_written;
+
+	return bytes_written;
+}
+
 static gboolean receive_callback(GIOChannel *channel, GIOCondition cond,
 				gpointer userdata)
 {
@@ -778,7 +815,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->bip.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->bip.tx_avail;
 	} else {
 		/* TODO send channel status event */
@@ -912,6 +959,70 @@ 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->bip.tx_avail) {
+		rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+		goto out;
+	}
+
+	if (stk->bip.channel.status ==
+			STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED &&
+			stk->bip.link_on_demand == TRUE) {
+		int err;
+		struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+		struct ofono_atom *gprs_atom;
+
+		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;
+			goto out;
+		}
+
+		err = __ofono_gprs_private_context_activate(
+					__ofono_atom_get_data(gprs_atom),
+					&stk->bip.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->bip.tx_avail -= data.len;
+		rsp.send_data.tx_avail = stk->bip.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;
@@ -3195,6 +3306,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->bip.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->bip.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)
@@ -3413,6 +3563,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 1e5869a..4c81bf8 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -90,6 +90,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;
@@ -519,6 +521,61 @@ 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->bip.channel.id;
+	e.event_download.channel_status.channel.status =
+						stk->bip.channel.status;
+
+	if (stk->bip.channel.status ==
+				STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED)
+		memcpy(&e.event_download.channel_status.bearer_desc,
+				&stk->bip.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->bip.channel.id;
+	e.event_download.data_available.channel.status =
+						stk->bip.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;
@@ -534,8 +591,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->bip.report_channel_status) {
+		/* user cancellation */
+		stk->bip.channel.status = STK_CHANNEL_LINK_DROPPED;
+		stk_send_channel_status_event(stk);
 	}
 
 	stk->bip.channel.id = 0;
@@ -672,11 +731,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->bip.rx_remaining == 0 &&
+				stk->bip.report_data_available) {
+			stk_send_data_available_event(stk, len);
+		}
 
 		stk->bip.rx_remaining = len;
 
@@ -711,7 +769,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->bip.report_channel_status)
+				stk_send_channel_status_event(stk);
 			return;
 		} else {
 			rsp.result.type = STK_RESULT_TYPE_NETWORK_UNAVAILABLE;
@@ -805,7 +864,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->bip.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->bip.channel.id;
@@ -828,7 +888,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 		}
 		rsp.send_data.tx_avail = stk->bip.tx_avail;
 	} else {
-		/* TODO send channel status event */
+		if (stk->bip.report_channel_status)
+			stk_send_channel_status_event(stk);
 		return;
 	}
 
@@ -2747,6 +2808,8 @@ static gboolean handle_command_refresh(const struct stk_command *cmd,
 		case 5:
 		case 6:
 			free_idle_mode_text(stk);
+			stk->bip.report_data_available = FALSE;
+			stk->bip.report_channel_status = FALSE;
 			__ofono_sim_refresh(sim, file_list, FALSE, TRUE);
 			break;
 		}
@@ -3355,6 +3418,38 @@ 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->bip.report_data_available = FALSE;
+	stk->bip.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->bip.report_data_available = TRUE;
+			break;
+		case STK_EVENT_TYPE_CHANNEL_STATUS:
+			DBG("Enable channel status event");
+			stk->bip.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)
@@ -3573,6 +3668,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] 12+ messages in thread

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

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

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

diff --git a/src/stk.c b/src/stk.c
index 4c81bf8..1b2ba32 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>
@@ -679,6 +680,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->bip.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)
 {
@@ -782,6 +821,8 @@ static void ofono_stk_activate_context_cb(int error, const char *interface,
 				STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
 	}
 
+	stk_add_host_route(stk, interface);
+
 	if (stk->bip.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] 12+ messages in thread

* [PATCH v2 11/11] gprs: Add API to set a 'detach'notification callback
  2011-07-04 16:06 [PATCH v2 00/11] Add BIP commands support Philippe Nunes
                   ` (9 preceding siblings ...)
  2011-07-04 16:06 ` [PATCH v2 10/11] stk: Add host route to route the traffic through the stk interface Philippe Nunes
@ 2011-07-04 16:06 ` Philippe Nunes
  10 siblings, 0 replies; 12+ messages in thread
From: Philippe Nunes @ 2011-07-04 16:06 UTC (permalink / raw)
  To: ofono

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

---
 src/gprs.c  |   28 ++++++++++++++++++++++++++++
 src/ofono.h |    5 +++++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/src/gprs.c b/src/gprs.c
index f6090ba..a8b8e7d 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -155,6 +155,7 @@ struct gprs_private_context {
 	union {
 		__ofono_gprs_private_context_activate_cb_t act;
 		__ofono_gprs_private_context_deactivate_cb_t deact;
+		__ofono_gprs_private_context_detached_cb_t detach;
 	};
 	void *cb_data;
 };
@@ -1502,6 +1503,10 @@ static void gprs_attached_update(struct ofono_gprs *gprs)
 
 		if (stk_context) {
 			gprs_private_context_release(stk_context);
+
+			if (stk_context->detach)
+				stk_context->detach(stk_context->cb_data);
+
 			g_free(stk_context);
 			stk_context = NULL;
 		}
@@ -2210,6 +2215,10 @@ static void gprs_context_unregister(struct ofono_atom *atom)
 
 	if (stk_context && stk_context->context_driver == gc) {
 		gprs_private_context_release(stk_context);
+
+		if (stk_context->detach)
+			stk_context->detach(stk_context->cb_data);
+
 		g_free(stk_context);
 		stk_context = NULL;
 	}
@@ -2287,6 +2296,10 @@ void ofono_gprs_context_deactivated(struct ofono_gprs_context *gc,
 
 	if (stk_context && stk_context->context_driver == gc) {
 		gprs_private_context_release(stk_context);
+
+		if (stk_context->detach)
+			stk_context->detach(stk_context->cb_data);
+
 		g_free(stk_context);
 		stk_context = NULL;
 	}
@@ -3240,3 +3253,18 @@ int __ofono_gprs_private_context_deactivate(struct ofono_gprs *gprs,
 				deactivate_request_callback, stk_context);
 	return 0;
 }
+
+int __ofono_gprs_private_context_set_detached_notify(struct ofono_gprs *gprs,
+				__ofono_gprs_private_context_detached_cb_t cb,
+				void *data)
+{
+	if (stk_context == NULL)
+		return -ENOENT;
+
+	if (stk_context->context_driver->gprs != gprs)
+		return -EINVAL;
+
+	stk_context->detach = cb;
+	stk_context->cb_data = data;
+	return 0;
+}
diff --git a/src/ofono.h b/src/ofono.h
index 274912d..9ea16c5 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -248,6 +248,7 @@ typedef void (*__ofono_gprs_private_context_activate_cb_t)(int error,
 						const char *interface,
 						const char *ip,
 						void *data);
+typedef void (*__ofono_gprs_private_context_detached_cb_t)(void *data);
 
 int __ofono_gprs_private_context_deactivate(struct ofono_gprs *gprs,
 				__ofono_gprs_private_context_deactivate_cb_t cb,
@@ -258,6 +259,10 @@ int __ofono_gprs_private_context_activate(struct ofono_gprs *gprs,
 				__ofono_gprs_private_context_activate_cb_t cb,
 				void *data);
 
+int __ofono_gprs_private_context_set_detached_notify(struct ofono_gprs *gprs,
+				__ofono_gprs_private_context_detached_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] 12+ messages in thread

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

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-04 16:06 [PATCH v2 00/11] Add BIP commands support Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 01/11] gprs: Add private APIs to activate/deactivate a private context for STK Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 02/11] stk: Add support for the proactive command 'Open channel' Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 03/11] stk: Add support for the proactive command 'Get channel status' Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 04/11] stk: Add support for the proactive command 'Close channel' Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 05/11] stk: Add 'ofono_stk_activate_cb' definition Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 06/11] stk: Add 'ofono_stk_deactivate_context_cb' definition Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 07/11] stk: Add support for the proactive command 'Receive data' Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 08/11] stk: Add support for the proactive command 'Send data' Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 09/11] stk: Add support of the Setup event list proactive command Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 10/11] stk: Add host route to route the traffic through the stk interface Philippe Nunes
2011-07-04 16:06 ` [PATCH v2 11/11] gprs: Add API to set a 'detach'notification callback Philippe Nunes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox