Teach USSD to recognise password change strings.
authorAndrzej Zaborowski <andrew.zaborowski@intel.com>
Thu, 18 Jun 2009 04:04:23 +0000 (06:04 +0200)
committerDenis Kenzior <denkenz@gmail.com>
Thu, 18 Jun 2009 21:57:58 +0000 (16:57 -0500)
This is slightly hacky, part of ussd.c responsible for registering services
is duplicated and parse_ss_control_string is modified to accept a fourth
SI fragment in the input string.

src/common.c
src/common.h
src/modem.h
src/ussd.c
src/ussd.h
unit/test-common.c

index 8653432..a9166bf 100644 (file)
@@ -465,7 +465,7 @@ const char *ss_control_type_to_string(enum ss_control_type type)
 gboolean parse_ss_control_string(char *str, int *ss_type,
                                        char **sc, char **sia,
                                        char **sib, char **sic,
-                                       char **dn)
+                                       char **sid, char **dn)
 {
        int len = strlen(str);
        int cur = 0;
@@ -533,6 +533,7 @@ gboolean parse_ss_control_string(char *str, int *ss_type,
        NEXT_FIELD(c, *sia);
        NEXT_FIELD(c, *sib);
        NEXT_FIELD(c, *sic);
+       NEXT_FIELD(c, *sid);
 
        if (*c == '\0')
                ret = TRUE;
index 1c0a776..0f7684e 100644 (file)
@@ -192,7 +192,7 @@ gboolean valid_ussd_string(const char *str);
 gboolean parse_ss_control_string(char *str, int *ss_type,
                                        char **sc, char **sia,
                                        char **sib, char **sic,
-                                       char **dn);
+                                       char **sid, char **dn);
 
 const char *ss_control_type_to_string(enum ss_control_type type);
 
index 6ed4a2a..d322df8 100644 (file)
@@ -28,6 +28,7 @@ struct ofono_modem {
        void            *userdata;
 
        GSList *ss_control_list;
+       GSList *ss_passwd_list;
 
        struct ofono_modem_data *modem_info;
        struct network_registration_data *network_registration;
index 7225398..d2251c8 100644 (file)
@@ -165,22 +165,148 @@ void ss_control_unregister(struct ofono_modem *modem, const char *str,
                                                l->data);
 }
 
+struct ss_passwd_entry {
+       char *service;
+       ss_passwd_cb_t cb;
+};
+
+static struct ss_passwd_entry *ss_passwd_entry_create(const char *service,
+                                                       ss_passwd_cb_t cb)
+{
+       struct ss_passwd_entry *r;
+
+       r = g_try_new0(struct ss_passwd_entry, 1);
+
+       if (!r)
+               return r;
+
+       r->service = g_strdup(service);
+       r->cb = cb;
+
+       return r;
+}
+
+static void ss_passwd_entry_destroy(struct ss_passwd_entry *ca)
+{
+       g_free(ca->service);
+       g_free(ca);
+}
+
+static gint ss_passwd_entry_compare(gconstpointer a, gconstpointer b)
+{
+       const struct ss_passwd_entry *ca = a;
+       const struct ss_passwd_entry *cb = b;
+       int ret;
+
+       ret = strcmp(ca->service, cb->service);
+
+       if (ret)
+               return ret;
+
+       if (ca->cb < cb->cb)
+               return -1;
+
+       if (ca->cb > cb->cb)
+               return 1;
+
+       return 0;
+}
+
+static gint ss_passwd_entry_find_by_service(gconstpointer a, gconstpointer b)
+{
+       const struct ss_passwd_entry *ca = a;
+
+       return strcmp(ca->service, b);
+}
+
+gboolean ss_passwd_register(struct ofono_modem *modem, const char *str,
+                               ss_passwd_cb_t cb)
+{
+       struct ss_passwd_entry *entry;
+
+       if (!modem)
+               return FALSE;
+
+       entry = ss_passwd_entry_create(str, cb);
+
+       if (!entry)
+               return FALSE;
+
+       modem->ss_passwd_list = g_slist_append(modem->ss_passwd_list, entry);
+
+       return TRUE;
+}
+
+void ss_passwd_unregister(struct ofono_modem *modem, const char *str,
+                               ss_passwd_cb_t cb)
+{
+       const struct ss_passwd_entry entry = { (char *)str, cb };
+       GSList *l;
+
+       if (!modem)
+               return;
+
+       l = g_slist_find_custom(modem->ss_passwd_list, &entry,
+                               ss_passwd_entry_compare);
+
+       if (!l)
+               return;
+
+       ss_passwd_entry_destroy(l->data);
+       modem->ss_passwd_list = g_slist_remove(modem->ss_passwd_list,
+                                               l->data);
+}
+
+static gboolean recognized_passwd_change_string(struct ofono_modem *modem,
+                                               int type, char *sc,
+                                               char *sia, char *sib,
+                                               char *sic, char *sid,
+                                               char *dn, DBusMessage *msg)
+{
+       GSList *l = modem->ss_passwd_list;
+
+       switch (type) {
+       case SS_CONTROL_TYPE_ACTIVATION:
+       case SS_CONTROL_TYPE_REGISTRATION:
+               break;
+
+       default:
+               return FALSE;
+       }
+
+       if (strcmp(sc, "03") || strlen(dn) || strcmp(sic, sid))
+               return FALSE;
+
+       while ((l = g_slist_find_custom(l, sia,
+                       ss_passwd_entry_find_by_service)) != NULL) {
+               struct ss_passwd_entry *entry = l->data;
+
+               if (entry->cb(modem, sia, sib, sic, msg))
+                       return TRUE;
+
+               l = l->next;
+       }
+
+       return FALSE;
+}
+
 static gboolean recognized_control_string(struct ofono_modem *modem,
                                                const char *ss_str,
                                                DBusMessage *msg)
 {
        char *str = g_strdup(ss_str);
-       char *sc, *sia, *sib, *sic, *dn;
+       char *sc, *sia, *sib, *sic, *sid, *dn;
        int type;
        gboolean ret = FALSE;
 
        ofono_debug("parsing control string");
 
-       if (parse_ss_control_string(str, &type, &sc, &sia, &sib, &sic, &dn)) {
+       if (parse_ss_control_string(str, &type, &sc,
+                               &sia, &sib, &sic, &sid, &dn)) {
                GSList *l = modem->ss_control_list;
 
-               ofono_debug("Got parse result: %d, %s, %s, %s, %s, %s",
-                               type, sc, sia, sib, sic, dn);
+               ofono_debug("Got parse result: %d, %s, %s, %s, %s, %s, %s",
+                               type, sc, sia, sib, sic, sid, dn);
 
                while ((l = g_slist_find_custom(l, sc,
                                ss_control_entry_find_by_service)) != NULL) {
@@ -193,6 +319,13 @@ static gboolean recognized_control_string(struct ofono_modem *modem,
 
                        l = l->next;
                }
+
+               /* A password change string needs to be treated separately
+                * because it uses a fourth SI and is thus not a valid
+                * control string.  */
+               if (recognized_passwd_change_string(modem, type, sc,
+                                       sia, sib, sic, sid, dn, msg))
+                       goto out;
        }
 
        /* TODO: Handle all strings that control voice calls */
@@ -205,9 +338,6 @@ static gboolean recognized_control_string(struct ofono_modem *modem,
         * by SEND and are not valid USSD requests.
         */
 
-       /* TODO: Handle Password registration according to 22.030 Section 6.5.4
-        */
-
 out:
        g_free(str);
 
index 5b956e5..5f40f61 100644 (file)
@@ -26,8 +26,18 @@ typedef gboolean (*ss_control_cb_t)(struct ofono_modem *modem,
                                        const char *sic, const char *dn,
                                        DBusMessage *msg);
 
+typedef gboolean (*ss_passwd_cb_t)(struct ofono_modem *modem, const char *sc,
+                                       const char *old, const char *new,
+                                       DBusMessage *msg);
+
 gboolean ss_control_register(struct ofono_modem *modem, const char *str,
                                ss_control_cb_t cb);
 
 void ss_control_unregister(struct ofono_modem *modem, const char *str,
                                ss_control_cb_t cb);
+
+gboolean ss_passwd_register(struct ofono_modem *modem, const char *str,
+                               ss_passwd_cb_t cb);
+
+void ss_passwd_unregister(struct ofono_modem *modem, const char *str,
+                               ss_passwd_cb_t cb);
index 5c753d3..96509bd 100644 (file)
@@ -57,6 +57,7 @@ static void test_invalid()
        char *sia;
        char *sib;
        char *sic;
+       char *sid;
        char *dn;
        int type;
 
@@ -71,7 +72,9 @@ static void test_invalid()
                str = strdup(invalid_strings[i]);
 
                ret = parse_ss_control_string(str, &type, &sc,
-                                               &sia, &sib, &sic, &dn);
+                                               &sia, &sib, &sic, &sid, &dn);
+               if (strlen(sid))
+                       ret = FALSE;
 
                g_assert(ret == FALSE);
 
@@ -105,6 +108,7 @@ static void test_valid()
        char *sia;
        char *sib;
        char *sic;
+       char *sid;
        char *dn;
        int type;
        gboolean ret;
@@ -119,7 +123,9 @@ static void test_valid()
                str = strdup(valid_strings[i]);
 
                ret = parse_ss_control_string(str, &type, &sc,
-                                               &sia, &sib, &sic, &dn);
+                                               &sia, &sib, &sic, &sid, &dn);
+               if (strlen(sid))
+                       ret = FALSE;
 
                g_assert(ret == TRUE);