From: Jessica Nilsson <jessica.j.nilsson(a)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