Register mandatory AT command handlers for DUN server. --- include/emulator.h | 2 + src/emulator.c | 381 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 383 insertions(+), 0 deletions(-)
diff --git a/include/emulator.h b/include/emulator.h index 641f38c..1ff813f 100644 --- a/include/emulator.h +++ b/include/emulator.h @@ -37,6 +37,8 @@ enum ofono_emulator_status { OFONO_EMULATOR_STATUS_DUN_CONNECT, OFONO_EMULATOR_STATUS_DUN_CONNECTED, OFONO_EMULATOR_STATUS_DUN_DISCONNECTED, + OFONO_EMULATOR_STATUS_SET_CGATT, + OFONO_EMULATOR_STATUS_SET_CGDCONT, }; enum _GAtServerResult; diff --git a/src/emulator.c b/src/emulator.c index 378426c..8811f6c 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -49,6 +49,14 @@ struct dun_context { struct ofono_gprs_primary_context pri_ctx; }; +struct modem_settings { + int mode; + int creg; + int cgreg; + int cops; + int attached; +}; + struct ofono_emulator { struct ofono_modem *modem; struct ofono_atom *atom; @@ -57,6 +65,7 @@ struct ofono_emulator { GAtServer *server; GAtPPP *ppp; struct dun_context context; + struct modem_settings settings; enum ofono_emulator_status status; struct ofono_watchlist *status_watches; }; @@ -146,6 +155,371 @@ static struct ofono_emulator_req *ofono_emulator_req_new(void *cb, return req; } +static void generic_cb(GAtServerResult res, void *user_data) +{ + struct ofono_emulator *e = user_data; + GAtServer *server = e->server; + + g_at_server_send_final(server, res); + + e->status = OFONO_EMULATOR_STATUS_IDLE; + + notify_status_watches(e, NULL); +} + +static gboolean send_ok(gpointer user_data) +{ + struct ofono_emulator *e = user_data; + + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + + return FALSE; +} + +static void cfun_cb(GAtServerRequestType type, GAtResult *cmd, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + char buf[50]; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_info(e, "+CFUN: (0-1)", TRUE); + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + snprintf(buf, sizeof(buf), "+CFUN: %d", e->settings.mode); + ofono_emulator_send_info(e, buf, TRUE); + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + int mode; + + g_at_result_iter_init(&iter, cmd); + g_at_result_iter_next(&iter, "+CFUN="); + + if (g_at_result_iter_next_number(&iter, &mode) == FALSE) + goto error; + + if (mode != 0 && mode != 1) + goto error; + + DBG("set CFUN to %d", mode); + + e->settings.mode = mode; + g_timeout_add_seconds(1, send_ok, e); + break; + } + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void cpin_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + /* not implement yet*/ + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void creg_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + int mode; + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+CREG="); + + if (g_at_result_iter_next_number(&iter, &mode) == FALSE) + goto error; + + if (mode < 0 || mode > 2) + goto error; + + DBG("set netreg status %d", mode); + + e->settings.creg = mode; + + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + + break; + } + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void cgreg_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + int mode; + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+CGREG="); + + if (g_at_result_iter_next_number(&iter, &mode) == FALSE) + goto error; + + if (mode < 0 || mode > 2) + goto error; + + DBG("set GPRS cgreg status %d", mode); + + e->settings.cgreg = mode; + + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + + break; + } + default: + goto error; + }; + + return; +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void cops_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + char buf[50]; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + snprintf(buf, sizeof(buf), "+COPS: %d", e->settings.cops); + ofono_emulator_send_info(e, buf, TRUE); + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + int mode; + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+COPS="); + + if (g_at_result_iter_next_number(&iter, &mode) == FALSE) + goto error; + + if (mode < 0 || mode > 2) + goto error; + + DBG("set GPRS cops status %d", mode); + + e->settings.cops = mode; + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + + break; + } + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void cgatt_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + struct ofono_emulator_req *req; + char buf[12]; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + snprintf(buf, sizeof(buf), "+CGATT: %d", e->settings.attached); + ofono_emulator_send_info(e, buf, TRUE); + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + int attached; + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+CGATT="); + + if (g_at_result_iter_next_number(&iter, &attached) == FALSE) + goto error; + + if (attached != 0 && attached != 1) + goto error; + + DBG("set GPRS attach status %d", attached); + + req = ofono_emulator_req_new(generic_cb, e); + if (!req) + goto error; + + req->data = &attached; + + e->status = OFONO_EMULATOR_STATUS_SET_CGATT; + + notify_status_watches(e, req); + + e->settings.attached = attached; + g_free(req); + break; + } + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); +} + +static void cgdcont_cb(GAtServerRequestType type, GAtResult *result, + gpointer user_data) +{ + struct ofono_emulator *e = user_data; + struct ofono_emulator_gprs_context_req *req; + struct dun_context *context = &e->context; + struct ofono_gprs_primary_context *ctx = &context->pri_ctx; + char buf[256]; + + switch (type) { + case G_AT_SERVER_REQUEST_TYPE_SUPPORT: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + case G_AT_SERVER_REQUEST_TYPE_QUERY: + { + const char *proto = gprs_proto_to_string(ctx->proto); + + snprintf(buf, sizeof(buf), "+CGDCONT: %d, \"%s\", \"%s\"", + ctx->cid, proto, ctx->apn); + ofono_emulator_send_info(e, buf, TRUE); + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_OK); + break; + } + case G_AT_SERVER_REQUEST_TYPE_SET: + { + GAtResultIter iter; + unsigned int cid; + const char *proto; + const char *apn; + + g_at_result_iter_init(&iter, result); + g_at_result_iter_next(&iter, "+CGDCONT="); + + if (g_at_result_iter_next_number(&iter, (gint *)&cid) == FALSE) + goto error; + + if (g_at_result_iter_next_string(&iter, &proto) == FALSE) + goto error; + + if (g_at_result_iter_next_string(&iter, &apn) == FALSE) + goto error; + + DBG("set CGDCONT %d %s %s", cid, proto, apn); + + if (cid <= 0 || proto == NULL || apn == NULL) + goto error; + + if (cid == ctx->cid) + goto error; + + if (context->active) + goto error; + + ctx->cid = cid; + gprs_proto_from_string(proto, &ctx->proto); + strncpy(ctx->apn, apn, OFONO_GPRS_MAX_APN_LENGTH); + ctx->apn[OFONO_GPRS_MAX_APN_LENGTH] = '\0'; + + req = g_try_new0(struct ofono_emulator_gprs_context_req, 1); + if (!req) + goto error; + + req->proto = proto; + req->apn = apn; + req->cb = generic_cb; + req->cb_data = e; + + e->status = OFONO_EMULATOR_STATUS_SET_CGDCONT; + + notify_status_watches(e, req); + + g_free(req); + break; + } + default: + goto error; + }; + + return; + +error: + ofono_emulator_send_final(e, G_AT_SERVER_RESULT_ERROR); + g_free(req); +} + static void ppp_connect(const char *interface, const char *local, const char *remote, const char *dns1, const char *dns2, @@ -426,6 +800,13 @@ struct ofono_emulator *ofono_emulator_create(struct ofono_modem *modem, __ofono_atom_register(e->atom, emulator_unregister); g_at_server_register(e->server, "D", dial_cb, e, NULL); + g_at_server_register(e->server, "+CFUN", cfun_cb, e, NULL); + g_at_server_register(e->server, "+CPIN", cpin_cb, e, NULL); + g_at_server_register(e->server, "+CREG", creg_cb, e, NULL); + g_at_server_register(e->server, "+CGREG", cgreg_cb, e, NULL); + g_at_server_register(e->server, "+COPS", cops_cb, e, NULL); + g_at_server_register(e->server, "+CGATT", cgatt_cb, e, NULL); + g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL); return e; } -- 1.7.0.4 _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono