From: Jessica Nilsson <jessica.j.nils...@stericsson.com>

---
 drivers/isimodem/debug.c |   56 +++
 drivers/isimodem/debug.h |    1 +
 drivers/isimodem/sms.c   |  972 +++++++++++++++++++++++++++++++++++++++-------
 drivers/isimodem/sms.h   |   34 ++
 4 files changed, 927 insertions(+), 136 deletions(-)

diff --git a/drivers/isimodem/debug.c b/drivers/isimodem/debug.c
index 33e4dcb..1fd2226 100644
--- a/drivers/isimodem/debug.c
+++ b/drivers/isimodem/debug.c
@@ -53,6 +53,7 @@ const char *pn_resource_name(int value)
                _(PN_GSS);
                _(PN_GPDS);
                _(PN_WRAN);
+               _(PN_UICC);
        }
        return "PN_<UNKNOWN>";
 }
@@ -218,6 +219,47 @@ const char *mce_rf_state_name(enum mce_rf_state value)
        return "MCE_RF<UNKNOWN>";
 }
 
+const char *uicc_message_id_name(enum uicc_message_id value)
+{
+       switch (value) {
+               _(UICC_REQ);
+               _(UICC_RESP);
+               _(UICC_IND);
+               _(UICC_CARD_REQ);
+               _(UICC_CARD_RESP);
+               _(UICC_CARD_IND);
+               _(UICC_APPLICATION_REQ);
+               _(UICC_APPLICATION_RESP);
+               _(UICC_APPLICATION_IND);
+               _(UICC_PIN_REQ);
+               _(UICC_PIN_RESP);
+               _(UICC_PIN_IND);
+               _(UICC_APPL_CMD_REQ);
+               _(UICC_APPL_CMD_RESP);
+               _(UICC_APPL_CMD_IND);
+               _(UICC_CONNECTOR_REQ);
+               _(UICC_CONNECTOR_RESP);
+               _(UICC_CAT_REQ);
+               _(UICC_CAT_RESP);
+               _(UICC_CAT_IND);
+               _(UICC_APDU_REQ);
+               _(UICC_APDU_RESP);
+               _(UICC_APDU_RESET_IND);
+               _(UICC_REFRESH_REQ);
+               _(UICC_REFRESH_RESP);
+               _(UICC_REFRESH_IND);
+               _(UICC_SIMLOCK_REQ);
+               _(UICC_SIMLOCK_RESP);
+               _(UICC_APDU_SAP_REQ);
+               _(UICC_APDU_SAP_RESP);
+               _(UICC_APDU_SAP_IND);
+               _(UICC_PWR_CTRL_REQ);
+               _(UICC_PWR_CTRL_RESP);
+               _(UICC_PWR_CTRL_IND);
+       }
+       return "UICC_<UNKNOWN>";
+}
+
 const char *uicc_status_name(uint8_t value)
 {
        switch (value) {
@@ -403,6 +445,15 @@ const char *sms_message_id_name(enum sms_message_id value)
                _(SMS_GSM_CB_ROUTING_RESP);
                _(SMS_GSM_CB_ROUTING_NTF);
                _(SMS_MESSAGE_SEND_STATUS_IND);
+               _(SMS_SETTINGS_UPDATE_REQ);
+               _(SMS_SETTINGS_UPDATE_RESP);
+               _(SMS_SETTINGS_READ_REQ);
+               _(SMS_SETTINGS_READ_RESP);
+               _(SMS_RECEIVED_MSG_REPORT_REQ);
+               _(SMS_RECEIVED_MSG_REPORT_RESP);
+               _(SMS_RECEIVE_MESSAGE_REQ);
+               _(SMS_RECEIVE_MESSAGE_RESP);
+               _(SMS_RECEIVED_MSG_IND);
                _(SMS_COMMON_MESSAGE);
        }
        return "SMS_<UNKNOWN>";
@@ -420,6 +471,9 @@ const char *sms_subblock_name(enum sms_subblock value)
                _(SMS_GSM_ROUTING);
                _(SMS_GSM_CB_MESSAGE);
                _(SMS_GSM_TPDU);
+               _(SMS_GSM_TPDU_25);
+               _(SMS_GSM_ROUTE_INFO);
+               _(SMS_GSM_PARAMETERS);
                _(SMS_COMMON_DATA);
                _(SMS_ADDRESS);
        }
@@ -1224,6 +1278,8 @@ static const char *res_to_name(uint8_t res, uint8_t id)
                return gss_message_id_name(id);
        case PN_GPDS:
                return gpds_message_id_name(id);
+       case PN_UICC:
+               return uicc_message_id_name(id);
        }
        return "UNKNOWN";
 }
diff --git a/drivers/isimodem/debug.h b/drivers/isimodem/debug.h
index db01f04..5648f7a 100644
--- a/drivers/isimodem/debug.h
+++ b/drivers/isimodem/debug.h
@@ -48,6 +48,7 @@ const char *mce_message_id_name(enum mce_message_id value);
 const char *mce_modem_state_name(enum mce_modem_state value);
 const char *mce_status_info(enum mce_status_info value);
 
+const char *uicc_message_id_name(enum uicc_message_id value);
 const char *uicc_subblock_name(uint8_t value);
 const char *uicc_status_name(uint8_t value);
 
diff --git a/drivers/isimodem/sms.c b/drivers/isimodem/sms.c
index 957b342..5ec1226 100644
--- a/drivers/isimodem/sms.c
+++ b/drivers/isimodem/sms.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
@@ -45,6 +46,7 @@
 #include "isimodem.h"
 #include "isiutil.h"
 #include "sms.h"
+#include "uicc.h"
 #include "debug.h"
 
 /* This is a straightforward copy of the EF_smsp structure */
@@ -60,6 +62,18 @@ struct sim_efsmsp{
        uint16_t alpha[17];
 };
 
