[PATCH] Simcom support
by Anthony Viallard
Add SIMCOM support.
I developped this with the SIM5216E chipset and ofono 1.12.
- SMS and GPRS work (in the same time) ;
- SIM card presence check ;
- No voice part because I can't test it ;
- Use default characters set instead GSM because it works like that
for what I'm doing (SMS+GPRS) (by default, the set is IRA for SIM5216E).
Also, the SIMCOM doc affraids me about problems when using GSM
(this setting causes easily software flow control (XON /XOFF) problems.).
Signed-off-by: Anthony Viallard <homer242 at gmail.com>
--- ofono-1.12.orig/Makefile.am 2012-04-20 21:06:29.000000000 +0200
+++ ofono-1.12/Makefile.am 2013-01-21 17:17:48.089627277 +0100
@@ -371,6 +371,9 @@ builtin_sources += plugins/samsung.c
builtin_modules += sim900
builtin_sources += plugins/sim900.c
+builtin_modules += simcom
+builtin_sources += plugins/simcom.c
+
if BLUETOOTH
builtin_modules += bluetooth
builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
--- ofono-1.12.orig/drivers/atmodem/sms.c 2012-04-20 21:06:29.000000000 +0200
+++ ofono-1.12/drivers/atmodem/sms.c 2013-01-21 16:48:44.460627485 +0100
@@ -805,6 +807,7 @@ static gboolean build_cnmi_string(char *
case OFONO_VENDOR_NOVATEL:
case OFONO_VENDOR_HUAWEI:
case OFONO_VENDOR_ZTE:
+ case OFONO_VENDOR_SIMCOM:
/* MSM devices advertise support for mode 2, but return an
* error if we attempt to actually use it. */
mode = "1";
diff -pruN ofono-1.12.orig/drivers/atmodem/sim.c ofono-1.12/drivers/atmodem/sim.c
--- ofono-1.12.orig/drivers/atmodem/sim.c 2013-01-23 11:38:22.959609087 +0100
+++ ofono-1.12/drivers/atmodem/sim.c 2013-01-23 11:57:52.602608948 +0100
@@ -1023,12 +1023,18 @@ static void at_pin_send_cb(gboolean ok,
FALSE, cbd, g_free);
return;
case OFONO_VENDOR_ZTE:
case OFONO_VENDOR_ALCATEL:
case OFONO_VENDOR_HUAWEI:
+ case OFONO_VENDOR_SIMCOM:
/*
* On ZTE modems, after pin is entered, SIM state is checked
* by polling CPIN as their modem doesn't provide unsolicited
* notification of SIM readiness.
+ *
+ * On SIMCOM modems, SIM is busy after pin is entered (we've
+ * got an "+CME ERROR: 14" at "AT+CPIN?" request) and ofono
+ * don't catch the "+CPIN: READY" message sent by the modem
+ * when SIM is ready. So, use extra CPIN to check the state.
*/
sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
2, 20, sim_state_cb, cbd,
diff -purN ofono-1.12/drivers/atmodem/network-registration.c ofono-patched/drivers/atmodem/network-registration.c
--- ofono-1.12/drivers/atmodem/network-registration.c 2013-01-18 15:04:03.598659165 +0100
+++ ofono-patched/drivers/atmodem/network-registration.c 2013-01-18 14:54:03.256659236 +0100
@@ -1411,6 +1411,14 @@ static void at_creg_set_cb(gboolean ok,
}
switch (nd->vendor) {
+ case OFONO_VENDOR_SIMCOM:
+ /* Register for CSQ changes */
+ g_at_chat_send(nd->chat, "AT+AUTOCSQ=1,1", none_prefix,
+ NULL, NULL, NULL);
+
+ g_at_chat_register(nd->chat, "+CSQ:",
+ csq_notify, FALSE, netreg, NULL);
+ break;
case OFONO_VENDOR_PHONESIM:
g_at_chat_register(nd->chat, "+CSQ:",
csq_notify, FALSE, netreg, NULL);
@@ -1534,7 +1537,6 @@ static void at_creg_set_cb(gboolean ok,
break;
case OFONO_VENDOR_NOKIA:
case OFONO_VENDOR_SAMSUNG:
- case OFONO_VENDOR_SIMCOM:
/* Signal strength reporting via CIND is not supported */
break;
default:
--- /dev/null 2013-01-28 10:34:59.843091650 +0100
+++ ofono-1.12/plugins/simcom.c 2013-02-15 16:16:38.058552544 +0100
@@ -0,0 +1,401 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2008-2011 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 <stdio.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/devinfo.h>
+#include <ofono/netreg.h>
+#include <ofono/sim.h>
+#include <ofono/cbs.h>
+#include <ofono/sms.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+#include <ofono/radio-settings.h>
+#include <ofono/phonebook.h>
+#include <ofono/log.h>
+
+#include <drivers/atmodem/atutil.h>
+#include <drivers/atmodem/vendor.h>
+
+#define MAX_IGNITION_POOL_CALL 7
+
+#define CMEERR_SIMBUSY 14
+
+static const char *none_prefix[] = { NULL };
+
+struct simcom_data {
+ GAtChat *modem;
+ GAtChat *data;
+ guint ignition_pool;
+ unsigned int ignition_pool_call;
+ unsigned int at_ignition_pending;
+ ofono_bool_t have_sim;
+};
+
+/* Callback and helpers functions */
+static void simcom_debug(const char *str, void *user_data)
+{
+ const char *prefix = user_data;
+
+ ofono_info("%s%s", prefix, str);
+}
+
+static gboolean simcom_ignition(gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ ++data->ignition_pool_call;
+
+ if(data->at_ignition_pending > 0)
+ {
+ if(data->ignition_pool_call > MAX_IGNITION_POOL_CALL)
+ {
+ ofono_error("Ignition timeout");
+ return FALSE;
+ }
+
+ /* Waiting reply of AT commands */
+ DBG("Waiting AT reply...");
+ return TRUE;
+ }
+
+ ofono_modem_set_powered(modem, TRUE);
+
+ return FALSE;
+}
+
+static void simcom_sim_status(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct ofono_error error;
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ --data->at_ignition_pending;
+
+ if(!ok)
+ {
+ decode_at_error(&error, g_at_result_final_response(result));
+ if(error.type == OFONO_ERROR_TYPE_CME)
+ {
+ if(error.error == CMEERR_SIMBUSY)
+ {
+ DBG("System is busy. Retry...");
+ g_at_chat_send(data->data, "AT+CPIN?",
+ none_prefix,
+ simcom_sim_status, modem,
+ NULL);
+ ++data->at_ignition_pending;
+ return;
+ }
+ }
+
+ data->have_sim = FALSE;
+ return;
+ }
+
+ /* If doesn't have an "fatal" error on AT+CPIN request,
+ * we can guess there a SIM card ...
+ */
+ data->have_sim = TRUE;
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("");
+
+ if (!ok) {
+ g_at_chat_unref(data->modem);
+ data->modem = NULL;
+
+ g_at_chat_unref(data->data);
+ data->data = NULL;
+
+ ofono_modem_set_powered(modem, FALSE);
+ return;
+ }
+
+ /* Get model and sim card status */
+ data->at_ignition_pending = 0;
+
+ g_at_chat_send(data->data, "AT+CPIN?", none_prefix,
+ simcom_sim_status, modem, NULL);
+ ++data->at_ignition_pending;
+
+ data->ignition_pool = g_timeout_add_seconds(1,
+ simcom_ignition,
+ modem);
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("");
+
+ g_at_chat_unref(data->data);
+ data->data = NULL;
+
+ if (ok)
+ ofono_modem_set_powered(modem, FALSE);
+}
+
+static GAtChat *open_device(struct ofono_modem *modem,
+ const char *key,
+ char *debug)
+{
+ const char *device;
+ GIOChannel *channel;
+ GAtSyntax *syntax;
+ GAtChat *chat;
+ /* GHashTable *options; */
+
+ device = ofono_modem_get_string(modem, key);
+ if (device == NULL)
+ {
+ ofono_error("Failed to get modem '%s'", key);
+ return NULL;
+ }
+
+ DBG("%s %s", key, device);
+
+ /* options = g_hash_table_new(g_str_hash, g_str_equal); */
+ /* if (options == NULL) */
+ /* return NULL; */
+
+ /* g_hash_table_insert(options, "Baud", "115200"); */
+ /* g_hash_table_insert(options, "Parity", "none"); */
+ /* g_hash_table_insert(options, "StopBits", "1"); */
+ /* g_hash_table_insert(options, "DataBits", "8"); */
+ /* g_hash_table_insert(options, "XonXoff", "off"); */
+ /* g_hash_table_insert(options, "RtsCts", "on"); */
+ /* g_hash_table_insert(options, "Local", "on"); */
+ /* g_hash_table_insert(options, "Read", "on"); */
+
+ channel = g_at_tty_open(device, NULL);
+
+ /* g_hash_table_destroy(options); */
+
+ if (channel == NULL)
+ {
+ ofono_error("Failed to get tty for '%s'", key);
+ return NULL;
+ }
+
+ syntax = g_at_syntax_new_gsm_permissive();
+ chat = g_at_chat_new(channel, syntax);
+ g_at_syntax_unref(syntax);
+
+ g_io_channel_unref(channel);
+
+ if (chat == NULL)
+ {
+ ofono_error("Failed to get chat for '%s'", key);
+ return NULL;
+ }
+
+ //if (getenv("OFONO_AT_DEBUG"))
+ g_at_chat_set_debug(chat, simcom_debug, debug);
+
+ return chat;
+}
+
+/* Modem interface function */
+static int simcom_probe(struct ofono_modem *modem)
+{
+ struct simcom_data *data;
+
+ DBG("%p", modem);
+
+ data = g_try_new0(struct simcom_data, 1);
+ if (data == NULL)
+ return -ENOMEM;
+
+ ofono_modem_set_data(modem, data);
+
+ return 0;
+}
+
+static void simcom_remove(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ if(data->ignition_pool > 0)
+ {
+ g_source_remove(data->ignition_pool);
+ data->ignition_pool = 0;
+ }
+
+ ofono_modem_set_data(modem, NULL);
+
+ /* Cleanup after hot-unplug */
+ g_at_chat_unref(data->data);
+
+ g_free(data);
+}
+
+static int simcom_enable(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ data->modem = open_device(modem, "Modem", "Modem: ");
+ if (data->modem == NULL)
+ return -EINVAL;
+
+ data->data = open_device(modem, "Data", "Data: ");
+ if (data->data == NULL) {
+ g_at_chat_unref(data->modem);
+ data->modem = NULL;
+ return -EIO;
+ }
+
+ g_at_chat_set_slave(data->modem, data->data);
+
+ g_at_chat_blacklist_terminator(data->data,
+ G_AT_CHAT_TERMINATOR_NO_CARRIER);
+
+ /* init modem */
+ g_at_chat_send(data->modem, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+ g_at_chat_send(data->data, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+
+ g_at_chat_send(data->data, "AT+CFUN=1", none_prefix,
+ cfun_enable, modem, NULL);
+
+ return -EINPROGRESS;
+}
+
+static int simcom_disable(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ g_at_chat_cancel_all(data->modem);
+ g_at_chat_unregister_all(data->modem);
+
+ g_at_chat_unref(data->modem);
+ data->modem = NULL;
+
+ g_at_chat_cancel_all(data->data);
+ g_at_chat_unregister_all(data->data);
+
+ g_at_chat_send(data->data, "AT+CFUN=4", none_prefix,
+ cfun_disable, modem, NULL);
+
+ return -EINPROGRESS;
+}
+
+static void simcom_pre_sim(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+ struct ofono_sim *sim;
+
+ DBG("%p", modem);
+
+ ofono_devinfo_create(modem, 0, "atmodem", data->data);
+ sim = ofono_sim_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
+ data->data);
+
+ if (sim)
+ ofono_sim_inserted_notify(sim, data->have_sim);
+}
+
+static void simcom_post_sim(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+ struct ofono_message_waiting *mw;
+ struct ofono_gprs *gprs;
+ struct ofono_gprs_context *gc;
+
+ DBG("%p", modem);
+
+ ofono_phonebook_create(modem, 0, "atmodem", data->data);
+
+ ofono_sms_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
+ data->data);
+
+ /* gprs things */
+ gprs = ofono_gprs_create(modem, 0, "atmodem", data->data);
+ gc = ofono_gprs_context_create(modem, 0, "atmodem", data->modem);
+
+ if(gprs && gc)
+ {
+ ofono_gprs_add_context(gprs, gc);
+ }
+}
+
+static void simcom_post_online(struct ofono_modem *modem)
+{
+ struct simcom_data *data = ofono_modem_get_data(modem);
+
+ DBG("%p", modem);
+
+ ofono_netreg_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->data);
+ ofono_cbs_create(modem, 0, "atmodem", data->data);
+ ofono_ussd_create(modem, 0, "atmodem", data->data);
+}
+
+static struct ofono_modem_driver simcom_driver = {
+ .name = "simcom",
+ .probe = simcom_probe,
+ .remove = simcom_remove,
+ .enable = simcom_enable,
+ .disable = simcom_disable,
+ .pre_sim = simcom_pre_sim,
+ .post_sim = simcom_post_sim,
+ .post_online = simcom_post_online,
+};
+
+static int simcom_init(void)
+{
+ return ofono_modem_driver_register(&simcom_driver);
+}
+
+static void simcom_exit(void)
+{
+ ofono_modem_driver_unregister(&simcom_driver);
+}
+
+OFONO_PLUGIN_DEFINE(simcom, "SIMCOM modem driver", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT,
+ simcom_init, simcom_exit)
2 weeks, 5 days
[PATCH_v4 0/5] Private network request to ConnMan
by Guillaume Zajac
Hi,
Changelog from v3 is:
- Add private-network source/include
- ConnMan plugin is independant from emulator
- Each application that need VPN will pass a callback as argument
when private network is requested. This callback will contain the
private network settings.
Guillaume Zajac (5):
gatppp: Add new contructor to use external fd
private-network: add callback typedef drivers and settings
private-network: add request/release functions and new feature to
Makefile.am
emulator: add request/release private network calls
connman: add plugin in oFono to request request/release private
network
Makefile.am | 10 +-
gatchat/gatppp.c | 33 +++++-
gatchat/gatppp.h | 1 +
gatchat/ppp.h | 2 +-
gatchat/ppp_net.c | 40 ++++---
include/private-network.h | 59 +++++++++
plugins/connman.c | 297 +++++++++++++++++++++++++++++++++++++++++++++
src/emulator.c | 49 ++++++--
src/ofono.h | 6 +
src/private-network.c | 89 ++++++++++++++
10 files changed, 556 insertions(+), 30 deletions(-)
create mode 100644 include/private-network.h
create mode 100644 plugins/connman.c
create mode 100644 src/private-network.c
3 weeks
Business
by Daser Jnr.
Hi all
>From a business point of view, can some one tell me what i can do with ofono
Cheers
Daser S.
2 months, 2 weeks
Voicecall while context is activate
by TengChou Yang
Hi,
I am able to create voicecalls, creating contexts by using Option module
GTM661W. Please see following for the issue,
if I activate the context,
/usr/lib/ofono/test/list-contexts
[ /hso_0 ]
[ /hso_0/context1 ]
Username = isp(a)cingulargprs.com
Protocol = ip
Name = Data Connect (old)
Settings = { }
IPv6.Settings = { }
Active = 0
AccessPointName = isp.cingular
Password = cingular1
Type = internet
/usr/lib/ofono/test/activate-context,
{ConnectionContext} [/hso_0/context1] Settings = { DomainNameServers =
209.183.35.23 209.183.33.23, Method = static, Netmask = 255.255.255.255,
Address = 166.204.XXX.XX, Interface = hso0, Gateway = 0.0.0.0 }
{ConnectionContext} [/hso_0/context1] Active = True
{ConnectionContext} [/hso_0/context1] Settings = {}
{ConnectionContext} [/hso_0/context1] Active = False
and than create the voicecall,
root@g2:~# /usr/lib/ofono/test/dial-number XXXXXXXXXX
Using modem /hso_0
/hso_0/voicecall01
the test case shows it had been created in voicecall01, but when I list the
phone call
root@g2:~# /usr/lib/ofono/test/list-calls
[ /hso_0 ]
[ /hso_0/voicecall02 ]
Name =
LineIdentification = 9496796229
Multiparty = 0
Emergency = 0
RemoteHeld = 0
State = alerting
RemoteMultiparty = 0
the voicecall which supposed to be at the first
interface(/hso_0/voicecall01) will be created at second
interface(/hso_0/voicecall02).
Does anyone have any clue for this problem?
Sincerely,
TengChou Yang
8 years, 6 months
huawei cdc_ncm devices
by Cedric Jehasse
Hi,
i'm trying to add support for the Huawei E3276 using a cdc_ncm interface.
To activate the pdp context for this device i need to send:
1. AT^NDISDUP=1,1
2. wait for an unsollicited reply ^NDISSTAT:
3. start a dhcp client on the wwanX interface
The huaweimodem gprs-context driver already implement AT^NDISDUP, but is
trying to get the ip address with AT^DHCP?. However this driver is not
being used.
Can i remove the code to send and handle AT^DHCP?, and replace with
^NDISSTAT?
Or should i keep it and add checks to see which at commands are supported?
thanks,
Cedric
8 years, 6 months
[PATCH 2/4] plugin: Interface for using plugins that find the MNC lenght from the IMSI
by Alfonso Sanchez-Beato
---
include/sim-mnclength.h | 45 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
create mode 100644 include/sim-mnclength.h
diff --git a/include/sim-mnclength.h b/include/sim-mnclength.h
new file mode 100644
index 0000000..67769f2
--- /dev/null
+++ b/include/sim-mnclength.h
@@ -0,0 +1,45 @@
+/*
+ *
+ * oFono - Open Telephony stack for Linux
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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
+ *
+ */
+
+#ifndef OFONO_SIM_MNCLENGTH_H
+#define OFONO_SIM_MNCLENGTH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct ofono_sim_mnclength_driver {
+ const char *name;
+ int (*get_mnclength)(const char *imsi);
+};
+
+int ofono_sim_mnclength_driver_register(
+ struct ofono_sim_mnclength_driver *driver);
+void ofono_sim_mnclength_driver_unregister(
+ const struct ofono_sim_mnclength_driver *driver);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OFONO_SIM_MNCLENGTH_H */
--
1.8.3.2
8 years, 6 months
[PATCH 1/4] plugin: Plugin that finds correspondence between MCC and MNC length
by Alfonso Sanchez-Beato
The implementation searchs in two tables, one of them with some special cases
for some operators and the other with the MNC length for a given MCC, as
recommended by the ITU (http://www.itu.int/pub/T-SP-E.212B).
---
plugins/mnclength.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 392 insertions(+)
create mode 100644 plugins/mnclength.c
diff --git a/plugins/mnclength.c b/plugins/mnclength.c
new file mode 100644
index 0000000..ee40857
--- /dev/null
+++ b/plugins/mnclength.c
@@ -0,0 +1,392 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2008-2011 Intel Corporation. All rights reserved.
+ * Copyright (C) 2013 Canonical Ltd.
+ *
+ * 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 <string.h>
+#include <stdlib.h>
+
+#include <glib.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/types.h>
+#include <ofono/log.h>
+#include <ofono/plugin.h>
+#include <ofono/sim-mnclength.h>
+
+
+struct mcc_mnclength {
+ int mcc;
+ int mnclength;
+};
+
+/*
+ * Database of MCC to MNC length correspondences based on "Mobile Network Codes
+ * (MNC) for the international identification plan for public networks and
+ * subscriptions (According to Recommendation ITU-T E.212 (05/2008))"
+ * Latest version of that document can be found in
+ * http://www.itu.int/pub/T-SP-E.212B.
+ */
+static struct mcc_mnclength mnclen_db[] = {
+ {202, 2},
+ {204, 2},
+ {206, 2},
+ {208, 2},
+ {212, 2},
+ {213, 2},
+ {214, 2},
+ {216, 2},
+ {218, 2},
+ {219, 2},
+ {220, 2},
+ {222, 2},
+ {225, 2},
+ {226, 2},
+ {228, 2},
+ {230, 2},
+ {231, 2},
+ {232, 2},
+ {234, 2},
+ {235, 2},
+ {238, 2},
+ {240, 2},
+ {242, 2},
+ {244, 2},
+ {246, 2},
+ {247, 2},
+ {248, 2},
+ {250, 2},
+ {255, 2},
+ {257, 2},
+ {259, 2},
+ {260, 2},
+ {262, 2},
+ {266, 2},
+ {268, 2},
+ {270, 2},
+ {272, 2},
+ {274, 2},
+ {276, 2},
+ {278, 2},
+ {280, 2},
+ {282, 2},
+ {283, 2},
+ {284, 2},
+ {286, 2},
+ {288, 2},
+ {289, 2},
+ {290, 2},
+ {292, 2},
+ {293, 2},
+ {294, 2},
+ {295, 2},
+ {297, 2},
+ {302, 3},
+ {308, 2},
+ {310, 3},
+ {311, 3},
+ {312, 3},
+ {313, 3},
+ {314, 3},
+ {315, 3},
+ {316, 3},
+ {330, 2},
+ {332, 2},
+ {334, 3},
+ {338, 3},
+ {340, 2},
+ {342, 3},
+ {344, 3},
+ {346, 3},
+ {348, 3},
+ {350, 2},
+ {352, 2},
+ {354, 2},
+ {356, 2},
+ {358, 2},
+ {360, 2},
+ {362, 2},
+ {363, 2},
+ {364, 2},
+ {365, 3},
+ {366, 2},
+ {368, 2},
+ {370, 2},
+ {372, 2},
+ {374, 2},
+ {376, 2},
+ {400, 2},
+ {401, 2},
+ {402, 2},
+ {404, 2},
+ {405, 2},
+ {410, 2},
+ {412, 2},
+ {413, 2},
+ {414, 2},
+ {415, 2},
+ {416, 2},
+ {417, 2},
+ {418, 2},
+ {419, 2},
+ {420, 2},
+ {421, 2},
+ {422, 2},
+ {423, 2},
+ {424, 2},
+ {425, 2},
+ {426, 2},
+ {427, 2},
+ {428, 2},
+ {429, 2},
+ {430, 2},
+ {431, 2},
+ {432, 2},
+ {434, 2},
+ {436, 2},
+ {437, 2},
+ {438, 2},
+ {440, 2},
+ {441, 2},
+ {450, 2},
+ {452, 2},
+ {454, 2},
+ {455, 2},
+ {456, 2},
+ {457, 2},
+ {460, 2},
+ {461, 2},
+ {466, 2},
+ {467, 2},
+ {470, 2},
+ {472, 2},
+ {502, 2},
+ {505, 2},
+ {510, 2},
+ {514, 2},
+ {515, 2},
+ {520, 2},
+ {525, 2},
+ {528, 2},
+ {530, 2},
+ {534, 2},
+ {535, 2},
+ {536, 2},
+ {537, 2},
+ {539, 2},
+ {540, 2},
+ {541, 2},
+ {542, 2},
+ {543, 2},
+ {544, 2},
+ {545, 2},
+ {546, 2},
+ {547, 2},
+ {548, 2},
+ {549, 2},
+ {550, 2},
+ {551, 2},
+ {552, 2},
+ {602, 2},
+ {603, 2},
+ {604, 2},
+ {605, 2},
+ {606, 2},
+ {607, 2},
+ {608, 2},
+ {609, 2},
+ {610, 2},
+ {611, 2},
+ {612, 2},
+ {613, 2},
+ {614, 2},
+ {615, 2},
+ {616, 2},
+ {617, 2},
+ {618, 2},
+ {619, 2},
+ {620, 2},
+ {621, 2},
+ {622, 2},
+ {623, 2},
+ {624, 2},
+ {625, 2},
+ {626, 2},
+ {627, 2},
+ {628, 2},
+ {629, 2},
+ {630, 2},
+ {631, 2},
+ {632, 2},
+ {633, 2},
+ {634, 2},
+ {635, 2},
+ {636, 2},
+ {637, 2},
+ {638, 2},
+ {639, 2},
+ {640, 2},
+ {641, 2},
+ {642, 2},
+ {643, 2},
+ {645, 2},
+ {646, 2},
+ {647, 2},
+ {648, 2},
+ {649, 2},
+ {650, 2},
+ {651, 2},
+ {652, 2},
+ {653, 2},
+ {654, 2},
+ {655, 2},
+ {657, 2},
+ {702, 2},
+ {704, 2},
+ {706, 2},
+ {708, 3},
+ {710, 2},
+ {712, 2},
+ {714, 2},
+ {716, 2},
+ {722, 3},
+ {724, 2},
+ {730, 2},
+ {732, 3},
+ {734, 2},
+ {736, 2},
+ {738, 2},
+ {740, 2},
+ {742, 2},
+ {744, 2},
+ {746, 2},
+ {748, 2},
+ {750, 2},
+};
+
+/*
+ * These MCC+MNC combinations have 3 digit MNC even though the default for
+ * the corresponing MCC in mnclen_db is length 2.
+ */
+static int codes_mnclen3_db[] = {
+ 405025, 405026, 405027, 405028, 405029, 405030, 405031, 405032,
+ 405033, 405034, 405035, 405036, 405037, 405038, 405039, 405040,
+ 405041, 405042, 405043, 405044, 405045, 405046, 405047, 405750,
+ 405751, 405752, 405753, 405754, 405755, 405756, 405799, 405800,
+ 405801, 405802, 405803, 405804, 405805, 405806, 405807, 405808,
+ 405809, 405810, 405811, 405812, 405813, 405814, 405815, 405816,
+ 405817, 405818, 405819, 405820, 405821, 405822, 405823, 405824,
+ 405825, 405826, 405827, 405828, 405829, 405830, 405831, 405832,
+ 405833, 405834, 405835, 405836, 405837, 405838, 405839, 405840,
+ 405841, 405842, 405843, 405844, 405845, 405846, 405847, 405848,
+ 405849, 405850, 405851, 405852, 405853, 405875, 405876, 405877,
+ 405878, 405879, 405880, 405881, 405882, 405883, 405884, 405885,
+ 405886, 405908, 405909, 405910, 405911, 405912, 405913, 405914,
+ 405915, 405916, 405917, 405918, 405919, 405920, 405921, 405922,
+ 405923, 405924, 405925, 405926, 405927, 405928, 405929, 405930,
+ 405931, 405932
+};
+
+static int comp_int(const void *key, const void *value)
+{
+ int mccmnckey = *(int *) key;
+ int mccmnccurr = *(int *) value;
+
+ return mccmnckey - mccmnccurr;
+}
+
+static int comp_mcc(const void *key, const void *value)
+{
+ int mcc = *(int *) key;
+ struct mcc_mnclength *mccmnc = (struct mcc_mnclength *) value;
+
+ return mcc - mccmnc->mcc;
+}
+
+static int mnclength_get_mnclength(const char *imsi)
+{
+ char mccmnc[OFONO_MAX_MCC_LENGTH + OFONO_MAX_MNC_LENGTH + 1];
+ size_t nelem_mnclen3 = sizeof(codes_mnclen3_db)
+ / sizeof(codes_mnclen3_db[0]);
+ size_t nelem_mccmnc = sizeof(mnclen_db)
+ / sizeof(mnclen_db[0]);
+ int mccmnc_num;
+ int *mccmnc3_res;
+ int mcc_num;
+ struct mcc_mnclength *mccmnc_res;
+
+ if (strlen(imsi) < 6)
+ return 0;
+
+ /* Special case for some operators */
+ strncpy(mccmnc, imsi, sizeof(mccmnc) - 1);
+ mccmnc[sizeof(mccmnc) - 1] = '\0';
+ errno = 0;
+ mccmnc_num = (int) strtol(mccmnc, NULL, 10);
+
+ if (errno == 0) {
+ mccmnc3_res =
+ bsearch(&mccmnc_num, codes_mnclen3_db, nelem_mnclen3,
+ sizeof(codes_mnclen3_db[0]), comp_int);
+
+ if (mccmnc3_res)
+ return 3;
+ }
+
+ /* General case */
+ mccmnc[OFONO_MAX_MCC_LENGTH] = '\0';
+ errno = 0;
+ mcc_num = (int) strtol(mccmnc, NULL, 10);
+
+ if (errno == 0) {
+ mccmnc_res =
+ bsearch(&mcc_num, mnclen_db, nelem_mccmnc,
+ sizeof(mnclen_db[0]), comp_mcc);
+
+ if (mccmnc_res)
+ return mccmnc_res->mnclength;
+ }
+
+ return 0;
+}
+
+static struct ofono_sim_mnclength_driver mnclength_driver = {
+ .name = "MNC length",
+ .get_mnclength = mnclength_get_mnclength
+};
+
+static int mnclength_init(void)
+{
+ return ofono_sim_mnclength_driver_register(&mnclength_driver);
+}
+
+static void mnclength_exit(void)
+{
+ ofono_sim_mnclength_driver_unregister(&mnclength_driver);
+}
+
+OFONO_PLUGIN_DEFINE(mnclength, "MNC length Plugin", VERSION,
+ OFONO_PLUGIN_PRIORITY_DEFAULT,
+ mnclength_init, mnclength_exit)
--
1.8.3.2
8 years, 6 months
[PATCH 4/4] sim: mnclength plugin is called in case no MNC lenght is found in the SIM
by Alfonso Sanchez-Beato
---
src/ofono.h | 4 ++++
src/sim.c | 18 +++++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/ofono.h b/src/ofono.h
index 8abaf1e..b0d12d0 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -519,3 +519,7 @@ ofono_bool_t __ofono_cdma_provision_get_name(const char *sid, char **name);
void __ofono_private_network_release(int id);
ofono_bool_t __ofono_private_network_request(ofono_private_network_cb_t cb,
int *id, void *data);
+
+#include <ofono/sim-mnclength.h>
+
+int __ofono_sim_mnclength_get_mnclength(const char *imsi);
diff --git a/src/sim.c b/src/sim.c
index edae5eb..beec74e 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -1435,6 +1435,18 @@ static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
"SubscriberIdentity",
DBUS_TYPE_STRING, &sim->imsi);
+ /*
+ * sim->mnc_length = 0 means that EFad was not present or that EFad did
+ * not contain the MNC length field (MNC length is not mandatory for
+ * SIMs (non-USIM) - see TS 51.011).
+ *
+ * MNC can have either 2 or 3 digits depending on the MCC: we will try
+ * to find a correspondence in an MCC-MNC length database
+ */
+ if (sim->mnc_length == 0)
+ sim->mnc_length =
+ __ofono_sim_mnclength_get_mnclength(sim->imsi);
+
if (sim->mnc_length) {
const char *str;
@@ -1772,8 +1784,12 @@ static void sim_ad_read_cb(int ok, int length, int record,
if (!ok)
return;
+ if (length < 3) {
+ ofono_error("EFad should contain at least three bytes");
+ return;
+ }
if (length < 4) {
- ofono_error("EFad should contain at least four bytes");
+ ofono_info("EFad does not contain MNC length");
return;
}
--
1.8.3.2
8 years, 6 months
[PATCH 3/4] sim: Glue for making mnclength plugin reachable
by Alfonso Sanchez-Beato
---
Makefile.am | 7 ++++--
src/sim-mnclength.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 75 insertions(+), 2 deletions(-)
create mode 100644 src/sim-mnclength.c
diff --git a/Makefile.am b/Makefile.am
index 21e8b68..167a350 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,7 @@ pkginclude_HEADERS = include/log.h include/plugin.h include/history.h \
include/cdma-connman.h include/gnss.h \
include/private-network.h include/cdma-netreg.h \
include/cdma-provision.h include/handsfree.h \
- include/handsfree-audio.h
+ include/handsfree-audio.h include/sim-mnclength.h
nodist_pkginclude_HEADERS = include/version.h
@@ -463,6 +463,9 @@ builtin_sources += plugins/provision.c
builtin_modules += cdma_provision
builtin_sources += plugins/cdma-provision.c
+
+builtin_modules += mnclength
+builtin_sources += plugins/mnclength.c
endif
if MAINTAINER_MODE
@@ -518,7 +521,7 @@ src_ofonod_SOURCES = $(builtin_sources) src/ofono.ver \
src/cdma-sms.c src/private-network.c src/cdma-netreg.c \
src/cdma-provision.c src/handsfree.c \
src/handsfree-audio.c src/bluetooth.h \
- src/hfp.h
+ src/hfp.h src/sim-mnclength.c
src_ofonod_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
@GLIB_LIBS@ @DBUS_LIBS@ -ldl
diff --git a/src/sim-mnclength.c b/src/sim-mnclength.c
new file mode 100644
index 0000000..9ff6409
--- /dev/null
+++ b/src/sim-mnclength.c
@@ -0,0 +1,70 @@
+/*
+ *
+ * oFono - Open Source Telephony
+ *
+ * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * 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 <string.h>
+#include <glib.h>
+#include "ofono.h"
+#include "sim-mnclength.h"
+
+static GSList *g_drivers = NULL;
+
+int __ofono_sim_mnclength_get_mnclength(const char *imsi)
+{
+ GSList *d;
+ int mnclen;
+
+ for (d = g_drivers; d != NULL; d = d->next) {
+ const struct ofono_sim_mnclength_driver *driver = d->data;
+
+ if (driver->get_mnclength == NULL)
+ continue;
+
+ DBG("Calling mnclength plugin '%s'", driver->name);
+
+ if ((mnclen = driver->get_mnclength(imsi)) <= 0)
+ continue;
+
+ return mnclen;
+ }
+
+ return 0;
+}
+
+int ofono_sim_mnclength_driver_register(
+ struct ofono_sim_mnclength_driver *driver)
+{
+ DBG("driver: %p name: %s", driver, driver->name);
+
+ g_drivers = g_slist_prepend(g_drivers, driver);
+ return 0;
+}
+
+void ofono_sim_mnclength_driver_unregister(
+ const struct ofono_sim_mnclength_driver *driver)
+{
+ DBG("driver: %p name: %s", driver, driver->name);
+
+ g_drivers = g_slist_remove(g_drivers, driver);
+}
--
1.8.3.2
8 years, 6 months
[PATCH] Fix gprs provisioning for some SIM (non-USIM) cards
by Alfonso Sanchez-Beato
In some cases the field MNC length in EFad is not present. MNC can
have either 2 or 3 digits depending on the MCC: we will try with
those 2 lengths when searching in the database for this corner case
(this situation can happen for SIMs (non-USIM), as MNC lenght field
is not mandatory for them - see 3gpp TS 51.011)
---
include/sim.h | 1 +
src/gprs.c | 26 +++++++++++++++++++++----
src/sim.c | 61 ++++++++++++++++++++++++++++++++++++++++-------------------
3 files changed, 65 insertions(+), 23 deletions(-)
diff --git a/include/sim.h b/include/sim.h
index ed850f9..f63324a 100644
--- a/include/sim.h
+++ b/include/sim.h
@@ -191,6 +191,7 @@ void *ofono_sim_get_data(struct ofono_sim *sim);
const char *ofono_sim_get_imsi(struct ofono_sim *sim);
const char *ofono_sim_get_mcc(struct ofono_sim *sim);
const char *ofono_sim_get_mnc(struct ofono_sim *sim);
+unsigned ofono_sim_get_mnc_length(struct ofono_sim *sim);
const char *ofono_sim_get_spn(struct ofono_sim *sim);
enum ofono_sim_phase ofono_sim_get_phase(struct ofono_sim *sim);
diff --git a/src/gprs.c b/src/gprs.c
index e379f7b..0218696 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -2967,7 +2967,7 @@ static void provision_context(const struct ofono_gprs_provision_data *ap,
gprs->contexts = g_slist_append(gprs->contexts, context);
}
-static void provision_contexts(struct ofono_gprs *gprs, const char *mcc,
+static int provision_contexts(struct ofono_gprs *gprs, const char *mcc,
const char *mnc, const char *spn)
{
struct ofono_gprs_provision_data *settings;
@@ -2977,13 +2977,15 @@ static void provision_contexts(struct ofono_gprs *gprs, const char *mcc,
if (__ofono_gprs_provision_get_settings(mcc, mnc, spn,
&settings, &count) == FALSE) {
ofono_warn("Provisioning failed");
- return;
+ return -EINVAL;
}
for (i = 0; i < count; i++)
provision_context(&settings[i], gprs);
__ofono_gprs_provision_free_settings(settings, count);
+
+ return 0;
}
static void ofono_gprs_finish_register(struct ofono_gprs *gprs)
@@ -3021,9 +3023,25 @@ static void spn_read_cb(const char *spn, const char *dc, void *data)
struct ofono_gprs *gprs = data;
struct ofono_modem *modem = __ofono_atom_get_modem(gprs->atom);
struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
+ const char *mnc = ofono_sim_get_mnc(sim);
+ const char *mcc = ofono_sim_get_mcc(sim);
+
+ if (ofono_sim_get_mnc_length(sim) == 0 && mnc != NULL) {
+ /* MNC length not found in EFad: we try with length 3 and 2 */
+ char aux_mnc[OFONO_MAX_MNC_LENGTH + 1];
- provision_contexts(gprs, ofono_sim_get_mcc(sim),
- ofono_sim_get_mnc(sim), spn);
+ strncpy(aux_mnc, mnc, OFONO_MAX_MNC_LENGTH);
+ aux_mnc[OFONO_MAX_MNC_LENGTH] = '\0';
+
+ if (provision_contexts(gprs, mcc, aux_mnc, spn) != 0) {
+ ofono_info("MNC length is not 3: trying length 2");
+ aux_mnc[OFONO_MAX_MNC_LENGTH - 1] = '\0';
+ provision_contexts(gprs, mcc, aux_mnc, spn);
+ }
+
+ } else {
+ provision_contexts(gprs, mcc, mnc, spn);
+ }
ofono_sim_remove_spn_watch(sim, &gprs->spn_watch);
diff --git a/src/sim.c b/src/sim.c
index edae5eb..3d31386 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -1427,6 +1427,8 @@ static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
{
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(sim->atom);
+ unsigned char aux_mnc_length;
+ const char *str;
sim->imsi = g_strdup(imsi);
@@ -1435,27 +1437,36 @@ static void sim_imsi_obtained(struct ofono_sim *sim, const char *imsi)
"SubscriberIdentity",
DBUS_TYPE_STRING, &sim->imsi);
- if (sim->mnc_length) {
- const char *str;
+ /*
+ * sim->mnc_length = 0 means that EFad did not contain the MNC length
+ * field. So we will copy 3 digits from the IMSI in the MNC. MNC can
+ * have either 2 or 3 digits depending on the MCC: we will try with
+ * those 2 lengths when searching in the database for this corner case
+ * (this situation can happen for SIMs (non-USIM), as MNC lenght field
+ * is not mandatory for them - see TS 51.011)
+ */
+ if (sim->mnc_length)
+ aux_mnc_length = sim->mnc_length;
+ else
+ aux_mnc_length = OFONO_MAX_MNC_LENGTH;
- strncpy(sim->mcc, sim->imsi, OFONO_MAX_MCC_LENGTH);
- sim->mcc[OFONO_MAX_MCC_LENGTH] = '\0';
- strncpy(sim->mnc, sim->imsi + OFONO_MAX_MCC_LENGTH,
- sim->mnc_length);
- sim->mnc[sim->mnc_length] = '\0';
+ strncpy(sim->mcc, sim->imsi, OFONO_MAX_MCC_LENGTH);
+ sim->mcc[OFONO_MAX_MCC_LENGTH] = '\0';
+ strncpy(sim->mnc, sim->imsi + OFONO_MAX_MCC_LENGTH,
+ aux_mnc_length);
+ sim->mnc[aux_mnc_length] = '\0';
- str = sim->mcc;
- ofono_dbus_signal_property_changed(conn, path,
- OFONO_SIM_MANAGER_INTERFACE,
- "MobileCountryCode",
- DBUS_TYPE_STRING, &str);
+ str = sim->mcc;
+ ofono_dbus_signal_property_changed(conn, path,
+ OFONO_SIM_MANAGER_INTERFACE,
+ "MobileCountryCode",
+ DBUS_TYPE_STRING, &str);
- str = sim->mnc;
- ofono_dbus_signal_property_changed(conn, path,
- OFONO_SIM_MANAGER_INTERFACE,
- "MobileNetworkCode",
- DBUS_TYPE_STRING, &str);
- }
+ str = sim->mnc;
+ ofono_dbus_signal_property_changed(conn, path,
+ OFONO_SIM_MANAGER_INTERFACE,
+ "MobileNetworkCode",
+ DBUS_TYPE_STRING, &str);
sim_set_ready(sim);
@@ -1772,8 +1783,12 @@ static void sim_ad_read_cb(int ok, int length, int record,
if (!ok)
return;
+ if (length < 3) {
+ ofono_error("EFad should contain at least three bytes");
+ return;
+ }
if (length < 4) {
- ofono_error("EFad should contain at least four bytes");
+ ofono_info("EFad does not contain MNC length");
return;
}
@@ -2234,6 +2249,14 @@ const char *ofono_sim_get_mnc(struct ofono_sim *sim)
return sim->mnc;
}
+unsigned ofono_sim_get_mnc_length(struct ofono_sim *sim)
+{
+ if (sim == NULL)
+ return 0;
+
+ return sim->mnc_length;
+}
+
const char *ofono_sim_get_spn(struct ofono_sim *sim)
{
if (sim == NULL)
--
1.8.1.2
8 years, 6 months