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

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

Reply via email to