+/* USIM structure, 3GPP TS 31.102 */
+struct usim_efsmp {
+       uint8_t alphalen; /* not part of the USIM EF_smsp structure */
+       uint8_t alpha[241];
+       uint8_t indicators; /* parameter indicators */
+       uint8_t tp_dst[12];
+       uint8_t tp_sca[12];
+       uint8_t tp_pid; /* protocol identifier */
+       uint8_t tp_dcs; /* data coding scheme */
+       uint8_t tp_vp; /* validity period */
+};
+
 /* Sub-block used by PN_SMS */
 struct sms_params {
        uint8_t location;
@@ -99,12 +113,51 @@ struct sms_common {
        uint8_t *data;
 };
 
+const unsigned char SMS_STATUS_REPORT = 0x02;
+
 struct sms_data {
        GIsiClient *client;
        GIsiClient *sim;
-       struct sim_efsmsp params;
+       struct sim_efsmsp sim_params;
+       struct usim_efsmp usim_params;
 };
 
+static gboolean check_uicc_status(const GIsiMessage *msg, uint8_t msgid,
+                                       uint8_t service)
+{
+       uint8_t type;
+       uint8_t cause;
+
+       if (g_isi_msg_error(msg) < 0) {
+               DBG("Error: %s", strerror(-g_isi_msg_error(msg)));
+               return FALSE;
+       }
+
+       if (g_isi_msg_id(msg) != msgid) {
+               DBG("Unexpected msg: %s",
+                       uicc_message_id_name(g_isi_msg_id(msg)));
+               return FALSE;
+       }
+
+       if (!g_isi_msg_data_get_byte(msg, 0, &type))
+               return FALSE;
+
+       if (type != service) {
+               DBG("Unexpected service type: 0x%02X", type);
+               return FALSE;
+       }
+
+       if (!g_isi_msg_data_get_byte(msg, 1, &cause))
+               return FALSE;
+
+       if (cause != UICC_STATUS_OK) {
+               DBG("Request failed: %s", uicc_status_name(cause));
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 static gboolean check_sim_status(const GIsiMessage *msg, uint8_t msgid,
                                        uint8_t service)
 {
@@ -141,7 +194,8 @@ static gboolean check_sim_status(const GIsiMessage *msg, 
uint8_t msgid,
        return TRUE;
 }
 
-static gboolean check_sms_status(const GIsiMessage *msg, uint8_t msgid)
+static gboolean check_sms_status_with_cause(const GIsiMessage *msg,
+                       uint8_t msgid, uint8_t expected_cause, int cause_pos)
 {
        uint8_t cause;
 
@@ -156,12 +210,12 @@ static gboolean check_sms_status(const GIsiMessage *msg, 
uint8_t msgid)
                return FALSE;
        }
 
-       if (!g_isi_msg_data_get_byte(msg, 0, &cause)) {
+       if (!g_isi_msg_data_get_byte(msg, cause_pos, &cause)) {
                DBG("Unable to parse cause");
                return FALSE;
        }
 
-       if (cause == SMS_OK)
+       if (cause == expected_cause)
                return TRUE;
 
        if (cause == SMS_ERR_PP_RESERVED) {
@@ -178,6 +232,101 @@ static gboolean check_sms_status(const GIsiMessage *msg, 
uint8_t msgid)
        return FALSE;
 }
 
+static gboolean check_sms_status(const GIsiMessage *msg, uint8_t msgid)
+{
+       return check_sms_status_with_cause(msg, msgid, SMS_OK, 0);
+}
+
+static void sca_query_resp_uicc_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       struct ofono_sms *sms = cbd->user;
+       struct sms_data *sd = ofono_sms_get_data(sms);
+       ofono_sms_sca_query_cb_t cb = cbd->cb;
+
+       struct ofono_phone_number sca;
+       uint8_t bcd_len;
+       GIsiSubBlockIter iter;
+       int alphalen = 0;
+       uint32_t data_len = 0;
+       uint8_t sbcount = 0;
+
+       int i;
+       DBG("");
+
+       if (!check_uicc_status(msg, UICC_APPL_CMD_RESP,
+                                       UICC_APPL_READ_LINEAR_FIXED))
+               goto error;
+
+       if (!g_isi_msg_data_get_byte(msg, 5, &sbcount) || sbcount == 0)
+               goto error;
+
+       DBG("starting");
+       for (g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+                                       g_isi_sb_iter_is_valid(&iter);
+                                       g_isi_sb_iter_next(&iter)) {
+               if (g_isi_sb_iter_get_id(&iter) != UICC_SB_FILE_DATA)
+                       continue;
+               DBG("found UICC_SB_FILE_DATA");
+               g_isi_sb_iter_get_dword(&iter, &data_len, 4);
+
+               DBG("got length %d", data_len);
+               if (data_len < 28)
+                       goto error;
+
+               /*y is alpha identifier see 3GPP TS 31.102*/
+               alphalen = data_len - 28;
+
+               sd->usim_params.alphalen = alphalen;
+               for (i = 0; i < alphalen; i++) {
+                       uint8_t t_byte;
+                       g_isi_sb_iter_get_byte(&iter, &t_byte, 8 + i);
+                       sd->usim_params.alpha[i] = t_byte;
+               }
+
+               g_isi_sb_iter_get_byte(&iter, &(sd->usim_params.indicators),
+                                       8 + alphalen);
+
+               for (i = 0; i < 12; i++) {
+                       uint8_t t_byte;
+                       g_isi_sb_iter_get_byte(&iter, &t_byte,
+                                               8 + alphalen + 1 + i);
+                       sd->usim_params.tp_dst[i] = t_byte;
+                       g_isi_sb_iter_get_byte(&iter, &t_byte,
+                                                8 + alphalen + 1 + 12 + i);
+                       sd->usim_params.tp_sca[i] = t_byte;
+               }
+               g_isi_sb_iter_get_byte(&iter, &(sd->usim_params.tp_pid),
+                                       alphalen + 1 + 12 + 12);
+               g_isi_sb_iter_get_byte(&iter, &(sd->usim_params.tp_dcs),
+                                       alphalen + 1 + 12 + 12 + 1);
+               g_isi_sb_iter_get_byte(&iter, &(sd->usim_params.tp_vp),
+                                       alphalen + 1 + 12 + 12 + 1 + 1);
+
+               DBG("indicators: %d", sd->usim_params.indicators & 0x2);
+               /*if TS-Service Centre Address absent*/
+               if (sd->usim_params.indicators & 0x2)
+                       goto error;
+
+               bcd_len = sd->usim_params.tp_sca[0];
+
+               DBG("bcd length: %d", bcd_len);
+               if (bcd_len <= 1 || bcd_len > 12)
+                       goto error;
+
+               extract_bcd_number(sd->usim_params.tp_sca + 2, bcd_len - 1,
+                               sca.number);
+               sca.type = sd->usim_params.tp_sca[1];
+               DBG("new sca: %04X",
+                               (unsigned int) strlen(sca.number));
+               CALLBACK_WITH_SUCCESS(cb, &sca, cbd->data);
+               return;
+       }
+
+error:
+       CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+}
+
 static void sca_query_resp_cb(const GIsiMessage *msg, void *data)
 {
        struct isi_cb_data *cbd = data;
@@ -203,16 +352,19 @@ static void sca_query_resp_cb(const GIsiMessage *msg, 
void *data)
 
        info->alpha[info->alphalen - 1] = '\0';
 
-       sd->params.absent = info->absent;
-       sd->params.tp_pid = info->tp_pid;
-       sd->params.tp_dcs = info->tp_dcs;
-       sd->params.tp_vp = info->tp_vp;
+       sd->sim_params.absent = info->absent;
+       sd->sim_params.tp_pid = info->tp_pid;
+       sd->sim_params.tp_dcs = info->tp_dcs;
+       sd->sim_params.tp_vp = info->tp_vp;
 
-       memcpy(sd->params.dst, info->dst, sizeof(sd->params.dst));
-       memcpy(sd->params.sca, info->sca, sizeof(sd->params.sca));
+       memmove(sd->sim_params.dst, info->dst,
+               sizeof(sd->sim_params.dst));
+       memmove(sd->sim_params.sca, info->sca,
+               sizeof(sd->sim_params.sca));
 
-       sd->params.alphalen = info->alphalen;
-       memcpy(sd->params.alpha, info->alpha, sizeof(sd->params.alpha));
+       sd->sim_params.alphalen = info->alphalen;
+       memmove(sd->sim_params.alpha, info->alpha,
+               sizeof(sd->sim_params.alpha));
 
        /*
         * Bitmask indicating absence of parameters --
@@ -236,21 +388,85 @@ error:
        CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
 }
 
+static gboolean sca_query_uicc(struct sms_data *sd, struct isi_cb_data *cbd)
+{
+       int8_t app_id = get_app_id();
+       uint8_t client_id = get_client_id();
+       int app_type = get_app_type();
+       DBG("");
+       if (app_id != -1 && client_id != 0) {
+               int mf_path = 0x3F00;
+               int df_path = (app_type == UICC_APPL_TYPE_UICC_USIM) ? 0x7FFF
+                                                       : 0x7F10;
+               int df_len = 4;
+               uint8_t msg[] = {
+                       UICC_APPL_CMD_REQ,
+                       UICC_APPL_READ_LINEAR_FIXED,
+                       app_id,
+                       UICC_SESSION_ID_NOT_USED,
+                       0, 0, /*fillers*/
+                       3, /*nro of sub blocks*/
+
+                       UICC_SB_CLIENT >> 8, /*1st subblock*/
+                       UICC_SB_CLIENT & 0xFF,
+                       0,/*subblock length*/
+                       8,/*subblock length*/
+                       0, 0, 0,/*fillers*/
+                       client_id,
+
+                       UICC_SB_APPL_PATH >> 8,/*2nd subblock*/
+                       UICC_SB_APPL_PATH & 0xFF,
+                       0,/*subblock length*/
+                       16,/*subblock length*/
+                       0x6F42 >> 8,/*Elementary file ID for EFsmsp*/
+                       0x6F42 & 0xFF,
+                       UICC_SFI_NOT_PRESENT,
+                       0,/*filler*/
+                       df_len,/*Path length*/
+                       0,/*filler*/
+                       mf_path >> 8,/*DF Path MF*/
+                       mf_path & 0xFF,
+                       df_path >> 8,/*DF Path DFtelecom*/
+                       df_path & 0xFF,
+                       0, 0,/*fillers 0-3*/
+                       UICC_SB_LINEAR_FIXED >> 8,/*3rd subblock*/
+                       UICC_SB_LINEAR_FIXED & 0xFF,
+                       0,/*subblock length*/
+                       8,/*subblock length*/
+                       1,/*The record in the file*/
+                       0,/*offset 0 == beginning of the record*/
+                       0,/*data amount 0 == until end of record*/
+                       0,/*filler*/
+               };
+
+               return g_isi_client_send(sd->sim, msg, sizeof(msg),
+                                       sca_query_resp_uicc_cb, cbd, g_free);
+       }
+
+       return FALSE;
+}
+
 static void isi_sca_query(struct ofono_sms *sms,
                                ofono_sms_sca_query_cb_t cb, void *data)
 {
        struct sms_data *sd = ofono_sms_get_data(sms);
        struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
-
-       const uint8_t msg[] = {
+       uint8_t msg[] = {
                SIM_SMS_REQ,
                READ_PARAMETER,
                1,      /* Location, default is 1 */
        };
+       DBG("");
 
-       if (cbd == NULL || sd == NULL || sd->sim == NULL)
+       if (sd == NULL || sd->sim == NULL || cbd == NULL)
                goto error;
 
+       if (PN_UICC == g_isi_client_resource(sd->sim)) {
+               if (!sca_query_uicc(sd, cbd))
+                       goto error;
+               return;
+       }
+
        if (g_isi_client_send(sd->sim, msg, sizeof(msg),
                                sca_query_resp_cb, cbd, g_free))
                return;
@@ -260,6 +476,20 @@ error:
        g_free(cbd);
 }
 
+static void sca_set_resp_uicc_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       ofono_sms_sca_set_cb_t cb = cbd->cb;
+
+       if (!check_uicc_status(msg, UICC_APPL_CMD_RESP,
+                               UICC_APPL_UPDATE_LINEAR_FIXED)) {
+               CALLBACK_WITH_FAILURE(cb, cbd->data);
+               return;
+       }
+
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+}
+
 static void sca_set_resp_cb(const GIsiMessage *msg, void *data)
 {
        struct isi_cb_data *cbd = data;
@@ -273,6 +503,102 @@ static void sca_set_resp_cb(const GIsiMessage *msg, void 
*data)
        CALLBACK_WITH_SUCCESS(cb, cbd->data);
 }
 
+static gboolean sca_uicc_set(struct sms_data *sd, struct isi_cb_data *cbd,
+                               const struct ofono_phone_number *sca)
+{
+       int8_t app_id = get_app_id();
+       int8_t app_type = get_app_type();
+       int8_t client_id = get_client_id();
+       int mf_path = 0x3F00;
+       int df_path = (app_type == UICC_APPL_TYPE_UICC_USIM) ? 0x7FFF : 0x7F10;
+       int df_len = 4;
+       int sca_len = 1 + (strlen(sca->number) + 1) / 2;
+       size_t sb_file_data_length = 2 + 2 + 4 + sca_len + 1 + 1 + 12;
+       size_t fill_count = 4 - (sb_file_data_length % 4);
+       uint8_t bcd[sca_len + 12 + 1 + 1];
+       uint8_t *fill_data = g_try_malloc0(fill_count);
+       int i;
+
+       encode_bcd_number(sca->number, bcd + 15);
+       bcd[0] = sd->usim_params.indicators & 0xFD;
+
+       for (i = 0; i < 12; i++) {
+               if (sd->usim_params.tp_dst[0] == '\0')
+                       bcd[i + 1] = 0xFF;
+               else
+                       bcd[i + 1] = sd->usim_params.tp_dst[i];
+       }
+
+       bcd[13] = sca_len;
+       bcd[14] = sca->type;
+
+       if ((app_id != -1) && (client_id != -1)) {
+               uint8_t msg[] = {
+                       UICC_APPL_CMD_REQ,
+                       UICC_APPL_UPDATE_LINEAR_FIXED,
+                       app_id,
+                       UICC_SESSION_ID_NOT_USED,
+                       0, 0, /*fillers*/
+                       4, /*nro of sub blocks*/
+                       /*1*/
+                       UICC_SB_CLIENT >> 8, /*1st subblock*/
+                       UICC_SB_CLIENT & 0xFF,
+                       0,/*subblock length*/
+                       8,/*subblock length*/
+                       0, 0, 0,/*fillers*/
+                       client_id,
+                       /*2*/
+                       UICC_SB_LINEAR_FIXED >> 8,/*3rd subblock*/
+                       UICC_SB_LINEAR_FIXED & 0xFF,
+                       0,/*subblock length*/
+                       8,/*subblock length*/
+                       1,/*The record in the file*/
+                       sd->usim_params.alphalen,
+                       /* offset 0 == beginning of the record */
+                       sca_len + 1 + 12 + 1, /* data amount 0
+                                               * == until end of
+                                               * record */
+                       0,/*filler*/
+                       /*3*/
+                       UICC_SB_APPL_PATH >> 8,/*2nd subblock*/
+                       UICC_SB_APPL_PATH & 0xFF,
+                       0,/*subblock length*/
+                       16,/*subblock length*/
+                       0x6F42 >> 8,/*Elementary file ID for EFsmsp*/
+                       0x6F42 & 0xFF,
+                       UICC_SFI_NOT_PRESENT,
+                       0,/*filler*/
+                       df_len,/*Path length*/
+                       0,/*filler*/
+                       mf_path >> 8,/*DF Path MF*/
+                       mf_path & 0xFF,
+                       df_path >> 8,/*DF Path DFtelecom*/
+                       df_path & 0xFF,
+                       0, 0,/*fillers 0-3*/
+                       /*4*/
+                       UICC_SB_FILE_DATA >> 8,
+                       UICC_SB_FILE_DATA & 0xFF,
+                       (sb_file_data_length + fill_count) >> 8,
+                       (sb_file_data_length + fill_count) & 0xFF,
+                       (sca_len + 1 + 12 + 1) >> 24,
+                       (sca_len + 1 + 12 + 1) >> 16,
+                       (sca_len + 1 + 12 + 1) >> 8,
+                       (sca_len + 1 + 12 + 1) & 0xFF,
+               };
+               struct iovec iov[3] = {
+                               { msg, sizeof(msg) },
+                               { bcd, sizeof(bcd) },
+                               { fill_data, fill_count },
+               };
+
+               return g_isi_client_vsend(sd->sim, iov, G_N_ELEMENTS(iov),
+                                       sca_set_resp_uicc_cb, cbd, g_free);
+       }
+       g_free(fill_data);
+       return FALSE;
+
+}
+
 static void isi_sca_set(struct ofono_sms *sms,
                        const struct ofono_phone_number *sca,
                        ofono_sms_sca_set_cb_t cb, void *data)
@@ -280,29 +606,34 @@ static void isi_sca_set(struct ofono_sms *sms,
        struct sms_data *sd = ofono_sms_get_data(sms);
        struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
        uint8_t *bcd;
-
        uint8_t msg[] = {
                SIM_SMS_REQ,
                UPDATE_PARAMETER,
                1,      /* Location, default is 1 */
        };
-
-       struct iovec iov[2] = {
+       struct iovec iov[] = {
                { msg, sizeof(msg) },
-               { &sd->params, sizeof(sd->params) },
+               { &sd->sim_params, sizeof(sd->sim_params) },
        };
 
        if (cbd == NULL || sd == NULL)
                goto error;
 
-       bcd = sd->params.sca;
-       sd->params.absent &= ~0x02;
+       if (PN_UICC == g_isi_client_resource(sd->sim)) {
+               if (!sca_uicc_set(sd, cbd, sca))
+                       goto error;
+               return;
+       }
+
+       bcd = sd->sim_params.sca;
+       sd->sim_params.absent &= ~0x02;
 
        encode_bcd_number(sca->number, bcd + 2);
        bcd[0] = 1 + (strlen(sca->number) + 1) / 2;
        bcd[1] = sca->type & 0xFF;
 
-       if (g_isi_client_vsend(sd->sim, iov, 2, sca_set_resp_cb, cbd, g_free))
+       if (g_isi_client_vsend(sd->sim, iov, G_N_ELEMENTS(iov),
+                       sca_set_resp_cb, cbd, g_free))
                return;
 
 error:
@@ -310,6 +641,32 @@ error:
        g_free(cbd);
 }
 
+static void submit_resp_v2_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       ofono_sms_submit_cb_t cb = cbd->cb;
+       struct sms_report *report;
+       size_t len = sizeof(struct sms_report);
+       DBG("");
+
+       if (g_isi_msg_id(msg) != SMS_MESSAGE_SEND_RESP)
+               goto error;
+
+       if (len > g_isi_msg_data_len(msg))
+               goto error;
+
+       if (!g_isi_msg_data_get_struct(msg, 0, (const void **) &report, len))
+               goto error;
+
+       if (report->type == SMS_CAUSE_TYPE_COMMON && report->cause == SMS_OK) {
+               CALLBACK_WITH_SUCCESS(cb, report->ref, cbd->data);
+               return;
+       }
+
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
+
 static void submit_resp_cb(const GIsiMessage *msg, void *data)
 {
        struct isi_cb_data *cbd = data;
@@ -348,84 +705,253 @@ static void isi_submit(struct ofono_sms *sms, unsigned 
char *pdu,
 {
        struct sms_data *sd = ofono_sms_get_data(sms);
        struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
+       GIsiModem *modem;
 
-       uint8_t use_sca = pdu_len - tpdu_len != 1 || pdu[0] == 0;
-
-       uint8_t *tpdu = pdu + pdu_len - tpdu_len;
-       uint8_t filler_len = (-tpdu_len) & 3;
-       uint8_t tpdu_sb_len = 4 + tpdu_len + filler_len;
+       if (sd == NULL)
+               goto error;
 
-       uint8_t sca_sb_len = use_sca ? 16 : 0;
+       modem = g_isi_client_modem(sd->client);
+
+       if (g_isi_modem_version_major(modem) == 2 &&
+               g_isi_modem_version_minor(modem) >= 0) {
+
+               uint8_t sca_len = pdu_len - tpdu_len;
+               uint8_t *tpdu = pdu + sca_len;
+               uint8_t msg[] = {
+                               SMS_MESSAGE_SEND_REQ,
+                               mms,    /* More messages to send*/
+                               SMS_ROUTE_DEFAULT,
+                               FALSE,  /* Repeated message*/
+                               0, 0,   /* fillers*/
+                               2,      /* no of subblocks*/
+                               SMS_GSM_TPDU_25 >> 8,   /* first subblock*/
+                               SMS_GSM_TPDU_25 & 0xFF,
+                               (tpdu_len + 6) >> 8,
+                               (tpdu_len + 6) & 0xFF,
+                               tpdu_len,
+                               0x00,
+                               /* databytes come here */
+               };
+               uint8_t parameters[] = {
+                               SMS_GSM_PARAMETERS >> 8,
+                               SMS_GSM_PARAMETERS & 0xFF,
+                               8 >> 8, /* subblock length*/
+                               8 & 0xFF,
+                               /*
+                                * location. We might have to fetch this by
+                                * SMS_SETTINGS_READ_REQ
+                                */
+                               1,/*SMS_DEFAULT_PARAMETER_LOCATION = 0 else
+                               range 1-255*/
+                               0x02,   /*SMS_PI_SERVICE_CENTRE_ADDRESS*/
+                               0, 0,
+               };
+               struct iovec iov[3] = {
+                               { msg, sizeof(msg) },
+                               { tpdu, tpdu_len },
+                               { parameters, sizeof(parameters) },
+               };
+
+               if ((g_isi_client_vsend_with_timeout(sd->client, iov,
+                               G_N_ELEMENTS(iov), SMS_TIMEOUT,
+                               submit_resp_v2_cb, cbd, g_free)))
+                       return;
+       } else {
+               uint8_t use_sca = pdu_len - tpdu_len != 1 || pdu[0] == 0;
+
+               uint8_t *tpdu = pdu + pdu_len - tpdu_len;
+               uint8_t filler_len = (-tpdu_len) & 3;
+               uint8_t tpdu_sb_len = 4 + tpdu_len + filler_len;
+
+               uint8_t sca_sb_len = use_sca ? 16 : 0;
+
+               uint8_t msg[] = {
+                       SMS_MESSAGE_SEND_REQ,
+                       mms,
+                       SMS_ROUTE_CS_PREF,
+                       0,      /* Is this a re-send? */
+                       SMS_SENDER_ANY,
+                       SMS_TYPE_TEXT_MESSAGE,
+                       1,      /* Sub blocks */
+                       SMS_GSM_TPDU,
+                       4 + tpdu_sb_len + sca_sb_len,
+                       0,      /* Filler */
+                       use_sca ? 2 : 1,        /* Sub-sub blocks */
+                       SMS_COMMON_DATA,
+                       tpdu_sb_len,
+                       tpdu_len,
+                       0,      /* Packing required? */
+                       /* TPDU */
+               };
+
+               static uint8_t filler[4];
+
+               uint8_t sca_sb[16] = {
+                       SMS_ADDRESS,
+                       16,
+                       SMS_GSM_0411_ADDRESS,
+                       0,
+               };
+
+               struct iovec iov[4] = {
+                       { msg, sizeof(msg) },
+                       { tpdu, tpdu_len },
+                       { filler, filler_len },
+                       { sca_sb, sca_sb_len },
+               };
+
+               if (cbd == NULL || sd == NULL)
+                       goto error;
 
-       uint8_t msg[] = {
-               SMS_MESSAGE_SEND_REQ,
-               mms,
-               SMS_ROUTE_CS_PREF,
-               0,      /* Is this a re-send? */
-               SMS_SENDER_ANY,
-               SMS_TYPE_TEXT_MESSAGE,
-               1,      /* Sub blocks */
-               SMS_GSM_TPDU,
-               4 + tpdu_sb_len + sca_sb_len,
-               0,      /* Filler */
-               use_sca ? 2 : 1,        /* Sub-sub blocks */
-               SMS_COMMON_DATA,
-               tpdu_sb_len,
-               tpdu_len,
-               0,      /* Packing required? */
-               /* TPDU */
-       };
+               if (use_sca) {
+                       sca_sb[3] = pdu_len - tpdu_len;
+                       memmove(sca_sb + 4, pdu, sca_sb[3]);
+               }
 
-       static uint8_t filler[4];
+               /*
+                * Modem seems to time out SMS_MESSAGE_SEND_REQ in 5 seconds.
+                * Wait normal timeout plus the modem timeout.
+                */
+               if (g_isi_client_vsend_with_timeout(sd->client, iov, 4,
+                                       SMS_TIMEOUT + 5,
+                                       submit_resp_cb, cbd, g_free))
+                       return;
+       }
 
-       uint8_t sca_sb[16] = {
-               SMS_ADDRESS,
-               16,
-               SMS_GSM_0411_ADDRESS,
-               0,
-       };
+error:
+       CALLBACK_WITH_FAILURE(cb, -1, data);
+       g_free(cbd);
+}
 
-       struct iovec iov[4] = {
-               { msg, sizeof(msg) },
-               { tpdu, tpdu_len },
-               { filler, filler_len },
-               { sca_sb, sca_sb_len },
-       };
+static void bearer_query_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       ofono_sms_bearer_query_cb_t cb = cbd->cb;
+       int bearer = 0;
+       uint8_t bear_high;
+       uint8_t bear_low;
 
-       if (cbd == NULL || sd == NULL)
+       if (!check_sms_status(msg, SMS_SETTINGS_READ_RESP))
                goto error;
 
-       if (use_sca) {
-               sca_sb[3] = pdu_len - tpdu_len;
-               memcpy(sca_sb + 4, pdu, sca_sb[3]);
-       }
+       g_isi_msg_data_get_byte(msg, 6, &bear_high);
+       g_isi_msg_data_get_byte(msg, 7, &bear_low);
 
-       /*
-        * Modem seems to time out SMS_MESSAGE_SEND_REQ in 5 seconds.
-        * Wait normal timeout plus the modem timeout.
-        */
-       if (g_isi_client_vsend_with_timeout(sd->client, iov, 4,
-                               SMS_TIMEOUT + 5,
-                               submit_resp_cb, cbd, g_free))
+       /* check what bearer type was set */
+       if (bear_high == 0x00 && bear_low == 0x01)
+               bearer = 0;
+       else if (bear_high == 0x01 && bear_low == 0x00)
+               bearer = 1;
+       else if (bear_high == 0x02 && bear_low == 0x01)
+               bearer = 2;
+       else if (bear_high == 0x01 && bear_low == 0x02)
+               bearer = 3;
+
+       CALLBACK_WITH_SUCCESS(cb, bearer, cbd->data);
+       return;
+error:
+       CALLBACK_WITH_FAILURE(cb, bearer, cbd->data);
+}
+
+static void set_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct isi_cb_data *cbd = data;
+       ofono_sms_bearer_set_cb_t cb = cbd->cb;
+       struct sms_data *sd;
+       GIsiModem *modem;
+       int cause_pos = 0;
+
+       if (cbd == NULL)
                return;
+       sd = ofono_sms_get_data(cbd->user);
+
+       if (sd == NULL)
+               goto error;
+
+       modem = g_isi_client_modem(sd->client);
+
+       if (g_isi_modem_version_major(modem) == 2 &&
+               g_isi_modem_version_minor(modem) >= 0)
+               cause_pos = 1;
+
+       if (!check_sms_status_with_cause(msg, SMS_SETTINGS_UPDATE_RESP, SMS_OK,
+                       cause_pos))
+               goto error;
 
+       CALLBACK_WITH_SUCCESS(cb, cbd->data);
+       return;
 error:
-       CALLBACK_WITH_FAILURE(cb, -1, data);
-       g_free(cbd);
+       CALLBACK_WITH_FAILURE(cb, cbd->data);
 }
 
 static void isi_bearer_query(struct ofono_sms *sms,
                                ofono_sms_bearer_query_cb_t cb, void *data)
 {
-       DBG("Not implemented");
-       CALLBACK_WITH_FAILURE(cb, -1, data);
+       struct sms_data *sd = ofono_sms_get_data(sms);
+       struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
+       unsigned char msg[] = {
+                       SMS_SETTINGS_READ_REQ,
+                       SMS_SETTING_TYPE_ROUTE,
+                       0
+       };
+
+       if (cbd && g_isi_client_send_with_timeout(sd->client, msg, sizeof(msg),
+                       SMS_TIMEOUT, bearer_query_resp_cb, cbd, g_free))
+               return;
+
+       CALLBACK_WITH_FAILURE(cb, 0, data);
+       g_free(cbd);
 }
 
 static void isi_bearer_set(struct ofono_sms *sms, int bearer,
                                ofono_sms_bearer_set_cb_t cb, void *data)
 {
-       DBG("Not implemented");
+       struct sms_data *sd = ofono_sms_get_data(sms);
+       struct isi_cb_data *cbd = isi_cb_data_new(sms, cb, data);
+       unsigned char bearer_type[2] = {SMS_ROUTE_NOT_AVAILABLE,
+                       SMS_ROUTE_NOT_AVAILABLE
+       };
+
+       switch (bearer) {
+       case 0:
+               bearer_type[0] = SMS_ROUTE_NOT_AVAILABLE;
+               bearer_type[1] = SMS_ROUTE_PRIORITY_1;
+               break;
+       case 1:
+               bearer_type[0] = SMS_ROUTE_PRIORITY_1;
+               bearer_type[1] = SMS_ROUTE_NOT_AVAILABLE;
+               break;
+       case 2:
+               bearer_type[0] = SMS_ROUTE_PRIORITY_2;
+               bearer_type[1] = SMS_ROUTE_PRIORITY_1;
+               break;
+       case 3:
+               bearer_type[0] = SMS_ROUTE_PRIORITY_1;
+               bearer_type[1] = SMS_ROUTE_PRIORITY_2;
+               break;
+       }
+
+       if (cbd != NULL && sd != NULL) {
+               unsigned char msg[] = {
+                       SMS_SETTINGS_UPDATE_REQ,
+                       SMS_SETTING_TYPE_ROUTE,
+                       1, /* one subblock */
+                       SMS_GSM_ROUTE_INFO >> 8,
+                       SMS_GSM_ROUTE_INFO & 0xFF,
+                       8 >> 8,
+                       8 & 0xFF,
+                       bearer_type[0], /* cs priority */
+                       bearer_type[1], /* ps priority */
+                       0, 0
+               };
+
+               if (g_isi_client_send_with_timeout(sd->client, msg, sizeof(msg),
+                               SMS_TIMEOUT, set_resp_cb, cbd, g_free))
+                       return;
+       }
+
        CALLBACK_WITH_FAILURE(cb, data);
+       g_free(cbd);
 }
 
 static void send_status_ind_cb(const GIsiMessage *msg, void *data)
@@ -456,7 +982,8 @@ static void report_resp_cb(const GIsiMessage *msg, void 
*data)
        if (g_isi_msg_error(msg) < 0)
                return;
 
-       if (g_isi_msg_id(msg) != SMS_GSM_RECEIVED_PP_REPORT_RESP)
+       if (g_isi_msg_id(msg) != SMS_GSM_RECEIVED_PP_REPORT_RESP &&
+                       g_isi_msg_id(msg) != SMS_RECEIVED_MSG_REPORT_RESP)
                return;
 
        if (!g_isi_msg_data_get_byte(msg, 0, &cause))
@@ -465,27 +992,46 @@ static void report_resp_cb(const GIsiMessage *msg, void 
*data)
        DBG("Report resp cause=0x%"PRIx8, cause);
 }
 
-static gboolean send_deliver_report(GIsiClient *client, gboolean success)
+static gboolean send_deliver_report(struct sms_data *sd, gboolean success)
 {
        uint8_t cause_type = !success ? SMS_CAUSE_TYPE_GSM : 0;
        uint8_t cause = !success ? SMS_GSM_ERR_MEMORY_CAPACITY_EXC : 0;
+       GIsiModem *modem;
 
-       uint8_t msg[] = {
-               SMS_GSM_RECEIVED_PP_REPORT_REQ,
-               cause_type,     /* Cause type */
-               cause,          /* SMS cause */
-               0, 0, 0,        /* Filler */
-               1,              /* Sub blocks */
-               SMS_GSM_DELIVER_REPORT,
-               8,
-               0,              /* Message parameters */
-               0,              /* Cause type */
-               0, 0, 0,        /* Filler */
-               0,              /* Sub blocks */
-       };
-       size_t len = sizeof(msg);
+       if (sd == NULL)
+               return FALSE;
 
-       return g_isi_client_send(client, msg, len, report_resp_cb, NULL, NULL);
+       modem = g_isi_client_modem(sd->client);
+
+       if (g_isi_modem_version_major(modem) == 2 &&
+               g_isi_modem_version_minor(modem) >= 0) {
+               uint8_t msg[] = {
+                       SMS_RECEIVED_MSG_REPORT_REQ,
+                       cause_type,
+                       cause,
+                       0, 0, 0,        /* Filler */
+                       0,              /* nro of subblocks*/
+               };
+               return g_isi_client_send(sd->client, msg, sizeof(msg),
+                               report_resp_cb, NULL, NULL);
+       } else {
+               uint8_t msg[] = {
+                       SMS_GSM_RECEIVED_PP_REPORT_REQ,
+                       cause_type,     /* Cause type */
+                       cause,          /* SMS cause */
+                       0, 0, 0,        /* Filler */
+                       1,              /* Sub blocks */
+                       SMS_GSM_DELIVER_REPORT,
+                       8,
+                       0,              /* Message parameters */
+                       0,              /* Cause type */
+                       0, 0, 0,        /* Filler */
+                       0,              /* Sub blocks */
+               };
+
+               return g_isi_client_send(sd->client, msg, sizeof(msg),
+                                       report_resp_cb, NULL, NULL);
+       }
 }
 
 static gboolean parse_sms_address(GIsiSubBlockIter *iter, struct sms_addr *add)
@@ -583,8 +1129,8 @@ static void routing_ntf_cb(const GIsiMessage *msg, void 
*data)
                        tpdu.len + addr.len > sizeof(pdu))
                return;
 
-       memcpy(pdu, addr.data, addr.len);
-       memcpy(pdu + addr.len, tpdu.data, tpdu.len);
+       memmove(pdu, addr.data, addr.len);
+       memmove(pdu + addr.len, tpdu.data, tpdu.len);
 
        ofono_sms_deliver_notify(sms, pdu, tpdu.len + addr.len, tpdu.len);
 
@@ -594,19 +1140,101 @@ static void routing_ntf_cb(const GIsiMessage *msg, void 
*data)
         * no such indication from core, so we just blindly trust that
         * it did The Right Thing here.
         */
-       send_deliver_report(sd->client, TRUE);
+       send_deliver_report(sd, TRUE);
 }
 
