big re-write.. copy quectel.. copy cinterion..

be more struct in when we update what.. deal with enable or disable
actually failing.. and leaking the atchat

create netreg only after we have moved to the online state.. this
avoids crashes in case the sim is partially initialized.

Use +WIND only for the SIM ready/inserted state.. We can probably
try to use AT+CFUN=1,0 on the initial startup.. only tested with the
SL8xxx modem bank and serial.. let's see how AT+CFUN=1,1 behaves on
a true USB device..
This commit is contained in:
root 2016-03-13 20:30:42 +01:00
parent 24ba6f8923
commit 6a7ff31f0f
1 changed files with 227 additions and 66 deletions

View File

@ -49,19 +49,28 @@
#include <ofono/voicecall.h>
#include <ofono.h>
#include <drivers/atmodem/atutil.h>
#include <drivers/atmodem/vendor.h>
static const char *cfun_prefix[] = { "+CFUN:", NULL };
static const char *wind_prefix[] = { "+WIND:", NULL };
static const char *none_prefix[] = { NULL };
static int wavecom_probe(struct ofono_modem *modem)
{
return 0;
}
struct wavecom_data {
GAtChat *chat;
int have_enabled;
gboolean have_sim;
gboolean have_sms;
};
static void wavecom_remove(struct ofono_modem *modem)
static enum ofono_vendor vendor(struct ofono_modem *modem)
{
const char *model;
model = ofono_modem_get_string(modem, "Model");
if (model && strcmp(model, "Q2XXX") == 0)
return OFONO_VENDOR_WAVECOM_Q2XXX;
return 0;
}
static void wavecom_debug(const char *str, void *user_data)
@ -71,22 +80,48 @@ static void wavecom_debug(const char *str, void *user_data)
ofono_info("%s%s", prefix, str);
}
static int wavecom_probe(struct ofono_modem *modem)
{
struct wavecom_data *data;
ofono_error("%p: %s", modem, __func__);
data = g_try_new0(struct wavecom_data, 1);
if (data == NULL)
return -ENOMEM;
ofono_modem_set_data(modem, data);
return 0;
}
static void wavecom_remove(struct ofono_modem *modem)
{
struct wavecom_data *data = ofono_modem_get_data(modem);
ofono_error("%p: %s", modem, __func__);
ofono_modem_set_data(modem, NULL);
g_at_chat_unref(data->chat);
g_free(data);
}
static void rf_off_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
ofono_modem_set_powered(modem, TRUE);
}
static void wind_notify(GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct wavecom_data *data = ofono_modem_get_data(modem);
struct ofono_sim *sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
GAtChat *chat = ofono_modem_get_data(modem);
GAtResultIter iter;
int val;
const char *model;
enum ofono_vendor vendor = 0;
struct ofono_message_waiting *mw;
DBG("%p", modem);
model = ofono_modem_get_string(modem, "Model");
if (model && strcmp(model, "Q2XXX") == 0)
vendor = OFONO_VENDOR_WAVECOM_Q2XXX;
ofono_error("%p: %s", modem, __func__);
g_at_result_iter_init(&iter, result);
@ -98,30 +133,31 @@ static void wind_notify(GAtResult *result, gpointer user_data)
switch (val) {
case 3: /* ready to process AT commands */
ofono_modem_set_powered(modem, TRUE);
ofono_error("%s ready for AT commands. moving to off", ofono_modem_get_string(modem, "Device"));
if (!data->have_enabled) {
data->have_enabled = TRUE;
g_at_chat_send(data->chat, "AT+CFUN=4", none_prefix, rf_off_cb, modem, NULL);
}
break;
case 0: /* sim removed */
ofono_error("%p sim removed", modem);
data->have_sim = FALSE;
if (sim)
ofono_sim_inserted_notify(sim, FALSE);
break;
case 1: /* sim inserted */
ofono_error("%p sim inserted", modem);
data->have_sim = TRUE;
break;
case 16: /* SMS and SMS-CB services initialized */
ofono_sms_create(modem, vendor, "atmodem", chat);
ofono_error("%p SMS ready %d", modem, data->have_sms);
if (sim)
ofono_sim_inserted_notify(sim, TRUE);
break;
case 7: /* service available for emergency call */
ofono_voicecall_create(modem, 0, "atmodem", chat);
ofono_ussd_create(modem, 0, "atmodem", chat);
ofono_call_forwarding_create(modem, 0, "atmodem", chat);
ofono_call_settings_create(modem, 0, "atmodem", chat);
ofono_netreg_create(modem, 0, "atmodem", chat);
ofono_call_meter_create(modem, 0, "atmodem", chat);
ofono_call_barring_create(modem, 0, "atmodem", chat);
mw = ofono_message_waiting_create(modem);
if (mw)
ofono_message_waiting_register(mw);
break;
case 8: /* network is lost */
case 10: /* reload status of SIM phonebook */
sim = ofono_sim_create(modem, vendor, "atmodem", chat);
ofono_sim_inserted_notify(sim, TRUE);
ofono_phonebook_create(modem, 0, "atmodem", chat);
break;
case 11: /* checksum of SIM phoenbook */
case 13: /* rack has been detected closed */
@ -129,53 +165,32 @@ static void wind_notify(GAtResult *result, gpointer user_data)
}
}
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
GAtChat *chat = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok) {
g_at_chat_unref(chat);
ofono_modem_set_powered(modem, FALSE);
return;
}
ofono_modem_set_powered(modem, TRUE);
}
static void cfun_disable2enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
GAtChat *chat = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok)
return;
g_at_chat_send(chat, "AT+CFUN=1", none_prefix,
cfun_enable, modem, NULL);
}
static void wind_set(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
GAtChat *chat = ofono_modem_get_data(modem);
DBG("");
ofono_error("%s", __func__);
}
static int wavecom_enable(struct ofono_modem *modem)
{
struct wavecom_data *data;
GAtChat *chat;
GIOChannel *channel;
GAtSyntax *syntax;
const char *device;
GHashTable *options;
DBG("%p", modem);
ofono_error("%p: %s", modem, __func__);
data = ofono_modem_get_data(modem);
if (data->chat) {
ofono_error("%p the chat is still there!!!!", modem);
g_at_chat_cancel_all(data->chat);
g_at_chat_unregister_all(data->chat);
g_at_chat_unref(data->chat);
data->chat = NULL;
}
device = ofono_modem_get_string(modem, "Device");
if (device == NULL)
@ -219,17 +234,160 @@ static int wavecom_enable(struct ofono_modem *modem)
if (getenv("OFONO_AT_DEBUG"))
g_at_chat_set_debug(chat, wavecom_debug, "");
ofono_modem_set_data(modem, chat);
data->chat = chat;
g_at_chat_send(chat, "AT+WIND=32767", wind_prefix,
wind_set, modem, NULL);
g_at_chat_send(chat, "AT+CFUN=0", cfun_prefix,
cfun_disable2enable, modem, NULL);
/* restart and wait for the +WIND */
data->have_enabled = FALSE;
data->have_sim = FALSE;
guint res = g_at_chat_send(chat, "AT+CFUN=1,1", none_prefix,
NULL, modem, NULL);
ofono_error("%p %p reset res %d\n", chat, modem, res);
return -EINPROGRESS;
}
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
struct wavecom_data *data = ofono_modem_get_data(modem);
ofono_error("%p: %s", modem, __func__);
g_at_chat_unref(data->chat);
data->chat = NULL;
if (ok)
ofono_modem_set_powered(modem, FALSE);
else
ofono_error("%p power down has failed!!!!", modem);
}
static int wavecom_disable(struct ofono_modem *modem)
{
struct wavecom_data *data = ofono_modem_get_data(modem);
ofono_error("%p: %s", modem, __func__);
g_at_chat_cancel_all(data->chat);
g_at_chat_unregister_all(data->chat);
g_at_chat_send(data->chat, "AT+CFUN=0", cfun_prefix,
cfun_disable, modem, NULL);
return -EINPROGRESS;
}
static void set_online_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;
decode_at_error(&error, g_at_result_final_response(result));
cb(&error, cbd->data);
}
static void wavecom_set_online(struct ofono_modem *modem, ofono_bool_t online,
ofono_modem_online_cb_t cb, void *user_data)
{
struct wavecom_data *data = ofono_modem_get_data(modem);
struct cb_data *cbd = cb_data_new(cb, user_data);
char const *command = online ? "AT+CFUN=1,0" : "AT+CFUN=4";
ofono_error("%p: %s %d", modem, __func__, online);
DBG("modem %p %s", modem, online ? "online" : "offline");
if (g_at_chat_send(data->chat, command, cfun_prefix, set_online_cb,
cbd, g_free) > 0)
return;
CALLBACK_WITH_FAILURE(cb, cbd->data);
g_free(cbd);
}
static void wavecom_pre_sim(struct ofono_modem *modem)
{
struct wavecom_data *data = ofono_modem_get_data(modem);
struct ofono_sim *sim;
ofono_error("%p: %s", modem, __func__);
ofono_devinfo_create(modem, 0, "atmodem", data->chat);
sim = ofono_sim_create(modem, vendor(modem), "atmodem", data->chat);
ofono_voicecall_create(modem, 0, "atmodem", data->chat);
if (sim && data->have_sim == TRUE) {
data->have_sim = FALSE;
ofono_sim_inserted_notify(sim, TRUE);
}
}
static void wavecom_post_sim(struct ofono_modem *modem)
{
struct wavecom_data *data = ofono_modem_get_data(modem);
ofono_error("%p: %s", modem, __func__);
/* TODO GPRS if we have aux line to the modem */
/* only called... in case no one has asked to online us */
}
static void wavecom_post_online(struct ofono_modem *modem)
{
struct ofono_message_waiting *mw;
struct wavecom_data *data = ofono_modem_get_data(modem);
ofono_error("%p: %s", modem, __func__);
ofono_ussd_create(modem, 0, "atmodem", data->chat);
ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
ofono_call_settings_create(modem, 0, "atmodem", data->chat);
ofono_netreg_create(modem, 0, "atmodem", data->chat);
ofono_call_meter_create(modem, 0, "atmodem", data->chat);
ofono_call_barring_create(modem, 0, "atmodem", data->chat);
mw = ofono_message_waiting_create(modem);
if (mw)
ofono_message_waiting_register(mw);
ofono_phonebook_create(modem, 0, "atmodem", data->chat);
ofono_sms_create(modem, vendor(modem), "atmodem", data->chat);
}
#if 0
static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
GAtChat *chat = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok) {
g_at_chat_unref(chat);
ofono_modem_set_powered(modem, FALSE);
return;
}
ofono_modem_set_powered(modem, TRUE);
}
static void cfun_disable2enable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
GAtChat *chat = ofono_modem_get_data(modem);
DBG("ok %d", ok);
if (!ok)
return;
g_at_chat_send(chat, "AT+CFUN=1", none_prefix,
cfun_enable, modem, NULL);
}
static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
{
struct ofono_modem *modem = user_data;
@ -275,6 +433,7 @@ static void wavecom_post_sim(struct ofono_modem *modem)
DBG("%p", modem);
}
#endif
static struct ofono_modem_driver wavecom_driver = {
.name = "wavecom",
@ -282,8 +441,10 @@ static struct ofono_modem_driver wavecom_driver = {
.remove = wavecom_remove,
.enable = wavecom_enable,
.disable = wavecom_disable,
.set_online = wavecom_set_online,
.pre_sim = wavecom_pre_sim,
.post_sim = wavecom_post_sim,
.post_online = wavecom_post_online,
};
static int wavecom_init(void)