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
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to