Add GPRS registration status implementation

This commit is contained in:
Denis Kenzior 2009-10-22 18:00:07 -05:00 committed by Denis Kenzior
parent 8cb2bb7608
commit 43256236a0
1 changed files with 44 additions and 182 deletions

View File

@ -39,6 +39,7 @@
#include "atmodem.h"
static const char *cgreg_prefix[] = { "+CGREG:", NULL };
static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
static const char *none_prefix[] = { NULL };
@ -81,213 +82,73 @@ error:
CALLBACK_WITH_FAILURE(cb, data);
}
static void at_cgdcont_cb(gboolean ok, GAtResult *result, gpointer user_data)
static void at_cgreg_cb(gboolean ok, GAtResult *result, gpointer user_data)
{
struct set_active_req *req = user_data;
struct gprs_data *gd =
ofono_gprs_get_data(req->gprs);
struct cb_data *cbd = user_data;
GAtResultIter iter;
ofono_gprs_status_cb_t cb = cbd->cb;
int status;
const char *str;
int lac = -1, ci = -1, tech = -1;
struct ofono_error error;
char buf[64];
dump_response("cgdcont_cb", ok, result);
dump_response("at_cgreg_cb", ok, result);
decode_at_error(&error, g_at_result_final_response(result));
if (!ok) {
req->cb(&error, req->data);
g_free(req);
cb(&error, -1, -1, -1, -1, cbd->data);
return;
}
/* Context is no longer undefined */
gd->new_contexts = g_slist_remove(gd->new_contexts, req->ctx);
g_at_result_iter_init(&iter, result);
sprintf(buf, "AT+CGACT=1,%u", req->ctx->id);
if (g_at_chat_send(gd->chat, buf, none_prefix,
at_cgact_cb, req, g_free) > 0)
if (!g_at_result_iter_next(&iter, "+CGREG:")) {
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, cbd->data);
return;
CALLBACK_WITH_FAILURE(req->cb, req->data);
g_free(req);
}
static void at_pdp_set_active(struct ofono_gprs *gprs, unsigned id,
int active, ofono_gprs_cb_t cb,
void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct set_active_req *req = NULL;
char buf[64];
struct ofono_gprs_primary_context *ctx;
gint cid = id;
int len;
GSList *l;
l = g_slist_find_custom(gd->contexts, &cid, context_id_compare);
if (!l)
goto error;
ctx = l->data;
req = g_new0(struct set_active_req, 1);
if (!req)
goto error;
req->gprs = gprs;
req->ctx = ctx;
req->active = active;
req->cb = cb;
req->data = data;
if (active) {
len = sprintf(buf, "AT+CGDCONT=%u,\"IP\"", id);
if (ctx->apn)
snprintf(buf + len, sizeof(buf) - len - 3, ",\"%s\"",
ctx->apn);
if (g_at_chat_send(gd->chat, buf, none_prefix,
at_cgdcont_cb, req, NULL) > 0)
return;
} else {
sprintf(buf, "AT+CGACT=0,%u", id);
if (g_at_chat_send(gd->chat, buf, none_prefix,
at_cgact_cb, req, g_free) > 0)
return;
}
error:
if (req)
g_free(req);
/* Skip <n> the unsolicited result code */
g_at_result_iter_skip_next(&iter);
CALLBACK_WITH_FAILURE(cb, data);
g_at_result_iter_next_number(&iter, &status);
if (g_at_result_iter_next_string(&iter, &str) == TRUE)
lac = strtol(str, NULL, 16);
else
goto out;
if (g_at_result_iter_next_string(&iter, &str) == TRUE)
ci = strtol(str, NULL, 16);
else
goto out;
g_at_result_iter_next_number(&iter, &tech);
out:
ofono_debug("cgreg_cb: %d, %d, %d, %d", status, lac, ci, tech);
cb(&error, status, lac, ci, tech, cbd->data);
}
static void at_pdp_set_active_all(struct ofono_gprs *gprs,
int active, ofono_gprs_cb_t cb,
void *data)
static void at_gprs_registration_status(struct ofono_gprs *gprs,
ofono_gprs_status_cb_t cb,
void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct set_active_req *req;
char buf[64];
struct cb_data *cbd = cb_data_new(cb, data);
req = g_new0(struct set_active_req, 1);
if (!req)
if (!cbd)
goto error;
req->gprs = gprs;
req->active = active;
req->cb = cb;
req->data = data;
sprintf(buf, "AT+CGACT=%i", active ? 1 : 0);
if (g_at_chat_send(gd->chat, buf, none_prefix,
at_cgact_cb, req, g_free) > 0)
if (g_at_chat_send(gd->chat, "AT+CGREG?", cgreg_prefix,
at_cgreg_cb, cbd, g_free) > 0)
return;
error:
if (req)
g_free(req);
if (cbd)
g_free(cbd);
CALLBACK_WITH_FAILURE(cb, data);
}
static void at_pdp_alloc(struct ofono_gprs *gprs,
ofono_gprs_alloc_cb_t cb,
void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_gprs_primary_context *ctx;
struct ofono_error e;
unsigned id = find_next_primary_id(gd);
if (!id) {
CALLBACK_WITH_FAILURE(cb, NULL, data);
return;
}
ctx = g_try_new0(struct ofono_gprs_primary_context, 1);
if (!ctx) {
CALLBACK_WITH_FAILURE(cb, NULL, data);
return;
}
ctx->id = id;
ctx->apn = g_strdup("");
ctx->username = g_strdup("");
ctx->password = g_strdup("");
gd->new_contexts = g_slist_insert_sorted(gd->new_contexts,
ctx, context_compare);
gd->contexts = g_slist_insert_sorted(gd->contexts,
ctx, context_compare);
/* The context will be defined (+CGDCONT) lazily, once it's needed
* and the parameters are already set in ctx. Right now just call
* back */
e.type = OFONO_ERROR_TYPE_NO_ERROR;
e.error = 0;
cb(&e, ctx, data);
ofono_gprs_notify(gprs, ctx);
}
static void at_pdp_undefine_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
dump_response("undefine_cb", ok, result);
if (!ok)
ofono_error("Undefining primary context failed");
}
static void at_pdp_free(struct ofono_gprs *gprs, unsigned id,
ofono_gprs_cb_t cb, void *data)
{
struct gprs_data *gd = ofono_gprs_get_data(gprs);
struct ofono_error e;
char buf[64];
struct ofono_gprs_primary_context *ctx;
GSList *l;
gint cid = id;
l = g_slist_find_custom(gd->contexts, &cid, context_id_compare);
if (!l) {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
ctx = l->data;
if (ctx->active) {
CALLBACK_WITH_FAILURE(cb, data);
return;
}
/* We can call back already -- even if the request to undefine
* the context fails, the ID can be re-used. */
e.type = OFONO_ERROR_TYPE_NO_ERROR;
e.error = 0;
cb(&e, data);
context_free(ctx);
gd->contexts = g_slist_remove(gd->contexts, ctx);
if (g_slist_find(gd->new_contexts, ctx)) {
gd->new_contexts = g_slist_remove(gd->new_contexts, ctx);
return;
}
sprintf(buf, "AT+CGDCONT=%u", id);
g_at_chat_send(gd->chat, buf, none_prefix,
at_pdp_undefine_cb, NULL, NULL);
CALLBACK_WITH_FAILURE(cb, -1, -1, -1, -1, data);
}
static void at_cgact_read_cb(gboolean ok, GAtResult *result,
@ -501,6 +362,7 @@ static struct ofono_gprs_driver driver = {
.probe = at_gprs_probe,
.remove = at_gprs_remove,
.set_attached = at_gprs_set_attached,
.registration_status = at_gprs_registration_status,
};
void at_gprs_init()