* [PATCH v3 2/7] stk: Introduce BIP command handlers
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
@ 2011-05-13 17:21 ` Philippe Nunes
2011-05-16 15:54 ` Andrzej Zaborowski
2011-05-13 17:22 ` [PATCH v3 3/7] gprs: Add 'stk' gprs context type Philippe Nunes
` (4 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:21 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 13679 bytes --]
---
src/stk.c | 425 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 424 insertions(+), 1 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 8214b65..dec0439 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,11 @@ struct ofono_stk {
__ofono_sms_sim_download_cb_t sms_pp_cb;
void *sms_pp_userdata;
+ struct stk_channel channel;
+ struct stk_channel_data rx_buffer;
+ struct stk_channel_data tx_buffer;
+ gboolean link_on_demand;
+ struct ofono_gprs *gprs;
};
struct envelope_op {
@@ -104,6 +110,13 @@ static void timers_update(struct ofono_stk *stk);
result.additional_len = sizeof(addn_info); \
result.additional = addn_info; \
+/*
+ * 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)
{
@@ -474,12 +487,49 @@ static void emit_menu_changed(struct ofono_stk *stk)
g_dbus_send_message(conn, signal);
}
+static void stk_close_channel(struct ofono_stk *stk)
+{
+ /*
+ * TODO
+ * Deactivate and remove PDP context
+ * Send the Terminal Response once the PDP context is deactivated
+ */
+
+ /* Temporary implementation */
+ g_free(stk->rx_buffer.data.array);
+ g_free(stk->tx_buffer.data.array);
+ stk->rx_buffer.data.array = NULL;
+ stk->tx_buffer.data.array = NULL;
+
+ 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_SUCCESS);
+ else {
+ /*
+ * TODO
+ * Send Event channel status
+ */
+ }
+}
+
static void user_termination_cb(enum stk_agent_result result, void *user_data)
{
struct ofono_stk *stk = user_data;
- if (result == STK_AGENT_RESULT_TERMINATE)
+ if (result != STK_AGENT_RESULT_TERMINATE)
+ return;
+
+ if (stk->pending_cmd) {
+ stk->cancel_cmd(stk);
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,
@@ -510,6 +560,143 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
stk_agent_request_cancel(stk->current_agent);
}
+
+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 };
+
+ 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;
+
+ stk->rx_buffer.data.array = g_try_malloc(oc->buf_size);
+ if (stk->rx_buffer.data.array == NULL) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ stk->tx_buffer.data.array = g_try_malloc(oc->buf_size);
+ if (stk->tx_buffer.data.array == NULL) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ stk->rx_buffer.data.len = oc->buf_size;
+ stk->tx_buffer.data.len = oc->buf_size;
+ stk->link_on_demand = (stk->pending_cmd->qualifier &
+ STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
+
+ /*
+ * TODO
+ * Add a new primary PDP context based on the provided settings
+ * Send the Terminal Response or wait until the PDP context is activated
+ * in case of immediate link establishment not in background.
+ */
+out:
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&failure, 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 };
+ unsigned int offset;
+
+ memset(&rsp, 0, sizeof(rsp));
+ rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+
+ if (data.len > stk->tx_buffer.data.len) {
+ rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+ goto out;
+ }
+
+ if (qualifier == STK_SEND_DATA_STORE_DATA) {
+
+ /*
+ * check if the requested number of bytes of empty space
+ * is available
+ */
+ if (data.len > stk->tx_buffer.tx_avail) {
+ rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
+ goto out;
+ }
+
+ offset = stk->tx_buffer.data.len - stk->tx_buffer.tx_avail;
+ memcpy(stk->tx_buffer.data.array + offset, data.array,
+ data.len);
+
+ stk->tx_buffer.tx_avail -= data.len;
+ rsp.send_data.tx_avail = stk->tx_buffer.tx_avail;
+ goto out;
+ }
+
+ if (stk->channel.status == STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED
+ && stk->link_on_demand == TRUE) {
+ /*
+ * TODO
+ * activate the context, update the channel status
+ * once the context is activated, send the data immediately
+ * and flush the tx buffer
+ */
+ } else {
+ /*
+ * TODO
+ * send the data immediately, flush the tx buffer
+ */
+ stk->tx_buffer.tx_avail = stk->tx_buffer.data.len;
+ rsp.send_data.tx_avail = stk->tx_buffer.data.len;
+ }
+
+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 data_len)
+{
+ 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 (stk->rx_buffer.rx_remaining == 0) {
+ rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+ goto out;
+ }
+
+ if (data_len > stk->rx_buffer.rx_remaining) {
+ rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
+ data_len = stk->rx_buffer.rx_remaining;
+ }
+
+ if (data_len > CHANNEL_DATA_OBJECT_MAX_LENGTH)
+ data_len = CHANNEL_DATA_OBJECT_MAX_LENGTH;
+
+ rsp.receive_data.rx_data.array = stk->rx_buffer.data.array;
+ rsp.receive_data.rx_data.len = data_len;
+ stk->rx_buffer.rx_remaining -= data_len;
+ rsp.receive_data.rx_remaining = stk->rx_buffer.rx_remaining;
+
+out:
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&failure, stk);
+
+ if (rsp.receive_data.rx_data.len && stk->rx_buffer.rx_remaining > 0)
+ memmove(stk->rx_buffer.data.array, stk->rx_buffer.data.array +
+ data_len, stk->rx_buffer.rx_remaining);
+}
+
static int duration_to_msecs(const struct stk_duration *duration)
{
int msecs = duration->interval;
@@ -2589,6 +2776,217 @@ static gboolean handle_command_launch_browser(const struct stk_command *cmd,
return FALSE;
}
+
+static void open_channel_cancel(struct ofono_stk *stk)
+{
+ /* TODO */
+}
+
+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_TERMINATE:
+ send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
+ return;
+
+ case STK_AGENT_RESULT_TIMEOUT:
+ confirm = FALSE;
+ /* Fall through */
+
+ case STK_AGENT_RESULT_OK:
+ if (confirm)
+ break;
+ /* Fall through */
+
+ default:
+ send_simple_response(stk, STK_RESULT_TYPE_TERMINAL_BUSY);
+ 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 = open_channel_cancel;
+
+ /*
+ * Don't ask for user confirmation if AID is a null data object
+ * or is not provided
+ */
+ if (oc->alpha_id && strlen(oc->alpha_id) > 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) {
+ rsp->result.type = STK_RESULT_TYPE_TERMINAL_BUSY;
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+ stk_open_channel(stk);
+
+ 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 && strlen(cc->alpha_id) > 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_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 && strlen(rd->alpha_id) > 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_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 && strlen(sd->alpha_id) > 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)
+{
+ 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)
@@ -2782,6 +3180,31 @@ 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;
+
+ case STK_COMMAND_TYPE_CLOSE_CHANNEL:
+ respond = handle_command_close_channel(stk->pending_cmd,
+ &rsp, stk);
+ break;
+
+ case STK_COMMAND_TYPE_RECEIVE_DATA:
+ respond = handle_command_receive_data(stk->pending_cmd,
+ &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);
+ break;
+
default:
rsp.result.type = STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD;
break;
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH v3 2/7] stk: Introduce BIP command handlers
2011-05-13 17:21 ` [PATCH v3 2/7] stk: Introduce BIP command handlers Philippe Nunes
@ 2011-05-16 15:54 ` Andrzej Zaborowski
2011-05-17 9:55 ` Philippe Nunes
0 siblings, 1 reply; 10+ messages in thread
From: Andrzej Zaborowski @ 2011-05-16 15:54 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 11112 bytes --]
Hi Philippe,
On 13 May 2011 19:21, Philippe Nunes <philippe.nunes@linux.intel.com> wrote:
> ---
> src/stk.c | 425 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 424 insertions(+), 1 deletions(-)
>
> diff --git a/src/stk.c b/src/stk.c
> index 8214b65..dec0439 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,11 @@ struct ofono_stk {
>
> __ofono_sms_sim_download_cb_t sms_pp_cb;
> void *sms_pp_userdata;
> + struct stk_channel channel;
> + struct stk_channel_data rx_buffer;
> + struct stk_channel_data tx_buffer;
> + gboolean link_on_demand;
> + struct ofono_gprs *gprs;
> };
>
> struct envelope_op {
> @@ -104,6 +110,13 @@ static void timers_update(struct ofono_stk *stk);
> result.additional_len = sizeof(addn_info); \
> result.additional = addn_info; \
>
> +/*
> + * 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)
> {
> @@ -474,12 +487,49 @@ static void emit_menu_changed(struct ofono_stk *stk)
> g_dbus_send_message(conn, signal);
> }
>
> +static void stk_close_channel(struct ofono_stk *stk)
> +{
> + /*
> + * TODO
> + * Deactivate and remove PDP context
> + * Send the Terminal Response once the PDP context is deactivated
> + */
> +
> + /* Temporary implementation */
> + g_free(stk->rx_buffer.data.array);
> + g_free(stk->tx_buffer.data.array);
> + stk->rx_buffer.data.array = NULL;
> + stk->tx_buffer.data.array = NULL;
> +
> + 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_SUCCESS);
> + else {
> + /*
> + * TODO
> + * Send Event channel status
> + */
> + }
> +}
> +
> static void user_termination_cb(enum stk_agent_result result, void *user_data)
> {
> struct ofono_stk *stk = user_data;
>
> - if (result == STK_AGENT_RESULT_TERMINATE)
> + if (result != STK_AGENT_RESULT_TERMINATE)
> + return;
> +
> + if (stk->pending_cmd) {
> + stk->cancel_cmd(stk);
> 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,
> @@ -510,6 +560,143 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
> stk_agent_request_cancel(stk->current_agent);
> }
>
> +
> +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 };
> +
> + 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;
> +
> + stk->rx_buffer.data.array = g_try_malloc(oc->buf_size);
> + if (stk->rx_buffer.data.array == NULL) {
> + rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> + goto out;
> + }
> +
> + stk->tx_buffer.data.array = g_try_malloc(oc->buf_size);
> + if (stk->tx_buffer.data.array == NULL) {
> + rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
> + goto out;
> + }
A minor nitpick: we tend to return one of the temporary error codes
when out of memory.
> +
> + stk->rx_buffer.data.len = oc->buf_size;
> + stk->tx_buffer.data.len = oc->buf_size;
> + stk->link_on_demand = (stk->pending_cmd->qualifier &
> + STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
> +
> + /*
> + * TODO
> + * Add a new primary PDP context based on the provided settings
> + * Send the Terminal Response or wait until the PDP context is activated
> + * in case of immediate link establishment not in background.
> + */
> +out:
> + if (stk_respond(stk, &rsp, stk_command_cb))
> + stk_command_cb(&failure, 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 };
> + unsigned int offset;
> +
> + memset(&rsp, 0, sizeof(rsp));
> + rsp.result.type = STK_RESULT_TYPE_SUCCESS;
> +
> + if (data.len > stk->tx_buffer.data.len) {
> + rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
> + goto out;
> + }
> +
> + if (qualifier == STK_SEND_DATA_STORE_DATA) {
> +
> + /*
> + * check if the requested number of bytes of empty space
> + * is available
> + */
> + if (data.len > stk->tx_buffer.tx_avail) {
> + rsp.result.type = STK_RESULT_TYPE_BIP_ERROR;
> + goto out;
> + }
> +
> + offset = stk->tx_buffer.data.len - stk->tx_buffer.tx_avail;
> + memcpy(stk->tx_buffer.data.array + offset, data.array,
> + data.len);
> +
> + stk->tx_buffer.tx_avail -= data.len;
> + rsp.send_data.tx_avail = stk->tx_buffer.tx_avail;
> + goto out;
> + }
> +
> + if (stk->channel.status == STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED
> + && stk->link_on_demand == TRUE) {
> + /*
> + * TODO
> + * activate the context, update the channel status
> + * once the context is activated, send the data immediately
> + * and flush the tx buffer
> + */
> + } else {
> + /*
> + * TODO
> + * send the data immediately, flush the tx buffer
> + */
> + stk->tx_buffer.tx_avail = stk->tx_buffer.data.len;
> + rsp.send_data.tx_avail = stk->tx_buffer.data.len;
> + }
> +
> +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 data_len)
> +{
> + 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 (stk->rx_buffer.rx_remaining == 0) {
> + rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
> + goto out;
> + }
> +
> + if (data_len > stk->rx_buffer.rx_remaining) {
> + rsp.result.type = STK_RESULT_TYPE_MISSING_INFO;
> + data_len = stk->rx_buffer.rx_remaining;
> + }
> +
> + if (data_len > CHANNEL_DATA_OBJECT_MAX_LENGTH)
> + data_len = CHANNEL_DATA_OBJECT_MAX_LENGTH;
> +
> + rsp.receive_data.rx_data.array = stk->rx_buffer.data.array;
> + rsp.receive_data.rx_data.len = data_len;
> + stk->rx_buffer.rx_remaining -= data_len;
> + rsp.receive_data.rx_remaining = stk->rx_buffer.rx_remaining;
> +
> +out:
> + if (stk_respond(stk, &rsp, stk_command_cb))
> + stk_command_cb(&failure, stk);
> +
> + if (rsp.receive_data.rx_data.len && stk->rx_buffer.rx_remaining > 0)
> + memmove(stk->rx_buffer.data.array, stk->rx_buffer.data.array +
> + data_len, stk->rx_buffer.rx_remaining);
> +}
> +
> static int duration_to_msecs(const struct stk_duration *duration)
> {
> int msecs = duration->interval;
> @@ -2589,6 +2776,217 @@ static gboolean handle_command_launch_browser(const struct stk_command *cmd,
> return FALSE;
> }
>
> +
> +static void open_channel_cancel(struct ofono_stk *stk)
> +{
> + /* TODO */
> +}
> +
> +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_TERMINATE:
> + send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
> + return;
> +
> + case STK_AGENT_RESULT_TIMEOUT:
> + confirm = FALSE;
> + /* Fall through */
> +
> + case STK_AGENT_RESULT_OK:
> + if (confirm)
> + break;
> + /* Fall through */
According to 6.4.27 we should return STK_RESULT_TYPE_USER_REJECT if
the user does not accept the channel setup.
> +
> + default:
> + send_simple_response(stk, STK_RESULT_TYPE_TERMINAL_BUSY);
> + return;
> + }
I think Jeevaka determined that this needs an additional info field.
Best regards
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v3 2/7] stk: Introduce BIP command handlers
2011-05-16 15:54 ` Andrzej Zaborowski
@ 2011-05-17 9:55 ` Philippe Nunes
0 siblings, 0 replies; 10+ messages in thread
From: Philippe Nunes @ 2011-05-17 9:55 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2336 bytes --]
Hi Andrew,
>> +
>> + stk->tx_buffer.data.array = g_try_malloc(oc->buf_size);
>> + if (stk->tx_buffer.data.array == NULL) {
>> + rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
>> + goto out;
>> + }
>
> A minor nitpick: we tend to return one of the temporary error codes
> when out of memory.
>
OK, I will return in this case the general result
"STK_RESULT_TYPE_TERMINAL_BUSY" with the additional info "no specific
cause".
>> +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_TERMINATE:
>> + send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
>> + return;
>> +
>> + case STK_AGENT_RESULT_TIMEOUT:
>> + confirm = FALSE;
>> + /* Fall through */
>> +
>> + case STK_AGENT_RESULT_OK:
>> + if (confirm)
>> + break;
>> + /* Fall through */
>
> According to 6.4.27 we should return STK_RESULT_TYPE_USER_REJECT if
> the user does not accept the channel setup.
>
>> +
>> + default:
>> + send_simple_response(stk, STK_RESULT_TYPE_TERMINAL_BUSY);
>> + return;
>> + }
>
> I think Jeevaka determined that this needs an additional info field.
In practice, I applied the same code than "confirm_launch_browser_cb".
But you're right, for Open channel, we should return the terminal
response "User did not accept the proactive command".
For the additional info field, I just simplified the code seen in
"confirm_launch_browser_cb" as in this case, no specific cause is given.
But your remark is true, it is mandatory to return an additional
information in case of general result "STK_RESULT_TYPE_TERMINAL_BUSY".
To clean both issues you raised and for an homogeneous behavior, I
propose to follow the code written in "confirm_call_cb".Thus, in case of
no answer, I will return STK_RESULT_TYPE_USER_TERMINATED and not
STK_RESULT_TYPE_TERMINAL_BUSY.
Thank you for your review.
Best regards,
Philippe.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 3/7] gprs: Add 'stk' gprs context type
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
2011-05-13 17:21 ` [PATCH v3 2/7] stk: Introduce BIP command handlers Philippe Nunes
@ 2011-05-13 17:22 ` Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 4/7] gprs: Add private APIs for adding/activating/removing hidden PDP contexts Philippe Nunes
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:22 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1405 bytes --]
---
include/gprs-context.h | 1 +
src/gprs.c | 7 +++++++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/include/gprs-context.h b/include/gprs-context.h
index f82fcaa..e7976a1 100644
--- a/include/gprs-context.h
+++ b/include/gprs-context.h
@@ -46,6 +46,7 @@ enum ofono_gprs_context_type {
OFONO_GPRS_CONTEXT_TYPE_MMS,
OFONO_GPRS_CONTEXT_TYPE_WAP,
OFONO_GPRS_CONTEXT_TYPE_IMS,
+ OFONO_GPRS_CONTEXT_TYPE_STK,
};
struct ofono_gprs_primary_context {
diff --git a/src/gprs.c b/src/gprs.c
index deffeb8..9657a3e 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -188,6 +188,8 @@ static const char *gprs_context_default_name(enum ofono_gprs_context_type type)
return "WAP";
case OFONO_GPRS_CONTEXT_TYPE_IMS:
return "IMS";
+ case OFONO_GPRS_CONTEXT_TYPE_STK:
+ return "STK";
}
return NULL;
@@ -207,6 +209,8 @@ static const char *gprs_context_type_to_string(
return "wap";
case OFONO_GPRS_CONTEXT_TYPE_IMS:
return "ims";
+ case OFONO_GPRS_CONTEXT_TYPE_STK:
+ return "stk";
}
return NULL;
@@ -227,6 +231,9 @@ static gboolean gprs_context_string_to_type(const char *str,
} else if (g_str_equal(str, "ims")) {
*out = OFONO_GPRS_CONTEXT_TYPE_IMS;
return TRUE;
+ } else if (g_str_equal(str, "stk")) {
+ *out = OFONO_GPRS_CONTEXT_TYPE_STK;
+ return TRUE;
}
return FALSE;
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 4/7] gprs: Add private APIs for adding/activating/removing hidden PDP contexts
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
2011-05-13 17:21 ` [PATCH v3 2/7] stk: Introduce BIP command handlers Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 3/7] gprs: Add 'stk' gprs context type Philippe Nunes
@ 2011-05-13 17:22 ` Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 5/7] stk: Use Gprs private APIs to handle the Open channel/Close Channel Philippe Nunes
` (2 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:22 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 7902 bytes --]
---
src/gprs.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/ofono.h | 25 ++++++
2 files changed, 260 insertions(+), 0 deletions(-)
diff --git a/src/gprs.c b/src/gprs.c
index 9657a3e..49b13b9 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -147,6 +147,8 @@ struct pri_context {
struct ofono_gprs_primary_context context;
struct ofono_gprs_context *context_driver;
struct ofono_gprs *gprs;
+ void *notify;
+ void *notify_data;
};
static void gprs_netreg_update(struct ofono_gprs *gprs);
@@ -356,6 +358,35 @@ static struct pri_context *gprs_context_by_path(struct ofono_gprs *gprs,
return NULL;
}
+static struct pri_context *gprs_context_by_id(struct ofono_gprs *gprs,
+ unsigned int id)
+{
+ GSList *l;
+
+ for (l = gprs->contexts; l; l = l->next) {
+ struct pri_context *ctx = l->data;
+
+ if (ctx->id == id)
+ return ctx;
+ }
+
+ 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) {
@@ -2968,3 +2999,207 @@ void *ofono_gprs_get_data(struct ofono_gprs *gprs)
{
return gprs->driver_data;
}
+
+unsigned int __ofono_gprs_add_pdp_context(struct ofono_gprs *gprs,
+ enum ofono_gprs_context_type context_type,
+ enum ofono_gprs_proto proto,
+ const char *apn,
+ const char *username,
+ const char *password,
+ const char *host)
+{
+ unsigned int id;
+ struct pri_context *context;
+ struct pri_context *default_ctx = NULL;
+ const char *name;
+
+ /* Sanity check */
+ if (apn && strlen(apn) > OFONO_GPRS_MAX_APN_LENGTH)
+ return 0;
+
+ if (username && strlen(username) > OFONO_GPRS_MAX_USERNAME_LENGTH)
+ return 0;
+
+ if (password && strlen(password) > OFONO_GPRS_MAX_PASSWORD_LENGTH)
+ return 0;
+
+ if (apn == NULL || (username == NULL && password == NULL)) {
+ /* take the default primary internet context */
+ default_ctx = gprs_get_default_context(gprs);
+
+ if (default_ctx == NULL && apn == NULL)
+ return 0;
+ }
+
+ if (apn && is_valid_apn(apn) == FALSE)
+ return 0;
+
+ name = gprs_context_default_name(context_type);
+ if (name == NULL)
+ return 0;
+
+ if (gprs->last_context_id)
+ id = idmap_alloc_next(gprs->pid_map, gprs->last_context_id);
+ else
+ id = idmap_alloc(gprs->pid_map);
+
+ if (id > idmap_get_max(gprs->pid_map))
+ return 0;
+
+ context = pri_context_create(gprs, name, context_type);
+ if (context == NULL) {
+ idmap_put(gprs->pid_map, id);
+ return 0;
+ }
+
+ context->id = id;
+
+ if (username != NULL)
+ strcpy(context->context.username, username);
+
+ if (password != NULL)
+ strcpy(context->context.password, password);
+
+ if (username == NULL && password == NULL && default_ctx) {
+ if (default_ctx->context.username)
+ strcpy(context->context.username,
+ default_ctx->context.username);
+ if (default_ctx->context.password)
+ strcpy(context->context.password,
+ default_ctx->context.password);
+ }
+
+ if (apn)
+ strcpy(context->context.apn, apn);
+ else if (default_ctx) {
+ strcpy(context->context.apn, default_ctx->context.apn);
+ if (default_ctx->context.username)
+ strcpy(context->context.username,
+ default_ctx->context.username);
+ if (default_ctx->context.password)
+ strcpy(context->context.password,
+ default_ctx->context.password);
+ }
+
+ context->context.proto = proto;
+
+ gprs->last_context_id = id;
+ gprs->contexts = g_slist_append(gprs->contexts, context);
+
+ return id;
+}
+
+static void activate_request_callback(const struct ofono_error *error,
+ void *data)
+{
+ struct pri_context *ctx = data;
+ struct ofono_gprs_context *gc = ctx->context_driver;
+
+ DBG("%p", ctx);
+
+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+ DBG("Activating context failed with error: %s",
+ telephony_error_to_str(error));
+ context_settings_free(ctx->context_driver->settings);
+ release_context(ctx);
+
+ if (ctx->notify)
+ ((__ofono_gprs_add_pdp_context_cb_t) ctx->notify)
+ (-ENOSYS, NULL, NULL, NULL, ctx->notify_data);
+ return;
+ }
+
+ ctx->active = TRUE;
+
+ if (gc->settings->interface != NULL)
+ pri_ifupdown(gc->settings->interface, TRUE);
+
+ if (ctx->notify) {
+ char *ipv4 = NULL;
+ char *ipv6 = NULL;
+
+ if (gc->settings->ipv4)
+ ipv4 = gc->settings->ipv4->ip;
+ else if (gc->settings->ipv6)
+ ipv6 = gc->settings->ipv6->ip;
+
+ ((__ofono_gprs_add_pdp_context_cb_t) ctx->notify)
+ (0, gc->settings->interface, ipv4, ipv6,
+ ctx->notify_data);
+ }
+}
+
+int __ofono_gprs_activate_pdp_context(struct ofono_gprs *gprs, unsigned int id,
+ __ofono_gprs_add_pdp_context_cb_t cb,
+ void *data)
+{
+ struct pri_context *ctx;
+ struct ofono_gprs_context *gc;
+
+ ctx = gprs_context_by_id(gprs, id);
+ if (ctx == NULL)
+ return -EINVAL;
+
+ if (ctx->active == TRUE)
+ return 0;
+
+ if (assign_context(ctx) == FALSE)
+ return -ENOSYS;
+
+ gc = ctx->context_driver;
+
+ ctx->notify = cb;
+ ctx->notify_data = data;
+
+ gc->driver->activate_primary(gc, &ctx->context,
+ activate_request_callback, ctx);
+ return 0;
+}
+
+static void remove_request_callback(const struct ofono_error *error,
+ void *data)
+{
+ struct pri_context *ctx = data;
+ struct ofono_gprs *gprs = ctx->gprs;
+ int err = 0;
+
+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+ DBG("Removing context failed with error: %s",
+ telephony_error_to_str(error));
+ err = -ENOSYS;
+ }
+
+ pri_reset_context_settings(ctx);
+ release_context(ctx);
+ gprs->contexts = g_slist_remove(gprs->contexts, ctx);
+
+ if (ctx->notify)
+ ((__ofono_gprs_remove_pdp_context_cb_t) ctx->notify)
+ (err, ctx->notify_data);
+}
+
+int __ofono_gprs_remove_pdp_context(struct ofono_gprs *gprs, unsigned int id,
+ __ofono_gprs_remove_pdp_context_cb_t cb,
+ void *data)
+{
+ struct pri_context *ctx;
+
+ ctx = gprs_context_by_id(gprs, id);
+ if (ctx == NULL)
+ return -EINVAL;
+
+ if (ctx->active) {
+ struct ofono_gprs_context *gc = ctx->context_driver;
+
+ ctx->notify = cb;
+ ctx->notify_data = data;
+
+ gc->driver->deactivate_primary(gc, ctx->context.cid,
+ remove_request_callback, ctx);
+ return -EINPROGRESS;
+ }
+
+ gprs->contexts = g_slist_remove(gprs->contexts, ctx);
+
+ return 0;
+}
diff --git a/src/ofono.h b/src/ofono.h
index 82d7e34..74ebe7f 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -239,6 +239,31 @@ 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_add_pdp_context_cb_t)(int error,
+ const char *interface,
+ const char *ipv4,
+ const char *ipv6,
+ void *data);
+
+typedef void (*__ofono_gprs_remove_pdp_context_cb_t)(int error, void *data);
+
+unsigned int __ofono_gprs_add_pdp_context(struct ofono_gprs *gprs,
+ enum ofono_gprs_context_type type,
+ enum ofono_gprs_proto proto,
+ const char *apn,
+ const char *username,
+ const char *password,
+ const char *host);
+
+int __ofono_gprs_remove_pdp_context(struct ofono_gprs *gprs, unsigned int id,
+ __ofono_gprs_remove_pdp_context_cb_t cb,
+ void *data);
+
+int __ofono_gprs_activate_pdp_context(struct ofono_gprs *gprs, unsigned int id,
+ __ofono_gprs_add_pdp_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] 10+ messages in thread* [PATCH v3 5/7] stk: Use Gprs private APIs to handle the Open channel/Close Channel
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
` (2 preceding siblings ...)
2011-05-13 17:22 ` [PATCH v3 4/7] gprs: Add private APIs for adding/activating/removing hidden PDP contexts Philippe Nunes
@ 2011-05-13 17:22 ` Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 6/7] gprs: Add a host route for STK context type Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 7/7] stk: Add support of the Setup event list proactive command Philippe Nunes
5 siblings, 0 replies; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:22 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 6959 bytes --]
---
src/stk.c | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 152 insertions(+), 25 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index dec0439..62e5465 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -85,6 +85,7 @@ struct ofono_stk {
struct stk_channel_data tx_buffer;
gboolean link_on_demand;
struct ofono_gprs *gprs;
+ struct stk_bearer_description bearer_desc;
};
struct envelope_op {
@@ -487,32 +488,56 @@ static void emit_menu_changed(struct ofono_stk *stk)
g_dbus_send_message(conn, signal);
}
-static void stk_close_channel(struct ofono_stk *stk)
+static void ofono_stk_remove_pdp_context_cb(int error, void *data)
{
- /*
- * TODO
- * Deactivate and remove PDP context
- * Send the Terminal Response once the PDP context is deactivated
- */
+ struct ofono_stk *stk = data;
+
+ DBG("");
- /* Temporary implementation */
+ stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+
+ if (stk->pending_cmd && stk->pending_cmd->type ==
+ STK_COMMAND_TYPE_CLOSE_CHANNEL) {
+ if (error < 0)
+ send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
+ else
+ send_simple_response(stk, STK_RESULT_TYPE_SUCCESS);
+ } else {
+ /*
+ * TODO
+ * Send Event channel status
+ */
+ }
+
+ /* free the buffers even in case of error */
g_free(stk->rx_buffer.data.array);
g_free(stk->tx_buffer.data.array);
stk->rx_buffer.data.array = NULL;
stk->tx_buffer.data.array = NULL;
stk->channel.id = 0;
- stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED;
+}
+
+static void stk_close_channel(struct ofono_stk *stk)
+{
+ int err;
+
+ err = __ofono_gprs_remove_pdp_context(stk->gprs, stk->channel.id,
+ ofono_stk_remove_pdp_context_cb, stk);
- if (stk->pending_cmd &&
- stk->pending_cmd->type ==
+ if (err == 0) {
+ g_free(stk->rx_buffer.data.array);
+ g_free(stk->tx_buffer.data.array);
+ stk->rx_buffer.data.array = NULL;
+ stk->tx_buffer.data.array = NULL;
+
+ 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_SUCCESS);
- else {
- /*
- * TODO
- * Send Event channel status
- */
+ send_simple_response(stk, STK_RESULT_TYPE_SUCCESS);
}
}
@@ -560,12 +585,66 @@ static void stk_alpha_id_unset(struct ofono_stk *stk)
stk_agent_request_cancel(stk->current_agent);
}
+static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
+ const char *ipv4,
+ const char *ipv6,
+ void *data)
+{
+ struct ofono_stk *stk = data;
+ struct stk_response rsp;
+ struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+
+ DBG("");
+
+ memset(&rsp, 0, sizeof(rsp));
+
+ if (error < 0) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ } else {
+ DBG("Interface %s, ipv4 = %s, ipv6 = %s", interface, ipv4,
+ ipv6);
+ stk->channel.status = STK_CHANNEL_PACKET_DATA_SERVICE_ACTIVATED;
+ }
+
+ if (stk->pending_cmd == NULL) {
+ /*
+ * TODO
+ * Send Event channel status
+ */
+ return;
+ }
+
+ 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->rx_buffer.data.len;
+ 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) {
+
+ if (error == 0) {
+ /*
+ * TODO
+ * send the data immediately, flush the tx buffer
+ */
+ stk->tx_buffer.tx_avail = stk->tx_buffer.data.len;
+ rsp.send_data.tx_avail = stk->tx_buffer.tx_avail;
+ }
+ }
+
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&failure, stk);
+}
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 };
+ char *host = NULL;
+ unsigned int id;
+ int err;
if (stk->pending_cmd == NULL ||
stk->pending_cmd->type != STK_COMMAND_TYPE_OPEN_CHANNEL)
@@ -592,13 +671,54 @@ static void stk_open_channel(struct ofono_stk *stk)
stk->tx_buffer.data.len = oc->buf_size;
stk->link_on_demand = (stk->pending_cmd->qualifier &
STK_OPEN_CHANNEL_FLAG_IMMEDIATE) ? FALSE : TRUE;
+ memcpy(&stk->bearer_desc, &oc->bearer_desc,
+ sizeof(struct stk_bearer_description));
/*
- * TODO
* Add a new primary PDP context based on the provided settings
- * Send the Terminal Response or wait until the PDP context is activated
- * in case of immediate link establishment not in background.
+ * According 3GPP TS 31.111, the packet data protocol type is set to 02
+ * '02' = IP (Internet Protocol, IETF STD 5)
*/
+ id = __ofono_gprs_add_pdp_context(stk->gprs,
+ OFONO_GPRS_CONTEXT_TYPE_STK,
+ OFONO_GPRS_PROTO_IP, oc->apn,
+ oc->text_usr, oc->text_passwd, host);
+
+ if (id == 0) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ stk->channel.id = id;
+
+ if (stk->link_on_demand) {
+ rsp.open_channel.channel.id = 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_pdp_context(stk->gprs, id,
+ ofono_stk_activate_pdp_context_cb, stk);
+
+ 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 = 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);
@@ -642,12 +762,19 @@ static void stk_send_data(struct ofono_stk *stk,
if (stk->channel.status == STK_CHANNEL_PACKET_DATA_SERVICE_NOT_ACTIVATED
&& stk->link_on_demand == TRUE) {
- /*
- * TODO
- * activate the context, update the channel status
- * once the context is activated, send the data immediately
- * and flush the tx buffer
- */
+ int err;
+
+ err = __ofono_gprs_activate_pdp_context(stk->gprs,
+ stk->channel.id,
+ ofono_stk_activate_pdp_context_cb,
+ stk);
+
+ if (err < 0) {
+ rsp.result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ goto out;
+ }
+
+ return;
} else {
/*
* TODO
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 6/7] gprs: Add a host route for STK context type.
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
` (3 preceding siblings ...)
2011-05-13 17:22 ` [PATCH v3 5/7] stk: Use Gprs private APIs to handle the Open channel/Close Channel Philippe Nunes
@ 2011-05-13 17:22 ` Philippe Nunes
2011-05-13 17:22 ` [PATCH v3 7/7] stk: Add support of the Setup event list proactive command Philippe Nunes
5 siblings, 0 replies; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:22 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5746 bytes --]
---
src/gprs.c | 54 ++++++++++++++++++++++++++++++++++--------------------
src/stk.c | 15 +++++++++++++++
2 files changed, 49 insertions(+), 20 deletions(-)
diff --git a/src/gprs.c b/src/gprs.c
index 49b13b9..a58ce43 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -141,8 +141,8 @@ struct pri_context {
unsigned int id;
char *path;
char *key;
- char *proxy_host;
- uint16_t proxy_port;
+ char *host;
+ uint16_t port;
DBusMessage *pending;
struct ofono_gprs_primary_context context;
struct ofono_gprs_context *context_driver;
@@ -613,16 +613,16 @@ static void pri_parse_proxy(struct pri_context *ctx, const char *proxy)
host += 3;
if (strcasecmp(scheme, "https") == 0)
- ctx->proxy_port = 443;
+ ctx->port = 443;
else if (strcasecmp(scheme, "http") == 0)
- ctx->proxy_port = 80;
+ ctx->port = 80;
else {
g_free(scheme);
return;
}
} else {
host = scheme;
- ctx->proxy_port = 80;
+ ctx->port = 80;
}
path = strchr(host, '/');
@@ -636,12 +636,12 @@ static void pri_parse_proxy(struct pri_context *ctx, const char *proxy)
if (*end == '\0') {
*port = '\0';
- ctx->proxy_port = tmp;
+ ctx->port = tmp;
}
}
- g_free(ctx->proxy_host);
- ctx->proxy_host = g_strdup(host);
+ g_free(ctx->host);
+ ctx->host = g_strdup(host);
g_free(scheme);
}
@@ -725,7 +725,7 @@ done:
close(sk);
}
-static void pri_setproxy(const char *interface, const char *proxy)
+static void pri_add_host_route(const char *interface, const char *host)
{
struct rtentry rt;
struct sockaddr_in addr;
@@ -744,7 +744,7 @@ static void pri_setproxy(const char *interface, const char *proxy)
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = inet_addr(proxy);
+ addr.sin_addr.s_addr = inet_addr(host);
memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
memset(&addr, 0, sizeof(addr));
@@ -758,7 +758,7 @@ static void pri_setproxy(const char *interface, const char *proxy)
memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
if (ioctl(sk, SIOCADDRT, &rt) < 0)
- ofono_error("Failed to add proxy host route");
+ ofono_error("Failed to add host route");
close(sk);
}
@@ -785,12 +785,13 @@ static void pri_reset_context_settings(struct pri_context *ctx)
pri_context_signal_settings(ctx, signal_ipv4, signal_ipv6);
- if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS) {
+ if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_MMS ||
+ ctx->type == OFONO_GPRS_CONTEXT_TYPE_STK) {
pri_set_ipv4_addr(interface, NULL);
- g_free(ctx->proxy_host);
- ctx->proxy_host = NULL;
- ctx->proxy_port = 0;
+ g_free(ctx->host);
+ ctx->host = NULL;
+ ctx->port = 0;
}
pri_ifupdown(interface, FALSE);
@@ -808,12 +809,12 @@ static void pri_update_mms_context_settings(struct pri_context *ctx)
pri_parse_proxy(ctx, ctx->message_proxy);
- DBG("proxy %s port %u", ctx->proxy_host, ctx->proxy_port);
+ DBG("host %s port %u", ctx->host, ctx->port);
pri_set_ipv4_addr(settings->interface, settings->ipv4->ip);
- if (ctx->proxy_host)
- pri_setproxy(settings->interface, ctx->proxy_host);
+ if (ctx->host)
+ pri_add_host_route(settings->interface, ctx->host);
}
static void append_context_properties(struct pri_context *ctx,
@@ -1363,7 +1364,7 @@ static void pri_context_destroy(gpointer userdata)
{
struct pri_context *ctx = userdata;
- g_free(ctx->proxy_host);
+ g_free(ctx->host);
g_free(ctx->path);
g_free(ctx);
}
@@ -3083,6 +3084,9 @@ unsigned int __ofono_gprs_add_pdp_context(struct ofono_gprs *gprs,
context->context.proto = proto;
+ if (host)
+ context->host = g_strdup(host);
+
gprs->last_context_id = id;
gprs->contexts = g_slist_append(gprs->contexts, context);
@@ -3111,9 +3115,19 @@ static void activate_request_callback(const struct ofono_error *error,
ctx->active = TRUE;
- if (gc->settings->interface != NULL)
+ if (gc->settings->interface != NULL) {
pri_ifupdown(gc->settings->interface, TRUE);
+ if (ctx->type == OFONO_GPRS_CONTEXT_TYPE_STK &&
+ gc->settings->ipv4) {
+ pri_set_ipv4_addr(gc->settings->interface,
+ gc->settings->ipv4->ip);
+ if (ctx->host)
+ pri_add_host_route(gc->settings->interface,
+ ctx->host);
+ }
+ }
+
if (ctx->notify) {
char *ipv4 = NULL;
char *ipv6 = NULL;
diff --git a/src/stk.c b/src/stk.c
index 62e5465..5ff9441 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -28,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
+#include <arpa/inet.h>
#include <glib.h>
#include <gdbus.h>
@@ -674,6 +675,17 @@ static void stk_open_channel(struct ofono_stk *stk)
memcpy(&stk->bearer_desc, &oc->bearer_desc,
sizeof(struct stk_bearer_description));
+ if (oc->data_dest_addr.type == STK_ADDRESS_IPV4) {
+ host = g_try_malloc0(INET_ADDRSTRLEN);
+ inet_ntop(AF_INET, (const void *)(oc->data_dest_addr.addr.ipv4),
+ host, INET_ADDRSTRLEN);
+ } else if (oc->data_dest_addr.type == STK_ADDRESS_IPV6) {
+ host = g_try_malloc0(INET6_ADDRSTRLEN);
+ inet_ntop(AF_INET6,
+ (const void *)(oc->data_dest_addr.addr.ipv6),
+ host, INET6_ADDRSTRLEN);
+ }
+
/*
* Add a new primary PDP context based on the provided settings
* According 3GPP TS 31.111, the packet data protocol type is set to 02
@@ -716,10 +728,13 @@ static void stk_open_channel(struct ofono_stk *stk)
goto out;
}
+ g_free(host);
/* wait for the PDP context activation to send the Terminal Response */
return;
out:
+ g_free(host);
+
if (stk_respond(stk, &rsp, stk_command_cb))
stk_command_cb(&failure, stk);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH v3 7/7] stk: Add support of the Setup event list proactive command
2011-05-13 17:21 [PATCH v3 1/7] stk: Clear 'respond_on_exit' flag after sending the terminal response Philippe Nunes
` (4 preceding siblings ...)
2011-05-13 17:22 ` [PATCH v3 6/7] gprs: Add a host route for STK context type Philippe Nunes
@ 2011-05-13 17:22 ` Philippe Nunes
2011-05-16 17:00 ` Andrzej Zaborowski
5 siblings, 1 reply; 10+ messages in thread
From: Philippe Nunes @ 2011-05-13 17:22 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4135 bytes --]
---
src/stk.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 80 insertions(+), 10 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 5ff9441..7122477 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -85,6 +85,8 @@ struct ofono_stk {
struct stk_channel_data rx_buffer;
struct stk_channel_data tx_buffer;
gboolean link_on_demand;
+ gboolean report_data_available;
+ gboolean report_channel_status;
struct ofono_gprs *gprs;
struct stk_bearer_description bearer_desc;
};
@@ -489,6 +491,40 @@ static void emit_menu_changed(struct ofono_stk *stk)
g_dbus_send_message(conn, signal);
}
+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.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 ofono_stk_remove_pdp_context_cb(int error, void *data)
{
struct ofono_stk *stk = data;
@@ -503,12 +539,8 @@ static void ofono_stk_remove_pdp_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 Event channel status
- */
- }
+ } else if (stk->report_channel_status)
+ stk_send_channel_status_event(stk);
/* free the buffers even in case of error */
g_free(stk->rx_buffer.data.array);
@@ -608,10 +640,8 @@ static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
}
if (stk->pending_cmd == NULL) {
- /*
- * TODO
- * Send Event channel status
- */
+ if (stk->report_channel_status)
+ stk_send_channel_status_event(stk);
return;
}
@@ -3129,6 +3159,41 @@ 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;
+
+ 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;
+ }
+ }
+
+ if (sel->event_list.len == 0) {
+ stk->report_data_available = FALSE;
+ stk->report_channel_status = FALSE;
+ }
+
+ rsp->result.type = STK_RESULT_TYPE_SUCCESS;
+ return TRUE;
+}
+
static void stk_proactive_command_cancel(struct ofono_stk *stk)
{
if (stk->immediate_response)
@@ -3347,6 +3412,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] 10+ messages in thread* Re: [PATCH v3 7/7] stk: Add support of the Setup event list proactive command
2011-05-13 17:22 ` [PATCH v3 7/7] stk: Add support of the Setup event list proactive command Philippe Nunes
@ 2011-05-16 17:00 ` Andrzej Zaborowski
0 siblings, 0 replies; 10+ messages in thread
From: Andrzej Zaborowski @ 2011-05-16 17:00 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5643 bytes --]
On 13 May 2011 19:22, Philippe Nunes <philippe.nunes@linux.intel.com> wrote:
> ---
> src/stk.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
> 1 files changed, 80 insertions(+), 10 deletions(-)
>
> diff --git a/src/stk.c b/src/stk.c
> index 5ff9441..7122477 100644
> --- a/src/stk.c
> +++ b/src/stk.c
> @@ -85,6 +85,8 @@ struct ofono_stk {
> struct stk_channel_data rx_buffer;
> struct stk_channel_data tx_buffer;
> gboolean link_on_demand;
> + gboolean report_data_available;
> + gboolean report_channel_status;
> struct ofono_gprs *gprs;
> struct stk_bearer_description bearer_desc;
> };
> @@ -489,6 +491,40 @@ static void emit_menu_changed(struct ofono_stk *stk)
> g_dbus_send_message(conn, signal);
> }
>
> +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.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 ofono_stk_remove_pdp_context_cb(int error, void *data)
> {
> struct ofono_stk *stk = data;
> @@ -503,12 +539,8 @@ static void ofono_stk_remove_pdp_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 Event channel status
> - */
> - }
> + } else if (stk->report_channel_status)
> + stk_send_channel_status_event(stk);
>
> /* free the buffers even in case of error */
> g_free(stk->rx_buffer.data.array);
> @@ -608,10 +640,8 @@ static void ofono_stk_activate_pdp_context_cb(int error, const char *interface,
> }
>
> if (stk->pending_cmd == NULL) {
> - /*
> - * TODO
> - * Send Event channel status
> - */
> + if (stk->report_channel_status)
> + stk_send_channel_status_event(stk);
> return;
> }
>
> @@ -3129,6 +3159,41 @@ 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;
> +
> + 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;
> + }
> + }
> +
> + if (sel->event_list.len == 0) {
> + stk->report_data_available = FALSE;
> + stk->report_channel_status = FALSE;
> + }
These flags should probably be cleared unconditionally before the loop
above because "Any subsequent SET UP EVENT LIST command replaces the
current list of events..".
Best regards
^ permalink raw reply [flat|nested] 10+ messages in thread