[PATCH 01/15] Add parser for access technology objects
by Yang Gu
---
src/stkutil.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/src/stkutil.c b/src/stkutil.c
index 0d4be68..69d5a4a 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -1243,6 +1243,18 @@ static gboolean parse_dataobj_aid(struct comprehension_tlv_iter *iter,
return TRUE;
}
+/*
+ * Defined in TS 102.223 Section 8.61. According to it, the technology field
+ * can have at most 127 bytes. However, all the defined values are only 1 byte,
+ * so we just use 1 byte to represent it.
+ */
+static gboolean parse_dataobj_access_technology(
+ struct comprehension_tlv_iter *iter, void *user)
+{
+ unsigned char *byte = user;
+ return parse_dataobj_common_byte(iter, byte);
+}
+
/* Defined in TS 102.223 Section 8.72 */
static gboolean parse_dataobj_text_attr(struct comprehension_tlv_iter *iter,
void *user)
@@ -1393,6 +1405,8 @@ static dataobj_handler handler_for_type(enum stk_data_object_type type)
return parse_dataobj_uicc_te_interface;
case STK_DATA_OBJECT_TYPE_AID:
return parse_dataobj_aid;
+ case STK_DATA_OBJECT_TYPE_ACCESS_TECHNOLOGY:
+ return parse_dataobj_access_technology;
case STK_DATA_OBJECT_TYPE_TEXT_ATTRIBUTE:
return parse_dataobj_text_attr;
case STK_DATA_OBJECT_TYPE_FRAME_ID:
--
1.7.0.4
10 years, 8 months
[PATCH 01/17] Add parser for item text attribute list objects
by Yang Gu
---
src/stkutil.c | 20 ++++++++++++++++++++
src/stkutil.h | 6 ++++++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/src/stkutil.c b/src/stkutil.c
index 43c06cd..5b97aeb 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -1207,6 +1207,24 @@ static gboolean parse_dataobj_other_address(
return TRUE;
}
+/* Defined in TS 102.223 Section 8.59 */
+static gboolean parse_dataobj_uicc_te_interface(
+ struct comprehension_tlv_iter *iter, void *user)
+{
+ struct stk_uicc_te_interface *uti = user;
+ const unsigned char *data;
+ unsigned char len = comprehension_tlv_iter_get_length(iter);
+
+ if (len != 3)
+ return FALSE;
+
+ data = comprehension_tlv_iter_get_data(iter);
+ uti->protocol = data[0];
+ uti->port = (data[1] << 8) + data[2];
+
+ return TRUE;
+}
+
/* Defined in TS 102.223 Section 8.72 */
static gboolean parse_dataobj_text_attr(struct comprehension_tlv_iter *iter,
void *user)
@@ -1353,6 +1371,8 @@ static dataobj_handler handler_for_type(enum stk_data_object_type type)
return parse_dataobj_card_reader_id;
case STK_DATA_OBJECT_TYPE_OTHER_ADDRESS:
return parse_dataobj_other_address;
+ case STK_DATA_OBJECT_TYPE_UICC_TE_INTERFACE:
+ return parse_dataobj_uicc_te_interface;
case STK_DATA_OBJECT_TYPE_TEXT_ATTRIBUTE:
return parse_dataobj_text_attr;
case STK_DATA_OBJECT_TYPE_FRAME_ID:
diff --git a/src/stkutil.h b/src/stkutil.h
index 1c05440..1c7c970 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -570,6 +570,12 @@ struct stk_other_address {
unsigned char type;
};
+/* Defined in TS 102.223 Section 8.59 */
+struct stk_uicc_te_interface {
+ unsigned char protocol;
+ unsigned short port;
+};
+
/*
* According to 102.223 Section 8.72 the length of text attribute CTLV is 1
* byte. This means that the maximum size is 127 according to the rules
--
1.7.0.4
10 years, 8 months
[PATCH 7/8] Add AT driver for STK atom.
by Andrzej Zaborowski
---
Makefile.am | 1 +
drivers/atmodem/atmodem.c | 2 +
drivers/atmodem/atmodem.h | 3 +
drivers/atmodem/stk.c | 258 +++++++++++++++++++++++++++++++++++++++++++++
plugins/atgen.c | 2 +
plugins/phonesim.c | 3 +
6 files changed, 269 insertions(+), 0 deletions(-)
create mode 100644 drivers/atmodem/stk.c
diff --git a/Makefile.am b/Makefile.am
index 7a18c41..a506dba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -124,6 +124,7 @@ builtin_sources += $(gatchat_sources) \
drivers/atmodem/call-meter.c \
drivers/atmodem/network-registration.c \
drivers/atmodem/sim.c \
+ drivers/atmodem/stk.c \
drivers/atmodem/ussd.c \
drivers/atmodem/voicecall.c \
drivers/atmodem/call-barring.c \
diff --git a/drivers/atmodem/atmodem.c b/drivers/atmodem/atmodem.c
index 0ac8182..c88f6b2 100644
--- a/drivers/atmodem/atmodem.c
+++ b/drivers/atmodem/atmodem.c
@@ -45,6 +45,7 @@ static int atmodem_init(void)
at_ussd_init();
at_sms_init();
at_sim_init();
+ at_stk_init();
at_netreg_init();
at_cbs_init();
at_call_volume_init();
@@ -56,6 +57,7 @@ static int atmodem_init(void)
static void atmodem_exit(void)
{
+ at_stk_exit();
at_sim_exit();
at_sms_exit();
at_ussd_exit();
diff --git a/drivers/atmodem/atmodem.h b/drivers/atmodem/atmodem.h
index 1fb4bfa..2ee47f5 100644
--- a/drivers/atmodem/atmodem.h
+++ b/drivers/atmodem/atmodem.h
@@ -45,6 +45,9 @@ extern void at_call_barring_exit();
extern void at_sim_init();
extern void at_sim_exit();
+extern void at_stk_init();
+extern void at_stk_exit();
+
extern void at_sms_init();
extern void at_sms_exit();
diff --git a/drivers/atmodem/stk.c b/drivers/atmodem/stk.c
new file mode 100644
index 0000000..05c1138
--- /dev/null
+++ b/drivers/atmodem/stk.c
@@ -0,0 +1,258 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2008-2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/stk.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "atmodem.h"
+
+struct stk_data {
+ GAtChat *chat;
+};
+
+static const char *csim_prefix[] = { "+CSIM:", NULL };
+
+static void at_csim_envelope_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ GAtResultIter iter;
+ ofono_stk_envelope_cb_t cb = cbd->cb;
+ struct ofono_error error;
+ const guint8 *response;
+ gint rlen, len;
+
+ decode_at_error(&error, g_at_result_final_response(result));
+
+ if (!ok)
+ goto error;
+
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+CSIM:"))
+ goto error;
+
+ if (!g_at_result_iter_next_number(&iter, &rlen))
+ goto error;
+
+ if (!g_at_result_iter_next_hexstring(&iter, &response, &len))
+ goto error;
+
+ if (rlen != len * 2 || len < 2)
+ goto error;
+
+ if (response[len - 2] != 0x90 && response[len - 2] != 0x91)
+ goto error;
+
+ if (response[len - 2] == 0x90 && response[len - 1] != 0)
+ goto error;
+
+ DBG("csim_envelope_cb: %i", len);
+
+ cb(&error, response, len - 2, cbd->data);
+ return;
+
+error:
+ CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+}
+
+static void at_stk_envelope(struct ofono_stk *stk, int length,
+ const guint8 *command,
+ ofono_stk_envelope_cb_t cb, void *data)
+{
+ struct stk_data *sd = ofono_stk_get_data(stk);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ char *buf = g_try_new(char, 64 + length * 2);
+ int len, ret;
+
+ if (!cbd || !buf)
+ goto error;
+
+ len = sprintf(buf, "AT+CSIM=%i,A0C20000%02hhX",
+ 12 + length * 2, length);
+
+ for (; length; length--)
+ len += sprintf(buf + len, "%02hhX", *command++);
+
+ len += sprintf(buf + len, "FF");
+
+ ret = g_at_chat_send(sd->chat, buf, csim_prefix,
+ at_csim_envelope_cb, cbd, g_free);
+
+ g_free(buf);
+ buf = NULL;
+
+ if (ret > 0)
+ return;
+
+error:
+ if (buf)
+ g_free(buf);
+
+ if (cbd)
+ g_free(cbd);
+
+ CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+}
+
+static void at_csim_terminal_response_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ GAtResultIter iter;
+ ofono_stk_generic_cb_t cb = cbd->cb;
+ struct ofono_error error;
+ const guint8 *response;
+ gint rlen, len;
+
+ decode_at_error(&error, g_at_result_final_response(result));
+
+ if (!ok)
+ goto error;
+
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+CSIM:"))
+ goto error;
+
+ if (!g_at_result_iter_next_number(&iter, &rlen))
+ goto error;
+
+ if (!g_at_result_iter_next_hexstring(&iter, &response, &len))
+ goto error;
+
+ if (rlen != len * 2 || len < 2)
+ goto error;
+
+ if (response[len - 2] != 0x90 && response[len - 2] != 0x91)
+ goto error;
+
+ if (response[len - 2] == 0x90 && response[len - 1] != 0)
+ goto error;
+
+ DBG("csim_terminal_response_cb: %i", len);
+
+ cb(&error, cbd->data);
+ return;
+
+error:
+ CALLBACK_WITH_FAILURE(cb, cbd->data);
+}
+
+static void at_stk_terminal_response(struct ofono_stk *stk, int length,
+ const unsigned char *value, ofono_stk_generic_cb_t cb,
+ void *data)
+{
+ struct stk_data *sd = ofono_stk_get_data(stk);
+ struct cb_data *cbd = cb_data_new(cb, data);
+ char *buf = g_try_new(char, 64 + length * 2);
+ int len, ret;
+
+ if (!cbd || !buf)
+ goto error;
+
+ len = sprintf(buf, "AT+CSIM=%i,A0140000%02hhX",
+ 10 + length * 2, length);
+
+ for (; length; length--)
+ len += sprintf(buf + len, "%02hhX", *value++);
+
+ ret = g_at_chat_send(sd->chat, buf, csim_prefix,
+ at_csim_terminal_response_cb, cbd, g_free);
+
+ g_free(buf);
+ buf = NULL;
+
+ if (ret > 0)
+ return;
+
+error:
+ if (cbd)
+ g_free(cbd);
+
+ CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static gboolean at_stk_register(gpointer user)
+{
+ struct ofono_stk *stk = user;
+
+ ofono_stk_register(stk);
+
+ return FALSE;
+}
+
+static int at_stk_probe(struct ofono_stk *stk, unsigned int vendor,
+ void *data)
+{
+ GAtChat *chat = data;
+ struct stk_data *sd;
+
+ sd = g_new0(struct stk_data, 1);
+ sd->chat = chat;
+
+ ofono_stk_set_data(stk, sd);
+ g_idle_add(at_stk_register, stk);
+
+ return 0;
+}
+
+static void at_stk_remove(struct ofono_stk *stk)
+{
+ struct stk_data *sd = ofono_stk_get_data(stk);
+
+ ofono_stk_set_data(stk, NULL);
+
+ g_free(sd);
+}
+
+static struct ofono_stk_driver driver = {
+ .name = "atmodem",
+ .probe = at_stk_probe,
+ .remove = at_stk_remove,
+ .envelope = at_stk_envelope,
+ .terminal_response = at_stk_terminal_response,
+};
+
+void at_stk_init()
+{
+ ofono_stk_driver_register(&driver);
+}
+
+void at_stk_exit()
+{
+ ofono_stk_driver_unregister(&driver);
+}
diff --git a/plugins/atgen.c b/plugins/atgen.c
index ed963c2..262d32f 100644
--- a/plugins/atgen.c
+++ b/plugins/atgen.c
@@ -43,6 +43,7 @@
#include <ofono/netreg.h>
#include <ofono/phonebook.h>
#include <ofono/sim.h>
+#include <ofono/stk.h>
#include <ofono/sms.h>
#include <ofono/ssn.h>
#include <ofono/ussd.h>
@@ -163,6 +164,7 @@ static void atgen_pre_sim(struct ofono_modem *modem)
ofono_devinfo_create(modem, 0, "atmodem", chat);
sim = ofono_sim_create(modem, 0, "atmodem", chat);
ofono_voicecall_create(modem, 0, "atmodem", chat);
+ ofono_stk_create(modem, 0, "atmodem", chat);
if (sim)
ofono_sim_inserted_notify(sim, TRUE);
diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index 4c3b3ce..9153e1b 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -50,6 +50,7 @@
#include <ofono/netreg.h>
#include <ofono/phonebook.h>
#include <ofono/sim.h>
+#include <ofono/stk.h>
#include <ofono/sms.h>
#include <ofono/ssn.h>
#include <ofono/ussd.h>
@@ -289,6 +290,8 @@ static void phonesim_pre_sim(struct ofono_modem *modem)
else
ofono_voicecall_create(modem, 0, "atmodem", data->chat);
+ ofono_stk_create(modem, 0, "atmodem", data->chat);
+
if (sim)
ofono_sim_inserted_notify(sim, TRUE);
}
--
1.6.1
10 years, 9 months
[PATCH] phonesim: Free some resources after client disconnects.
by Andrzej Zaborowski
Also zero SimRules::toolkitApp to avoid segfaults before the field
is initialised.
Note there may be more places leaking resources.
---
src/phonesim.cpp | 22 ++++++++++++++++++++++
1 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/src/phonesim.cpp b/src/phonesim.cpp
index d363c29..d5d7d87 100644
--- a/src/phonesim.cpp
+++ b/src/phonesim.cpp
@@ -501,6 +501,7 @@ SimRules::SimRules( int fd, QObject *p, const QString& filename, HardwareManipu
{
setSocketDescriptor(fd);
machine = 0;
+ toolkitApp = 0;
if (hmf)
machine = hmf->create(this, 0);
@@ -554,6 +555,7 @@ SimRules::SimRules( int fd, QObject *p, const QString& filename, HardwareManipu
SimXmlHandler *handler = new SimXmlHandler();
if ( !readXmlFile( handler, filename ) ) {
qWarning() << filename << ": could not parse simulator rule file";
+ delete handler;
return;
}
@@ -837,6 +839,26 @@ void SimRules::tryReadCommand()
void SimRules::destruct()
{
+ if ( toolkitApp != defaultToolkitApp )
+ delete toolkitApp;
+ delete defaultToolkitApp;
+ toolkitApp = NULL;
+
+ if ( getMachine() )
+ getMachine()->handleNewApp();
+
+ if ( defState )
+ delete defState;
+ defState = NULL;
+
+ if ( _callManager )
+ delete _callManager;
+ _callManager = NULL;
+
+ if ( fileSystem )
+ delete fileSystem;
+ fileSystem = NULL;
+
if (machine) machine->deleteLater();
deleteLater();
}
--
1.6.1
10 years, 9 months
[PATCH] Add script for entering pin
by Daniel Wagner
---
I found this script helpful during debugging. Feel free to add.
test/enter-pin | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
create mode 100755 test/enter-pin
diff --git a/test/enter-pin b/test/enter-pin
new file mode 100755
index 0000000..792b6b2
--- /dev/null
+++ b/test/enter-pin
@@ -0,0 +1,26 @@
+#!/usr/bin/python
+
+import dbus
+import sys
+
+bus = dbus.SystemBus()
+
+if len(sys.argv) == 4:
+ path = sys.argv[1]
+ pin_type = sys.argv[2]
+ pin = sys.argv[3]
+elif len(sys.argv) == 3:
+ manager = dbus.Interface(bus.get_object('org.ofono', '/'),
+ 'org.ofono.Manager')
+ properties = manager.GetProperties()
+ path = properties["Modems"][0]
+ pin_type = sys.argv[1]
+ pin = sys.argv[2]
+else:
+ print "%s [PATH] pin_type pin" % (sys.argv[0])
+
+print "Enter Pin for modem %s..." % path
+simmanager = dbus.Interface(bus.get_object('org.ofono', path),
+ 'org.ofono.SimManager')
+
+simmanager.EnterPin(pin_type, pin)
--
1.6.6.1
10 years, 9 months
[PATCH] Added Wavecom modem plugin.
by Matthias
The Wavecom WMP100 assumes CPIN to be the final response, therefore some special handling is
neccessary (see 6d28f82dc1ccb3de3a028a88eafb96fb001c7e61). Now the vendor id OFONO_VENDOR_WAVECOM
is passed with all "*create" functions.
---
Makefile.am | 3 +
plugins/modemconf.c | 1 +
plugins/wavecom.c | 212 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 216 insertions(+), 0 deletions(-)
create mode 100644 plugins/wavecom.c
diff --git a/Makefile.am b/Makefile.am
index 0eaadda..9b4b31c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -187,6 +187,9 @@ builtin_sources += plugins/atgen.c
builtin_modules += g1
builtin_sources += plugins/g1.c
+builtin_modules += wavecom
+builtin_sources += plugins/wavecom.c
+
builtin_modules += calypso
builtin_sources += plugins/calypso.c
diff --git a/plugins/modemconf.c b/plugins/modemconf.c
index cf0ee8b..f38ca98 100644
--- a/plugins/modemconf.c
+++ b/plugins/modemconf.c
@@ -121,6 +121,7 @@ static struct {
{ "phonesim", set_address },
{ "atgen", set_device },
{ "g1", set_device },
+ { "wavecom", set_device },
{ "ste", set_device },
{ "calypso", set_device },
{ "palmpre", set_device },
diff --git a/plugins/wavecom.c b/plugins/wavecom.c
new file mode 100644
index 0000000..7beeb5b
--- /dev/null
+++ b/plugins/wavecom.c
@@ -0,0 +1,212 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2008-2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/call-barring.h>
+#include <ofono/call-forwarding.h>
+#include <ofono/call-meter.h>
+#include <ofono/call-settings.h>
+#include <ofono/devinfo.h>
+#include <ofono/message-waiting.h>
+#include <ofono/netreg.h>
+#include <ofono/phonebook.h>
+#include <ofono/sim.h>
+#include <ofono/sms.h>
+#include <ofono/ssn.h>
+#include <ofono/ussd.h>
+#include <ofono/voicecall.h>
+
+#include <drivers/atmodem/vendor.h>
+
+static const char *tty_opts[] = {
+ "Baud",
+ "Read",
+ "Local",
+ "StopBits",
+ "DataBits",
+ "Parity",
+ "XonXoff",
+ "RtsCts",
+ NULL,
+};
+
+static int wavecom_probe(struct ofono_modem *modem)
+{
+ return 0;
+}
+
+static void wavecom_remove(struct ofono_modem *modem)
+{
+}
+
+static void wavecom_debug(const char *str, void *user_data)
+{
+ ofono_info("%s", str);
+}
+
+static int wavecom_enable(struct ofono_modem *modem)
+{
+ GAtChat *chat;
+ GIOChannel *channel;
+ GAtSyntax *syntax;
+ const char *device;
+ const char *value;
+ GHashTable *options;
+ int i;
+
+ DBG("%p", modem);
+
+ device = ofono_modem_get_string(modem, "Device");
+ if (!device)
+ return -EINVAL;
+
+ options = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, g_free);
+ if (!options)
+ return -ENOMEM;
+
+ for (i = 0; tty_opts[i]; i++) {
+ value = ofono_modem_get_string(modem, tty_opts[i]);
+
+ if (value == NULL)
+ continue;
+
+ g_hash_table_insert(options, g_strdup(tty_opts[i]),
+ g_strdup(value));
+ }
+
+ channel = g_at_tty_open(device, options);
+
+ g_hash_table_destroy(options);
+
+ if (!channel) {
+ return -EIO;
+ }
+
+ value = ofono_modem_get_string(modem, "GsmSyntax");
+ if (value) {
+ if (g_str_equal(value, "V1"))
+ syntax = g_at_syntax_new_gsmv1();
+ else if (g_str_equal(value, "Permissive"))
+ syntax = g_at_syntax_new_gsm_permissive();
+ else
+ return -EINVAL;
+ } else {
+ syntax = g_at_syntax_new_gsmv1();
+ }
+
+ chat = g_at_chat_new(channel, syntax);
+ g_at_syntax_unref(syntax);
+ g_io_channel_unref(channel);
+
+ if (!chat)
+ return -ENOMEM;
+
+ if (getenv("OFONO_AT_DEBUG"))
+ g_at_chat_set_debug(chat, wavecom_debug, NULL);
+
+ ofono_modem_set_data(modem, chat);
+
+ return 0;
+}
+
+static int wavecom_disable(struct ofono_modem *modem)
+{
+ GAtChat *chat = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ ofono_modem_set_data(modem, NULL);
+
+ g_at_chat_unref(chat);
+
+ return 0;
+}
+
+static void wavecom_pre_sim(struct ofono_modem *modem)
+{
+ GAtChat *chat = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ ofono_devinfo_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_sim_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_voicecall_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+}
+
+static void wavecom_post_sim(struct ofono_modem *modem)
+{
+ GAtChat *chat = ofono_modem_get_data(modem);
+ struct ofono_message_waiting *mw;
+
+ DBG("%p", modem);
+
+ ofono_ussd_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_call_forwarding_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_call_settings_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_netreg_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_call_meter_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_call_barring_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_ssn_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_sms_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+ ofono_phonebook_create(modem, OFONO_VENDOR_WAVECOM, "atmodem", chat);
+
+ mw = ofono_message_waiting_create(modem);
+ if (mw)
+ ofono_message_waiting_register(mw);
+}
+
+static struct ofono_modem_driver wavecom_driver = {
+ .name = "wavecom",
+ .probe = wavecom_probe,
+ .remove = wavecom_remove,
+ .enable = wavecom_enable,
+ .disable = wavecom_disable,
+ .pre_sim = wavecom_pre_sim,
+ .post_sim = wavecom_post_sim,
+};
+
+static int wavecom_init(void)
+{
+ return ofono_modem_driver_register(&wavecom_driver);
+}
+
+static void wavecom_exit(void)
+{
+ ofono_modem_driver_unregister(&wavecom_driver);
+}
+
+OFONO_PLUGIN_DEFINE(wavecom, "Wavecom driver", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT, wavecom_init, wavecom_exit)
--
1.6.3.3
10 years, 9 months
[PATCH 0/2] hdlc fixes
by Kristen Carlson Accardi
Kristen Carlson Accardi (2):
hdlc: allow for scanning and escaping
hdlc: handle wrapped buffers
gatchat/gathdlc.c | 121 ++++++++++++++++++++++++++++++++++++++--------------
gatchat/gathdlc.h | 12 +++++
2 files changed, 100 insertions(+), 33 deletions(-)
10 years, 9 months
[PATCH 0/8] Prototype to integrate gatserver with oFono
by Zhenhua Zhang
These 8 patches are prototypes to integrate gatserver with oFono core:
1. Move watch_list into struct ofono_atom so that each component can be watched in an unique way.
2. Add src/emulator.c and dbus interface to create emulator.
3. Add at emulator plugin to watch call status and handle dial command request. Now it calls modem's "Dial" method through dbus interface, so it's not so effective. To avoid dbus method call, however, require big changes in ofono core code.
10 years, 9 months
[PATCH 2/2] phonesim: Refactor SimApplication api, add a UI.
by Andrzej Zaborowski
Try to move all the AT parsing / generating out of applications, just send
ready envelopes, terminal responses, commands between the application
and the SimRules class.
---
src/control.cpp | 35 +++++++++++
src/control.h | 1 +
src/controlbase.ui | 71 ++++++++++++++++++++++
src/hardwaremanipulator.cpp | 42 +++++++++++++
src/hardwaremanipulator.h | 7 ++
src/phonesim.cpp | 138 +++++++++++++++++++++++++++++++++++++++----
src/phonesim.h | 6 ++
src/simapplication.cpp | 137 ++++++++++++++----------------------------
src/simapplication.h | 27 +++++----
9 files changed, 349 insertions(+), 115 deletions(-)
diff --git a/src/control.cpp b/src/control.cpp
index c14909f..34a228f 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -49,6 +49,7 @@ public:
void handleFromData( const QString& );
void handleToData( const QString& );
+ void handleNewApp();
private slots:
void sendSQ();
@@ -70,6 +71,9 @@ private slots:
void sendEVMNotify();
void sendUSSD();
void cancelUSSD();
+ void simInsertRemove();
+ void simAppStart();
+ void simAppAbort();
signals:
void unsolicitedCommand(const QString &);
@@ -134,12 +138,17 @@ ControlWidget::ControlWidget(const QString &ruleFile, Control *parent)
connect(ui->pbNotifyUDHEnhanced, SIGNAL(clicked()), this, SLOT(sendEVMNotify()));
connect(ui->pbSendUSSD, SIGNAL(clicked()), this, SLOT(sendUSSD()));
connect(ui->pbCancelUSSD, SIGNAL(clicked()), this, SLOT(cancelUSSD()));
+ connect(ui->cbSimInserted, SIGNAL(clicked()), this, SLOT(simInsertRemove()));
+ connect(ui->pbStart, SIGNAL(clicked()), this, SLOT(simAppStart()));
+ connect(ui->pbAbort, SIGNAL(clicked()), this, SLOT(simAppAbort()));
QStringList headers;
headers << "Sender" << "Priority" << "Notification Status";
ui->twMessageList->setHorizontalHeaderLabels( headers );
ui->twMessageList->verticalHeader()->hide();
+ handleNewApp();
+
show();
}
@@ -473,3 +482,29 @@ void ControlWidget::cancelUSSD()
ui->lblResponse->setText( "" );
ui->leUSSDString->setText( "" );
}
+
+void ControlWidget::simInsertRemove()
+{
+ p->setSimPresent( ui->cbSimInserted->isChecked() );
+}
+
+void ControlWidget::handleNewApp()
+{
+ ui->lblApplicationName->setText( "Current application: " +
+ p->getSimAppName() );
+}
+
+void Control::handleNewApp()
+{
+ widget->handleNewApp();
+}
+
+void ControlWidget::simAppStart()
+{
+ p->simAppStart();
+}
+
+void ControlWidget::simAppAbort()
+{
+ p->simAppAbort();
+}
diff --git a/src/control.h b/src/control.h
index e8b20a9..32db57e 100644
--- a/src/control.h
+++ b/src/control.h
@@ -36,6 +36,7 @@ public slots:
void handleFromData( const QString& );
void handleToData( const QString& );
void setPhoneNumber( const QString& );
+ void handleNewApp();
protected:
virtual void warning( const QString&, const QString& );
diff --git a/src/controlbase.ui b/src/controlbase.ui
index a0468f2..eca1898 100644
--- a/src/controlbase.ui
+++ b/src/controlbase.ui
@@ -1370,6 +1370,77 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tab_6" >
+ <attribute name="title" >
+ <string>SIM</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>9</number>
+ </property>
+ <property name="topMargin" >
+ <number>9</number>
+ </property>
+ <property name="rightMargin" >
+ <number>9</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>9</number>
+ </property>
+ <item>
+ <widget class="QGroupBox" name="gbCard" >
+ <property name="title" >
+ <string>Card</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QCheckBox" name="cbSimInserted" >
+ <property name="text" >
+ <string>Card inserted</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="gbSATK" >
+ <property name="title" >
+ <string>Application</string>
+ </property>
+ <layout class="QHBoxLayout" >
+ <item>
+ <widget class="QPushButton" name="pbStart" >
+ <property name="text" >
+ <string>Start</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="pbAbort" >
+ <property name="text" >
+ <string>Abort</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="lblApplicationName" >
+ <property name="toolTip" >
+ <string>Shows current selected application's name</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
diff --git a/src/hardwaremanipulator.cpp b/src/hardwaremanipulator.cpp
index 61b98f3..f7b13e9 100644
--- a/src/hardwaremanipulator.cpp
+++ b/src/hardwaremanipulator.cpp
@@ -28,6 +28,7 @@
#include <qwsppdu.h>
#include <qatutils.h>
#include <phonesim.h>
+#include <simapplication.h>
#define NIBBLE_MAX 15
#define TWO_BYTE_MAX 65535
@@ -56,6 +57,7 @@ void HardwareManipulator::warning( const QString &title, const QString &message)
void HardwareManipulator::setPhoneNumber( const QString& )
{
+ simPresent = true;
}
QString PS_toHex( const QByteArray& binary );
@@ -290,3 +292,43 @@ void HardwareManipulator::sendUSSD( bool cancel, bool response,
QString::number( response ? 1 : 0 ) + ",\"" +
QAtUtils::quote( content, codec ) + "\",0" );
}
+
+bool HardwareManipulator::getSimPresent()
+{
+ return simPresent;
+}
+
+void HardwareManipulator::setSimPresent( bool present )
+{
+ simPresent = present;
+}
+
+QString HardwareManipulator::getSimAppName()
+{
+ SimApplication *app = rules->simApplication();
+
+ if (app)
+ return app->getName();
+
+ return "None";
+}
+
+void HardwareManipulator::handleNewApp()
+{
+}
+
+void HardwareManipulator::simAppStart()
+{
+ SimApplication *app = rules->simApplication();
+
+ if (app)
+ return app->start();
+}
+
+void HardwareManipulator::simAppAbort()
+{
+ SimApplication *app = rules->simApplication();
+
+ if (app)
+ return app->abort();
+}
diff --git a/src/hardwaremanipulator.h b/src/hardwaremanipulator.h
index 7b59167..6571c06 100644
--- a/src/hardwaremanipulator.h
+++ b/src/hardwaremanipulator.h
@@ -34,6 +34,8 @@ Q_OBJECT
public:
HardwareManipulator(SimRules *sr, QObject *parent=0);
QSMSMessageList & getSMSList();
+ bool getSimPresent();
+ QString getSimAppName();
public slots:
virtual void handleFromData( const QString& );
@@ -43,6 +45,10 @@ public slots:
virtual void sendSMS( const QSMSMessage& m );
virtual void sendVMNotify( int type, int count, const QList<QVMMessage> &received, const QList<QVMMessage> &deleted, const QString &mailbox );
virtual void sendUSSD( bool cancel, bool response, const QString &content );
+ virtual void setSimPresent( bool present );
+ virtual void simAppStart();
+ virtual void simAppAbort();
+ virtual void handleNewApp();
signals:
void unsolicitedCommand(const QString &cmd);
@@ -63,6 +69,7 @@ protected:
private:
QSMSMessageList SMSList;
SimRules *rules;
+ bool simPresent;
};
class HardwareManipulatorFactory
diff --git a/src/phonesim.cpp b/src/phonesim.cpp
index a1d3546..d363c29 100644
--- a/src/phonesim.cpp
+++ b/src/phonesim.cpp
@@ -544,10 +544,11 @@ SimRules::SimRules( int fd, QObject *p, const QString& filename, HardwareManipu
currentChannel = 1;
incomingUsed = 0;
lineUsed = 0;
- defaultToolkitApp = toolkitApp = new DemoSimApplication( this );
- toolkitApp->setSimRules( this );
+ defaultToolkitApp = toolkitApp = new DemoSimApplication( this, this );
connect( _callManager, SIGNAL(controlEvent(QSimControlEvent)),
toolkitApp, SLOT(controlEvent(QSimControlEvent)) );
+ if ( machine )
+ machine->handleNewApp();
// Load the simulator rules into memory as a DOM-like tree.
SimXmlHandler *handler = new SimXmlHandler();
@@ -857,8 +858,10 @@ void SimRules::setSimApplication( SimApplication *app )
if ( toolkitApp != defaultToolkitApp )
delete toolkitApp;
toolkitApp = ( app ? app : defaultToolkitApp );
- toolkitApp->setSimRules( this );
toolkitApp->start();
+
+ if ( getMachine() )
+ getMachine()->handleNewApp();
}
void SimRules::switchTo(const QString& name)
@@ -890,23 +893,111 @@ SimState *SimRules::state( const QString& name ) const
return 0;
}
+bool SimRules::simCsimOk( const QByteArray& payload )
+{
+ unsigned char sw1 = 0x90;
+ unsigned char sw2 = 0x00;
+ QByteArray resp = payload;
+
+ if ( toolkitApp ) {
+ QByteArray cmd = toolkitApp->fetch();
+ if ( !cmd.isEmpty() )
+ sw1 = 0x91;
+ sw2 = cmd.size();
+ }
+
+ resp += sw1;
+ resp += sw2;
+ respond( "+CSIM: " + QString::number( resp.size() * 2 ) + "," +
+ QAtUtils::toHex( resp ) + "\\n\\nOK" );
+
+ return true;
+}
bool SimRules::simCommand( const QString& cmd )
{
+ /* Process SIM toolkit begin and end commands by forcing the
+ * app back to the main menu. */
+ if ( cmd == "AT*TSTB" || cmd == "AT*TSTE" ) {
+ if ( !toolkitApp ) {
+ respond( "ERROR" );
+ return true;
+ }
+
+ respond( "OK" );
+ toolkitApp->abort();
+ return true;
+ }
+
// If not AT+CSIM, then this is not a SIM toolkit command.
if ( !cmd.startsWith( "AT+CSIM=" ) )
return false;
+ if ( getMachine() && !getMachine()->getSimPresent() )
+ return true;
+
// Extract the binary payload of the AT+CSIM command.
int comma = cmd.indexOf( QChar(',') );
if ( comma < 0 )
return false;
QByteArray param = QAtUtils::fromHex( cmd.mid(comma + 1) );
- if ( param.length() < 5 || param[0] != (char)0xA0 )
+
+ if ( param.length() < 4 ) {
+ /* Wrong length */
+ respond( "+CSIM: 4,6700\\n\\nOK" );
return false;
+ }
+
+ if ( param[0] != (char)0xA0 ) {
+ /* CLA not supported */
+ respond( "+CSIM: 4,6800\\n\\nOK" );
+ return false;
+ }
// Determine what kind of command we are dealing with.
- if ( param[1] == (char)0x2C && param[4] == (char)0x10 && param.size() >= 21 ) {
+ // Check for TERMINAL PROFILE, FETCH, TERMINAL RESPONSE,
+ // ENVELOPE and UNBLOCK CHV packets.
+ if ( param[1] == (char)0x10 ) {
+ /* Abort the SIM application and force it to return to the main menu. */
+ if ( toolkitApp )
+ toolkitApp->abort();
+
+ /* Download of a TERMINAL PROFILE. We respond with a simple OK,
+ * on the assumption that what we were sent was valid. */
+ return simCsimOk( QByteArray() );
+ } else if ( param[1] == (char)0x12 ) {
+ if ( !toolkitApp ) {
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
+ return true;
+ }
+
+ /* Fetch the current command contents. */
+ QByteArray resp = toolkitApp->fetch( true );
+ if ( resp.isEmpty() ) {
+ /* We weren't expecting a FETCH. */
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
+ return true;
+ }
+
+ return simCsimOk( resp );
+ } else if ( param.length() >= 5 && param[1] == (char)0x14 ) {
+ if ( !toolkitApp ) {
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
+ return true;
+ }
+
+ /* Process a TERMINAL RESPONSE message. */
+ QSimTerminalResponse resp =
+ QSimTerminalResponse::fromPdu( param.mid(5) );
+
+ if ( toolkitApp->response( resp ) )
+ return simCsimOk( QByteArray() );
+
+ /* Response to the wrong type of command. */
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
+ return true;
+ } else if ( param.length() >= 5 && param[1] == (char)0x2c &&
+ param[4] == (char)0x10 && param.size() >= 21 ) {
// UNBLOCK CHV command, for resetting a PIN using a PUK.
QString pinName = "PINVALUE";
QString pukName = "PUKVALUE";
@@ -924,13 +1015,32 @@ bool SimRules::simCommand( const QString& cmd )
respond( "+CSIM: 4,9804\\n\\nOK" );
} else {
setVariable( pinName, QString::fromUtf8( pinValue ) );
- respond( "+CSIM: 4,9000\\n\\nOK" );
+ simCsimOk( QByteArray() );
+ }
+
+ return true;
+ } else if ( param.length() >= 5 && param[1] == (char)0xC2 ) {
+ /* ENVELOPE */
+ if ( !toolkitApp ) {
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
+ return true;
}
+
+ QSimEnvelope env = QSimEnvelope::fromPdu( param.mid(5) );
+ if ( toolkitApp->envelope( env ) )
+ return simCsimOk( QByteArray() );
+
+ /* Envelope not supported or current command doesn't allow envelopes. */
+ respond( "+CSIM: 4,6F00\\n\\nOK" );
return true;
+ } else if ( param[1] == (char)0xf2 ) {
+ /* STATUS command, for now ignore the parameters */
+ return simCsimOk( QByteArray() );
}
// Don't know this SIM command.
- return false;
+ respond( "+CSIM: 4,6D00\\n\\nOK" );
+ return true;
}
void SimRules::command( const QString& cmd )
@@ -943,10 +1053,6 @@ void SimRules::command( const QString& cmd )
return;
// Process SIM toolkit related commands with the current SIM application.
- if ( toolkitApp && toolkitApp->execute( cmd ) )
- return;
-
- // Process other SIM commands sent via AT+CSIM.
if ( simCommand( cmd ) )
return;
@@ -1458,6 +1564,16 @@ void SimRules::respond( const QString& resp, int delay, bool eol )
getMachine()->handleFromData(QString(escaped));
}
+void SimRules::proactiveCommandNotify( const QByteArray& cmd )
+{
+ unsolicited( "*TCMD: " + QString::number( cmd.size() ) );
+}
+
+void SimRules::callControlEventNotify( const QSimControlEvent& evt )
+{
+ unsolicited( "*TCC: " + QString::number( (int) (evt.type()) ) +
+ "," + QAtUtils::toHex( evt.toPdu() ) );
+}
void SimRules::delayTimeout()
{
diff --git a/src/phonesim.h b/src/phonesim.h
index d48b48e..cb7a5e1 100644
--- a/src/phonesim.h
+++ b/src/phonesim.h
@@ -31,6 +31,7 @@
#include <qmap.h>
#include <qtimer.h>
#include <qpointer.h>
+#include <qsimcontrolevent.h>
#include <string.h>
#include <stdlib.h>
@@ -307,6 +308,9 @@ public slots:
// Send a response line.
void respond( const QString& resp ) { respond( resp, 0 ); }
+ void proactiveCommandNotify( const QByteArray& cmd );
+ void callControlEventNotify( const QSimControlEvent& event );
+
private slots:
void tryReadCommand();
void destruct();
@@ -352,6 +356,8 @@ private:
QMap< QString, SimPhoneBook * > phoneBooks;
CallManager *_callManager;
+
+ bool simCsimOk( const QByteArray& payload );
};
diff --git a/src/simapplication.cpp b/src/simapplication.cpp
index 09825ab..5212030 100644
--- a/src/simapplication.cpp
+++ b/src/simapplication.cpp
@@ -26,7 +26,6 @@ class SimApplicationPrivate
public:
SimApplicationPrivate()
{
- rules = 0;
expectedType = QSimCommand::NoCommand;
target = 0;
slot = 0;
@@ -41,10 +40,11 @@ public:
bool inResponse;
};
-SimApplication::SimApplication( QObject *parent )
+SimApplication::SimApplication( SimRules *rules, QObject *parent )
: QObject( parent )
{
d = new SimApplicationPrivate();
+ d->rules = rules;
}
SimApplication::~SimApplication()
@@ -80,8 +80,7 @@ void SimApplication::command( const QSimCommand& cmd,
// the middle of processing a TERMINAL RESPONSE or ENVELOPE,
// then delay the unsolicited notification until later.
if ( d->rules && !d->inResponse ) {
- d->rules->unsolicited
- ( "*TCMD: " + QString::number( d->currentCommand.size() ) );
+ d->rules->proactiveCommandNotify( d->currentCommand );
}
}
@@ -90,11 +89,8 @@ void SimApplication::command( const QSimCommand& cmd,
*/
void SimApplication::controlEvent( const QSimControlEvent& event )
{
- if ( d->rules ) {
- d->rules->unsolicited
- ( "*TCC: " + QString::number( (int)(event.type()) ) +
- "," + QAtUtils::toHex( event.toPdu() ) );
- }
+ if ( d->rules )
+ d->rules->callControlEventNotify( event );
}
/*!
@@ -160,99 +156,49 @@ void SimApplication::mainMenuHelpRequest( int id )
mainMenu();
}
-void SimApplication::setSimRules( SimRules *rules )
+bool SimApplication::envelope( const QSimEnvelope& env )
{
- d->rules = rules;
-}
-
-bool SimApplication::execute( const QString& cmd )
-{
- // Process SIM toolkit begin and end commands by forcing the app back to the main menu.
- if ( cmd == "AT*TSTB" || cmd == "AT*TSTE") {
- d->rules->respond( "OK" );
- abort();
+ /* Process a menu selection ENVELOPE message. We turn it into a
+ * QSimTerminalResponse to make it easier to process. */
+ if ( env.type() == QSimEnvelope::EventDownload )
return true;
- }
- // If not AT+CSIM, then this is not a SIM toolkit command.
- if ( !cmd.startsWith( "AT+CSIM=" ) )
+ if ( env.type() != QSimEnvelope::MenuSelection )
+ /* Not supported */
return false;
- // Extract the binary payload of the AT+CSIM command.
- int comma = cmd.indexOf( QChar(',') );
- if ( comma < 0 )
- return false;
- QByteArray param = QAtUtils::fromHex( cmd.mid(comma + 1) );
- if ( param.length() < 5 || param[0] != (char)0xA0 )
+ if ( d->expectedType != QSimCommand::SetupMenu )
+ /* Envelope sent for the wrong type of command. */
return false;
- // Check for TERMINAL PROFILE, FETCH, TERMINAL RESPONSE,
- // and ENVELOPE packets.
- if ( param[1] == (char)0x10 ) {
- // Download of a TERMINAL PROFILE. We respond with a simple OK,
- // on the assumption that what we were sent was valid.
- d->rules->respond( "+CSIM: 4,9000\\n\\nOK" );
+ d->expectedType = QSimCommand::NoCommand;
+ d->currentCommand = QByteArray();
+ d->target = 0;
+ d->slot = 0;
+ if ( env.requestHelp() )
+ mainMenuHelpRequest( env.menuItem() );
+ else
+ mainMenuSelection( env.menuItem() );
- // Abort the SIM application and force it to return to the main menu.
- abort();
- } else if ( param[1] == (char)0x12 ) {
- // Fetch the current command contents.
- QByteArray resp = d->currentCommand;
- if ( resp.isEmpty() ) {
- // We weren't expecting a FETCH.
- d->rules->respond( "+CSIM: 4,6F00\\n\\nOK" );
- return true;
- }
- resp += (char)0x90;
- resp += (char)0x00;
- d->rules->respond( "+CSIM: " + QString::number( resp.size() * 2 ) + "," +
- QAtUtils::toHex( resp ) + "\\n\\nOK" );
- } else if ( param[1] == (char)0x14 ) {
- // Process a TERMINAL RESPONSE message.
- QSimTerminalResponse resp;
- resp = QSimTerminalResponse::fromPdu( param.mid(5) );
- if ( resp.command().type() != QSimCommand::NoCommand &&
- resp.command().type() != d->expectedType ) {
- // Response to the wrong type of command.
- d->rules->respond( "+CSIM: 4,6F00\\n\\nOK" );
- return true;
- }
- response( resp );
- } else if ( param[1] == (char)0xC2 ) {
- // Process a menu selection ENVELOPE message. We turn it into a
- // QSimTerminalResponse to make it easier to process.
- QSimEnvelope env;
- env = QSimEnvelope::fromPdu( param.mid(5) );
- if ( env.type() == QSimEnvelope::EventDownload ) {
- d->rules->respond( "+CSIM: 4,9000\\n\\nOK" );
- return true;
- }
- if ( env.type() != QSimEnvelope::MenuSelection )
- return false;
- if ( d->expectedType != QSimCommand::SetupMenu ) {
- // Envelope sent for the wrong type of command.
- d->rules->respond( "+CSIM: 4,6F00\\n\\nOK" );
- return true;
- }
- d->rules->respond( "+CSIM: 4,9000\\n\\nOK" );
- d->expectedType = QSimCommand::NoCommand;
+ return true;
+}
+
+QByteArray SimApplication::fetch( bool clear )
+{
+ QByteArray resp = d->currentCommand;
+
+ if ( clear )
d->currentCommand = QByteArray();
- d->target = 0;
- d->slot = 0;
- if ( env.requestHelp() )
- mainMenuHelpRequest( env.menuItem() );
- else
- mainMenuSelection( env.menuItem() );
- } else {
- // This SIM command is not related to SIM toolkit - ignore it.
- return false;
- }
- return true;
+ return resp;
}
-void SimApplication::response( const QSimTerminalResponse& resp )
+bool SimApplication::response( const QSimTerminalResponse& resp )
{
+ if ( resp.command().type() != QSimCommand::NoCommand &&
+ resp.command().type() != d->expectedType )
+ return false;
+
// Save the target information.
QObject *target = d->target;
const char *slot = d->slot;
@@ -284,7 +230,7 @@ void SimApplication::response( const QSimTerminalResponse& resp )
// Answer the AT+CSIM command and send notification of the new command.
if ( !d->rules )
- return;
+ return false;////
if ( d->currentCommand.isEmpty() || resp.command().type() == QSimCommand::SetupMenu ) {
// No new command, so respond with a simple OK.
d->rules->respond( "+CSIM: 4,9000\\n\\nOK" );
@@ -300,10 +246,12 @@ void SimApplication::response( const QSimTerminalResponse& resp )
d->rules->unsolicited
( "*TCMD: " + QString::number( d->currentCommand.size() ) );
}
+
+ return true;
}
-DemoSimApplication::DemoSimApplication( QObject *parent )
- : SimApplication( parent )
+DemoSimApplication::DemoSimApplication( SimRules *rules, QObject *parent )
+ : SimApplication( rules, parent )
{
}
@@ -311,6 +259,11 @@ DemoSimApplication::~DemoSimApplication()
{
}
+const QString DemoSimApplication::getName()
+{
+ return "Demo SIM Application";
+}
+
#define MainMenu_News 1
#define MainMenu_Sports 2
#define MainMenu_Time 3
diff --git a/src/simapplication.h b/src/simapplication.h
index 3fd5bcb..1cfcbe4 100644
--- a/src/simapplication.h
+++ b/src/simapplication.h
@@ -31,41 +31,44 @@ class SimApplicationPrivate;
class SimApplication : public QObject
{
Q_OBJECT
- friend class SimRules;
public:
- SimApplication( QObject *parent = 0 );
+ SimApplication( SimRules *rules, QObject *parent = 0 );
~SimApplication();
- void command( const QSimCommand& cmd,
- QObject *target, const char *slot,
- QSimCommand::ToPduOptions options
- = QSimCommand::NoPduOptions );
+ virtual bool envelope( const QSimEnvelope& env );
+ virtual bool response( const QSimTerminalResponse& resp );
+ virtual QByteArray fetch( bool clear = false );
+
+ virtual const QString getName() = 0;
public slots:
- void controlEvent( const QSimControlEvent& event );
virtual void start();
virtual void abort();
protected slots:
+ void command( const QSimCommand& cmd,
+ QObject *target, const char *slot,
+ QSimCommand::ToPduOptions options
+ = QSimCommand::NoPduOptions );
+ void controlEvent( const QSimControlEvent& event );
+
virtual void mainMenu() = 0;
virtual void mainMenuSelection( int id );
virtual void mainMenuHelpRequest( int id );
private:
SimApplicationPrivate *d;
-
- void setSimRules( SimRules *rules );
- bool execute( const QString& cmd );
- void response( const QSimTerminalResponse& resp );
};
class DemoSimApplication : public SimApplication
{
Q_OBJECT
public:
- DemoSimApplication( QObject *parent = 0 );
+ DemoSimApplication( SimRules *rules, QObject *parent = 0 );
~DemoSimApplication();
+ const QString getName();
+
protected slots:
void mainMenu();
void mainMenuSelection( int id );
--
1.6.1
10 years, 9 months
[PATCH 1/2] phonesim: Add a simple USSD UI.
by Andrzej Zaborowski
This is not the best UI in the world...
---
src/control.cpp | 40 +++++++++++++++++++++++-
src/control.h | 6 ++--
src/controlbase.ui | 70 +++++++++++++++++++++++++++++++++++++++++++
src/hardwaremanipulator.cpp | 19 ++++++++++-
src/hardwaremanipulator.h | 9 ++++--
src/phonesim.cpp | 2 +-
6 files changed, 135 insertions(+), 11 deletions(-)
diff --git a/src/control.cpp b/src/control.cpp
index b897b9e..c14909f 100644
--- a/src/control.cpp
+++ b/src/control.cpp
@@ -68,6 +68,8 @@ private slots:
void delVoicemail();
void sendVMNotify( int type = 0 );
void sendEVMNotify();
+ void sendUSSD();
+ void cancelUSSD();
signals:
void unsolicitedCommand(const QString &);
@@ -130,6 +132,8 @@ ControlWidget::ControlWidget(const QString &ruleFile, Control *parent)
connect(ui->pbRemoveMessage, SIGNAL(clicked()), this, SLOT(delVoicemail()));
connect(ui->pbNotifyUDH, SIGNAL(clicked()), this, SLOT(sendVMNotify()));
connect(ui->pbNotifyUDHEnhanced, SIGNAL(clicked()), this, SLOT(sendEVMNotify()));
+ connect(ui->pbSendUSSD, SIGNAL(clicked()), this, SLOT(sendUSSD()));
+ connect(ui->pbCancelUSSD, SIGNAL(clicked()), this, SLOT(cancelUSSD()));
QStringList headers;
headers << "Sender" << "Priority" << "Notification Status";
@@ -145,8 +149,9 @@ void ControlWidget::closeEvent(QCloseEvent *event)
hide();
}
-Control::Control(const QString& ruleFile, QObject *parent)
- : HardwareManipulator(parent), widget(new ControlWidget(ruleFile, this))
+Control::Control(const QString& ruleFile, SimRules *sr, QObject *parent)
+ : HardwareManipulator(sr, parent),
+ widget(new ControlWidget(ruleFile, this))
{
QList<QByteArray> proxySignals;
proxySignals
@@ -339,6 +344,18 @@ void ControlWidget::handleToData( const QString& cmd )
ui->atViewer->append( dataItem + " : " + translator->translateCommand(dataItem) );
}
}
+
+ if ( cmd.startsWith("AT+CUSD=") ) {
+ int comma = cmd.indexOf( QChar(',') );
+ if ( comma >= 0 ) {
+ QString content = cmd.mid(comma + 1);
+ content.remove( QChar('"') );
+ ui->lblResponse->setText( content );
+ }
+
+ if ( cmd.startsWith("AT+CUSD=2") )
+ ui->lblResponse->setText( "" );
+ }
}
void Control::handleToData( const QString& cmd )
@@ -437,3 +454,22 @@ ControlWidget::VoicemailItem::VoicemailItem( const QString &from, bool urgent )
id = nextId++;
}
+
+void ControlWidget::sendUSSD()
+{
+ bool ask = ui->chkAskResponse->isChecked();
+ QString text = ui->leUSSDString->text();
+
+ p->sendUSSD( false, ask, text );
+
+ ui->lblResponse->setText( "" );
+ ui->leUSSDString->setText( "" );
+}
+
+void ControlWidget::cancelUSSD()
+{
+ p->sendUSSD( true, false, "" );
+
+ ui->lblResponse->setText( "" );
+ ui->leUSSDString->setText( "" );
+}
diff --git a/src/control.h b/src/control.h
index 8d712fc..e8b20a9 100644
--- a/src/control.h
+++ b/src/control.h
@@ -29,7 +29,7 @@ class Control: public HardwareManipulator
Q_OBJECT
public:
- Control(const QString& ruleFile, QObject *parent=0);
+ Control(const QString& ruleFile, SimRules *sr, QObject *parent=0);
virtual ~Control();
public slots:
@@ -48,8 +48,8 @@ private:
class ControlFactory : public HardwareManipulatorFactory
{
public:
- inline virtual HardwareManipulator *create(QObject *parent)
- { return new Control(ruleFile(), parent); }
+ inline virtual HardwareManipulator *create(SimRules *sr, QObject *parent)
+ { return new Control(ruleFile(), sr, parent); }
};
diff --git a/src/controlbase.ui b/src/controlbase.ui
index bdaf3b4..a0468f2 100644
--- a/src/controlbase.ui
+++ b/src/controlbase.ui
@@ -1300,6 +1300,76 @@ p, li { white-space: pre-wrap; }
</item>
</layout>
</widget>
+ <widget class="QWidget" name="tab_5" >
+ <attribute name="title" >
+ <string>USSD</string>
+ </attribute>
+ <layout class="QVBoxLayout" >
+ <property name="spacing" >
+ <number>6</number>
+ </property>
+ <property name="leftMargin" >
+ <number>9</number>
+ </property>
+ <property name="topMargin" >
+ <number>9</number>
+ </property>
+ <property name="rightMargin" >
+ <number>9</number>
+ </property>
+ <property name="bottomMargin" >
+ <number>9</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" >
+ <item row="0" column="0" >
+ <widget class="QCheckBox" name="chkAskResponse" >
+ <property name="text" >
+ <string>Request response</string>
+ </property>
+ <property name="checked" >
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QLineEdit" name="leUSSDString" >
+ <property name="inputMask" >
+ <string/>
+ </property>
+ <property name="maxLength" >
+ <number>120</number>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2" >
+ <widget class="QPushButton" name="pbSendUSSD" >
+ <property name="text" >
+ <string>Send</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QLabel" name="lblResponse" >
+ <property name="toolTip" >
+ <string>User response</string>
+ </property>
+ <property name="text" >
+ <string></string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2" >
+ <widget class="QPushButton" name="pbCancelUSSD" >
+ <property name="text" >
+ <string>Cancel session</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
</widget>
</item>
<item>
diff --git a/src/hardwaremanipulator.cpp b/src/hardwaremanipulator.cpp
index b5d4465..61b98f3 100644
--- a/src/hardwaremanipulator.cpp
+++ b/src/hardwaremanipulator.cpp
@@ -26,6 +26,8 @@
#include <qcbsmessage.h>
#include <qgsmcodec.h>
#include <qwsppdu.h>
+#include <qatutils.h>
+#include <phonesim.h>
#define NIBBLE_MAX 15
#define TWO_BYTE_MAX 65535
@@ -36,8 +38,8 @@
#define ONE_CHAR 1
#define HEX_BASE 16
-HardwareManipulator::HardwareManipulator(QObject *parent)
- : QObject(parent)
+HardwareManipulator::HardwareManipulator(SimRules *sr, QObject *parent)
+ : QObject(parent), rules(sr)
{
}
@@ -275,3 +277,16 @@ void HardwareManipulator::sendVMNotify( int type, int count, const QList<QVMMess
sendSMS( m );
}
+
+void HardwareManipulator::sendUSSD( bool cancel, bool response,
+ const QString &content )
+{
+ QTextCodec *codec = QAtUtils::codec( rules->variable("SCS") );
+ /* TODO: if rules->variable("USD") == "0" then return */
+ if (cancel)
+ emit unsolicitedCommand( "+CUSD: 2" );
+ else
+ emit unsolicitedCommand( "+CUSD: " +
+ QString::number( response ? 1 : 0 ) + ",\"" +
+ QAtUtils::quote( content, codec ) + "\",0" );
+}
diff --git a/src/hardwaremanipulator.h b/src/hardwaremanipulator.h
index 64a8d8e..7b59167 100644
--- a/src/hardwaremanipulator.h
+++ b/src/hardwaremanipulator.h
@@ -26,12 +26,13 @@
class QSMSMessage;
class QVMMessage;
+class SimRules;
class HardwareManipulator : public QObject
{
Q_OBJECT
public:
- HardwareManipulator(QObject *parent=0);
+ HardwareManipulator(SimRules *sr, QObject *parent=0);
QSMSMessageList & getSMSList();
public slots:
@@ -41,6 +42,7 @@ public slots:
virtual void constructSMSMessage(const int type, const QString &sender, const QString &serviceCenter, const QString &text);
virtual void sendSMS( const QSMSMessage& m );
virtual void sendVMNotify( int type, int count, const QList<QVMMessage> &received, const QList<QVMMessage> &deleted, const QString &mailbox );
+ virtual void sendUSSD( bool cancel, bool response, const QString &content );
signals:
void unsolicitedCommand(const QString &cmd);
@@ -60,14 +62,15 @@ protected:
private:
QSMSMessageList SMSList;
+ SimRules *rules;
};
class HardwareManipulatorFactory
{
public:
virtual ~HardwareManipulatorFactory() {};
- inline virtual HardwareManipulator *create(QObject *p)
- { return new HardwareManipulator(p); }
+ inline virtual HardwareManipulator *create(SimRules *sr, QObject *p)
+ { return new HardwareManipulator(sr, p); }
QString ruleFile() const { return ruleFilename; }
void setRuleFile(const QString& filename) { ruleFilename = filename; }
diff --git a/src/phonesim.cpp b/src/phonesim.cpp
index 885ff9f..a1d3546 100644
--- a/src/phonesim.cpp
+++ b/src/phonesim.cpp
@@ -503,7 +503,7 @@ SimRules::SimRules( int fd, QObject *p, const QString& filename, HardwareManipu
machine = 0;
if (hmf)
- machine = hmf->create(0);
+ machine = hmf->create(this, 0);
if (machine) {
connect(machine, SIGNAL(unsolicitedCommand(QString)),
--
1.6.1
10 years, 9 months