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