summaryrefslogtreecommitdiffstats
path: root/plugins/huawei.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2011-07-28 22:06:29 +0200
committerMarcel Holtmann <marcel@holtmann.org>2011-07-28 22:06:29 +0200
commit158b8331bdf337b449642a3c3c828aeb516559f6 (patch)
treeb2b6e62bc1a78703d4a4110a9ad4dd6cef6cd5d0 /plugins/huawei.c
parente256a6b7c8eeac1667f0cd74f7da48c911099b84 (diff)
downloadofono-158b8331bdf337b449642a3c3c828aeb516559f6.tar.bz2
huawei: Complete rewrite to better support state transitions
When switching from offline into online mode, the SIM card access gets temporarily disabled by the modem firmware. To work around this limitation poll the SIM card state.
Diffstat (limited to 'plugins/huawei.c')
-rw-r--r--plugins/huawei.c542
1 files changed, 284 insertions, 258 deletions
diff --git a/plugins/huawei.c b/plugins/huawei.c
index b915a85f..4ede2bd5 100644
--- a/plugins/huawei.c
+++ b/plugins/huawei.c
@@ -2,7 +2,7 @@
*
* oFono - Open Source Telephony
*
- * Copyright (C) 2008-2010 Intel Corporation. All rights reserved.
+ * 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
@@ -23,7 +23,6 @@
#include <config.h>
#endif
-#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
@@ -56,34 +55,32 @@
#include <drivers/atmodem/vendor.h>
static const char *none_prefix[] = { NULL };
+static const char *cfun_prefix[] = { "+CFUN:", NULL };
static const char *sysinfo_prefix[] = { "^SYSINFO:", NULL };
static const char *ussdmode_prefix[] = { "^USSDMODE:", NULL };
static const char *cvoice_prefix[] = { "^CVOICE:", NULL };
-enum huawei_sim_state {
- HUAWEI_SIM_STATE_INVALID_OR_LOCKED = 0,
- HUAWEI_SIM_STATE_VALID = 1,
- HUAWEI_SIM_STATE_INVALID_CS = 2,
- HUAWEI_SIM_STATE_INVALID_PS = 3,
- HUAWEI_SIM_STATE_INVALID_PS_AND_CS = 4,
- HUAWEI_SIM_STATE_NOT_EXISTENT = 255
+enum {
+ SIM_STATE_INVALID_OR_LOCKED = 0,
+ SIM_STATE_VALID = 1,
+ SIM_STATE_INVALID_CS = 2,
+ SIM_STATE_INVALID_PS = 3,
+ SIM_STATE_INVALID_PS_AND_CS = 4,
+ SIM_STATE_NOT_EXISTENT = 255,
};
struct huawei_data {
GAtChat *modem;
GAtChat *pcui;
- struct ofono_sim *sim;
- enum huawei_sim_state sim_state;
- const char *cfun_offline_mode;
+ gboolean have_sim;
+ int sim_state;
+ guint sysinfo_poll_source;
+ guint sysinfo_poll_count;
+ struct cb_data *online_cbd;
+ const char *offline_command;
gboolean voice;
- guint sim_poll_timeout;
- guint sim_poll_count;
};
-#define MAX_SIM_POLL_COUNT 5
-
-static gboolean query_sim_state(gpointer user_data);
-
static int huawei_probe(struct ofono_modem *modem)
{
struct huawei_data *data;
@@ -162,238 +159,216 @@ static void ussdmode_support_cb(gboolean ok, GAtResult *result,
ussdmode_query_cb, data, NULL);
}
-static void cfun_offline(gboolean ok, GAtResult *result, gpointer user_data)
+static void cvoice_query_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct huawei_data *data = ofono_modem_get_data(modem);
+ GAtResultIter iter;
+ gint mode, rate, bits, period;
- if (!ok) {
- ofono_modem_set_powered(modem, FALSE);
- return;
- }
-
- if (data->sim == NULL)
+ if (!ok)
return;
- ofono_sim_inserted_notify(data->sim, TRUE);
-}
-
-static gboolean notify_sim_state(struct ofono_modem *modem,
- enum huawei_sim_state sim_state)
-{
- struct huawei_data *data = ofono_modem_get_data(modem);
+ g_at_result_iter_init(&iter, result);
- DBG("%d", sim_state);
+ if (!g_at_result_iter_next(&iter, "^CVOICE:"))
+ return;
- data->sim_state = sim_state;
+ if (!g_at_result_iter_next_number(&iter, &mode))
+ return;
- switch (sim_state) {
- case HUAWEI_SIM_STATE_NOT_EXISTENT:
- /* SIM is not ready, try again a bit later */
- return TRUE;
- case HUAWEI_SIM_STATE_INVALID_OR_LOCKED:
- ofono_modem_set_powered(modem, TRUE);
+ if (!g_at_result_iter_next_number(&iter, &rate))
+ return;
- return FALSE;
- case HUAWEI_SIM_STATE_VALID:
- case HUAWEI_SIM_STATE_INVALID_CS:
- case HUAWEI_SIM_STATE_INVALID_PS:
- case HUAWEI_SIM_STATE_INVALID_PS_AND_CS:
- if (data->sim_poll_timeout) {
- g_source_remove(data->sim_poll_timeout);
- data->sim_poll_timeout = 0;
- }
+ if (!g_at_result_iter_next_number(&iter, &bits))
+ return;
- /*
- * In the "warm start" case the modem skips
- * HUAWEI_SIM_STATE_INVALID_OR_LOCKED altogether, so need
- * to set power also here
- */
- ofono_modem_set_powered(modem, TRUE);
+ if (!g_at_result_iter_next_number(&iter, &period))
+ return;
- if (ofono_modem_get_online(modem) == FALSE)
- g_at_chat_send(data->pcui, data->cfun_offline_mode,
- none_prefix, cfun_offline, modem, NULL);
+ data->voice = TRUE;
- return FALSE;
- }
+ ofono_info("Voice channel: %d Hz, %d bits, %dms period",
+ rate, bits, period);
- return FALSE;
+ /* check available voice ports */
+ g_at_chat_send(data->pcui, "AT^DDSETEX=?", none_prefix,
+ NULL, NULL, NULL);
}
-static void cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
+static void cvoice_support_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
{
struct ofono_modem *modem = user_data;
+ struct huawei_data *data = ofono_modem_get_data(modem);
+ GAtResultIter iter;
if (!ok)
return;
- /* Force notification of SIM ready because it's in a locked state */
- notify_sim_state(modem, HUAWEI_SIM_STATE_VALID);
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "^CVOICE:"))
+ return;
+
+ /* query current voice setting */
+ g_at_chat_send(data->pcui, "AT^CVOICE?", cvoice_prefix,
+ cvoice_query_cb, modem, NULL);
}
-static gboolean query_sim_locked(gpointer user_data)
+static void simst_notify(GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct huawei_data *data = ofono_modem_get_data(modem);
+ GAtResultIter iter;
+ int sim_state;
- data->sim_poll_timeout = 0;
+ g_at_result_iter_init(&iter, result);
- g_at_chat_send(data->pcui, "AT+CPIN?", NULL,
- cpin_cb, modem, NULL);
+ if (!g_at_result_iter_next(&iter, "^SIMST:"))
+ return;
- return FALSE;
+ if (!g_at_result_iter_next_number(&iter, &sim_state))
+ return;
+
+ DBG("%d -> %d", data->sim_state, sim_state);
+
+ data->sim_state = sim_state;
}
-static void sysinfo_cb(gboolean ok, GAtResult *result, gpointer user_data)
+static gboolean parse_sysinfo_result(GAtResult *result, int *srv_status,
+ int *srv_domain, int *sim_state)
{
- struct ofono_modem *modem = user_data;
- struct huawei_data *data = ofono_modem_get_data(modem);
- gboolean rerun;
- gint sim_state;
GAtResultIter iter;
- if (!ok)
- return;
-
g_at_result_iter_init(&iter, result);
if (!g_at_result_iter_next(&iter, "^SYSINFO:"))
- return;
+ return FALSE;
- if (!g_at_result_iter_skip_next(&iter))
- return;
+ if (!g_at_result_iter_next_number(&iter, srv_status))
+ return FALSE;
- if (!g_at_result_iter_skip_next(&iter))
- return;
+ if (!g_at_result_iter_next_number(&iter, srv_domain))
+ return FALSE;
if (!g_at_result_iter_skip_next(&iter))
- return;
+ return FALSE;
if (!g_at_result_iter_skip_next(&iter))
- return;
+ return FALSE;
- if (!g_at_result_iter_next_number(&iter, &sim_state))
- return;
+ if (!g_at_result_iter_next_number(&iter, sim_state))
+ return FALSE;
- rerun = notify_sim_state(modem, (enum huawei_sim_state) sim_state);
-
- if (rerun && data->sim_poll_count < MAX_SIM_POLL_COUNT) {
- data->sim_poll_count++;
- data->sim_poll_timeout = g_timeout_add_seconds(2,
- query_sim_state,
- modem);
- } else if (sim_state == HUAWEI_SIM_STATE_INVALID_OR_LOCKED &&
- !data->sim_poll_timeout) {
- data->sim_poll_timeout = g_timeout_add_seconds(2,
- query_sim_locked,
- modem);
- }
+ return TRUE;
}
-static gboolean query_sim_state(gpointer user_data)
+static void shutdown_device(struct huawei_data *data)
{
- struct ofono_modem *modem = user_data;
- struct huawei_data *data = ofono_modem_get_data(modem);
-
- DBG("");
+ g_at_chat_cancel_all(data->modem);
+ g_at_chat_unregister_all(data->modem);
- data->sim_poll_timeout = 0;
+ g_at_chat_unref(data->modem);
+ data->modem = NULL;
- g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
- sysinfo_cb, modem, NULL);
+ g_at_chat_cancel_all(data->pcui);
+ g_at_chat_unregister_all(data->pcui);
- return FALSE;
+ g_at_chat_unref(data->pcui);
+ data->pcui = NULL;
}
-static void simst_notify(GAtResult *result, gpointer user_data)
+static void cfun_offline(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
- GAtResultIter iter;
- gint sim_state;
-
- g_at_result_iter_init(&iter, result);
+ struct huawei_data *data = ofono_modem_get_data(modem);
- if (!g_at_result_iter_next(&iter, "^SIMST:"))
- return;
+ DBG("");
- if (!g_at_result_iter_next_number(&iter, &sim_state))
+ if (!ok) {
+ shutdown_device(data);
+ ofono_modem_set_powered(modem, FALSE);
return;
+ }
- notify_sim_state(modem, (enum huawei_sim_state) sim_state);
+ ofono_modem_set_powered(modem, TRUE);
}
-static void cvoice_query_cb(gboolean ok, GAtResult *result,
+static gboolean sysinfo_enable_check(gpointer user_data);
+
+static void sysinfo_enable_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct huawei_data *data = ofono_modem_get_data(modem);
- GAtResultIter iter;
- gint mode, rate, bits, period;
+ int srv_status, srv_domain, sim_state;
if (!ok)
- return;
+ goto failure;
- g_at_result_iter_init(&iter, result);
+ if (parse_sysinfo_result(result, &srv_status, &srv_domain,
+ &sim_state) == FALSE)
+ goto failure;
- if (!g_at_result_iter_next(&iter, "^CVOICE:"))
- return;
+ DBG("%d -> %d", data->sim_state, sim_state);
- if (!g_at_result_iter_next_number(&iter, &mode))
- return;
+ data->sim_state = sim_state;
- if (!g_at_result_iter_next_number(&iter, &rate))
- return;
+ if (sim_state == SIM_STATE_NOT_EXISTENT) {
+ data->sysinfo_poll_count++;
- if (!g_at_result_iter_next_number(&iter, &bits))
- return;
+ if (data->sysinfo_poll_count > 5)
+ goto failure;
- if (!g_at_result_iter_next_number(&iter, &period))
+ data->sysinfo_poll_source = g_timeout_add_seconds(1,
+ sysinfo_enable_check, modem);
return;
+ }
- data->voice = TRUE;
+ data->have_sim = TRUE;
- ofono_info("Voice channel: %d Hz, %d bits, %dms period",
- rate, bits, period);
+ /* switch data carrier detect signal off */
+ g_at_chat_send(data->modem, "AT&C0", NULL, NULL, NULL, NULL);
+ g_at_chat_send(data->pcui, "AT&C0", NULL, NULL, NULL, NULL);
- /* check available voice ports */
- g_at_chat_send(data->pcui, "AT^DDSETEX=?", none_prefix,
+ /* query current device settings */
+ g_at_chat_send(data->pcui, "AT^U2DIAG?", none_prefix,
NULL, NULL, NULL);
-}
-static void cvoice_support_cb(gboolean ok, GAtResult *result,
- gpointer user_data)
-{
- struct ofono_modem *modem = user_data;
- struct huawei_data *data = ofono_modem_get_data(modem);
- GAtResultIter iter;
+ /* query current port settings */
+ g_at_chat_send(data->pcui, "AT^GETPORTMODE", none_prefix,
+ NULL, NULL, NULL);
- if (!ok)
- return;
+ /* check USSD mode support */
+ g_at_chat_send(data->pcui, "AT^USSDMODE=?", ussdmode_prefix,
+ ussdmode_support_cb, data, NULL);
- g_at_result_iter_init(&iter, result);
+ /* check for voice support */
+ g_at_chat_send(data->pcui, "AT^CVOICE=?", cvoice_prefix,
+ cvoice_support_cb, modem, NULL);
- if (!g_at_result_iter_next(&iter, "^CVOICE:"))
+ if (g_at_chat_send(data->pcui, data->offline_command, none_prefix,
+ cfun_offline, modem, NULL) > 0)
return;
- /* query current voice setting */
- g_at_chat_send(data->pcui, "AT^CVOICE?", cvoice_prefix,
- cvoice_query_cb, modem, NULL);
+failure:
+ shutdown_device(data);
+ ofono_modem_set_powered(modem, FALSE);
}
-static void shutdown_device(struct huawei_data *data)
+static gboolean sysinfo_enable_check(gpointer user_data)
{
- g_at_chat_cancel_all(data->modem);
- g_at_chat_unregister_all(data->modem);
+ struct ofono_modem *modem = user_data;
+ struct huawei_data *data = ofono_modem_get_data(modem);
- g_at_chat_unref(data->modem);
- data->modem = NULL;
+ data->sysinfo_poll_source = 0;
- g_at_chat_cancel_all(data->pcui);
- g_at_chat_unregister_all(data->pcui);
+ g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
+ sysinfo_enable_cb, modem, NULL);
- g_at_chat_unref(data->pcui);
- data->pcui = NULL;
+ return FALSE;
}
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
@@ -409,10 +384,16 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
return;
}
- query_sim_state(modem);
+ /* follow sim state changes */
+ g_at_chat_register(data->pcui, "^SIMST:", simst_notify,
+ FALSE, modem, NULL);
+
+ data->sysinfo_poll_count = 0;
+
+ sysinfo_enable_check(modem);
}
-static void set_offline_mode(GAtResult *result, struct huawei_data *data)
+static void parse_cfun_support(GAtResult *result, struct huawei_data *data)
{
GAtResultIter iter;
int min, max;
@@ -429,15 +410,14 @@ static void set_offline_mode(GAtResult *result, struct huawei_data *data)
if (!g_at_result_iter_next_range(&iter, &min, &max))
break;
- if (min <= 7 && max >= 7)
- data->cfun_offline_mode = "AT+CFUN=7";
+ if (min <= 7 && max >= 7) {
+ data->offline_command = "AT+CFUN=7";
+ return;
+ }
}
- if (data->cfun_offline_mode != NULL)
- return;
-
fallback:
- data->cfun_offline_mode = "AT+CFUN=5";
+ data->offline_command = "AT+CFUN=5";
}
static void cfun_support(gboolean ok, GAtResult *result, gpointer user_data)
@@ -451,38 +431,26 @@ static void cfun_support(gboolean ok, GAtResult *result, gpointer user_data)
return;
}
- set_offline_mode(result, data);
+ parse_cfun_support(result, data);
- /* query current device settings */
- g_at_chat_send(data->pcui, "AT^U2DIAG?", none_prefix,
- NULL, NULL, NULL);
-
- /* query current port settings */
- g_at_chat_send(data->pcui, "AT^GETPORTMODE", none_prefix,
- NULL, NULL, NULL);
-
- /* check USSD mode support */
- g_at_chat_send(data->pcui, "AT^USSDMODE=?", ussdmode_prefix,
- ussdmode_support_cb, data, NULL);
-
- /* check for voice support */
- g_at_chat_send(data->pcui, "AT^CVOICE=?", cvoice_prefix,
- cvoice_support_cb, modem, NULL);
-
- /* follow sim state */
- g_at_chat_register(data->pcui, "^SIMST:", simst_notify,
- FALSE, modem, NULL);
-
- g_at_chat_send(data->pcui, "AT+CFUN=1", NULL,
+ g_at_chat_send(data->pcui, "AT+CFUN=1", none_prefix,
cfun_enable, modem, NULL);
}
-static GAtChat *create_port(const char *device)
+static GAtChat *open_device(struct ofono_modem *modem,
+ const char *key, char *debug)
{
- GAtSyntax *syntax;
+ const char *device;
GIOChannel *channel;
+ GAtSyntax *syntax;
GAtChat *chat;
+ device = ofono_modem_get_string(modem, key);
+ if (device == NULL)
+ return NULL;
+
+ DBG("%s %s", key, device);
+
channel = g_at_tty_open(device, NULL);
if (channel == NULL)
return NULL;
@@ -490,27 +458,9 @@ static GAtChat *create_port(const char *device)
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)
- return NULL;
-
- return chat;
-}
-
-static GAtChat *open_device(struct ofono_modem *modem,
- const char *key, char *debug)
-{
- const char *device;
- GAtChat *chat;
-
- device = ofono_modem_get_string(modem, key);
- if (device == NULL)
- return NULL;
- DBG("%s %s", key, device);
+ g_io_channel_unref(channel);
- chat = create_port(device);
if (chat == NULL)
return NULL;
@@ -532,9 +482,6 @@ static int huawei_enable(struct ofono_modem *modem)
if (data->modem == NULL)
return -EINVAL;
- g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", NULL,
- NULL, NULL, NULL);
-
data->pcui = open_device(modem, "Pcui", "PCUI: ");
if (data->pcui == NULL) {
g_at_chat_unref(data->modem);
@@ -544,12 +491,12 @@ static int huawei_enable(struct ofono_modem *modem)
g_at_chat_set_slave(data->modem, data->pcui);
- data->sim_state = 0;
+ g_at_chat_send(data->modem, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+ g_at_chat_send(data->pcui, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
- g_at_chat_send(data->pcui, "ATE0 &C0 +CMEE=1", NULL,
- NULL, NULL, NULL);
+ data->sim_state = SIM_STATE_NOT_EXISTENT;
- g_at_chat_send(data->pcui, "AT+CFUN=?", NULL,
+ g_at_chat_send(data->pcui, "AT+CFUN=?", cfun_prefix,
cfun_support, modem, NULL);
return -EINPROGRESS;
@@ -574,25 +521,104 @@ static int huawei_disable(struct ofono_modem *modem)
DBG("%p", modem);
- if (data->sim_poll_timeout > 0) {
- g_source_remove(data->sim_poll_timeout);
- data->sim_poll_timeout = 0;
- }
-
g_at_chat_cancel_all(data->modem);
g_at_chat_unregister_all(data->modem);
g_at_chat_cancel_all(data->pcui);
g_at_chat_unregister_all(data->pcui);
- g_at_chat_send(data->pcui, "AT+CFUN=0", NULL,
+ g_at_chat_send(data->pcui, "AT+CFUN=0", none_prefix,
cfun_disable, modem, NULL);
return -EINPROGRESS;
}
+static gboolean sysinfo_online_check(gpointer user_data);
+
+static void sysinfo_online_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct huawei_data *data = user_data;
+ ofono_modem_online_cb_t cb = data->online_cbd->cb;
+ int srv_status, srv_domain, sim_state;
+
+ if (!ok)
+ goto failure;
+
+ if (parse_sysinfo_result(result, &srv_status, &srv_domain,
+ &sim_state) == FALSE)
+ goto failure;
+
+ DBG("%d -> %d", data->sim_state, sim_state);
+
+ data->sim_state = sim_state;
+
+ /* Valid service status and at minimum PS domain */
+ if (srv_status > 0 && srv_domain > 1) {
+ CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
+ goto done;
+ }
+
+ switch (sim_state) {
+ case SIM_STATE_VALID:
+ case SIM_STATE_INVALID_CS:
+ case SIM_STATE_INVALID_PS:
+ case SIM_STATE_INVALID_PS_AND_CS:
+ CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
+ goto done;
+ }
+
+ data->sysinfo_poll_count++;
+
+ if (data->sysinfo_poll_count > 15)
+ goto failure;
+
+ data->sysinfo_poll_source = g_timeout_add_seconds(2,
+ sysinfo_online_check, data);
+ return;
+
+failure:
+ CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
+
+done:
+ g_free(data->online_cbd);
+ data->online_cbd = NULL;
+}
+
+static gboolean sysinfo_online_check(gpointer user_data)
+{
+ struct huawei_data *data = user_data;
+
+ data->sysinfo_poll_source = 0;
+
+ g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
+ sysinfo_online_cb, data, NULL);
+
+ return FALSE;
+}
+
static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
+ struct ofono_modem *modem = user_data;
+ struct huawei_data *data = ofono_modem_get_data(modem);
+
+ if (!ok) {
+ ofono_modem_online_cb_t cb = data->online_cbd->cb;
+
+ CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
+
+ g_free(data->online_cbd);
+ data->online_cbd = NULL;
+ return;
+ }
+
+ data->sysinfo_poll_count = 0;
+
+ sysinfo_online_check(data);
+}
+
+static void set_offline_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
struct cb_data *cbd = user_data;
ofono_modem_online_cb_t cb = cbd->cb;
struct ofono_error error;
@@ -605,34 +631,51 @@ static void huawei_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *user_data)
{
struct huawei_data *data = ofono_modem_get_data(modem);
- struct cb_data *cbd = cb_data_new(cb, user_data);
- char const *command = online ? "AT+CFUN=1" : data->cfun_offline_mode;
DBG("modem %p %s", modem, online ? "online" : "offline");
- if (g_at_chat_send(data->pcui, command, none_prefix,
- set_online_cb, cbd, g_free) > 0)
- return;
+ if (online == TRUE) {
+ data->online_cbd = cb_data_new(cb, user_data);
- CALLBACK_WITH_FAILURE(cb, cbd->data);
+ if (g_at_chat_send(data->pcui, "AT+CFUN=1", none_prefix,
+ set_online_cb, modem, NULL) > 0)
+ return;
- g_free(cbd);
+ g_free(data->online_cbd);
+ data->online_cbd = NULL;
+ } else {
+ struct cb_data *cbd = cb_data_new(cb, user_data);
+
+ if (g_at_chat_send(data->pcui, data->offline_command,
+ none_prefix, set_offline_cb, cbd, g_free) > 0)
+ return;
+
+ g_free(cbd);
+ }
+
+ CALLBACK_WITH_FAILURE(cb, user_data);
}
static void huawei_pre_sim(struct ofono_modem *modem)
{
struct huawei_data *data = ofono_modem_get_data(modem);
+ struct ofono_sim *sim;
DBG("%p", modem);
ofono_devinfo_create(modem, 0, "atmodem", data->pcui);
- data->sim = ofono_sim_create(modem, OFONO_VENDOR_HUAWEI,
+ sim = ofono_sim_create(modem, OFONO_VENDOR_HUAWEI,
"atmodem", data->pcui);
+
+ if (sim && data->have_sim == TRUE)
+ ofono_sim_inserted_notify(sim, TRUE);
}
static void huawei_post_sim(struct ofono_modem *modem)
{
struct huawei_data *data = ofono_modem_get_data(modem);
+ struct ofono_gprs *gprs;
+ struct ofono_gprs_context *gc;
DBG("%p", modem);
@@ -646,6 +689,13 @@ static void huawei_post_sim(struct ofono_modem *modem)
ofono_radio_settings_create(modem, 0, "huaweimodem", data->pcui);
ofono_sms_create(modem, OFONO_VENDOR_HUAWEI, "atmodem", data->pcui);
+
+ gprs = ofono_gprs_create(modem, OFONO_VENDOR_HUAWEI,
+ "atmodem", data->pcui);
+ gc = ofono_gprs_context_create(modem, 0, "atmodem", data->modem);
+
+ if (gprs && gc)
+ ofono_gprs_add_context(gprs, gc);
}
static void huawei_post_online(struct ofono_modem *modem)
@@ -654,14 +704,6 @@ static void huawei_post_online(struct ofono_modem *modem)
DBG("%p", modem);
- if (data->sim_state != HUAWEI_SIM_STATE_VALID &&
- data->sim_state != HUAWEI_SIM_STATE_INVALID_CS &&
- data->sim_state != HUAWEI_SIM_STATE_INVALID_PS) {
- ofono_info("huawei: invalid sim state in post online (%d)",
- data->sim_state);
- return;
- }
-
ofono_netreg_create(modem, OFONO_VENDOR_HUAWEI, "atmodem", data->pcui);
ofono_cbs_create(modem, OFONO_VENDOR_QUALCOMM_MSM,
@@ -669,23 +711,7 @@ static void huawei_post_online(struct ofono_modem *modem)
ofono_ussd_create(modem, OFONO_VENDOR_QUALCOMM_MSM,
"atmodem", data->pcui);
- if (data->sim_state == HUAWEI_SIM_STATE_VALID ||
- data->sim_state == HUAWEI_SIM_STATE_INVALID_CS) {
- struct ofono_gprs *gprs;
- struct ofono_gprs_context *gc;
-
- gprs = ofono_gprs_create(modem, OFONO_VENDOR_HUAWEI,
- "atmodem", data->pcui);
- gc = ofono_gprs_context_create(modem, 0,
- "atmodem", data->modem);
-
- if (gprs && gc)
- ofono_gprs_add_context(gprs, gc);
- }
-
- if ((data->sim_state == HUAWEI_SIM_STATE_VALID ||
- data->sim_state == HUAWEI_SIM_STATE_INVALID_PS) &&
- data->voice == TRUE) {
+ if (data->voice == TRUE) {
struct ofono_message_waiting *mw;
ofono_call_forwarding_create(modem, 0, "atmodem", data->pcui);
@@ -704,10 +730,10 @@ static struct ofono_modem_driver huawei_driver = {
.remove = huawei_remove,
.enable = huawei_enable,
.disable = huawei_disable,
- .set_online = huawei_set_online,
+ .set_online = huawei_set_online,
.pre_sim = huawei_pre_sim,
.post_sim = huawei_post_sim,
- .post_online = huawei_post_online,
+ .post_online = huawei_post_online,
};
static int huawei_init(void)