I've not tested this on a real SIM yet.
---
src/message-waiting.c | 51 ++++++++++++++++++++++++++++++++++++------------
src/simutil.c | 27 +++++++++++++++++++++++++
src/simutil.h | 2 +
src/smsutil.c | 47 +++++++++++++++++++++++++++++---------------
src/smsutil.h | 8 +++++++
5 files changed, 106 insertions(+), 29 deletions(-)
diff --git a/src/message-waiting.c b/src/message-waiting.c
index 14a6e9c..568cea6 100644
--- a/src/message-waiting.c
+++ b/src/message-waiting.c
@@ -164,12 +164,12 @@ static DBusMessage *mw_get_properties(DBusConnection *conn,
return reply;
}
-static void mbdn_set_cb(gboolean ok, void *data)
+static void mbdn_set_cb(struct ofono_modem *modem, int ok, void *data)
{
struct mbdn_set_request *req = data;
struct ofono_phone_number *old = &req->mw->mailbox_number[req->mailbox];
const char *property;
- DBusMessage *reply;
+ DBusMessage *reply = 0; /* Quiet a warning */
if (!ok) {
if (req->msg)
@@ -208,11 +208,19 @@ out:
g_free(req);
}
-static void set_mbdn(struct ofono_modem *modem, int mailbox,
+static DBusMessage *set_mbdn(struct ofono_modem *modem, int mailbox,
const char *number, DBusMessage *msg)
{
DBusConnection *conn = ofono_dbus_get_connection();
struct mbdn_set_request *req;
+ unsigned char efmbdn[255];
+
+ if (modem->message_waiting->efmbdn_record_id[mailbox] == 0) {
+ if (msg)
+ return __ofono_error_failed(msg);
+
+ return NULL;
+ }
req = g_new0(struct mbdn_set_request, 1);
@@ -222,8 +230,19 @@ static void set_mbdn(struct ofono_modem *modem, int mailbox,
string_to_phone_number(number, &req->number);
req->msg = dbus_message_ref(msg);
- /* TODO: Fill the actual sim_write data */
- mbdn_set_cb(TRUE, req);
+ sim_adn_build(efmbdn, req->mw->efmbdn_length, &req->number);
+
+ if (ofono_sim_write(modem, SIM_EFMBDN_FILEID, mbdn_set_cb,
+ OFONO_SIM_FILE_STRUCTURE_FIXED,
+ req->mw->efmbdn_record_id[mailbox],
+ efmbdn, req->mw->efmbdn_length, req) == -1) {
+ g_free(req);
+
+ if (msg)
+ return __ofono_error_failed(msg);
+ }
+
+ return NULL;
}
static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
@@ -275,8 +294,7 @@ static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage
*msg,
if (g_str_equal(cur_number, value))
return dbus_message_new_method_return(msg);
- set_mbdn(modem, i, value, msg);
- return NULL;
+ return set_mbdn(modem, i, value, msg);
}
return __ofono_error_invalid_args(msg);
@@ -599,6 +617,7 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
{
int profile, n;
gboolean set;
+ struct sms_address mailbox_address;
if (length < 3)
return;
@@ -614,9 +633,10 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
if (discard)
*discard = (iei[0] & (1 << 4)) ? FALSE : TRUE;
- /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
- n = 2 + (iei[1] + 1) / 2;
- if (length < n + 11)
+ /* VM_MAILBOX_ACCESS_ADDRESS */
+ n = 0;
+ if (!sms_decode_address_field(iei + 1, length - 1, &n,
+ FALSE, &mailbox_address))
return;
/* TODO: VM_MESSAGE_PRIORITY_INDICATION */
@@ -636,9 +656,10 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
if (discard)
*discard = (iei[0] & (1 << 4)) ? FALSE : TRUE;
- /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
- n = 2 + (iei[1] + 1) / 2;
- if (length < n + 11)
+ /* VM_MAILBOX_ACCESS_ADDRESS */
+ n = 0;
+ if (!sms_decode_address_field(iei + 1, length - 1, &n,
+ FALSE, &mailbox_address))
return;
/* Other parameters currently not supported */
@@ -647,6 +668,10 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
mw_set_indicator(modem, profile, SMS_MWI_TYPE_VOICE,
set, iei[n + 2]);
}
+
+ if (mailbox_address.address[0] != '\0')
+ set_mbdn(modem, SMS_MWI_TYPE_VOICE,
+ sms_address_to_string(&mailbox_address), NULL);
}
void ofono_handle_sms_mwi(struct ofono_modem *modem,
diff --git a/src/simutil.c b/src/simutil.c
index 51b1f5c..7a0830e 100644
--- a/src/simutil.c
+++ b/src/simutil.c
@@ -426,3 +426,30 @@ gboolean sim_adn_parse(const unsigned char *data, int length,
return TRUE;
}
+
+void sim_adn_build(unsigned char *data, int length,
+ const struct ofono_phone_number *ph)
+{
+ int number_len = strlen(ph->number);
+
+ /* Alpha-Identifier field */
+ if (length > 14) {
+ memset(data, 0xff, length - 14);
+ data += length - 14;
+ }
+
+ number_len = (number_len + 1) / 2;
+ *data++ = number_len + 1;
+
+ /* Use given number type and 'Unknown' for Numbering Plan */
+ *data++ = 0x80 | (ph->type << 4) | 0;
+
+ encode_bcd_number(ph->number, data);
+ memset(data + number_len, 0xff, 10 - number_len);
+ data += 10;
+
+ /* CCP1 unused */
+ *data++ = 0xff;
+ /* Ext1 unused */
+ *data++ = 0xff;
+}
diff --git a/src/simutil.h b/src/simutil.h
index c2b1e20..9d198db 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -82,3 +82,5 @@ static inline enum sim_file_access file_access_condition_decode(int
bcd)
gboolean sim_adn_parse(const unsigned char *data, int length,
struct ofono_phone_number *ph);
+void sim_adn_build(unsigned char *data, int length,
+ const struct ofono_phone_number *ph);
diff --git a/src/smsutil.c b/src/smsutil.c
index ad38ed9..ba2bbc1 100644
--- a/src/smsutil.c
+++ b/src/smsutil.c
@@ -110,6 +110,17 @@ static inline int to_semi_oct(char in)
return digit;
}
+void encode_bcd_number(const char *number, unsigned char *out)
+{
+ while (number[0] != '\0' && number[1] != '\0') {
+ *out = to_semi_oct(*number++);
+ *out++ |= to_semi_oct(*number++) << 4;
+ }
+
+ if (*number)
+ *out = to_semi_oct(*number) | 0xf0;
+}
+
/* Returns whether the DCS could be parsed successfully, e.g. no reserved
* values were used
*/
@@ -446,8 +457,8 @@ static gboolean encode_validity_period(const struct
sms_validity_period *vp,
return FALSE;
}
-static gboolean encode_address(const struct sms_address *in, gboolean sc,
- unsigned char *pdu, int *offset)
+gboolean sms_encode_address_field(const struct sms_address *in, gboolean sc,
+ unsigned char *pdu, int *offset)
{
size_t len = strlen(in->address);
unsigned char addr_len = 0;
@@ -533,9 +544,9 @@ out:
return TRUE;
}
-static gboolean decode_address(const unsigned char *pdu, int len,
- int *offset, gboolean sc,
- struct sms_address *out)
+gboolean sms_decode_address_field(const unsigned char *pdu, int len,
+ int *offset, gboolean sc,
+ struct sms_address *out)
{
unsigned char addr_len;
unsigned char addr_type;
@@ -635,7 +646,7 @@ static gboolean encode_deliver(const struct sms_deliver *in, unsigned
char *pdu,
set_octet(pdu, offset, oct);
- if (encode_address(&in->oaddr, FALSE, pdu, offset) == FALSE)
+ if (sms_encode_address_field(&in->oaddr, FALSE, pdu, offset) == FALSE)
return FALSE;
set_octet(pdu, offset, in->pid);
@@ -672,7 +683,8 @@ static gboolean decode_deliver(const unsigned char *pdu, int len,
out->deliver.udhi = is_bit_set(octet, 6);
out->deliver.rp = is_bit_set(octet, 7);
- if (!decode_address(pdu, len, &offset, FALSE, &out->deliver.oaddr))
+ if (!sms_decode_address_field(pdu, len, &offset,
+ FALSE, &out->deliver.oaddr))
return FALSE;
if (!next_octet(pdu, len, &offset, &out->deliver.pid))
@@ -883,7 +895,7 @@ static gboolean encode_status_report(const struct sms_status_report
*in,
set_octet(pdu, offset, in->mr);
- if (!encode_address(&in->raddr, FALSE, pdu, offset))
+ if (!sms_encode_address_field(&in->raddr, FALSE, pdu, offset))
return FALSE;
if (!encode_scts(&in->scts, pdu, offset))
@@ -935,8 +947,8 @@ static gboolean decode_status_report(const unsigned char *pdu, int
len,
if (!next_octet(pdu, len, &offset, &out->status_report.mr))
return FALSE;
- if (!decode_address(pdu, len, &offset, FALSE,
- &out->status_report.raddr))
+ if (!sms_decode_address_field(pdu, len, &offset, FALSE,
+ &out->status_report.raddr))
return FALSE;
if (!decode_scts(pdu, len, &offset, &out->status_report.scts))
@@ -1173,7 +1185,7 @@ static gboolean encode_submit(const struct sms_submit *in,
set_octet(pdu, offset, in->mr);
- if (encode_address(&in->daddr, FALSE, pdu, offset) == FALSE)
+ if (sms_encode_address_field(&in->daddr, FALSE, pdu, offset) == FALSE)
return FALSE;
set_octet(pdu, offset, in->pid);
@@ -1215,7 +1227,8 @@ static gboolean decode_submit(const unsigned char *pdu, int len,
if (!next_octet(pdu, len, &offset, &out->submit.mr))
return FALSE;
- if (!decode_address(pdu, len, &offset, FALSE, &out->submit.daddr))
+ if (!sms_decode_address_field(pdu, len, &offset,
+ FALSE, &out->submit.daddr))
return FALSE;
if (!next_octet(pdu, len, &offset, &out->submit.pid))
@@ -1265,7 +1278,7 @@ static gboolean encode_command(const struct sms_command *in,
set_octet(pdu, offset, in->mn);
- if (!encode_address(&in->daddr, FALSE, pdu, offset))
+ if (!sms_encode_address_field(&in->daddr, FALSE, pdu, offset))
return FALSE;
set_octet(pdu, offset, in->cdl);
@@ -1305,7 +1318,8 @@ static gboolean decode_command(const unsigned char *pdu, int len,
if (!next_octet(pdu, len, &offset, &out->command.mn))
return FALSE;
- if (!decode_address(pdu, len, &offset, FALSE, &out->command.daddr))
+ if (!sms_decode_address_field(pdu, len, &offset,
+ FALSE, &out->command.daddr))
return FALSE;
if (!next_octet(pdu, len, &offset, &out->command.cdl))
@@ -1328,7 +1342,7 @@ gboolean sms_encode(const struct sms *in, int *len, int *tpdu_len,
if (in->type == SMS_TYPE_DELIVER || in->type == SMS_TYPE_SUBMIT ||
in->type == SMS_TYPE_COMMAND)
- if (!encode_address(&in->sc_addr, TRUE, pdu, &offset))
+ if (!sms_encode_address_field(&in->sc_addr, TRUE, pdu, &offset))
return FALSE;
tpdu_start = offset;
@@ -1396,7 +1410,8 @@ gboolean sms_decode(const unsigned char *pdu, int len, gboolean
outgoing,
return FALSE;
if (tpdu_len < len) {
- if (!decode_address(pdu, len, &offset, TRUE, &out->sc_addr))
+ if (!sms_decode_address_field(pdu, len, &offset,
+ TRUE, &out->sc_addr))
return FALSE;
}
diff --git a/src/smsutil.h b/src/smsutil.h
index d362aa9..95d0c78 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -401,6 +401,7 @@ static inline unsigned char bit_field(unsigned char oct, int start,
int num)
}
void extract_bcd_number(const unsigned char *buf, int len, char *out);
+void encode_bcd_number(const char *number, unsigned char *out);
gboolean sms_decode(const unsigned char *pdu, int len, gboolean outgoing,
int tpdu_len, struct sms *out);
@@ -408,6 +409,13 @@ gboolean sms_decode(const unsigned char *pdu, int len, gboolean
outgoing,
gboolean sms_encode(const struct sms *in, int *len, int *tpdu_len,
unsigned char *pdu);
+gboolean sms_decode_address_field(const unsigned char *pdu, int len,
+ int *offset, gboolean sc,
+ struct sms_address *out);
+
+gboolean sms_encode_address_field(const struct sms_address *in, gboolean sc,
+ unsigned char *pdu, int *offset);
+
int sms_udl_in_bytes(guint8 ud_len, guint8 dcs);
time_t sms_scts_to_time(const struct sms_scts *scts, struct tm *remote);
--
1.6.1