mirror of git://git.sysmocom.de/ofono
atmodem: Implement the list_activated_contexts callback
The callback calls cgact and cgdcont to get information regarding any activate context.
This commit is contained in:
parent
9a1b490e78
commit
e3d5ac1f16
|
@ -29,6 +29,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <ell/ell.h>
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
#include <ofono/log.h>
|
#include <ofono/log.h>
|
||||||
|
@ -41,6 +42,8 @@
|
||||||
#include "atmodem.h"
|
#include "atmodem.h"
|
||||||
#include "vendor.h"
|
#include "vendor.h"
|
||||||
|
|
||||||
|
#define MAX_CONTEXTS 255
|
||||||
|
|
||||||
static const char *cgreg_prefix[] = { "+CGREG:", NULL };
|
static const char *cgreg_prefix[] = { "+CGREG:", NULL };
|
||||||
static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
|
static const char *cgdcont_prefix[] = { "+CGDCONT:", NULL };
|
||||||
static const char *cgact_prefix[] = { "+CGACT:", NULL };
|
static const char *cgact_prefix[] = { "+CGACT:", NULL };
|
||||||
|
@ -54,6 +57,47 @@ struct gprs_data {
|
||||||
int attached;
|
int attached;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct list_contexts_data
|
||||||
|
{
|
||||||
|
struct ofono_gprs *gprs;
|
||||||
|
void *cb;
|
||||||
|
void *data;
|
||||||
|
struct l_uintset *active_cids;
|
||||||
|
int ref_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct list_contexts_data * list_contexts_data_new(
|
||||||
|
struct ofono_gprs *gprs, void *cb, void *data)
|
||||||
|
{
|
||||||
|
struct list_contexts_data *ret;
|
||||||
|
|
||||||
|
ret = g_new0(struct list_contexts_data, 1);
|
||||||
|
ret->ref_count = 1;
|
||||||
|
ret->gprs = gprs;
|
||||||
|
ret->cb = cb;
|
||||||
|
ret->data = data;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct list_contexts_data * list_contexts_data_ref(
|
||||||
|
struct list_contexts_data *ld)
|
||||||
|
{
|
||||||
|
ld->ref_count++;
|
||||||
|
return ld;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void list_contexts_data_unref(gpointer user_data)
|
||||||
|
{
|
||||||
|
struct list_contexts_data *ld = user_data;
|
||||||
|
|
||||||
|
if (--ld->ref_count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
l_uintset_free(ld->active_cids);
|
||||||
|
g_free(ld);
|
||||||
|
}
|
||||||
|
|
||||||
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
static void at_cgatt_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
struct cb_data *cbd = user_data;
|
struct cb_data *cbd = user_data;
|
||||||
|
@ -146,14 +190,43 @@ static void at_gprs_registration_status(struct ofono_gprs *gprs,
|
||||||
CALLBACK_WITH_FAILURE(cb, -1, data);
|
CALLBACK_WITH_FAILURE(cb, -1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void at_cgdcont_parse(struct ofono_gprs *gprs, GAtResult *result,
|
||||||
|
struct l_uintset *cids)
|
||||||
|
{
|
||||||
|
GAtResultIter iter;
|
||||||
|
|
||||||
|
g_at_result_iter_init(&iter, result);
|
||||||
|
|
||||||
|
while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
|
||||||
|
int read_cid;
|
||||||
|
const char *apn = NULL;
|
||||||
|
|
||||||
|
if (!g_at_result_iter_next_number(&iter, &read_cid))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!l_uintset_contains(cids, read_cid))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* ignore protocol */
|
||||||
|
g_at_result_iter_skip_next(&iter);
|
||||||
|
|
||||||
|
g_at_result_iter_next_string(&iter, &apn);
|
||||||
|
|
||||||
|
if (apn)
|
||||||
|
ofono_gprs_cid_activated(gprs, read_cid, apn);
|
||||||
|
else
|
||||||
|
ofono_warn("cid %d: Activated but no apn present",
|
||||||
|
read_cid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
|
static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ofono_gprs *gprs = user_data;
|
struct ofono_gprs *gprs = user_data;
|
||||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||||
int activated_cid = gd->last_auto_context_id;
|
int activated_cid = gd->last_auto_context_id;
|
||||||
const char *apn = NULL;
|
struct l_uintset *cids;
|
||||||
GAtResultIter iter;
|
|
||||||
|
|
||||||
DBG("ok %d", ok);
|
DBG("ok %d", ok);
|
||||||
|
|
||||||
|
@ -162,47 +235,52 @@ static void at_cgdcont_read_cb(gboolean ok, GAtResult *result,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gd->last_auto_context_id == -1) {
|
if (activated_cid == -1) {
|
||||||
DBG("Context got deactivated while calling CGDCONT");
|
DBG("Context got deactivated while calling CGDCONT");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_at_result_iter_init(&iter, result);
|
cids = l_uintset_new(activated_cid);
|
||||||
|
|
||||||
while (g_at_result_iter_next(&iter, "+CGDCONT:")) {
|
l_uintset_put(cids, activated_cid);
|
||||||
int read_cid;
|
|
||||||
|
|
||||||
if (!g_at_result_iter_next_number(&iter, &read_cid))
|
at_cgdcont_parse(gprs, result, cids);
|
||||||
break;
|
|
||||||
|
|
||||||
if (read_cid != activated_cid)
|
l_uintset_free(cids);
|
||||||
continue;
|
}
|
||||||
|
|
||||||
/* ignore protocol */
|
static void at_cgdcont_act_read_cb(gboolean ok, GAtResult *result,
|
||||||
g_at_result_iter_skip_next(&iter);
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
struct list_contexts_data *ld = user_data;
|
||||||
|
ofono_gprs_cb_t cb = ld->cb;
|
||||||
|
struct ofono_error error;
|
||||||
|
|
||||||
g_at_result_iter_next_string(&iter, &apn);
|
decode_at_error(&error, g_at_result_final_response(result));
|
||||||
|
|
||||||
break;
|
if (!ok)
|
||||||
}
|
ofono_warn("Can't read CGDCONT context.");
|
||||||
|
|
||||||
if (apn)
|
|
||||||
ofono_gprs_cid_activated(gprs, activated_cid, apn);
|
|
||||||
else
|
else
|
||||||
ofono_warn("cid %u: Received activated but no apn present",
|
at_cgdcont_parse(ld->gprs, result, ld->active_cids);
|
||||||
activated_cid);
|
|
||||||
|
cb(&error, ld->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void at_cgact_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
static void at_cgact_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||||
{
|
{
|
||||||
struct ofono_gprs *gprs = user_data;
|
struct list_contexts_data *ld = user_data;
|
||||||
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
struct gprs_data *gd = ofono_gprs_get_data(ld->gprs);
|
||||||
|
ofono_gprs_cb_t cb = ld->cb;
|
||||||
|
struct ofono_error error;
|
||||||
GAtResultIter iter;
|
GAtResultIter iter;
|
||||||
|
|
||||||
DBG("ok %d", ok);
|
decode_at_error(&error, g_at_result_final_response(result));
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
ofono_warn("Can't read CGACT contexts.");
|
ofono_warn("Can't read CGACT contexts.");
|
||||||
|
|
||||||
|
cb(&error, ld->data);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,17 +300,43 @@ static void at_cgact_cb(gboolean ok, GAtResult *result, gpointer user_data)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Flag this as auto context as it was obviously active */
|
/* Flag this as auto context as it was obviously active */
|
||||||
if (gd->last_auto_context_id == 0)
|
if (gd->last_auto_context_id == -1)
|
||||||
gd->last_auto_context_id = read_cid;
|
gd->last_auto_context_id = read_cid;
|
||||||
|
|
||||||
if (read_cid != gd->last_auto_context_id)
|
if (!ld->active_cids)
|
||||||
continue;
|
ld->active_cids = l_uintset_new(MAX_CONTEXTS);
|
||||||
|
|
||||||
g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
|
l_uintset_put(ld->active_cids, read_cid);
|
||||||
at_cgdcont_read_cb, gprs, NULL);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ld->active_cids != NULL) {
|
||||||
|
if (g_at_chat_send(gd->chat, "AT+CGDCONT?", cgdcont_prefix,
|
||||||
|
at_cgdcont_act_read_cb, ld,
|
||||||
|
list_contexts_data_unref)) {
|
||||||
|
list_contexts_data_ref(ld);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CALLBACK_WITH_FAILURE(cb, ld->data);
|
||||||
|
} else {
|
||||||
|
/* No active contexts found */
|
||||||
|
cb(&error, ld->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void at_gprs_list_active_contexts(struct ofono_gprs *gprs,
|
||||||
|
ofono_gprs_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
struct gprs_data *gd = ofono_gprs_get_data(gprs);
|
||||||
|
struct list_contexts_data *ld = list_contexts_data_new(gprs, cb, data);
|
||||||
|
|
||||||
|
if (g_at_chat_send(gd->chat, "AT+CGACT?", cgact_prefix,
|
||||||
|
at_cgact_cb, ld, list_contexts_data_unref))
|
||||||
|
return;
|
||||||
|
|
||||||
|
list_contexts_data_unref(ld);
|
||||||
|
|
||||||
|
CALLBACK_WITH_FAILURE(cb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cgreg_notify(GAtResult *result, gpointer user_data)
|
static void cgreg_notify(GAtResult *result, gpointer user_data)
|
||||||
|
@ -538,10 +642,6 @@ static void gprs_initialized(gboolean ok, GAtResult *result, gpointer user_data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if there is any already activated contexts at init */
|
|
||||||
g_at_chat_send(gd->chat, "AT+CGACT?", cgact_prefix,
|
|
||||||
at_cgact_cb, gprs, NULL);
|
|
||||||
|
|
||||||
ofono_gprs_register(gprs);
|
ofono_gprs_register(gprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,6 +805,7 @@ static const struct ofono_gprs_driver driver = {
|
||||||
.remove = at_gprs_remove,
|
.remove = at_gprs_remove,
|
||||||
.set_attached = at_gprs_set_attached,
|
.set_attached = at_gprs_set_attached,
|
||||||
.attached_status = at_gprs_registration_status,
|
.attached_status = at_gprs_registration_status,
|
||||||
|
.list_active_contexts = at_gprs_list_active_contexts,
|
||||||
};
|
};
|
||||||
|
|
||||||
void at_gprs_init(void)
|
void at_gprs_init(void)
|
||||||
|
|
Loading…
Reference in New Issue