From: Jessica Nilsson <[email protected]>

---
 drivers/isimodem/cbs.c   |  414 +++++++++++++++++++++++++++++++++++++++++-----
 drivers/isimodem/debug.c |    4 +
 drivers/isimodem/sms.h   |    7 +-
 3 files changed, 383 insertions(+), 42 deletions(-)

diff --git a/drivers/isimodem/cbs.c b/drivers/isimodem/cbs.c
index b969c1f..67274be 100644
--- a/drivers/isimodem/cbs.c
+++ b/drivers/isimodem/cbs.c
@@ -3,6 +3,7 @@
  *  oFono - Open Source Telephony
  *
  *  Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ *  Copyright (C) ST-Ericsson SA 2011.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
@@ -47,12 +48,16 @@
 
 struct cbs_data {
        GIsiClient *client;
+       uint8_t subscription_nr;
+       GIsiVersion version;
 };
 
 struct cbs_info {
        uint8_t pdu[88];
 };
 
+GIsiClient *pn_sms_client;
+
 static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid)
 {
        uint8_t cause;
@@ -89,18 +94,292 @@ static gboolean check_response_status(const GIsiMessage 
*msg, uint8_t msgid)
        return FALSE;
 }
 
+static void reset_buf(char *buf, char *buf_2, int buf_len)
+{
+       memset(buf, '\0', buf_len);
+       memset(buf_2, '\0', buf_len);
+}
+
+static int get_topics_len(const char *topics)
+{
+       int i = 0;
+       int k = 0;
+       int length = 0;
+       char buf[6];
+       char buf_2[6];
+
+       reset_buf(buf, buf_2, 6);
+
+       while (*topics != '\0') {
+               if (*topics == ',') {
+                       reset_buf(buf, buf_2, 6);
+                       k = 0;
+                       length++;
+               } else if (*topics != ',' && *topics != '-') {
+                       buf[k] = *topics;
+                       k++;
+               } else if (*topics == '-') {
+                       topics++;
+                       i++;
+                       k = 0;
+
+                       while (*topics != ',' && *topics != '\0') {
+                               buf_2[k] = *topics;
+                               topics++;
+                               i++;
+                               k++;
+                       }
+
+                       length = length + atoi(buf_2) - atoi(buf) + 1;
+                       k = 0;
+               }
+               if (*topics != '\0') {
+                       topics++;
+                       i++;
+               }
+       }
+
+       topics = topics - i;
+       return length;
+}
+
+static void parse_topics(const char *topics, gint16 *topics_parsed)
+{
+       int j = 0;
+       int k = 0;
+       char buf[6];
+       char buf_2[6];
+
+       reset_buf(buf, buf_2, 6);
+
+       while (*topics != '\0') {
+               if (*topics != ',' && *topics != '-') {
+                       buf[j] = *topics;
+                       j++;
+               } else if (*topics == '-') {
+                       topics++;
+                       j = 0;
+
+                       while (*topics != ',' && *topics != '\0') {
+                               buf_2[j] = *topics;
+                               topics++;
+                               j++;
+                       }
+
+                       for (j = 0; j <= (atoi(buf_2) - atoi(buf)); j++) {
+                               topics_parsed[k] = atoi(buf) + j;
+                               topics_parsed[k] = g_ntohs(topics_parsed[k]);
+                               k++;
+                       }
+
+                       j = 0;
+               } else if (*topics == ',') {
+                       topics_parsed[k] = atoi(buf);
+                       topics_parsed[k] = g_ntohs(topics_parsed[k]);
+                       reset_buf(buf, buf_2, 6);
+                       j = 0;
+                       k++;
+               }
+               if (*topics != '\0')
+                       topics++;
+       }
+}
+
+static void set_topics_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       struct cbs_data *cd = ofono_cbs_get_data(cbd->user);
+       ofono_cbs_set_cb_t cb = cbd->cb;
+       uint8_t result;
+       DBG("");
+
+       if (g_isi_msg_error(msg) < 0) {
+               DBG("Error: %s", strerror(-g_isi_msg_error(msg)));
+               return;
+       }
+
+       if (g_isi_msg_data_len(msg) < 2 || g_isi_msg_id(msg) !=
+                       SMS_CB_ROUTING_RESP)
+               goto error;
+
+       g_isi_msg_data_get_byte(msg, 1, &result);
+
+       if (result != SMS_OK)
+               goto error;
+
+       g_isi_msg_data_get_byte(msg, 0, &cd->subscription_nr);
+
+       DBG("got subscription nr: %d", cd->subscription_nr);
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+       return;
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
+}
+
 static void isi_set_topics(struct ofono_cbs *cbs, const char *topics,
                                ofono_cbs_set_cb_t cb, void *data)
 {
-       DBG("Not implemented (topics=%s), all topics accepted", topics);
-       CALLBACK_WITH_SUCCESS(cb, data);
+       struct cbs_data *cd = ofono_cbs_get_data(cbs);
+       struct isi_cb_data *cbd = isi_cb_data_new(cbs, cb, data);
+       int topics_len = get_topics_len(topics);
+       gint16 topics_out[topics_len];
+
+       uint8_t msg[] = {
+               SMS_CB_ROUTING_REQ,
+               SMS_ROUTING_SET,
+               cd->subscription_nr,
+               0x00,                   /*Subscription type*/
+               0x00,                   /*Fillers*/
+               0x00,
+               0x01,                   /*Number of subblocks*/
+               0x00,
+               0x26,                   /*Subblock*/
+               0x00,
+               topics_len * 2 + 6,     /*Subblock length*/
+               0x00,
+               topics_len,             /*Number of topics*/
+       };
+       struct iovec iov[2] = {
+               { msg, sizeof(msg) },
+               { topics_out, sizeof(topics_out) },
+       };
+
+       if (cbd == NULL)
+               return;
+
+       if (cd == NULL)
+               goto error;
+
+       if (cd->version.major == 9 && cd->version.minor >= 1) {
+               parse_topics(topics, topics_out);
+
+               if (g_isi_client_vsend_with_timeout(cd->client, iov, 2,
+                               CBS_TIMEOUT, set_topics_resp_cb, cbd, g_free))
+                       return;
+
+               CALLBACK_WITH_FAILURE(cb, data);
+       } else {
+               /*
+                * TODO: This should probably be put first in
+                *       the function to avoid unecessary initialization
+                *       and allocation.  Fix when the version handling
+                *       issue has been solved.
+                */
+               DBG("Not implemented (topics=%s), all topics accepted", topics);
+               CALLBACK_WITH_SUCCESS(cb, data);
+       }
+
+error:
+       g_free(cbd);
+}
+
+static void clear_topics_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       struct cbs_data *cd = ofono_cbs_get_data(cbd->user);
+       ofono_cbs_set_cb_t cb = cbd->cb;
+       DBG("");
+
+       if (!check_response_status(msg, SMS_CB_ROUTING_RESP))
+               goto error;
+
+       cd->subscription_nr = 0;
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+       return;
+error:
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
 }
 
 static void isi_clear_topics(struct ofono_cbs *cbs,
                                ofono_cbs_set_cb_t cb, void *data)
 {
-       DBG("Not implemented");
-       CALLBACK_WITH_SUCCESS(cb, data);
+       struct cbs_data *cd = ofono_cbs_get_data(cbs);
+       struct isi_cb_data *cbd = isi_cb_data_new(cbs, cb, data);
+
+       uint8_t msg[] = {
+               SMS_CB_ROUTING_REQ,
+               SMS_ROUTING_RELEASE,
+               cd->subscription_nr,    /* Subscription number */
+               0x00,                   /* Subscription type */
+               0x00,                   /* Fillers */
+               0x00,
+               0x00                    /*No subblocks*/
+       };
+
+       if (cbd == NULL)
+               return;
+
+       if (cd == NULL)
+               goto error;
+
+       if (cd->version.major == 9 && cd->version.minor >= 1) {
+               if (g_isi_client_send_with_timeout(cd->client, msg, sizeof(msg),
+                                       CBS_TIMEOUT, clear_topics_resp_cb,
+                                       cbd, g_free))
+                       return;
+
+               CALLBACK_WITH_FAILURE(cb, data);
+       } else {
+               /*
+                * TODO: This should probably be put first in
+                *       the function to avoid unecessary initialization
+                *       and allocation.  Fix when the version handling
+                *       issue has been solved.
+                */
+               DBG("Not implemented");
+               CALLBACK_WITH_SUCCESS(cb, data);
+       }
+error:
+       g_free(cbd);
+}
+
+static void routing_ind_cb(const GIsiMessage *msg, void *data)
+{
+       struct ofono_cbs *cbs = data;
+       struct cbs_data *cd = ofono_cbs_get_data(cbs);
+       struct cbs_info info;
+       size_t len = sizeof(struct cbs_info);
+       GIsiSubBlockIter iter;
+       size_t subblock_len;
+       uint8_t sbcount;
+       uint8_t *pdu_data;
+
+       DBG("");
+
+       if (cd == NULL || !check_response_status(msg, SMS_CB_ROUTING_IND))
+               return;
+
+       g_isi_msg_data_get_byte(msg, 1, &sbcount);
+
+       for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, sbcount);
+               g_isi_sb_iter_is_valid(&iter);
+               g_isi_sb_iter_next(&iter)) {
+
+               if (g_isi_sb_iter_get_id(&iter) != SMS_GSM_CB_MESSAGE)
+                       continue;
+
+               subblock_len = g_isi_sb_iter_get_len(&iter) - 4;
+
+               if (subblock_len > len &&
+                       g_isi_sb_iter_get_data(&iter, (void **)&pdu_data, 4)) {
+                       unsigned int i;
+
+                       for (i = 0; i < len; i++) {
+                               if (i < 6) /*account for filler in pos 6*/
+                                       info.pdu[i] = pdu_data[i];
+                               else
+                                       info.pdu[i] = pdu_data[i+1];
+                       }
+
+                       DBG("CBS Message received");
+                       ofono_cbs_notify(cbs, info.pdu, len);
+                       return;
+               } else {
+                       DBG("Error reading CBS message");
+                       return;
+               }
+       }
 }
 
 static void routing_ntf_cb(const GIsiMessage *msg, void *data)