-static void routing_resp_cb(const GIsiMessage *msg, void *data)
+static void received_msg_ind_cb(const GIsiMessage *msg, void *data)
 {
        struct ofono_sms *sms = data;
        struct sms_data *sd = ofono_sms_get_data(sms);
 
-       if (!check_sms_status(msg, SMS_PP_ROUTING_RESP))
+       GIsiSubBlockIter iter;
+       uint8_t *sca = NULL;
+       uint8_t sca_len = 0;
+       uint8_t *tpdu = NULL;
+       uint8_t tpdu_len = 0;
+       unsigned char pdu[176];
+       unsigned char type;
+       uint8_t sbcount;
+       DBG("");
+
+       if (!check_sms_status(msg, SMS_RECEIVED_MSG_IND))
                return;
 
-       g_isi_client_ntf_subscribe(sd->client, SMS_PP_ROUTING_NTF,
-                                       routing_ntf_cb, sms);
+       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)) {
+               switch (g_isi_sb_iter_get_id(&iter)) {
+               uint8_t type;
+               void *data;
+               uint8_t data_len;
+               case SMS_ADDRESS:
+                       if (!g_isi_sb_iter_get_byte(&iter, &type, 4)
+                                       || !g_isi_sb_iter_get_byte(&iter,
+                                                       &data_len, 5)
+                                       || !g_isi_sb_iter_get_data(&iter,
+                                                       &data, 6)
+                                       || type != SMS_SMSC_ADDRESS)
+                               break;
+
+                       sca = data;
+                       sca_len = data_len;
+                       break;
+               case SMS_GSM_TPDU_25:
+                       if (!g_isi_sb_iter_get_byte(&iter, &data_len, 4)
+                                       || !g_isi_sb_iter_get_data(&iter,
+                                                       &data, 6))
+                               break;
+                       tpdu = data;
+                       tpdu_len = data_len;
+                       break;
+               }
+       }
+
+       if (tpdu == NULL || sca == NULL || tpdu_len + sca_len > sizeof(pdu))
+               return;
+
+       memmove(pdu, sca, sca_len);
+       memmove(pdu + sca_len, tpdu, tpdu_len);
+       /* 23.040 9.2.3.1 */
+       type = tpdu[0] & 0x03;
+
+       if (type == SMS_STATUS_REPORT) {
+               ofono_sms_status_notify(sms,
+                               pdu, tpdu_len + sca_len, tpdu_len);
+       } else {
+               ofono_sms_deliver_notify(sms,
+                               pdu, tpdu_len + sca_len, tpdu_len);
+       }
+
+       send_deliver_report(sd, TRUE);
+}
+
+static void receive_msg_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct ofono_sms *sms = data;
+
+       if (sms == NULL)
+               return;
+
+       if (!check_sms_status_with_cause(msg, SMS_RECEIVE_MESSAGE_RESP,
+                                       SMS_RECEPTION_ACTIVE, 0))
+               return;
+
+       ofono_sms_register(sms);
+}
+
+static void routing_resp_cb(const GIsiMessage *msg, void *data)
+{
+       struct ofono_sms *sms = data;
+
+       if (sms == NULL)
+               return;
+
+       if (!check_sms_status(msg, SMS_PP_ROUTING_RESP))
+               return;
 
        ofono_sms_register(sms);
 }
