#include "atmodem.h"
+static const char *cgreg_prefix[] = { "+CGREG:", NULL };
static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
static const char *none_prefix[] = { NULL };
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);
-
- sprintf(buf, "AT+CGACT=1,%u", req->ctx->id);
+ g_at_result_iter_init(&iter, result);
- 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;
+ /* Skip <n> the unsolicited result code */
+ g_at_result_iter_skip_next(&iter);
- l = g_slist_find_custom(gd->contexts, &cid, context_id_compare);
- if (!l)
- goto error;
+ g_at_result_iter_next_number(&iter, &status);
- ctx = l->data;
+ if (g_at_result_iter_next_string(&iter, &str) == TRUE)
+ lac = strtol(str, NULL, 16);
+ else
+ goto out;
- req = g_new0(struct set_active_req, 1);
- if (!req)
- goto error;
+ if (g_at_result_iter_next_string(&iter, &str) == TRUE)
+ ci = strtol(str, NULL, 16);
+ else
+ goto out;
- 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;
- }
+ g_at_result_iter_next_number(&iter, &tech);
-error:
- if (req)
- g_free(req);
+out:
+ ofono_debug("cgreg_cb: %d, %d, %d, %d", status, lac, ci, tech);
- CALLBACK_WITH_FAILURE(cb, data);
+ 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);
-
- 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);
+ if (cbd)
+ g_free(cbd);
- 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,
.probe = at_gprs_probe,
.remove = at_gprs_remove,
.set_attached = at_gprs_set_attached,
+ .registration_status = at_gprs_registration_status,
};
void at_gprs_init()