[PATCH 3/6] stk: Introduce BIP command handlers
by Philippe Nunes
---
src/stk.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 307 insertions(+), 0 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 68b6240..d224360 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -79,6 +79,9 @@ 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;
};
struct envelope_op {
@@ -2548,6 +2551,285 @@ 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;
+ unsigned char no_cause[] = { 0x00 };
+ struct ofono_error failure = { .type = OFONO_ERROR_TYPE_FAILURE };
+ struct stk_response rsp;
+
+ stk->respond_on_exit = FALSE;
+
+ 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:
+ memset(&rsp, 0, sizeof(rsp));
+ ADD_ERROR_RESULT(rsp.result, STK_RESULT_TYPE_TERMINAL_BUSY,
+ no_cause);
+
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&failure, stk);
+
+ return;
+ }
+
+ /*
+ * TODO
+ * setup the channel
+ */
+
+ /* For now, return "Command beyond terminal's capabilities" */
+ send_simple_response(stk, STK_RESULT_TYPE_NOT_CAPABLE);
+}
+
+static gboolean handle_command_open_channel(const struct stk_command *cmd,
+ struct stk_response *rsp,
+ struct ofono_stk *stk)
+{
+ const struct stk_command_open_channel *oc = &cmd->open_channel;
+ char *alpha_id;
+ int err;
+
+ /* Don't ask for user confirmation if AID is a null data object*/
+ if (oc->alpha_id && strlen(oc->alpha_id) == 0) {
+ /*
+ * TODO
+ * setup the channel
+ */
+
+ /* For now, return "Command beyond terminal's capabilities" */
+ rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ return TRUE;
+ }
+
+ alpha_id = dbus_apply_text_attributes(oc->alpha_id ? 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 };
+
+ /*
+ * We most likely got an out of memory error, tell SIM
+ * to retry
+ */
+ ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_TERMINAL_BUSY,
+ no_cause_result);
+ return TRUE;
+ }
+
+ stk->respond_on_exit = TRUE;
+ stk->cancel_cmd = stk_request_cancel;
+
+ return FALSE;
+}
+
+static void channel_activity_cb(enum stk_agent_result result, void *user_data)
+{
+ struct ofono_stk *stk = user_data;
+
+ if (result == STK_AGENT_RESULT_TERMINATE) {
+ stk->respond_on_exit = FALSE;
+ send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
+ }
+}
+
+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;
+ char *alpha_id;
+ int err;
+
+ /*
+ * Don't inform the user about the link closing phase if AID is
+ * a null data object
+ * */
+ if (cc->alpha_id && strlen(cc->alpha_id) == 0)
+ goto close;
+
+ alpha_id = dbus_apply_text_attributes(cc->alpha_id ? cc->alpha_id : "",
+ &cc->text_attr);
+ if (alpha_id == NULL) {
+ rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+ return TRUE;
+ }
+
+ err = stk_agent_display_channel_activity(stk->current_agent, alpha_id,
+ &cc->icon_id,
+ channel_activity_cb,
+ stk, NULL);
+ g_free(alpha_id);
+
+ if (err < 0) {
+ unsigned char no_cause_result[] = { 0x00 };
+
+ /*
+ * We most likely got an out of memory error, tell SIM
+ * to retry
+ */
+ ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_TERMINAL_BUSY,
+ no_cause_result);
+ return TRUE;
+ }
+
+close:
+ stk->respond_on_exit = TRUE;
+ stk->cancel_cmd = stk_request_cancel;
+ /*
+ * TODO
+ * close the channel
+ * Send the Terminal Response once the PDP context is deactivated
+ */
+
+ /* For now, return "Command beyond terminal's capabilities" */
+ rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ return TRUE;
+}
+
+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;
+ char *alpha_id;
+ int err;
+
+ /*
+ * Don't inform the user during data transfer
+ * if AID is a null data object
+ */
+ if (rd->alpha_id && strlen(rd->alpha_id) == 0)
+ goto receive;
+
+ alpha_id = dbus_apply_text_attributes(rd->alpha_id ? rd->alpha_id : "",
+ &rd->text_attr);
+ if (alpha_id == NULL) {
+ rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+ return TRUE;
+ }
+
+ err = stk_agent_display_channel_activity(stk->current_agent, alpha_id,
+ &rd->icon_id,
+ channel_activity_cb,
+ stk, NULL);
+ g_free(alpha_id);
+
+ if (err < 0) {
+ unsigned char no_cause_result[] = { 0x00 };
+
+ /*
+ * We most likely got an out of memory error, tell SIM
+ * to retry
+ */
+ ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_TERMINAL_BUSY,
+ no_cause_result);
+ return TRUE;
+ }
+
+ stk->respond_on_exit = TRUE;
+ stk->cancel_cmd = stk_request_cancel;
+
+receive:
+ /*
+ * TODO
+ * return data available in the Rx buffer corresponding to the
+ * channel identifier
+ */
+
+ /* For now, return "Command beyond terminal's capabilities" */
+ rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ return TRUE;
+}
+
+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;
+ char *alpha_id;
+ int err;
+
+ /*
+ * Don't inform the user during data transfer
+ * if AID is a null data object
+ */
+ if (sd->alpha_id && strlen(sd->alpha_id) == 0)
+ goto send;
+
+ alpha_id = dbus_apply_text_attributes(sd->alpha_id ? sd->alpha_id : "",
+ &sd->text_attr);
+ if (alpha_id == NULL) {
+ rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+ return TRUE;
+ }
+
+ err = stk_agent_display_channel_activity(stk->current_agent, alpha_id,
+ &sd->icon_id,
+ channel_activity_cb,
+ stk, NULL);
+ g_free(alpha_id);
+
+ if (err < 0) {
+ unsigned char no_cause_result[] = { 0x00 };
+
+ /*
+ * We most likely got an out of memory error, tell SIM
+ * to retry
+ */
+ ADD_ERROR_RESULT(rsp->result, STK_RESULT_TYPE_TERMINAL_BUSY,
+ no_cause_result);
+ return TRUE;
+ }
+
+ stk->respond_on_exit = TRUE;
+ stk->cancel_cmd = stk_request_cancel;
+
+send:
+ /*
+ * TODO
+ * send the data immediately or store the provided data in the Tx buffer
+ * corresponding to the channel identifier
+ */
+ /* For now, return "Command beyond terminal's capabilities" */
+ rsp->result.type = STK_RESULT_TYPE_NOT_CAPABLE;
+ return TRUE;
+}
+
+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)
@@ -2741,6 +3023,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
9 years, 9 months
[PATCH v2 4/4] test-stk-menu: Extend to support DisplayAction method
by Philippe Nunes
---
test/test-stk-menu | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/test/test-stk-menu b/test/test-stk-menu
index 639fe77..1fde700 100755
--- a/test/test-stk-menu
+++ b/test/test-stk-menu
@@ -198,6 +198,16 @@ class StkAgent(dbus.service.Object):
print "Text: %s" % (text)
print "Icon: %d" % (icon)
+ @dbus.service.method("org.ofono.SimToolkitAgent",
+ in_signature="sy", out_signature="")
+ def DisplayAction(self, text, icon):
+ print "Text: (%s)" % (text)
+ print "Icon: (%d)" % (icon)
+ key = raw_input("Press 't' to terminate the session ")
+
+ if key == 't':
+ raise EndSession("User wishes to terminate session")
+
def property_changed(name, value):
print "SimToolKit property: %s changed to '%s'" % (name, value)
--
1.7.1
9 years, 9 months
[PATCH v2 3/4] stkagent: Call the new display method when user termination is allowed
by Philippe Nunes
---
src/stkagent.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/stkagent.h | 9 ++++++++
2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/src/stkagent.c b/src/stkagent.c
index 2395182..15ad4fa 100644
--- a/src/stkagent.c
+++ b/src/stkagent.c
@@ -1081,3 +1081,64 @@ int stk_agent_confirm_launch_browser(struct stk_agent *agent, const char *text,
return 0;
}
+
+static void display_action_cb(DBusPendingCall *call, void *data)
+{
+ struct stk_agent *agent = data;
+ stk_agent_user_termination_cb cb = agent->user_cb;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ enum stk_agent_result result;
+ gboolean remove_agent;
+
+ if (check_error(agent, reply,
+ ALLOWED_ERROR_TERMINATE, &result) == -EINVAL) {
+ remove_agent = TRUE;
+ goto error;
+ }
+
+ if (dbus_message_get_args(reply, NULL, DBUS_TYPE_INVALID) == FALSE) {
+ ofono_error("Can't parse the reply to DisplayAction()");
+ remove_agent = TRUE;
+ goto error;
+ }
+
+ cb(result, agent->user_data);
+ goto done;
+
+ CALLBACK_END();
+}
+
+int stk_agent_display_action(struct stk_agent *agent,
+ const char *text,
+ const struct stk_icon_id *icon,
+ stk_agent_user_termination_cb cb,
+ void *user_data,
+ ofono_destroy_func destroy)
+{
+ DBusConnection *conn = ofono_dbus_get_connection();
+
+ agent->msg = dbus_message_new_method_call(agent->bus, agent->path,
+ OFONO_SIM_APP_INTERFACE,
+ "DisplayAction");
+ if (agent->msg == NULL)
+ return -ENOMEM;
+
+ dbus_message_append_args(agent->msg,
+ DBUS_TYPE_STRING, &text,
+ DBUS_TYPE_BYTE, &icon->id,
+ DBUS_TYPE_INVALID);
+
+ if (dbus_connection_send_with_reply(conn, agent->msg, &agent->call,
+ 0) == FALSE ||
+ agent->call == NULL)
+ return -EIO;
+
+ agent->user_cb = cb;
+ agent->user_data = user_data;
+ agent->user_destroy = destroy;
+
+ dbus_pending_call_set_notify(agent->call, display_action_cb,
+ agent, NULL);
+
+ return 0;
+}
diff --git a/src/stkagent.h b/src/stkagent.h
index 1f0c4fa..fd60824 100644
--- a/src/stkagent.h
+++ b/src/stkagent.h
@@ -60,6 +60,9 @@ typedef void (*stk_agent_string_cb)(enum stk_agent_result result,
typedef void (*stk_agent_tone_cb)(enum stk_agent_result result,
void *user_data);
+typedef void (*stk_agent_user_termination_cb)(enum stk_agent_result result,
+ void *user_data);
+
struct stk_agent *stk_agent_new(const char *path, const char *sender,
ofono_bool_t remove_on_terminate);
@@ -147,3 +150,9 @@ int stk_agent_confirm_launch_browser(struct stk_agent *agent, const char *text,
void *user_data,
ofono_destroy_func destroy,
int timeout);
+
+int stk_agent_display_action(struct stk_agent *agent, const char *text,
+ const struct stk_icon_id *icon,
+ stk_agent_user_termination_cb cb,
+ void *user_data,
+ ofono_destroy_func destroy);
--
1.7.1
9 years, 9 months
[PATCH v2 2/4] stk: Handle user termination for Send DTMF
by Philippe Nunes
---
src/stk.c | 26 +++++++++++++++++++++-----
1 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 94ad396..780e0c2 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -473,6 +473,16 @@ static void emit_menu_changed(struct ofono_stk *stk)
g_dbus_send_message(conn, signal);
}
+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) {
+ stk->respond_on_exit = FALSE;
+ send_simple_response(stk, STK_RESULT_TYPE_USER_TERMINATED);
+ }
+}
+
static void stk_alpha_id_set(struct ofono_stk *stk,
const char *text, const struct stk_text_attribute *attr,
const struct stk_icon_id *icon)
@@ -484,7 +494,13 @@ static void stk_alpha_id_set(struct ofono_stk *stk,
* and no alpha identifier cases equally. This may be changed once
* better idea is found out.
*/
- if (alpha != NULL)
+ if (alpha == NULL)
+ return;
+
+ if (stk->respond_on_exit)
+ stk_agent_display_action(stk->current_agent, alpha, icon,
+ user_termination_cb, stk, NULL);
+ else
stk_agent_display_action_info(stk->current_agent, alpha, icon);
g_free(alpha);
@@ -2329,10 +2345,6 @@ static gboolean handle_command_send_dtmf(const struct stk_command *cmd,
return TRUE;
}
- stk_alpha_id_set(stk, cmd->send_dtmf.alpha_id,
- &cmd->send_dtmf.text_attr,
- &cmd->send_dtmf.icon_id);
-
/*
* Note that we don't strictly require an agent to be connected,
* but to comply with 6.4.24 we need to send a End Session when
@@ -2342,6 +2354,10 @@ static gboolean handle_command_send_dtmf(const struct stk_command *cmd,
stk->cancel_cmd = send_dtmf_cancel;
stk->dtmf_id = err;
+ stk_alpha_id_set(stk, cmd->send_dtmf.alpha_id,
+ &cmd->send_dtmf.text_attr,
+ &cmd->send_dtmf.icon_id);
+
return FALSE;
}
--
1.7.1
9 years, 9 months
[PATCH 1/4] stk-api.txt: Introduce a new API to display abortable information
by Philippe Nunes
---
doc/stk-api.txt | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/doc/stk-api.txt b/doc/stk-api.txt
index f8a115e..fc69bb9 100644
--- a/doc/stk-api.txt
+++ b/doc/stk-api.txt
@@ -252,6 +252,7 @@ Methods byte RequestSelection(string title, byte icon_id,
Possible Errors: [service].Error.SimToolkit.EndSession
void DisplayActionInformation(string text, byte icon_id)
+ [noreply]
Supplies a text string and/or icon concerning the
current activity in the terminal and UICC. The
@@ -267,6 +268,16 @@ Methods byte RequestSelection(string title, byte icon_id,
confirmation message to oFono and then should open
the launch browser with the given url.
+ void DisplayAbortableActionInfo(string text, byte icon_id)
+
+ Supplies a text string and/or icon concerning the
+ current activity in the terminal and UICC. The
+ text should be displayed to the user on screen
+ until the call is canceled using Cancel() or until the
+ user decides to end the session.
+
+ Possible Errors: [service].Error.SimToolkit.EndSession
+
void Cancel() [noreply]
Asks the agent to cancel any ongoing operation in
--
1.7.1
9 years, 9 months
[PATCH] atmodem: gnss aggregate xml
by Jarko Poutiainen
---
Hi,
ok this is the very final patch from me for this. The parsing could be done better I know but seems to work. Hopefully this will any way give some idea for somebody else to finalise this.
br,
Jarko
drivers/atmodem/gnss.c | 135 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 119 insertions(+), 16 deletions(-)
diff --git a/drivers/atmodem/gnss.c b/drivers/atmodem/gnss.c
index e102815..719fb6d 100644
--- a/drivers/atmodem/gnss.c
+++ b/drivers/atmodem/gnss.c
@@ -45,6 +45,7 @@
struct gnss_data {
GAtChat *chat;
unsigned int vendor;
+ char *xml_data;
};
static const char *none_prefix[] = { NULL };
@@ -136,40 +137,138 @@ error:
}
static gboolean gnss_parse_report(GAtResult *result, const char *prefix,
- const char **xml)
+ char **xml, struct gnss_data *gd)
{
GAtResultIter iter;
+ char *buf, *temp_xml;
+ int len, old_len, xml_len;
+ const char *xml_result;
+
+ buf = NULL;
+ temp_xml = NULL;
+ xml_result = NULL;
+ xml_len = 0;
+ old_len = 0;
+ len = 0;
g_at_result_iter_init(&iter, result);
- if (!g_at_result_iter_next(&iter, prefix))
- return FALSE;
+ if (!g_at_result_iter_next(&iter, prefix)) {
+ if (gd->xml_data) {
+ g_free(gd->xml_data);
+ gd->xml_data = NULL;
+ }
+ goto error;
+ }
- if (!g_at_result_iter_next_unquoted_string(&iter, xml))
+ if (!g_at_result_iter_next_unquoted_string(&iter, &xml_result)) {
+ if (gd->xml_data) {
+ g_free(gd->xml_data);
+ gd->xml_data = NULL;
+ }
+ goto error;
+ }
+
+ if (xml_result == NULL) {
+ if (gd->xml_data) {
+ g_free(gd->xml_data);
+ gd->xml_data = NULL;
+ }
+ goto error;
+ }
+
+ len = strlen(xml_result);
+
+ if (len == 0)
return FALSE;
- return TRUE;
+ while ((xml_result[len-1] == '\n') || (xml_result[len-1] == '\r') ||
+ (xml_result[len-1] == ' ')) {
+ len = len - 1;
+ }
+
+ temp_xml = g_try_new(char, len+1);
+ if (!temp_xml) {
+ if (gd->xml_data) {
+ g_free(gd->xml_data);
+ gd->xml_data = NULL;
+ }
+ goto error;
+ }
+
+ g_memmove(temp_xml, xml_result, len);
+ temp_xml[len] = '\0';
+
+ if (temp_xml[len-1] == '>' && temp_xml[len-2] == 's'
+ && temp_xml[len-3] == 'o'
+ && temp_xml[len-4] == 'p'
+ && temp_xml[len-5] == '/') {
+ if (gd->xml_data) {
+ old_len = strlen(gd->xml_data);
+ buf = g_try_new(char, (old_len+len+1));
+ if (!buf) {
+ g_free(gd->xml_data);
+ g_free(temp_xml);
+ gd->xml_data = NULL;
+ goto error;
+ }
+
+ xml_len = sprintf(buf, "%s", gd->xml_data);
+ xml_len += sprintf(buf + xml_len, "%s", temp_xml);
+ buf[xml_len] = '\0';
+ g_free(gd->xml_data);
+ g_free(temp_xml);
+ gd->xml_data = NULL;
+ *xml = buf;
+ return TRUE;
+ } else {
+ *xml = temp_xml;
+ return TRUE;
+ }
+ } else {
+ if (gd->xml_data) {
+ old_len = strlen(gd->xml_data);
+ buf = g_try_new(char, (old_len+len+1));
+ if (!buf) {
+ g_free(gd->xml_data);
+ g_free(temp_xml);
+ gd->xml_data = NULL;
+ goto error;
+ }
+
+ xml_len = sprintf(buf, "%s", gd->xml_data);
+ xml_len += sprintf(buf + xml_len, "%s", temp_xml);
+ buf[xml_len] = '\0';
+ g_free(gd->xml_data);
+ gd->xml_data = buf;
+ g_free(temp_xml);
+ return FALSE;
+ } else {
+ gd->xml_data = temp_xml;
+ return FALSE;
+ }
+ }
+
+error:
+ ofono_error("Unable to parse CPOSR notification");
+ return FALSE;
}
static void gnss_report(GAtResult *result, gpointer user_data)
{
- const char *xml;
+ struct ofono_gnss *gnss = user_data;
+ struct gnss_data *gd = ofono_gnss_get_data(gnss);
+
+ char *xml;
DBG("");
xml = NULL;
- if (!gnss_parse_report(result, "+CPOSR:", &xml)) {
- ofono_error("Unable to parse CPOSR notification");
- return;
+ if (gnss_parse_report(result, "+CPOSR:", &xml, gd)) {
+ ofono_gnss_notify_posr_request(gnss, xml);
+ g_free(xml);
}
-
- if (xml == NULL) {
- ofono_error("Unable to parse CPOSR notification");
- return;
- }
-
- DBG("%s", xml);
}
static void at_gnss_reset_notify(GAtResult *result, gpointer user_data)
@@ -242,6 +341,7 @@ static int at_gnss_probe(struct ofono_gnss *gnss, unsigned int vendor,
gd->chat = g_at_chat_clone(chat);
gd->vendor = vendor;
+ gd->xml_data = NULL;
ofono_gnss_set_data(gnss, gd);
@@ -257,6 +357,9 @@ static void at_gnss_remove(struct ofono_gnss *gnss)
DBG("");
+ if (gd->xml_data)
+ g_free(gd->xml_data);
+
ofono_gnss_set_data(gnss, NULL);
g_at_chat_unref(gd->chat);
--
1.7.0.4
9 years, 9 months
[PATCH] atmodem: gnss aggregate xml
by Jarko Poutiainen
---
Hi,
this patch provides logic to re-construct XML-formatted string prefixed with +CPOSR as defined in 27.007.
Br,
Jarko
drivers/atmodem/gnss.c | 134 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 118 insertions(+), 16 deletions(-)
diff --git a/drivers/atmodem/gnss.c b/drivers/atmodem/gnss.c
index 4954bb8..5d5a883 100644
--- a/drivers/atmodem/gnss.c
+++ b/drivers/atmodem/gnss.c
@@ -47,6 +47,8 @@ struct gnss_data {
unsigned int vendor;
};
+char *xml_data;
+
static const char *none_prefix[] = { NULL };
static const char *cpos_prefix[] = { "+CPOS:", NULL };
static const char *cposr_prefix[] = { "+CPOSR:", NULL };
@@ -136,41 +138,136 @@ error:
}
static gboolean gnss_parse_report(GAtResult *result, const char *prefix,
- const char **xml)
+ char **xml)
{
GAtResultIter iter;
+ char *buf, *temp_xml;
+ int len, old_len, xml_len;
+ const char *xml_result;
+
+ buf = NULL;
+ temp_xml = NULL;
+ xml_result = NULL;
+ xml_len = 0;
+ old_len = 0;
+ len = 0;
g_at_result_iter_init(&iter, result);
- if (!g_at_result_iter_next(&iter, prefix))
- return FALSE;
+ if (!g_at_result_iter_next(&iter, prefix)) {
+ if (xml_data) {
+ g_free(xml_data);
+ xml_data = NULL;
+ }
+ goto error;
+ }
+
+ if (!g_at_result_iter_next_unquoted_string(&iter, &xml_result)) {
+ if (xml_data) {
+ g_free(xml_data);
+ xml_data = NULL;
+ }
+ goto error;
+ }
+
+ if (xml_result == NULL) {
+ if (xml_data) {
+ g_free(xml_data);
+ xml_data = NULL;
+ }
+ goto error;
+ }
- if (!g_at_result_iter_next_unquoted_string(&iter, xml))
+ len = strlen(xml_result);
+
+ if (len == 0)
return FALSE;
- return TRUE;
+ while ((xml_result[len-1] == '\n') || (xml_result[len-1] == '\r') ||
+ (xml_result[len-1] == ' ')) {
+ len = len - 1;
+ }
+
+ temp_xml = g_try_new(char, len+1);
+ if (!temp_xml) {
+ if (xml_data) {
+ g_free(xml_data);
+ xml_data = NULL;
+ }
+ goto error;
+ }
+
+ g_memmove(temp_xml, xml_result, len);
+ temp_xml[len] = '\0';
+
+ if (temp_xml[len-1] == '>' && temp_xml[len-2] == 's'
+ && temp_xml[len-3] == 'o'
+ && temp_xml[len-4] == 'p'
+ && temp_xml[len-5] == '/') {
+ if (xml_data) {
+ old_len = strlen(xml_data);
+ buf = g_try_new(char, (old_len+len+1));
+ if (!buf) {
+ g_free(xml_data);
+ g_free(temp_xml);
+ xml_data = NULL;
+ goto error;
+ }
+
+ xml_len = sprintf(buf, "%s", xml_data);
+ xml_len += sprintf(buf + xml_len, "%s", temp_xml);
+ buf[xml_len] = '\0';
+ g_free(xml_data);
+ g_free(temp_xml);
+ xml_data = NULL;
+ *xml = buf;
+ return TRUE;
+ } else {
+ *xml = temp_xml;
+ return TRUE;
+ }
+ } else {
+ if (xml_data) {
+ old_len = strlen(xml_data);
+ buf = g_try_new(char, (old_len+len+1));
+ if (!buf) {
+ g_free(xml_data);
+ g_free(temp_xml);
+ xml_data = NULL;
+ goto error;
+ }
+
+ xml_len = sprintf(buf, "%s", xml_data);
+ xml_len += sprintf(buf + xml_len, "%s", temp_xml);
+ buf[xml_len] = '\0';
+ g_free(xml_data);
+ xml_data = buf;
+ g_free(temp_xml);
+ return FALSE;
+ } else {
+ xml_data = temp_xml;
+ return FALSE;
+ }
+ }
+
+error:
+ ofono_error("Unable to parse CPOSR notification");
+ return FALSE;
}
static void gnss_report(GAtResult *result, gpointer user_data)
{
struct ofono_gnss *gnss = user_data;
- const char *xml;
+ char *xml;
DBG("");
xml = NULL;
- if (!gnss_parse_report(result, "+CPOSR:", &xml)) {
- ofono_error("Unable to parse CPOSR notification");
- return;
- }
-
- if (xml == NULL) {
- ofono_error("Unable to parse CPOSR notification");
- return;
+ if (gnss_parse_report(result, "+CPOSR:", &xml)) {
+ ofono_gnss_notify_posr_request(gnss, xml);
+ g_free(xml);
}
-
- DBG("%s", xml);
}
static void at_gnss_reset_notify(GAtResult *result, gpointer user_data)
@@ -237,6 +334,8 @@ static int at_gnss_probe(struct ofono_gnss *gnss, unsigned int vendor,
DBG("");
+ xml_data = NULL;
+
gd = g_try_new0(struct gnss_data, 1);
if (gd == NULL)
return -ENOMEM;
@@ -258,6 +357,9 @@ static void at_gnss_remove(struct ofono_gnss *gnss)
DBG("");
+ if (xml_data)
+ g_free(xml_data);
+
ofono_gnss_set_data(gnss, NULL);
g_at_chat_unref(gd->chat);
--
1.7.0.4
9 years, 9 months
[PATCH 0/2] Phonesim: add support for CSSU/CSSI notification
by Nicolas Bertrand
Add UI to be able to send CSSU and CSSI notification with phonesim
Nicolas Bertrand (2):
phonesim: add CSSU/CSSI UI
phonesim: Add CSSU/CSSI notification support
src/control.cpp | 30 +++++++++++++++++++++++-
src/control.h | 2 +
src/controlbase.ui | 65 +++++++++++++++++++++++++++++++++++++++++++--------
3 files changed, 85 insertions(+), 12 deletions(-)
9 years, 9 months
[PATCH 1/2] qsimcommand: Add properties and TLV builders to support BIP commands
by Philippe Nunes
---
src/qsimcommand.cpp | 201 +++++++++++++++++++++++++++++++++++++++++++++++++--
src/qsimcommand.h | 34 +++++++++
2 files changed, 228 insertions(+), 7 deletions(-)
diff --git a/src/qsimcommand.cpp b/src/qsimcommand.cpp
index ecdf43f..46b633f 100644
--- a/src/qsimcommand.cpp
+++ b/src/qsimcommand.cpp
@@ -69,6 +69,8 @@ public:
timerId = 0;
device = -1;
qualifier = 0;
+ bufferSize = 0;
+ dataLength = 0;
}
QSimCommandPrivate( QSimCommandPrivate *other )
{
@@ -102,6 +104,15 @@ public:
device = other->device;
qualifier = other->qualifier;
extensionData = other->extensionData;
+ bearerDesc = other->bearerDesc;
+ bufferSize = other->bufferSize;
+ dataLength = other->dataLength;
+ apn = other->apn;
+ uti = other->uti;
+ userLogin = other->userLogin;
+ userPassword = other->userPassword;
+ destAddress = other->destAddress;
+ localAddress = other->localAddress;
}
bool flag( int bit ) const
@@ -165,7 +176,15 @@ public:
int device;
int qualifier;
QByteArray extensionData;
-
+ QByteArray bearerDesc;
+ ushort bufferSize;
+ uint dataLength;
+ QByteArray apn;
+ QByteArray uti;
+ QString userLogin;
+ QString userPassword;
+ QByteArray destAddress;
+ QByteArray localAddress;
};
@@ -612,7 +631,7 @@ QSimMenuItem& QSimMenuItem::operator=( const QSimMenuItem & value )
\enum QSimCommand::Device
This enum defines the source or destination device for a SIM command, according
to 3GPP TS 11.14, section 12.7.
-
+ \
\value Keypad Keypad device
\value Display Display device
\value Earpiece Earpiece device
@@ -2202,6 +2221,86 @@ void QSimCommand::setTimerId( int id )
dwrite()->timerId = id;
}
+ushort QSimCommand::bufferSize() const
+{
+ return d->bufferSize;
+}
+
+void QSimCommand::setBufferSize( ushort value )
+{
+ dwrite()->bufferSize = value;
+}
+
+uint QSimCommand::dataLength() const
+{
+ return d->dataLength;
+}
+
+void QSimCommand::setDataLength( uint value )
+{
+ dwrite()->dataLength = value;
+}
+
+QString QSimCommand::userLogin() const
+{
+ return d->userLogin;
+}
+
+void QSimCommand::setUserLogin( const QString& value )
+{
+ dwrite()->userLogin = value;
+}
+
+QString QSimCommand::userPassword() const
+{
+ return d->userPassword;
+}
+
+void QSimCommand::setUserPassword( const QString& value )
+{
+ dwrite()->userPassword = value;
+}
+
+QByteArray QSimCommand::uti() const
+{
+ return d->uti;
+}
+
+void QSimCommand::setUti( const QByteArray& value )
+{
+ dwrite()->uti = value;
+}
+
+QByteArray QSimCommand::bearerDesc() const
+{
+ return d->bearerDesc;
+}
+
+void QSimCommand::setBearerDesc( const QByteArray& value )
+{
+ dwrite()->bearerDesc = value;
+}
+
+QByteArray QSimCommand::destAddress() const
+{
+ return d->destAddress;
+}
+
+void QSimCommand::setDestAddress( const QByteArray& value )
+{
+ dwrite()->destAddress = value;
+}
+
+QByteArray QSimCommand::apn() const
+{
+ return d->apn;
+}
+
+void QSimCommand::setApn( const QByteArray& value )
+{
+ dwrite()->apn = value;
+}
+
/*!
Copy the QSimCommand object \a value.
*/
@@ -3045,6 +3144,62 @@ void _qtopiaphone_writeTimerValue( QByteArray& data, uint value )
}
#define writeTimerValue _qtopiaphone_writeTimerValue
+// Write a Bearer description field.
+static void writeBearerDesc( QByteArray& data, const QByteArray& bearerDesc )
+{
+ if ( !bearerDesc.isEmpty() ) {
+ data += (char)0x35;
+ writeBerLength( data, bearerDesc.length() );
+ data += bearerDesc;
+ }
+}
+
+// Write a Network Access Name field as specified in TS 23.003
+static void writeApn( QByteArray& data, const QByteArray& apn )
+{
+ if ( !apn.isEmpty() ) {
+ data += (char)0x47;
+ writeBerLength( data, apn.length() );
+ data += apn;
+ }
+}
+
+// Write a Buffer size field.
+static void writeBufferSize( QByteArray& data, ushort size )
+{
+ if ( size ) {
+ data += 0x39;
+ data += 0x02;
+ data += (char)(size >> 8);
+ data += (char)size;
+ }
+}
+
+// Write a data length field.
+static void writeDataLength( QByteArray& data, uint value )
+{
+ data += 0x37;
+ data += 0x01;
+ data += (char) value;
+}
+
+static void writeUti( QByteArray& data, const QByteArray& uti )
+{
+ if ( !uti.isEmpty() ) {
+ data += (char)0x3C;
+ writeBerLength( data, uti.length() );
+ data += uti;
+ }
+}
+
+static void writeOtherAddress( QByteArray& data, const QByteArray& otherAddress )
+{
+ if ( !otherAddress.isEmpty() ) {
+ data += (char)0x3E;
+ writeBerLength( data, otherAddress.length() );
+ data += otherAddress;
+ }
+}
/*!
\enum QSimCommand::ToPduOptions
This enum defines additional options to use when encoding SIM commands with QSimCommand::toPdu().
@@ -3324,18 +3479,50 @@ QByteArray QSimCommand::toPdu( QSimCommand::ToPduOptions options ) const
if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
writeEFADN( data, text(), options, 0x05 );
writeIcon( data, iconId(), iconSelfExplanatory(), true );
- if ( !number().isEmpty() )
- writeEFADNNumber( data, number() );
- if ( !subAddress().isEmpty() )
- writeSubAddress( data, subAddress() );
+
+ writeBearerDesc( data, bearerDesc() );
+ writeBufferSize( data, bufferSize() );
+
+ if ( !apn().isEmpty() ) {
+ writeApn( data, apn() );
+ }
+
+ if ( !userLogin().isEmpty() ) {
+ writeTextString( data, userLogin(), QSimCommand::NoPduOptions, 0x0D );
+ }
+
+ if ( !userPassword().isEmpty() ) {
+ writeTextString( data, userPassword(), QSimCommand::NoPduOptions, 0x0D );
+ }
+ writeUti( data, uti() );
+ writeOtherAddress( data, destAddress() );
writeTextAttribute( data, textAttribute() );
}
break;
- case CloseChannel:
case ReceiveData:
+ {
+ if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+ writeEFADN( data, text(), options, 0x05 );
+ writeDataLength( data, dataLength() );
+ writeIcon( data, iconId(), iconSelfExplanatory(), true );
+ writeTextAttribute( data, textAttribute() );
+ }
+ break;
+
case SendData:
{
+ if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
+ writeEFADN( data, text(), options, 0x05 );
+ writeIcon( data, iconId(), iconSelfExplanatory(), true );
+ data += extData;
+ writeTextAttribute( data, textAttribute() );
+ }
+ break;
+
+ case CloseChannel:
+ case GetChannelStatus:
+ {
if ( !text().isEmpty() || ( options & QSimCommand::EncodeEmptyStrings ) != 0 )
writeEFADN( data, text(), options, 0x05 );
writeIcon( data, iconId(), iconSelfExplanatory(), true );
diff --git a/src/qsimcommand.h b/src/qsimcommand.h
index eadd768..2c55339 100644
--- a/src/qsimcommand.h
+++ b/src/qsimcommand.h
@@ -215,6 +215,16 @@ public:
Network = 0x83
};
+ enum OpenChannelQualifier {
+ OpenchannelOnDemand = 0x00,
+ OpenchannelImmediate = 0x01,
+ };
+
+ enum SendDataQualifier {
+ SendDataStoreData = 0x00,
+ SendDataImmediately = 0x01,
+ };
+
int commandNumber() const;
void setCommandNumber( int value );
@@ -362,6 +372,30 @@ public:
int qualifier() const;
void setQualifier( int value );
+ QByteArray bearerDesc() const;
+ void setBearerDesc( const QByteArray& value );
+
+ ushort bufferSize() const;
+ void setBufferSize( ushort value );
+
+ uint dataLength() const;
+ void setDataLength( uint value );
+
+ QByteArray apn() const;
+ void setApn( const QByteArray& value );
+
+ QByteArray destAddress() const;
+ void setDestAddress( const QByteArray& value );
+
+ QString userLogin() const;
+ void setUserLogin( const QString& value );
+
+ QString userPassword() const;
+ void setUserPassword( const QString& value );
+
+ QByteArray uti() const;
+ void setUti( const QByteArray& value );
+
QByteArray extensionData() const;
void setExtensionData( QByteArray value );
--
1.7.1
9 years, 9 months
[PATCH] TODO: set owner of HSP task
by Frédéric Dalleau
---
TODO | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/TODO b/TODO
index 9db9e0b..c4e78a6 100644
--- a/TODO
+++ b/TODO
@@ -142,6 +142,7 @@ Modem Emulator
Priority: Low
Complexity: C1
+ Owner: Frédéric Dalleau <frederic.dalleau(a)linux.intel.com>
- Support DUN emulator. Implement the Bluetooth DUN profile with only mandatory
AT command support. Implement USB DUN as well.
--
1.7.1
9 years, 9 months