Add GPRS registration status implementation
authorDenis Kenzior <denis.kenzior@intel.com>
Thu, 22 Oct 2009 23:00:07 +0000 (18:00 -0500)
committerDenis Kenzior <denkenz@gmail.com>
Fri, 23 Oct 2009 22:05:55 +0000 (17:05 -0500)
drivers/atmodem/gprs.c

index 1976bc6..a8d134b 100644 (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);
-
-       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,
@@ -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()