@@ -131,40 +410,70 @@ static void routing_ntf_cb(const GIsiMessage *msg, void 
*data)
 static void routing_resp_cb(const GIsiMessage *msg, void *data)
 {
        struct ofono_cbs *cbs = data;
+
+       ofono_cbs_register(cbs);
+}
+
+static void reachable_cb(const GIsiMessage *msg, void *data)
+{
+       struct ofono_cbs *cbs = data;
        struct cbs_data *cd = ofono_cbs_get_data(cbs);
+       uint8_t *new_msg;
 
-       if (cd == NULL || !check_response_status(msg, SMS_GSM_CB_ROUTING_RESP))
+       if (cd == NULL)
                return;
 
-       g_isi_client_ntf_subscribe(cd->client, SMS_GSM_CB_ROUTING_NTF,
-                                       routing_ntf_cb, cbs);
+       ISI_VERSION_DBG(msg);
+
+       cd->version.major = g_isi_msg_version_major(msg);
+       cd->version.minor = g_isi_msg_version_minor(msg);
+
+       if (cd->version.major == 9 && cd->version.minor >= 1) {
+               uint8_t t_msg[] = {
+                       SMS_CB_ROUTING_REQ,
+                       SMS_ROUTING_QUERY_ALL,
+                       0x00,   /* New subscription*/
+                       0x00,   /* Subscription type */
+                       0x00,   /* Fillers */
+                       0x00,
+                       0x00    /* No subblocks*/
+               };
+               new_msg = g_try_malloc0(sizeof(t_msg));
+               memmove(new_msg, t_msg, sizeof(t_msg));
+       } else {
+               uint8_t t_msg[] = {
+                       SMS_GSM_CB_ROUTING_REQ,
+                       SMS_ROUTING_SET,
+                       SMS_GSM_ROUTING_MODE_ALL,
+                       SMS_CB_NOT_ALLOWED_IDS_LIST,
+                       0x00,  /* Subject count */
+                       0x00,  /* Language count */
+                       0x00,  /* CB range */
+                       0x00,  /* Subject list MSBS */
+                       0x00,  /* Subject list LSBS */
+                       0x00   /* Languages */
+               };
+               new_msg = g_try_malloc0(sizeof(t_msg));
+               memmove(new_msg, t_msg, sizeof(t_msg));
+       }
 
-       ofono_cbs_register(cbs);
+       g_isi_client_send(cd->client, new_msg, sizeof(msg),
+                               routing_resp_cb, cbs, NULL);
+
+       g_free(new_msg);
 }
 
 static int isi_cbs_probe(struct ofono_cbs *cbs, unsigned int vendor,
                                void *user)
 {
        GIsiModem *modem = user;
-       struct cbs_data *cd;
-
-       const uint8_t msg[] = {
-               SMS_GSM_CB_ROUTING_REQ,
-               SMS_ROUTING_SET,
-               SMS_GSM_ROUTING_MODE_ALL,
-               SMS_CB_NOT_ALLOWED_IDS_LIST,
-               0x00,  /* Subject count */
-               0x00,  /* Language count */
-               0x00,  /* CB range */
-               0x00,  /* Subject list MSBS */
-               0x00,  /* Subject list LSBS */
-               0x00   /* Languages */
-       };
+       struct cbs_data *cd = g_try_new0(struct cbs_data, 1);
 
-       cd = g_try_new0(struct cbs_data, 1);
        if (cd == NULL)
                return -ENOMEM;
 
+       cd->subscription_nr = 0;
+
        cd->client = g_isi_client_create(modem, PN_SMS);
        if (cd->client == NULL) {
                g_free(cd);
@@ -173,34 +482,56 @@ static int isi_cbs_probe(struct ofono_cbs *cbs, unsigned 
int vendor,
 
        ofono_cbs_set_data(cbs, cd);
 
-       if (g_isi_client_send(cd->client, msg, sizeof(msg),
-                               routing_resp_cb, cbs, NULL))
-               return 0;
+       g_isi_client_ind_subscribe(cd->client, SMS_CB_ROUTING_IND,
+                       routing_ind_cb, cbs);
+
+       g_isi_client_ntf_subscribe(cd->client, SMS_GSM_CB_ROUTING_NTF,
+                       routing_ntf_cb, cbs);
 
-       return -errno;
+       g_isi_client_verify(cd->client, reachable_cb, cbs, NULL);
+
+       return 0;
 }
 
 static void isi_cbs_remove(struct ofono_cbs *cbs)
 {
        struct cbs_data *cd = ofono_cbs_get_data(cbs);
-       const uint8_t msg[] = {
-               SMS_GSM_CB_ROUTING_REQ,
-               SMS_ROUTING_RELEASE,
-               SMS_GSM_ROUTING_MODE_ALL,
-               SMS_CB_NOT_ALLOWED_IDS_LIST,
-               0x00,  /* Subject count */
-               0x00,  /* Language count */
-               0x00,  /* CB range */
-               0x00,  /* Subject list MSBS */
-               0x00,  /* Subject list LSBS */
-               0x00   /* Languages */
-       };
-
-       ofono_cbs_set_data(cbs, NULL);
+       uint8_t *msg;
 
        if (cd == NULL)
                return;
 
+       if (cd->version.major == 9 && cd->version.minor >= 1) {
+               uint8_t t_msg[] = {
+                       SMS_CB_ROUTING_REQ,
+                       SMS_ROUTING_RELEASE,
+                       cd->subscription_nr,    /* Subscription number */
+                       0x00,                   /* Subscription type */
+                       0x00,                   /* Fillers */
+                       0x00,
+                       0x00                    /* No subblocks*/
+               };
+               msg = g_try_malloc0(sizeof(t_msg));
+               memmove(msg, t_msg, sizeof(t_msg));
+       } else {
+               uint8_t t_msg[] = {
+                       SMS_GSM_CB_ROUTING_REQ,
+                       SMS_ROUTING_RELEASE,
+                       SMS_GSM_ROUTING_MODE_ALL,
+                       SMS_CB_NOT_ALLOWED_IDS_LIST,
+                       0x00,  /* Subject count */
+                       0x00,  /* Language count */
+                       0x00,  /* CB range */
+                       0x00,  /* Subject list MSBS */
+                       0x00,  /* Subject list LSBS */
+                       0x00   /* Languages */
+               };
+               msg = g_try_malloc0(sizeof(t_msg));
+               memmove(msg, t_msg, sizeof(t_msg));
+       }
+       ofono_cbs_set_data(cbs, NULL);
+
+
        /*
         * Send a promiscuous routing release, so as not to hog
         * resources unnecessarily after being removed.
@@ -209,6 +540,7 @@ static void isi_cbs_remove(struct ofono_cbs *cbs)
 
        g_isi_client_destroy(cd->client);
        g_free(cd);
+       g_free(msg);
 }
 
 static struct ofono_cbs_driver driver = {
diff --git a/drivers/isimodem/debug.c b/drivers/isimodem/debug.c
index 1fd2226..ec3f3b3 100644
--- a/drivers/isimodem/debug.c
+++ b/drivers/isimodem/debug.c
@@ -449,6 +449,9 @@ const char *sms_message_id_name(enum sms_message_id value)
                _(SMS_SETTINGS_UPDATE_RESP);
                _(SMS_SETTINGS_READ_REQ);
                _(SMS_SETTINGS_READ_RESP);
+               _(SMS_CB_ROUTING_REQ);
+               _(SMS_CB_ROUTING_RESP);
+               _(SMS_CB_ROUTING_IND);
                _(SMS_RECEIVED_MSG_REPORT_REQ);
                _(SMS_RECEIVED_MSG_REPORT_RESP);
                _(SMS_RECEIVE_MESSAGE_REQ);
@@ -473,6 +476,7 @@ const char *sms_subblock_name(enum sms_subblock value)
                _(SMS_GSM_TPDU);
                _(SMS_GSM_TPDU_25);
                _(SMS_GSM_ROUTE_INFO);
+               _(SMS_GSM_CBS_SUBSCRIPTION);
                _(SMS_GSM_PARAMETERS);
                _(SMS_COMMON_DATA);
                _(SMS_ADDRESS);
diff --git a/drivers/isimodem/sms.h b/drivers/isimodem/sms.h
index a51adf2..03db354 100644
--- a/drivers/isimodem/sms.h
+++ b/drivers/isimodem/sms.h
@@ -130,6 +130,9 @@ enum sms_message_id {
        SMS_SETTINGS_UPDATE_RESP = 0x31,
        SMS_SETTINGS_READ_REQ =  0x32,
        SMS_SETTINGS_READ_RESP = 0x33,
+       SMS_CB_ROUTING_REQ = 0x34,
+       SMS_CB_ROUTING_RESP = 0x35,
+       SMS_CB_ROUTING_IND = 0x36,
        SMS_RECEIVED_MSG_REPORT_REQ = 0x3B,
        SMS_RECEIVED_MSG_REPORT_RESP = 0x3C,
        SMS_RECEIVE_MESSAGE_REQ = 0x41,
@@ -150,6 +153,7 @@ enum sms_subblock {
        SMS_GSM_TPDU = 0x11,
        SMS_GSM_TPDU_25 = 0x001C,
        SMS_GSM_ROUTE_INFO = 0x0023,
+       SMS_GSM_CBS_SUBSCRIPTION = 0x002D,
        SMS_GSM_PARAMETERS = 0x0031,
        SMS_COMMON_DATA = 0x80,
        SMS_ADDRESS = 0x82,
@@ -160,7 +164,8 @@ enum sms_routing_command {
        SMS_ROUTING_SET = 0x01,
        SMS_ROUTING_SUSPEND = 0x02,
        SMS_ROUTING_RESUME = 0x03,
-       SMS_ROUTING_UPDATE = 0x04
+       SMS_ROUTING_UPDATE = 0x04,
+       SMS_ROUTING_QUERY_ALL = 0x06
 };
 
 enum sms_route_preference {
-- 
1.7.3.5

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to