* [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.