@@ -616,43 +1244,85 @@ static void sim_reachable_cb(const GIsiMessage *msg, 
void *data)
        struct ofono_sms *sms = data;
        struct sms_data *sd = ofono_sms_get_data(sms);
 
-       const uint8_t req[] = {
-               SMS_PP_ROUTING_REQ,
-               SMS_ROUTING_SET,
-               0x01,  /* Sub-block count */
-               SMS_GSM_ROUTING,
-               0x08,  /* Sub-block length */
-               SMS_GSM_TPDU_ROUTING,
-               SMS_GSM_MT_ALL_TYPE,
-               0x00, 0x00, 0x00,  /* Filler */
-               0x00  /* Sub-sub-block count */
-       };
-       size_t len = sizeof(req);
+       if (sd == NULL)
+               return;
 
        if (g_isi_msg_error(msg) < 0) {
                DBG("unable to find SIM resource");
                g_isi_client_destroy(sd->sim);
                sd->sim = NULL;
        }
+}
 
-       g_isi_client_ind_subscribe(sd->client, SMS_MESSAGE_SEND_STATUS_IND,
-                                       send_status_ind_cb, sms);
-       g_isi_client_send(sd->client, req, len, routing_resp_cb, sms, NULL);
+static void uicc_reachable_cb(const GIsiMessage *msg, void *data)
+{
+       struct ofono_sms *sms = data;
+       struct sms_data *sd = ofono_sms_get_data(sms);
+
+       if (sd == NULL)
+               return;
+
+       if (g_isi_msg_error(msg) < 0) {
+               GIsiModem *modem = g_isi_client_modem(sd->sim);
+               g_isi_client_destroy(sd->sim);
+               sd->sim = g_isi_client_create(modem, PN_SMS);
+
+               if (sd->sim == NULL)
+                       return;
+
+               g_isi_client_set_timeout(sd->sim, SIM_TIMEOUT);
+               g_isi_client_verify(sd->sim, sim_reachable_cb, sms, NULL);
+               return;
+       }
 }
 
 static void sms_reachable_cb(const GIsiMessage *msg, void *data)
 {
        struct ofono_sms *sms = data;
        struct sms_data *sd = ofono_sms_get_data(sms);
+       GIsiModem *modem;
 
        if (g_isi_msg_error(msg) < 0) {
                DBG("unable to find SMS resource");
                return;
        }
 
+       if (sd == NULL)
+               return;
+
        ISI_VERSION_DBG(msg);
 
-       g_isi_client_verify(sd->sim, sim_reachable_cb, sms, NULL);
+       modem = g_isi_client_modem(sd->client);
+
+       if (g_isi_modem_version_major(modem) == 2 &&
+               g_isi_modem_version_minor(modem) >= 0) {
+               uint8_t req[] = {
+                               SMS_RECEIVE_MESSAGE_REQ,
+                               SMS_RECEPTION_ACTIVATE,
+                               0,
+               };
+               size_t len = sizeof(req);
+               g_isi_client_send(sd->client, req, len,
+                                       receive_msg_resp_cb, sms, NULL);
+
+       } else {
+               uint8_t req[] = {
+                               SMS_PP_ROUTING_REQ,
+                               SMS_ROUTING_SET,
+                               0x01,  /* Sub-block count */
+                               SMS_GSM_ROUTING,
+                               0x08,  /* Sub-block length */
+                               SMS_GSM_TPDU_ROUTING,
+                               SMS_GSM_MT_ALL_TYPE,
+                               0x00, 0x00, 0x00,  /* Filler */
+                               0x00  /* Sub-sub-block count */
+               };
+               size_t len = sizeof(req);
+               g_isi_client_send(sd->client, req, len,
+                                       routing_resp_cb, sms, NULL);
+       }
+
+       g_isi_client_verify(sd->sim, uicc_reachable_cb, sms, NULL);
 }
 
 static int isi_sms_probe(struct ofono_sms *sms, unsigned int vendor,
@@ -664,28 +1334,44 @@ static int isi_sms_probe(struct ofono_sms *sms, unsigned 
int vendor,
        if (sd == NULL)
                return -ENOMEM;
 
-       sd->params.absent = 0xFF;
-       sd->params.alphalen = 1; /* Includes final UCS2-coded NUL */
+       sd->sim_params.absent = 0xFF;
+       sd->sim_params.alphalen = 1; /* Includes final UCS2-coded NUL */
+
+       sd->usim_params.indicators = 0xFF;
+       sd->usim_params.alphalen = 0; /* Includes final UCS2-coded NUL */
+
 
        sd->client = g_isi_client_create(modem, PN_SMS);
        if (sd->client == NULL)
                goto nomem;
 
-       sd->sim = g_isi_client_create(modem, PN_SIM);
+       sd->sim = g_isi_client_create(modem, PN_UICC);
+
        if (sd->sim == NULL)
                goto nomem;
 
-       g_isi_client_set_timeout(sd->client, SMS_TIMEOUT);
-       g_isi_client_set_timeout(sd->sim, SIM_TIMEOUT);
 
        ofono_sms_set_data(sms, sd);
 
+       g_isi_client_ind_subscribe(sd->client, SMS_MESSAGE_SEND_STATUS_IND,
+                                       send_status_ind_cb, sms);
+
+       g_isi_client_ind_subscribe(sd->client, SMS_RECEIVED_MSG_IND,
+                                       received_msg_ind_cb, sms);
+
+       g_isi_client_ntf_subscribe(sd->client, SMS_PP_ROUTING_NTF,
+                                       routing_ntf_cb, sms);
+
        g_isi_client_verify(sd->client, sms_reachable_cb, sms, NULL);
 
+       g_isi_client_set_timeout(sd->client, SMS_TIMEOUT);
+       g_isi_client_set_timeout(sd->sim, SIM_TIMEOUT);
+
        return 0;
 
 nomem:
        g_isi_client_destroy(sd->client);
+       g_isi_client_destroy(sd->sim);
        g_free(sd);
        return -ENOMEM;
 }
@@ -693,29 +1379,43 @@ nomem:
 static void isi_sms_remove(struct ofono_sms *sms)
 {
        struct sms_data *sd = ofono_sms_get_data(sms);
-
-       const uint8_t msg[] = {
-               SMS_PP_ROUTING_REQ,
-               SMS_ROUTING_RELEASE,
-               0x01,  /* Sub-block count */
-               SMS_GSM_ROUTING,
-               0x08,  /* Sub-block length */
-               SMS_GSM_TPDU_ROUTING,
-               SMS_GSM_MT_ALL_TYPE,
-               0x00, 0x00, 0x00,  /* Filler */
-               0x00  /* Sub-sub-block count */
-       };
-
-       ofono_sms_set_data(sms, NULL);
+       GIsiModem *modem;
 
        if (sd == NULL)
                return;
 
+       modem = g_isi_client_modem(sd->client);
+       ofono_sms_set_data(sms, NULL);
+
        /*
         * Send a promiscuous routing release, so as not to
         * hog resources unnecessarily after being removed
         */
-       g_isi_client_send(sd->client, msg, sizeof(msg), NULL, NULL, NULL);
+       if (g_isi_modem_version_major(modem) == 2 &&
+               g_isi_modem_version_minor(modem) >= 0) {
+               uint8_t msg[] = {
+                       SMS_RECEIVE_MESSAGE_REQ,
+                       SMS_RECEPTION_DEACTIVATE,
+                       0x0,
+               };
+               g_isi_client_send(sd->client, msg, sizeof(msg),
+                                       NULL, NULL, NULL);
+       } else {
+               uint8_t msg[] = {
+                       SMS_PP_ROUTING_REQ,
+                       SMS_ROUTING_RELEASE,
+                       0x01,  /* Sub-block count */
+                       SMS_GSM_ROUTING,
+                       0x08,  /* Sub-block length */
+                       SMS_GSM_TPDU_ROUTING,
+                       SMS_GSM_MT_ALL_TYPE,
+                       0x00, 0x00, 0x00,  /* Filler */
+                       0x00  /* Sub-sub-block count */
+               };
+               g_isi_client_send(sd->client, msg, sizeof(msg),
+                                       NULL, NULL, NULL);
+       }
+
        g_isi_client_destroy(sd->client);
        g_isi_client_destroy(sd->sim);
        g_free(sd);
diff --git a/drivers/isimodem/sms.h b/drivers/isimodem/sms.h
index cbfb124..a51adf2 100644
--- a/drivers/isimodem/sms.h
+++ b/drivers/isimodem/sms.h
@@ -55,6 +55,7 @@ enum sms_isi_cause {
 };
 
 enum sms_isi_cause_type {
+       SMS_CAUSE_TYPE_COMMON = 0x00,
        SMS_CAUSE_TYPE_GSM = 0x01,
 };
 
@@ -125,6 +126,15 @@ enum sms_message_id {
        SMS_GSM_CB_ROUTING_RESP = 0x0C,
        SMS_GSM_CB_ROUTING_NTF = 0x0D,
        SMS_MESSAGE_SEND_STATUS_IND = 0x22,
+       SMS_SETTINGS_UPDATE_REQ = 0x30,
+       SMS_SETTINGS_UPDATE_RESP = 0x31,
+       SMS_SETTINGS_READ_REQ =  0x32,
+       SMS_SETTINGS_READ_RESP = 0x33,
+       SMS_RECEIVED_MSG_REPORT_REQ = 0x3B,
+       SMS_RECEIVED_MSG_REPORT_RESP = 0x3C,
+       SMS_RECEIVE_MESSAGE_REQ = 0x41,
+       SMS_RECEIVE_MESSAGE_RESP = 0x42,
+       SMS_RECEIVED_MSG_IND = 0x43,
        SMS_COMMON_MESSAGE = 0xF0
 };
 
@@ -138,6 +148,9 @@ enum sms_subblock {
        SMS_GSM_ROUTING = 0x0D,
        SMS_GSM_CB_MESSAGE = 0x0E,
        SMS_GSM_TPDU = 0x11,
+       SMS_GSM_TPDU_25 = 0x001C,
+       SMS_GSM_ROUTE_INFO = 0x0023,
+       SMS_GSM_PARAMETERS = 0x0031,
        SMS_COMMON_DATA = 0x80,
        SMS_ADDRESS = 0x82,
 };
@@ -175,6 +188,7 @@ enum sms_address_type {
        SMS_UNICODE_ADDRESS = 0x00,
        SMS_GSM_0340_ADDRESS = 0x01,
        SMS_GSM_0411_ADDRESS = 0x02,
+       SMS_SMSC_ADDRESS = 0x02
 };
 
 enum sms_sender_type {
@@ -192,6 +206,26 @@ enum sms_subject_list_type {
        SMS_CB_NOT_ALLOWED_IDS_LIST = 0x01
 };
 
+enum sms_reception_command {
+       SMS_RECEPTION_ACTIVATE = 0x01,
+       SMS_RECEPTION_DEACTIVATE = 0x02
+};
+
+enum sms_reception_status {
+       SMS_RECEPTION_ACTIVE = 0x01,
+       SMS_RECEPTION_INACTIVE = 0x02
+};
+
+enum sms_setting_type {
+       SMS_SETTING_TYPE_ROUTE = 0x02
+};
+
+enum sms_route_priority {
+       SMS_ROUTE_NOT_AVAILABLE = 0x00,
+       SMS_ROUTE_PRIORITY_1 = 0x01,
+       SMS_ROUTE_PRIORITY_2 = 0x02
+};
+
 #ifdef __cplusplus
 };
 #endif
-- 
1.7.3.5

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to