Watch GPRS status changes to notify DUN client any unsolicited result,
like +CGREG status changes.
---
include/gprs.h | 11 +++++++
src/emulator.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gprs.c | 64 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 163 insertions(+), 0 deletions(-)
diff --git a/include/gprs.h b/include/gprs.h
index a1cbcd9..ca23c45 100644
--- a/include/gprs.h
+++ b/include/gprs.h
@@ -36,6 +36,8 @@ typedef void (*ofono_gprs_status_cb_t)(const struct
ofono_error *error,
typedef void (*ofono_gprs_cb_t)(const struct ofono_error *error, void *data);
+typedef void (*ofono_gprs_status_notify_cb_t)(const int status, void *data);
+
struct ofono_gprs_driver {
const char *name;
int (*probe)(struct ofono_gprs *gprs, unsigned int vendor,
@@ -67,6 +69,15 @@ void ofono_gprs_set_cid_range(struct ofono_gprs *gprs,
void ofono_gprs_add_context(struct ofono_gprs *gprs,
struct ofono_gprs_context *gc);
+unsigned int __ofono_gprs_add_status_watch(struct ofono_gprs *gprs,
+ ofono_gprs_status_notify_cb_t cb,
+ void *data, ofono_destroy_func destroy);
+
+gboolean __ofono_gprs_remove_status_watch(struct ofono_gprs *gprs,
+ unsigned int id);
+
+int ofono_gprs_get_status(struct ofono_gprs *gprs);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/emulator.c b/src/emulator.c
index 546a48b..3bb32ae 100644
--- a/src/emulator.c
+++ b/src/emulator.c
@@ -68,6 +68,10 @@ struct ofono_emulator {
int netreg_lac;
int netreg_ci;
int gprs_status;
+
+ struct ofono_gprs *gprs;
+ unsigned int gprs_watch;
+ unsigned int gprs_status_watch;
};
static GSList *emulator_list;
@@ -767,6 +771,18 @@ static void emulator_remove(struct ofono_atom *atom)
if (e->driver->remove)
e->driver->remove(e);
+ if (e->gprs_watch) {
+ if (e->gprs_status_watch) {
+ __ofono_gprs_remove_status_watch(e->gprs,
+ e->gprs_status_watch);
+ e->gprs_status_watch = 0;
+ }
+
+ __ofono_modem_remove_atom_watch(e->modem, e->gprs_watch);
+ e->gprs_watch = 0;
+ e->gprs = NULL;
+ }
+
__ofono_watchlist_free(e->status_watches);
ofono_emulator_release_id(e->id);
g_free(e);
@@ -794,6 +810,76 @@ void ofono_emulator_disable(struct ofono_emulator *e)
e->powered = FALSE;
}
+static void emulator_gprs_update(struct ofono_emulator *e)
+{
+ GAtServer *server = e->server;
+ char buf[256];
+
+ switch (e->modem_cgreg) {
+ case 0:
+ break;
+ case 1:
+ snprintf(buf, sizeof(buf), "+CGREG: %d", e->gprs_status);
+ g_at_server_send_unsolicited(server, buf);
+ break;
+ case 2:
+ snprintf(buf, sizeof(buf), "+CGREG: %d", e->gprs_status);
+ g_at_server_send_unsolicited(server, buf);
+ break;
+ default:
+ break;
+ }
+}
+
+static void gprs_status_changed(int status, void *data)
+{
+ struct ofono_emulator *e = data;
+
+ DBG("%d", status);
+
+ e->gprs_status = status;
+
+ emulator_gprs_update(e);
+}
+
+static void gprs_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond,
+ void *data)
+{
+ struct ofono_emulator *e = data;
+ struct ofono_gprs *gprs;
+
+ if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+ e->gprs_status_watch = 0;
+ e->gprs = NULL;
+ return;
+ }
+
+ gprs = __ofono_atom_get_data(atom);
+ e->gprs = gprs;
+ e->gprs_status = ofono_gprs_get_status(gprs);
+ e->gprs_status_watch = __ofono_gprs_add_status_watch(e->gprs,
+ gprs_status_changed, e, NULL);
+
+ emulator_gprs_update(e);
+}
+
+static void add_gprs_watches(struct ofono_emulator *e)
+{
+ struct ofono_modem *modem = e->modem;
+ struct ofono_atom *gprs_atom;
+
+ e->gprs_watch = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_GPRS,
+ gprs_watch, e, NULL);
+
+ gprs_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_GPRS);
+
+ if (gprs_atom && __ofono_atom_get_registered(gprs_atom))
+ gprs_watch(gprs_atom,
+ OFONO_ATOM_WATCH_CONDITION_REGISTERED, e);
+}
+
static int set_powered(struct ofono_emulator *e, ofono_bool_t powered, int fd)
{
int val;
@@ -843,6 +929,8 @@ ofono_bool_t ofono_emulator_enable(struct ofono_emulator
*e, int fd)
g_at_server_register(e->server, "+CGATT", cgatt_cb, e, NULL);
g_at_server_register(e->server, "+CGDCONT", cgdcont_cb, e, NULL);
+ add_gprs_watches(e);
+
g_io_channel_unref(channel);
e->powered = TRUE;
diff --git a/src/gprs.c b/src/gprs.c
index cb83e23..3ed056a 100644
--- a/src/gprs.c
+++ b/src/gprs.c
@@ -142,6 +142,8 @@ static const char *gprs_context_type_to_string(int type)
return "mms";
case GPRS_CONTEXT_TYPE_WAP:
return "wap";
+ case GPRS_CONTEXT_TYPE_DUN:
+ return "dun";
}
return NULL;
@@ -155,6 +157,8 @@ static enum gprs_context_type
gprs_context_string_to_type(const char *str)
return GPRS_CONTEXT_TYPE_WAP;
else if (g_str_equal(str, "mms"))
return GPRS_CONTEXT_TYPE_MMS;
+ else if (g_str_equal(str, "dun"))
+ return GPRS_CONTEXT_TYPE_DUN;
return GPRS_CONTEXT_TYPE_INVALID;
}
@@ -1467,6 +1471,51 @@ static GDBusSignalTable manager_signals[] = {
{ }
};
+unsigned int __ofono_gprs_add_status_watch(struct ofono_gprs *gprs,
+ ofono_gprs_status_notify_cb_t notify,
+ void *data, ofono_destroy_func destroy)
+{
+ struct ofono_watchlist_item *item;
+
+ DBG("%p", gprs);
+
+ if (gprs == NULL)
+ return 0;
+
+ if (notify == NULL)
+ return 0;
+
+ item = g_new0(struct ofono_watchlist_item, 1);
+
+ item->notify = notify;
+ item->destroy = destroy;
+ item->notify_data = data;
+
+ return __ofono_watchlist_add_item(gprs->status_watches, item);
+}
+
+gboolean __ofono_gprs_remove_status_watch(struct ofono_gprs *gprs,
+ unsigned int id)
+{
+ DBG("%p", gprs);
+
+ return __ofono_watchlist_remove_item(gprs->status_watches, id);
+}
+
+static void notify_status_watches(struct ofono_gprs *gprs)
+{
+ struct ofono_watchlist_item *item;
+ GSList *l;
+ ofono_gprs_status_notify_cb_t notify;
+
+ for (l = gprs->status_watches->items; l; l = l->next) {
+ item = l->data;
+ notify = item->notify;
+
+ notify(gprs->status, item->notify_data);
+ }
+}
+
void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
{
if (gprs->driver_attached == FALSE)
@@ -1476,6 +1525,8 @@ void ofono_gprs_detached_notify(struct ofono_gprs *gprs)
gprs_attached_update(gprs);
+ notify_status_watches(gprs);
+
/* TODO: The network forced a detach, we should wait for some time
* and try to re-attach
*/
@@ -1489,6 +1540,8 @@ void ofono_gprs_status_notify(struct ofono_gprs *gprs,
int status)
gprs->status = status;
gprs_attached_update(gprs);
+
+ notify_status_watches(gprs);
}
void ofono_gprs_set_cid_range(struct ofono_gprs *gprs,
@@ -1944,6 +1997,14 @@ struct ofono_modem *ofono_gprs_context_get_modem(struct
ofono_gprs_context *gc)
return __ofono_atom_get_modem(gc->atom);
}
+int ofono_gprs_get_status(struct ofono_gprs *gprs)
+{
+ if (gprs == NULL)
+ return -1;
+
+ return gprs->status;
+}
+
int ofono_gprs_driver_register(const struct ofono_gprs_driver *d)
{
DBG("driver: %p, name: %s", d, d->name);
@@ -1971,6 +2032,9 @@ static void gprs_unregister(struct ofono_atom *atom)
const char *path = __ofono_atom_get_path(atom);
GSList *l;
+ __ofono_watchlist_free(gprs->status_watches);
+ gprs->status_watches = NULL;
+
if (gprs->settings) {
storage_close(gprs->imsi, SETTINGS_STORE,
gprs->settings, TRUE);
--
1.6.3.3
_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono