diff --git a/src/cdma-sms.c b/src/cdma-sms.c
index ea88028..49a349f 100644
--- a/src/cdma-sms.c
+++ b/src/cdma-sms.c
@@ -100,7 +100,7 @@ static void ofono_cdma_sms_process_wmt_deliver(struct ofono_cdma_sms
*cdma_sms,
const char *oaddr;
const struct cdma_sms_ud *ud;
- ud = &incoming->p2p_msg.bd.wmt_deliver.ud;
+ ud = &incoming->p2p_msg.bd.deliver.ud;
/*
* If incoming message does not contain USER DATA, still
@@ -115,7 +115,7 @@ static void ofono_cdma_sms_process_wmt_deliver(struct ofono_cdma_sms
*cdma_sms,
if (message == NULL)
return;
- oaddr = cdma_sms_address_to_string(&incoming->p2p_msg.oaddr);
+ oaddr = cdma_sms_address_to_string(&incoming->p2p_msg.addr);
if (oaddr == NULL) {
g_free(message);
return;
diff --git a/src/cdma-smsutil.c b/src/cdma-smsutil.c
index dfa3403..3fac323 100644
--- a/src/cdma-smsutil.c
+++ b/src/cdma-smsutil.c
@@ -31,8 +31,9 @@
#include <unistd.h>
#include <glib.h>
-
+#include "stdio.h"
#include "cdma-smsutil.h"
+#include "smsutil.h"
#define uninitialized_var(x) x = x
@@ -40,7 +41,7 @@ enum cdma_sms_rec_flag {
CDMA_SMS_REC_FLAG_MANDATORY = 1,
};
-typedef gboolean (*rec_handler)(const guint8 *, guint8, void *);
+typedef gboolean (*dec_handler)(const guint8 *, guint8, void **);
struct simple_iter {
guint8 max;
@@ -51,6 +52,16 @@ struct simple_iter {
const guint8 *data;
};
+struct param_item {
+ guint8 id;
+ guint8 len;
+ void *data;
+};
+
+static gboolean decode_bearer_data(const guint8 *data, guint8 len,
+ struct cdma_sms_bearer_data *bd);
+static guint8 bit_field_unpack(const guint8 *buf, guint16 offset, guint8 nbit);
+
static void simple_iter_init(struct simple_iter *iter,
const guint8 *pdu, guint8 len)
{
@@ -112,6 +123,48 @@ static inline void set_bitmap(guint32 *bitmap, guint8 pos)
*bitmap = *bitmap | (1 << pos);
}
+
+static void free_param_item(struct param_item *item, void *user_data)
+{
+ if (item != NULL)
+ g_free(item->data);
+
+ g_free(item);
+}
+
+static void *get_param(GSList *params, guint id)
+{
+ GSList *l = params;
+
+ for (; l; l = l->next) {
+ struct param_item *item = l->data;
+
+ if (item->id == id)
+ return item->data;
+ }
+
+ return NULL;
+}
+
+static gboolean set_parameter(GSList *params, void *param, guint8 id,
+ guint32 size, guint32 *bitmap)
+{
+ void *value;
+
+ value = get_param(params, id);
+
+ if (value != NULL) {
+ memcpy(param, value, size);
+
+ if (bitmap != NULL)
+ set_bitmap(bitmap, id);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
/* Unpacks the byte stream. The field has to be <= 8 bits. */
static guint8 bit_field_unpack(const guint8 *buf, guint16 offset, guint8 nbit)
{
@@ -144,76 +197,125 @@ static gboolean dtmf_to_ascii(char *buf, const guint8 *addr,
* Note, 0 is NOT a valid value and not mapped to
* any valid DTMF digit.
*/
- static const char dtmf_digits[13] = {0, '1', '2', '3',
'4', '5', '6',
+ const char dtmf_digits[13] = {0, '1', '2', '3', '4',
'5', '6',
'7', '8', '9', '0', '*', '#'};
- guint8 index;
+ guint8 i;
guint8 value;
+ guint16 bit_offset = 0;
+
+ for (i = 0; i < num_fields; i++) {
+ value = bit_field_unpack(addr, bit_offset, 4);
+ bit_offset += 4;
- for (index = 0; index < num_fields; index++) {
- if (addr[index] == 0 || addr[index] > 12)
+ if (value == 0 || value > 12)
return FALSE; /* Invalid digit in address field */
- value = addr[index];
- buf[index] = dtmf_digits[value];
+ buf[i] = dtmf_digits[value];
}
- buf[index] = 0; /* Make it NULL terminated string */
+ buf[i] = 0; /* Make it NULL terminated string */
return TRUE;
}
-const char *cdma_sms_address_to_string(const struct cdma_sms_address *addr)
+static guint8 get_character_length(enum cdma_sms_msg_encoding encoding)
{
- static char buf[CDMA_SMS_MAX_ADDR_FIELDS + 1];
+ guint8 chari_len = 8;
- /* TODO: Only support CDMA_SMS_DIGIT_MODE_4BIT_DTMF currently */
- switch (addr->digit_mode) {
- case CDMA_SMS_DIGIT_MODE_4BIT_DTMF:
- if (dtmf_to_ascii(buf, addr->address,
- addr->num_fields) == TRUE)
- return buf;
- else
- return NULL;
- case CDMA_SMS_DIGIT_MODE_8BIT_ASCII:
- return NULL;
+ switch (encoding) {
+ case CDMA_SMS_MSG_ENCODING_OCTET:
+ case CDMA_SMS_MSG_ENCODING_SHIFT_JIS:
+ case CDMA_SMS_MSG_ENCODING_KOREAN:
+ case CDMA_SMS_MSG_ENCODING_LATIN_HEBREW:
+ case CDMA_SMS_MSG_ENCODING_LATIN:
+ chari_len = 8;
+ break;
+
+ case CDMA_SMS_MSG_ENCODING_7BIT_ASCII:
+ case CDMA_SMS_MSG_ENCODING_IA5:
+ case CDMA_SMS_MSG_ENCODING_GSM_7BIT:
+ chari_len = 7;
+ break;
+
+ case CDMA_SMS_MSG_ENCODING_UNICODE:
+ chari_len = 16;
+ break;
+
+ case CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG:
+ case CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING:
+ break;
}
- return NULL;
+ return chari_len;
}
-/* Decode Teleservice ID */
-static gboolean cdma_sms_decode_teleservice(const guint8 *buf, guint8 len,
- void *data)
-{
- enum cdma_sms_teleservice_id *id = data;
-
- *id = bit_field_unpack(buf, 0, 8) << 8 |
- bit_field_unpack(buf, 8, 8);
-
- switch (*id) {
- case CDMA_SMS_TELESERVICE_ID_CMT91:
- case CDMA_SMS_TELESERVICE_ID_WPT:
- case CDMA_SMS_TELESERVICE_ID_WMT:
- case CDMA_SMS_TELESERVICE_ID_VMN:
- case CDMA_SMS_TELESERVICE_ID_WAP:
- case CDMA_SMS_TELESERVICE_ID_WEMT:
- case CDMA_SMS_TELESERVICE_ID_SCPT:
- case CDMA_SMS_TELESERVICE_ID_CATPT:
- return TRUE;
+/* extract raw data from pdu
+ *
+ * total_bits: total bits to extract
+ * bit_offset: the start bit pos
+*/
+static void extract_raw_data(guint8 *to, const guint8 *from, guint16 total_bits,
+ guint16 bit_offset)
+{
+ guint8 i;
+ int count = total_bits / 8;
+ guint8 remain_bits = total_bits % 8;
+
+ for (i = 0; i < count; i++) {
+ to[i] = bit_field_unpack(from, bit_offset, 8);
+ bit_offset += 8;
}
- return FALSE; /* Invalid teleservice type */
+ if (remain_bits != 0)
+ to[i] = bit_field_unpack(from, bit_offset, remain_bits)
+ << (8 - remain_bits);
+}
+
+/* Decode Teleservice ID */
+static gboolean decode_param_teleservice(const guint8 *buf,
+ guint8 len, void **data)
+{
+ enum cdma_sms_teleservice_id *id;
+
+ if (len != 2)
+ return FALSE;
+
+ id = g_new0(enum cdma_sms_teleservice_id, 1);
+
+ *id = *buf << 8 | *(buf + 1);
+
+ *data = id;
+
+ return TRUE;
+}
+
+/* Decode Service category */
+static gboolean decode_param_service_category(const guint8 *buf,
+ guint8 len, void **data)
+{
+ enum cdma_sms_service_cat *cat;
+
+ if (len != 2)
+ return FALSE;
+
+ cat = g_new0(enum cdma_sms_service_cat, 1);
+
+ *cat = *buf << 8 | *(buf + 1);
+
+ *data = cat;
+
+ return TRUE;
}
-/* Decode Address parameter record */
-static gboolean cdma_sms_decode_addr(const guint8 *buf, guint8 len,
- void *data)
+/* Decode Address parameter */
+static gboolean decode_param_addr(const guint8 *buf, guint8 len, void **data)
{
- struct cdma_sms_address *addr = data;
+ struct cdma_sms_address *addr;
guint16 bit_offset = 0;
guint8 chari_len;
guint16 total_num_bits = len * 8;
- guint8 index;
+
+ addr = g_new0(struct cdma_sms_address, 1);
addr->digit_mode = bit_field_unpack(buf, bit_offset, 1);
bit_offset += 1;
@@ -232,8 +334,10 @@ static gboolean cdma_sms_decode_addr(const guint8 *buf, guint8 len,
bit_offset += 3;
if (addr->number_mode == CDMA_SMS_NUM_MODE_DIGIT) {
- if (bit_offset + 4 > total_num_bits)
+ if (bit_offset + 4 > total_num_bits) {
+ g_free(addr);
return FALSE;
+ }
addr->number_plan =
bit_field_unpack(buf, bit_offset, 4);
@@ -241,8 +345,10 @@ static gboolean cdma_sms_decode_addr(const guint8 *buf, guint8 len,
}
}
- if (bit_offset + 8 > total_num_bits)
+ if (bit_offset + 8 > total_num_bits) {
+ g_free(addr);
return FALSE;
+ }
addr->num_fields = bit_field_unpack(buf, bit_offset, 8);
bit_offset += 8;
@@ -252,484 +358,1279 @@ static gboolean cdma_sms_decode_addr(const guint8 *buf, guint8
len,
else
chari_len = 8;
- if ((bit_offset + chari_len * addr->num_fields) > total_num_bits)
+ if ((bit_offset + chari_len * addr->num_fields) > total_num_bits) {
+ g_free(addr);
return FALSE;
-
- for (index = 0; index < addr->num_fields; index++) {
- addr->address[index] = bit_field_unpack(buf,
- bit_offset,
- chari_len);
- bit_offset += chari_len;
}
+ extract_raw_data(addr->address, buf, addr->num_fields * chari_len,
+ bit_offset);
+
+ *data = addr;
+
return TRUE;
}
-static char *decode_text_7bit_ascii(const struct cdma_sms_ud *ud)
+static gboolean decode_param_subaddr(const guint8 *buf, guint8 len,
+ void **data)
+{
+ /* TODO */
+ return FALSE;
+}
+
+static gboolean decode_param_bearer_reply_option(const guint8 *buf,
+ guint8 len, void **data)
{
- char *buf;
+ struct cdma_sms_bearer_reply_option *option;
- buf = g_new(char, ud->num_fields + 1);
- if (buf == NULL)
- return NULL;
+ if (len != 1)
+ return FALSE;
- memcpy(buf, ud->chari, ud->num_fields);
- buf[ud->num_fields] = 0; /* Make it NULL terminated string */
+ option = g_new0(struct cdma_sms_bearer_reply_option, 1);
+ *data = option;
- return buf;
+ option->reply_seq = bit_field_unpack(buf, 0, 6);
+
+ return TRUE;
}
-char *cdma_sms_decode_text(const struct cdma_sms_ud *ud)
+static gboolean decode_param_cause_codes(const guint8 *buf,
+ guint8 len, void **data)
{
- switch (ud->msg_encoding) {
- case CDMA_SMS_MSG_ENCODING_OCTET:
- case CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG:
- return NULL; /* TODO */
- case CDMA_SMS_MSG_ENCODING_7BIT_ASCII:
- return decode_text_7bit_ascii(ud);
- case CDMA_SMS_MSG_ENCODING_IA5:
- case CDMA_SMS_MSG_ENCODING_UNICODE:
- case CDMA_SMS_MSG_ENCODING_SHIFT_JIS:
- case CDMA_SMS_MSG_ENCODING_KOREAN:
- case CDMA_SMS_MSG_ENCODING_LATIN_HEBREW:
- case CDMA_SMS_MSG_ENCODING_LATIN:
- case CDMA_SMS_MSG_ENCODING_GSM_7BIT:
- case CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING:
- return NULL; /* TODO */
- }
+ struct cdma_sms_cause_code *cause;
- return NULL;
+ if (len > 2 || len == 0)
+ return FALSE;
+
+ cause = g_new0(struct cdma_sms_cause_code, 1);
+ *data = cause;
+
+ cause->reply_seq = bit_field_unpack(buf, 0, 6);
+ cause->error_class = bit_field_unpack(buf, 6, 2);
+
+ if (len > 1)
+ cause->cause_code = *(buf + 1);
+
+ return TRUE;
}
-/* Decode User Data */
-static gboolean cdma_sms_decode_ud(const guint8 *buf, guint8 len, void *data)
+static gboolean decode_param_bearer_data(const guint8 *buf,
+ guint8 len, void **data)
{
- guint16 bit_offset = 0;
- guint8 chari_len = 0;
- guint16 total_num_bits = len * 8;
- guint8 index;
- enum cdma_sms_msg_encoding msg_encoding;
- struct cdma_sms_ud *ud = data;
+ struct cdma_sms_bearer_data *bd;
+ gboolean ret;
- if (total_num_bits < 13)
- return FALSE;
+ bd = g_new0(struct cdma_sms_bearer_data, 1);
- msg_encoding = bit_field_unpack(buf, bit_offset, 5);
- ud->msg_encoding = msg_encoding;
- bit_offset += 5;
+ ret = decode_bearer_data(buf, len, bd);
- if (msg_encoding == CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG ||
- msg_encoding == CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING) {
- /*
- * Skip message type field for now.
- * TODO: Add support for message type field.
- */
- bit_offset += 8;
- }
+ if (ret == FALSE)
+ g_free(bd);
- if (bit_offset + 8 > total_num_bits)
- return FALSE;
+ *data = bd;
- ud->num_fields = bit_field_unpack(buf, bit_offset, 8);
- bit_offset += 8;
+ return ret;
+}
- switch (msg_encoding) {
- case CDMA_SMS_MSG_ENCODING_OCTET:
- chari_len = 8;
- break;
- case CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG:
- return FALSE; /* TODO */
- case CDMA_SMS_MSG_ENCODING_7BIT_ASCII:
- case CDMA_SMS_MSG_ENCODING_IA5:
- chari_len = 7;
- break;
- case CDMA_SMS_MSG_ENCODING_UNICODE:
- case CDMA_SMS_MSG_ENCODING_SHIFT_JIS:
- case CDMA_SMS_MSG_ENCODING_KOREAN:
- return FALSE; /* TODO */
- case CDMA_SMS_MSG_ENCODING_LATIN_HEBREW:
- case CDMA_SMS_MSG_ENCODING_LATIN:
- chari_len = 8;
- break;
- case CDMA_SMS_MSG_ENCODING_GSM_7BIT:
- chari_len = 7;
- break;
- case CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING:
- return FALSE; /* TODO */
- }
+static dec_handler get_param_dec_handler_by_id(enum cdma_sms_param_id id)
+{
+ switch (id) {
+ case CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER:
+ return decode_param_teleservice;
- /* TODO: Add support for all other encoding types */
- if (chari_len == 0)
- return FALSE;
+ case CDMA_SMS_PARAM_ID_SERVICE_CATEGORY:
+ return decode_param_service_category;
- if (bit_offset + chari_len * ud->num_fields > total_num_bits)
- return FALSE;
+ case CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS:
+ case CDMA_SMS_PARAM_ID_DESTINATION_ADDRESS:
+ return decode_param_addr;
+
+ case CDMA_SMS_PARAM_ID_ORIGINATING_SUBADDRESS:
+ case CDMA_SMS_PARAM_ID_DESTINATION_SUBADDRESS:
+ return decode_param_subaddr;
+
+ case CDMA_SMS_PARAM_ID_BEARER_REPLY_OPTION:
+ return decode_param_bearer_reply_option;
+
+ case CDMA_SMS_PARAM_ID_CAUSE_CODE:
+ return decode_param_cause_codes;
- for (index = 0; index < ud->num_fields; index++) {
- ud->chari[index] = bit_field_unpack(buf,
- bit_offset,
- chari_len);
- bit_offset += chari_len;
+ case CDMA_SMS_PARAM_ID_BEARER_DATA:
+ return decode_param_bearer_data;
}
- return TRUE;
+ return NULL;
}
/* Decode Message Identifier */
-static gboolean cdma_sms_decode_message_id(const guint8 *buf, guint8 len,
- void *data)
+static gboolean decode_subparam_message_id(const guint8 *buf,
+ guint8 len, void **data)
{
- struct cdma_sms_identifier *id = data;
+ struct cdma_sms_msg_id *id;
if (len != 3)
return FALSE;
+ id = g_new0(struct cdma_sms_msg_id, 1);
+
id->msg_type = bit_field_unpack(buf, 0, 4);
if (id->msg_type <= 0 ||
- id->msg_type > CDMA_SMS_MSG_TYPE_SUBMIT_REPORT)
+ id->msg_type > CDMA_SMS_MSG_TYPE_SUBMIT_REPORT) {
+ g_free(id);
return FALSE; /* Invalid message type */
+ }
id->msg_id = (bit_field_unpack(buf, 4, 8) << 8) |
bit_field_unpack(buf, 12, 8);
id->header_ind = bit_field_unpack(buf, 20, 1);
+ *data = id;
+
return TRUE;
}
-static gboolean find_and_decode(struct simple_iter *iter, guint8 rec_id,
- rec_handler handler, void *data)
-{
- guint8 id;
- guint8 len;
- const guint8 *buf;
- while (simple_iter_next(iter) == TRUE) {
- id = simple_iter_get_id(iter);
- if (id != rec_id)
- continue;
+/* Decode User Data */
+static gboolean decode_subparam_ud(const guint8 *buf, guint8 len, void **data)
+{
+ enum cdma_sms_msg_encoding msg_encoding;
+ struct cdma_sms_ud *ud;
+ guint16 bit_offset = 0;
+ guint16 total_num_bits = len * 8;
+ guint8 chari_len;
- len = simple_iter_get_length(iter);
- buf = simple_iter_get_data(iter);
+ if (total_num_bits < 13)
+ return FALSE;
- return handler(buf, len, data);
- }
+ ud = g_new0(struct cdma_sms_ud, 1);
- return FALSE;
-}
+ msg_encoding = bit_field_unpack(buf, bit_offset, 5);
+ ud->msg_encoding = msg_encoding;
+ bit_offset += 5;
-static rec_handler subparam_handler_for_id(enum cdma_sms_subparam_id id)
-{
- switch (id) {
- case CDMA_SMS_SUBPARAM_ID_MESSAGE_ID:
- return cdma_sms_decode_message_id;
- case CDMA_SMS_SUBPARAM_ID_USER_DATA:
- return cdma_sms_decode_ud;
- case CDMA_SMS_SUBPARAM_ID_USER_RESPONSE_CODE:
- case CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP:
- case CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_ABSOLUTE:
- case CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_RELATIVE:
- case CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_ABSOLUTE:
- case CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_RELATIVE:
- case CDMA_SMS_SUBPARAM_ID_PRIORITY_INDICATOR:
- case CDMA_SMS_SUBPARAM_ID_PRIVACY_INDICATOR:
- case CDMA_SMS_SUBPARAM_ID_REPLY_OPTION:
- case CDMA_SMS_SUBPARAM_ID_NUMBER_OF_MESSAGES:
- case CDMA_SMS_SUBPARAM_ID_ALERT_ON_MESSAGE_DELIVERY:
- case CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR:
- case CDMA_SMS_SUBPARAM_ID_CALL_BACK_NUMBER:
- case CDMA_SMS_SUBPARAM_ID_MESSAGE_DISPLAY_MODE:
- case CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA:
- case CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX:
- case CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_DATA:
- case CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_RESULT:
- case CDMA_SMS_SUBPARAM_ID_MESSAGE_STATUS:
- case CDMA_SMS_SUBPARAM_ID_TP_FAILURE_CAUSE:
- case CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN:
- case CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN_ACK:
- return NULL; /* TODO */
+ if (msg_encoding == CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG ||
+ msg_encoding == CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING) {
+ ud->type = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
}
- return NULL;
-}
+ if (bit_offset + 8 > total_num_bits) {
+ g_free(ud);
+ return FALSE;
+ }
-struct subparam_handler_entry {
- enum cdma_sms_subparam_id id;
- int flags;
- gboolean found;
- void *data;
-};
+ ud->num_fields = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
-static gboolean decode_subparams(struct simple_iter *iter, guint32 *bitmap,
- void *data, ...)
-{
- GSList *entries = NULL;
- GSList *l;
- va_list args;
- gboolean decode_result = TRUE;
+ chari_len = get_character_length(msg_encoding);
- va_start(args, data);
+ if (bit_offset + ud->num_fields * chari_len > total_num_bits) {
+ g_free(ud);
+ return FALSE;
+ }
- while (data != NULL) {
- struct subparam_handler_entry *entry;
+ /* just copy orginal data */
+ extract_raw_data(ud->data, buf, ud->num_fields * chari_len,
+ bit_offset);
- entry = g_new0(struct subparam_handler_entry, 1);
+ *data = ud;
- entry->data = data;
- entry->id = va_arg(args, enum cdma_sms_subparam_id);
- entry->flags = va_arg(args, int);
+ return TRUE;
+}
- data = va_arg(args, void *);
- entries = g_slist_prepend(entries, entry);
- }
+static gboolean decode_subparam_time(const guint8 *buf,
+ guint8 len, void **data)
+{
+ struct cdma_sms_time *time;
- va_end(args);
+ if (len != 6)
+ return FALSE;
- entries = g_slist_reverse(entries);
+ time = g_new0(struct cdma_sms_time, 1);
- l = entries;
- while (simple_iter_next(iter) == TRUE) {
- rec_handler handler;
- struct subparam_handler_entry *entry;
- guint8 subparam_len;
- const guint8 *subparam_buf;
- GSList *l2;
+ time->year = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+ if (time->year >= 96)
+ time->year += 1900;
+ else
+ time->year += 2000;
+ buf++;
- for (l2 = l; l2; l2 = l2->next) {
- entry = l2->data;
+ time->month = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+ buf++;
- if (simple_iter_get_id(iter) == entry->id)
- break;
- }
+ time->day = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+ buf++;
- /* Ignore unexpected subparameter record */
- if (l2 == NULL)
- continue;
+ time->hour = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+ buf++;
- entry->found = TRUE;
+ time->min = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+ buf++;
- subparam_len = simple_iter_get_length(iter);
- subparam_buf = simple_iter_get_data(iter);
+ time->sec = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
- handler = subparam_handler_for_id(entry->id);
+ *data = time;
- decode_result = handler(subparam_buf,
- subparam_len,
- entry->data);
- if (decode_result == FALSE)
- break; /* Stop if decoding failed */
+ return TRUE;
+}
- set_bitmap(bitmap, entry->id);
- }
+static gboolean decode_subparam_byte(const guint8 *buf, guint8 len,
+ void **data)
+{
+ guint8 *byte;
- for (; l; l = l->next) {
- struct subparam_handler_entry *entry = l->data;
+ if (len != 1)
+ return FALSE;
- if ((entry->flags & CDMA_SMS_REC_FLAG_MANDATORY) &&
- (entry->found == FALSE)) {
- decode_result = FALSE;
- break;
- }
- }
+ byte = g_new0(guint8, 1);
+ *data = byte;
- g_slist_foreach(entries, (GFunc) g_free, NULL);
- g_slist_free(entries);
+ *byte = *buf;
- return decode_result;
+ return TRUE;
}
-/* Decode WMT */
-static gboolean cdma_sms_decode_wmt(struct simple_iter *iter,
- struct cdma_sms_bearer_data *bd)
+static gboolean decode_subparam_priority_indicator(const guint8 *buf,
+ guint8 len, void **data)
{
- switch (bd->id.msg_type) {
- case CDMA_SMS_MSG_TYPE_RESERVED:
- return FALSE; /* Invalid */
- case CDMA_SMS_MSG_TYPE_DELIVER:
- /*
- * WMT DELIVER, table 4.3.4-1 of C.S0015-B v2.0
- * TODO: Not all optional subparameters supported.
- */
- return decode_subparams(iter,
- &bd->subparam_bitmap,
- &bd->wmt_deliver.ud,
- CDMA_SMS_SUBPARAM_ID_USER_DATA,
- 0,
- NULL);
- break;
- case CDMA_SMS_MSG_TYPE_SUBMIT:
- case CDMA_SMS_MSG_TYPE_CANCEL:
- return FALSE; /* Invalid for MT WMT */
- case CDMA_SMS_MSG_TYPE_DELIVER_ACK:
- case CDMA_SMS_MSG_TYPE_USER_ACK:
- case CDMA_SMS_MSG_TYPE_READ_ACK:
- return FALSE; /* TODO: Not supported yet */
- case CDMA_SMS_MSG_TYPE_DELIVER_REPORT:
- case CDMA_SMS_MSG_TYPE_SUBMIT_REPORT:
- return FALSE; /* Invalid for MT WMT */
+ enum cdma_sms_priority *pri;
+
+ if (len != 1)
+ return FALSE;
+
+ pri = g_new0(enum cdma_sms_priority, 1);
+ *data = pri;
+
+ *pri = bit_field_unpack(buf, 0, 2);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_privacy_indicator(const guint8 *buf,
+ guint8 len, void **data)
+{
+ enum cdma_sms_privacy *pri;
+
+ if (len != 1)
+ return FALSE;
+
+ pri = g_new0(enum cdma_sms_privacy, 1);
+ *data = pri;
+
+ *pri = bit_field_unpack(buf, 0, 2);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_reply_option(const guint8 *buf,
+ guint8 len, void **data)
+{
+ struct cdma_sms_reply_option *option;
+
+ if (len != 1)
+ return FALSE;
+
+ option = g_new0(struct cdma_sms_reply_option, 1);
+ *data = option;
+
+ option->user_ack_req = bit_field_unpack(buf, 0, 1);
+ option->dak_req = bit_field_unpack(buf, 1, 1);
+ option->read_ack_req = bit_field_unpack(buf, 2, 1);
+ option->report_ack = bit_field_unpack(buf, 3, 1);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_num_of_msgs(const guint8 *buf,
+ guint8 len, void **data)
+{
+ guint8 *num;
+
+ if (len != 1)
+ return FALSE;
+
+ num = g_new0(guint8, 1);
+ *data = num;
+
+ *num = ((*buf & 0xF0) >> 4) * 10 + (*buf & 0x0F);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_alert_on_delivery(const guint8 *buf,
+ guint8 len, void **data)
+{
+ enum cdma_sms_alert *alert;
+
+ if (len != 1)
+ return FALSE;
+
+ alert = g_new0(enum cdma_sms_alert, 1);
+ *data = alert;
+
+ *alert = bit_field_unpack(buf, 0, 2);
+ return TRUE;
+}
+
+static gboolean decode_subparam_callback_number(const guint8 *buf,
+ guint8 len, void **data)
+{
+ struct cdma_sms_address *addr;
+ guint16 bit_offset = 0;
+ guint8 chari_len;
+ guint16 total_num_bits = len * 8;
+
+ addr = g_new0(struct cdma_sms_address, 1);
+
+ addr->digit_mode = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ if (addr->digit_mode == CDMA_SMS_DIGIT_MODE_8BIT_ASCII) {
+ addr->digi_num_type = bit_field_unpack(buf, bit_offset, 3);
+ bit_offset += 3;
+
+ addr->number_plan = bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
}
- return FALSE;
+ if (bit_offset + 8 > total_num_bits) {
+ g_free(addr);
+ return FALSE;
+ }
+
+ addr->num_fields = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ if (addr->digit_mode == CDMA_SMS_DIGIT_MODE_4BIT_DTMF)
+ chari_len = 4;
+ else
+ chari_len = 8;
+
+ if ((bit_offset + chari_len * addr->num_fields) > total_num_bits) {
+ g_free(addr);
+ return FALSE;
+ }
+
+ extract_raw_data(addr->address, buf, addr->num_fields * chari_len,
+ bit_offset);
+
+ *data = addr;
+
+ return TRUE;
}
-static gboolean p2p_decode_bearer_data(const guint8 *buf, guint8 len,
- enum cdma_sms_teleservice_id tele_id,
- struct cdma_sms_bearer_data *bd)
+static gboolean decode_subparam_display_mode(const guint8 *buf,
+ guint8 len, void **data)
{
- struct simple_iter iter;
+ enum cdma_sms_display_mode *mode;
+
+ if (len != 1)
+ return FALSE;
+
+ mode = g_new0(enum cdma_sms_display_mode, 1);
+ *data = mode;
+
+ *mode = bit_field_unpack(buf, 0, 2);
+
+ return TRUE;
+}
- simple_iter_init(&iter, buf, len);
+static gboolean decode_subparam_deposit_idx(const guint8 *buf,
+ guint8 len, void **data)
+{
+ guint16 *idx;
- /* Message Identifier is mandatory, * Section 4 of C.S0015-B v2.0 */
- if (find_and_decode(&iter,
- CDMA_SMS_SUBPARAM_ID_MESSAGE_ID,
- cdma_sms_decode_message_id,
- &bd->id) != TRUE)
+ if (len != 2)
return FALSE;
- set_bitmap(&bd->subparam_bitmap, CDMA_SMS_SUBPARAM_ID_MESSAGE_ID);
+ idx = g_new0(guint16, 1);
+ *data = idx;
+
+ *idx = *buf << 8 | *(buf + 1);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_service_category_program_data(
+ const guint8 *buf, guint8 len, void **data)
+{
+ struct cdma_sms_serive_category_program_data *scpd;
+ guint16 bit_offset = 0;
+ guint8 chari_len;
+ int i;
+
+ scpd = g_new0(struct cdma_sms_serive_category_program_data, 1);
+ scpd->encoding = bit_field_unpack(buf, bit_offset, 5);
+ bit_offset += 5;
+
+ scpd->fields_count = len / 6;
+
+ chari_len = get_character_length(scpd->encoding);
- simple_iter_init(&iter, buf, len);
+ for (i = 0; i < scpd->fields_count; i++) {
+ scpd->fields[i].op_code = bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
- switch (tele_id) {
- case CDMA_SMS_TELESERVICE_ID_CMT91:
- case CDMA_SMS_TELESERVICE_ID_WPT:
- return FALSE; /* TODO */
- case CDMA_SMS_TELESERVICE_ID_WMT:
- return cdma_sms_decode_wmt(&iter, bd);
- case CDMA_SMS_TELESERVICE_ID_VMN:
- case CDMA_SMS_TELESERVICE_ID_WAP:
- case CDMA_SMS_TELESERVICE_ID_WEMT:
- case CDMA_SMS_TELESERVICE_ID_SCPT:
- case CDMA_SMS_TELESERVICE_ID_CATPT:
- return FALSE; /* TODO */
+ scpd->fields[i].category =
+ (bit_field_unpack(buf, bit_offset, 8) << 8) +
+ bit_field_unpack(buf, bit_offset + 8, 8);
+ bit_offset += 16;
+
+ scpd->fields[i].language =
+ bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ scpd->fields[i].max_msg =
+ bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ scpd->fields[i].alart_option =
+ bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
+
+ scpd->fields[i].num_fields =
+ bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ extract_raw_data(scpd->fields[i].data,
+ buf,
+ scpd->fields[i].num_fields * chari_len,
+ bit_offset);
+
+ bit_offset += scpd->fields[i].num_fields * chari_len ;
}
- return FALSE;
+ *data = scpd;
+
+ return TRUE;
}
-/* Decode Bearer Data */
-static gboolean cdma_sms_decode_bearer_data(const guint8 *buf, guint8 len,
- void *data)
+static gboolean decode_subparam_service_category_program_results(
+ const guint8 *buf, guint8 len, void **data)
{
- struct cdma_sms *msg = data;
+ struct cdma_sms_serive_category_program_results *results;
+ int i;
- switch (msg->type) {
- case CDMA_SMS_TP_MSG_TYPE_P2P:
- return p2p_decode_bearer_data(buf, len,
- msg->p2p_msg.teleservice_id,
- &msg->p2p_msg.bd);
- case CDMA_SMS_TP_MSG_TYPE_BCAST:
- return FALSE; /* TODO */
- case CDMA_SMS_TP_MSG_TYPE_ACK:
- return FALSE; /* Invalid */
+ if (len < 3 || len % 3 != 0)
+ return FALSE;
+
+ results = g_new0(struct cdma_sms_serive_category_program_results,
+ len / 3);
+
+ for (i = 0; i < len / 3; i++) {
+ results[i].category = *buf << 8 | *(buf + 1);
+ results[i].result = (*(buf + 2) & 0xF0) >> 4;
+ buf += 3;
}
- return FALSE;
+ *data = results;
+
+ return TRUE;
}
-static rec_handler param_handler_for_id(enum cdma_sms_param_id id,
- struct cdma_sms *incoming,
- void **data)
+static gboolean decode_subparam_message_status(const guint8 *buf,
+ guint8 len, void **data)
{
- if (incoming->type != CDMA_SMS_TP_MSG_TYPE_P2P)
- return NULL; /* TODO: Other types not supported yet */
+ struct cdma_sms_msg_status *status;
+
+ if (len != 1)
+ return FALSE;
+
+ status = g_new0(struct cdma_sms_msg_status, 1);
+ *data = status;
+
+ status->error = bit_field_unpack(buf, 0, 2);
+ status->status = bit_field_unpack(buf, 2, 6);
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_enhanced_vmn(const guint8 *buf,
+ guint8 len, void **data)
+{
+ struct cdma_sms_enhanced_vmn *vmn;
+ guint16 bit_offset = 0;
+ guint8 chari_len;
+
+ vmn = g_new0(struct cdma_sms_enhanced_vmn, 1);
+
+ vmn->priority = bit_field_unpack(buf, bit_offset, 2);
+ bit_offset += 2;
+
+ vmn->pwd_required = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->setup_required = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->pwd_chg_required = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ if (vmn->setup_required == TRUE && vmn->pwd_chg_required == TRUE) {
+ vmn->min_pwd_len = bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
+
+ vmn->max_pwd_len = bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
+ }
+
+ vmn->unheard_msgs = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ vmn->almost_full = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->full = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->reply_allow = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->fax_include = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+ vmn->vm_length = (bit_field_unpack(buf, bit_offset, 8) << 8) |
+ bit_field_unpack(buf, bit_offset + 8, 4);
+ bit_offset += 12;
+
+ vmn->retention_days = bit_field_unpack(buf, bit_offset, 7);
+ bit_offset += 7;
+
+ vmn->msg_id = (bit_field_unpack(buf, bit_offset, 8) << 8) |
+ bit_field_unpack(buf, bit_offset + 8, 8);
+ bit_offset += 16;
+
+ vmn->mailbox_id = (bit_field_unpack(buf, bit_offset, 8) << 8) |
+ bit_field_unpack(buf, bit_offset + 8, 8);
+ bit_offset += 16;
+
+ vmn->access_number.digit_mode = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->access_number.digi_num_type =
+ bit_field_unpack(buf, bit_offset, 3);
+ bit_offset += 3;
+
+ if (vmn->access_number.digit_mode ==
+ CDMA_SMS_DIGIT_MODE_8BIT_ASCII) {
+ vmn->access_number.number_plan =
+ bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
+
+ chari_len = 8;
+ } else {
+ chari_len = 4;
+ }
+
+ vmn->access_number.num_fields = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ extract_raw_data(vmn->access_number.address, buf,
+ vmn->access_number.num_fields * chari_len, bit_offset);
+
+ bit_offset += vmn->access_number.num_fields * chari_len;
+
+ vmn->cli.digit_mode = bit_field_unpack(buf, bit_offset, 1);
+ bit_offset += 1;
+
+ vmn->cli.digi_num_type =
+ bit_field_unpack(buf, bit_offset, 3);
+ bit_offset += 3;
+
+ if (vmn->cli.digit_mode ==
+ CDMA_SMS_DIGIT_MODE_8BIT_ASCII) {
+ vmn->cli.number_plan =
+ bit_field_unpack(buf, bit_offset, 4);
+ bit_offset += 4;
+
+ chari_len = 8;
+ } else {
+ chari_len = 4;
+ }
+
+ vmn->cli.num_fields = bit_field_unpack(buf, bit_offset, 8);
+ bit_offset += 8;
+
+ extract_raw_data(vmn->cli.address, buf,
+ vmn->cli.num_fields * chari_len, bit_offset);
+
+ *data = vmn;
+
+ return TRUE;
+}
+
+static gboolean decode_subparam_enhanced_vmn_ack(const guint8 *buf,
+ guint8 len, void **data)
+{
+ struct cdma_sms_enhanced_vmn_ack *ack;
+ guint16 bit_offset = 0;
+ int i;
+
+ ack = g_new0(struct cdma_sms_enhanced_vmn_ack, 1);
+
+ ack->mailbox_id = *buf << 8 | *(buf + 1);
+ buf += 2;
+ ack->unheard_msgs = *buf++;
+
+ ack->del_acks_num = bit_field_unpack(buf, bit_offset, 3);
+ bit_offset += 3;
+
+ ack->play_acks_num = bit_field_unpack(buf, bit_offset, 3);
+ bit_offset += 3;
+
+ for (i = 0; i < ack->del_acks_num; i++) {
+ ack->da_id[i] = (bit_field_unpack(buf, bit_offset, 8) << 8) |
+ bit_field_unpack(buf, bit_offset + 8, 8);
+ bit_offset += 16;
+ }
+
+ for (i = 0; i < ack->play_acks_num; i++) {
+ ack->pa_id[i] = (bit_field_unpack(buf, bit_offset, 8) << 8) |
+ bit_field_unpack(buf, bit_offset + 8, 8);
+ bit_offset += 16;
+ }
+
+ *data = ack;
+
+ return TRUE;
+}
+
+static dec_handler get_subparam_dec_handler_by_id(enum cdma_sms_subparam_id id)
+{
switch (id) {
- case CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER:
- *data = &incoming->p2p_msg.teleservice_id;
- return cdma_sms_decode_teleservice;
- case CDMA_SMS_PARAM_ID_SERVICE_CATEGORY:
- return NULL; /* TODO */
- case CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS:
- *data = &incoming->p2p_msg.oaddr;
- return cdma_sms_decode_addr;
- case CDMA_SMS_PARAM_ID_ORIGINATING_SUBADDRESS:
- case CDMA_SMS_PARAM_ID_DESTINATION_ADDRESS:
- case CDMA_SMS_PARAM_ID_DESTINATION_SUBADDRESS:
- case CDMA_SMS_PARAM_ID_BEARER_REPLY_OPTION:
- case CDMA_SMS_PARAM_ID_CAUSE_CODE:
- return NULL; /* TODO */
- case CDMA_SMS_PARAM_ID_BEARER_DATA:
- *data = incoming;
- return cdma_sms_decode_bearer_data;
+ case CDMA_SMS_SUBPARAM_ID_MESSAGE_ID:
+ return decode_subparam_message_id;
+
+ case CDMA_SMS_SUBPARAM_ID_USER_DATA:
+ return decode_subparam_ud;
+
+ case CDMA_SMS_SUBPARAM_ID_USER_RESPONSE_CODE:
+ case CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_RELATIVE:
+ case CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_RELATIVE:
+ case CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR:
+ case CDMA_SMS_SUBPARAM_ID_TP_FAILURE_CAUSE:
+ return decode_subparam_byte;
+
+ case CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP:
+ case CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_ABSOLUTE:
+ case CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_ABSOLUTE:
+ return decode_subparam_time;
+
+ case CDMA_SMS_SUBPARAM_ID_PRIORITY_INDICATOR:
+ return decode_subparam_priority_indicator;
+
+ case CDMA_SMS_SUBPARAM_ID_PRIVACY_INDICATOR:
+ return decode_subparam_privacy_indicator;
+
+ case CDMA_SMS_SUBPARAM_ID_REPLY_OPTION:
+ return decode_subparam_reply_option;
+
+ case CDMA_SMS_SUBPARAM_ID_NUMBER_OF_MESSAGES:
+ return decode_subparam_num_of_msgs;
+
+ case CDMA_SMS_SUBPARAM_ID_ALERT_ON_MESSAGE_DELIVERY:
+ return decode_subparam_alert_on_delivery;
+
+ case CDMA_SMS_SUBPARAM_ID_CALL_BACK_NUMBER:
+ return decode_subparam_callback_number;
+
+ case CDMA_SMS_SUBPARAM_ID_MESSAGE_DISPLAY_MODE:
+ return decode_subparam_display_mode;
+
+ case CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA:
+ /* TODO */
+ return NULL;
+
+ case CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX:
+ return decode_subparam_deposit_idx;
+
+ case CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_DATA:
+ return decode_subparam_service_category_program_data;
+
+ case CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_RESULT:
+ return decode_subparam_service_category_program_results;
+
+ case CDMA_SMS_SUBPARAM_ID_MESSAGE_STATUS:
+ return decode_subparam_message_status;
+
+ case CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN:
+ return decode_subparam_enhanced_vmn;
+
+ case CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN_ACK:
+ return decode_subparam_enhanced_vmn_ack;
}
return NULL;
}
-static gboolean cdma_sms_p2p_decode(const guint8 *pdu, guint8 len,
- struct cdma_sms *incoming)
+static gboolean decode_params(const guint8 *data, guint len, GSList **params,
+ gboolean sub)
{
struct simple_iter iter;
- simple_iter_init(&iter, pdu, len);
+ simple_iter_init(&iter, data, len);
- /*
- * Teleservice Identifier is mandatory,
- * Table 3.4.2.1-1 of C.S0015-B v2.0
- */
- if (find_and_decode(&iter,
- CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER,
- cdma_sms_decode_teleservice,
- &incoming->p2p_msg.teleservice_id) != TRUE)
+ while (simple_iter_next(&iter) == TRUE) {
+ dec_handler handler;
+ guint8 id;
+ guint8 len;
+ const guint8 *buf;
+ void *uninitialized_var(dataobj);
+ struct param_item *item;
+
+ id = simple_iter_get_id(&iter);
+ len = simple_iter_get_length(&iter);
+ buf = simple_iter_get_data(&iter);
+
+ if (!sub)
+ handler = get_param_dec_handler_by_id(id);
+ else
+ handler = get_subparam_dec_handler_by_id(id);
+
+ if (handler != NULL) {
+ if (handler(buf, len, &dataobj) == FALSE)
+ continue;
+ }
+
+ item = g_new0(struct param_item, 1);
+ item->id = id;
+ item->len = len;
+ item->data = dataobj;
+
+ *params = g_slist_append(*params, item);
+ }
+
+ return TRUE;
+}
+
+static void decode_bearer_data_delivery(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_deliver *deliver = &bd->deliver;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &deliver->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(deliver->ud),
+ bitmap);
+
+ set_parameter(params, &deliver->time_stamp,
+ CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP,
+ sizeof(deliver->time_stamp),
+ bitmap);
+
+ set_parameter(params, &deliver->vp_absolute,
+ CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_ABSOLUTE,
+ sizeof(deliver->vp_absolute),
+ bitmap);
+
+ set_parameter(params, &deliver->vp,
+ CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_RELATIVE,
+ sizeof(deliver->vp),
+ bitmap);
+
+ set_parameter(params, &deliver->ddt_absolute,
+ CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_ABSOLUTE,
+ sizeof(deliver->ddt_absolute),
+ bitmap);
+
+ set_parameter(params, &deliver->ddt,
+ CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_RELATIVE,
+ sizeof(deliver->ddt),
+ bitmap);
+
+ set_parameter(params, &deliver->priority,
+ CDMA_SMS_SUBPARAM_ID_PRIORITY_INDICATOR,
+ sizeof(deliver->priority),
+ bitmap);
+
+ set_parameter(params, &deliver->privacy,
+ CDMA_SMS_SUBPARAM_ID_PRIVACY_INDICATOR,
+ sizeof(deliver->privacy),
+ bitmap);
+
+ set_parameter(params, &deliver->reply_option,
+ CDMA_SMS_SUBPARAM_ID_REPLY_OPTION,
+ sizeof(deliver->reply_option),
+ bitmap);
+
+ set_parameter(params, &deliver->msg_num,
+ CDMA_SMS_SUBPARAM_ID_NUMBER_OF_MESSAGES,
+ sizeof(deliver->msg_num),
+ bitmap);
+
+ set_parameter(params, &deliver->alert,
+ CDMA_SMS_SUBPARAM_ID_ALERT_ON_MESSAGE_DELIVERY,
+ sizeof(deliver->alert),
+ bitmap);
+
+ set_parameter(params, &deliver->language,
+ CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR,
+ sizeof(deliver->language),
+ bitmap);
+
+ set_parameter(params, &deliver->cb_number,
+ CDMA_SMS_SUBPARAM_ID_CALL_BACK_NUMBER,
+ sizeof(deliver->cb_number),
+ bitmap);
+
+ set_parameter(params, &deliver->display_mode,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_DISPLAY_MODE,
+ sizeof(deliver->display_mode),
+ bitmap);
+
+ set_parameter(params, &deliver->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(deliver->me_ud),
+ bitmap);
+
+ set_parameter(params, &deliver->deposit_idx,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX,
+ sizeof(deliver->deposit_idx),
+ bitmap);
+
+ set_parameter(params, &deliver->scpd,
+ CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_DATA,
+ sizeof(deliver->scpd),
+ bitmap);
+}
+
+static void decode_bearer_data_submit(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_submit *submit = &bd->submit;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &submit->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(submit->ud),
+ bitmap);
+
+ set_parameter(params, &submit->vp_absolute,
+ CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_ABSOLUTE,
+ sizeof(submit->vp_absolute),
+ bitmap);
+
+ set_parameter(params, &submit->vp,
+ CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_RELATIVE,
+ sizeof(submit->vp),
+ bitmap);
+
+ set_parameter(params, &submit->ddt_absolute,
+ CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_ABSOLUTE,
+ sizeof(submit->ddt_absolute),
+ bitmap);
+
+ set_parameter(params, &submit->ddt,
+ CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_RELATIVE,
+ sizeof(submit->ddt),
+ bitmap);
+
+ set_parameter(params, &submit->priority,
+ CDMA_SMS_SUBPARAM_ID_PRIORITY_INDICATOR,
+ sizeof(submit->priority),
+ bitmap);
+
+ set_parameter(params, &submit->privacy,
+ CDMA_SMS_SUBPARAM_ID_PRIVACY_INDICATOR,
+ sizeof(submit->privacy),
+ bitmap);
+
+ set_parameter(params, &submit->reply_option,
+ CDMA_SMS_SUBPARAM_ID_REPLY_OPTION,
+ sizeof(submit->reply_option),
+ bitmap);
+
+ set_parameter(params, &submit->alert,
+ CDMA_SMS_SUBPARAM_ID_ALERT_ON_MESSAGE_DELIVERY,
+ sizeof(submit->alert),
+ bitmap);
+
+ set_parameter(params, &submit->language,
+ CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR,
+ sizeof(submit->language),
+ bitmap);
+
+ set_parameter(params, &submit->cb_number,
+ CDMA_SMS_SUBPARAM_ID_CALL_BACK_NUMBER,
+ sizeof(submit->cb_number),
+ bitmap);
+
+ set_parameter(params, &submit->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(submit->me_ud),
+ bitmap);
+
+ set_parameter(params, &submit->deposit_idx,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX,
+ sizeof(submit->deposit_idx),
+ bitmap);
+
+ set_parameter(params, &submit->scpr,
+ CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_RESULT,
+ sizeof(submit->scpr),
+ bitmap);
+}
+
+static void decode_bearer_data_deliver_ack(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_deliver_ack *ack = &bd->deliver_ack;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &ack->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(ack->ud),
+ bitmap);
+
+ set_parameter(params, &ack->time_stamp,
+ CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP,
+ sizeof(ack->time_stamp),
+ bitmap);
+
+ set_parameter(params, &ack->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(ack->me_ud),
+ bitmap);
+
+ set_parameter(params, &ack->status,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_STATUS,
+ sizeof(ack->status),
+ bitmap);
+}
+
+static void decode_bearer_data_user_ack(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_user_ack *ack = &bd->user_ack;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &ack->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(ack->ud),
+ bitmap);
+
+ set_parameter(params, &ack->response,
+ CDMA_SMS_SUBPARAM_ID_USER_RESPONSE_CODE,
+ sizeof(ack->response),
+ bitmap);
+
+ set_parameter(params, &ack->time_stamp,
+ CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP,
+ sizeof(ack->time_stamp),
+ bitmap);
+
+ set_parameter(params, &ack->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(ack->me_ud),
+ bitmap);
+
+ set_parameter(params, &ack->deposit_idx,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX,
+ sizeof(ack->deposit_idx),
+ bitmap);
+}
+
+static void decode_bearer_data_read_ack(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_read_ack *ack = &bd->read_ack;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &ack->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(ack->ud),
+ bitmap);
+
+ set_parameter(params, &ack->time_stamp,
+ CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP,
+ sizeof(ack->time_stamp),
+ bitmap);
+
+ set_parameter(params, &ack->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(ack->me_ud),
+ bitmap);
+
+ set_parameter(params, &ack->deposit_idx,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX,
+ sizeof(ack->deposit_idx),
+ bitmap);
+}
+
+static void decode_bearer_data_report(GSList *params,
+ struct cdma_sms_bearer_data *bd)
+{
+ struct cdma_sms_report *report = &bd->report;
+ guint32 *bitmap = &bd->subparam_bitmap;
+
+ set_parameter(params, &report->cause,
+ CDMA_SMS_SUBPARAM_ID_TP_FAILURE_CAUSE,
+ sizeof(report->cause),
+ bitmap);
+
+ set_parameter(params, &report->ud,
+ CDMA_SMS_SUBPARAM_ID_USER_DATA,
+ sizeof(report->ud),
+ bitmap);
+
+ set_parameter(params, &report->language,
+ CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR,
+ sizeof(report->language),
+ bitmap);
+
+ set_parameter(params, &report->me_ud,
+ CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA,
+ sizeof(report->me_ud),
+ bitmap);
+}
+
+static gboolean decode_bearer_data(const guint8 *data, guint8 len,
+ struct cdma_sms_bearer_data *bd)
+{
+ GSList *subparams;
+ gboolean ret;
+
+ subparams = NULL;
+
+ ret = decode_params(data, len, &subparams, TRUE);
+
+ if (ret == FALSE) {
+ g_slist_foreach(subparams, (GFunc) free_param_item, NULL);
+ g_slist_free(subparams);
return FALSE;
+ }
- set_bitmap(&incoming->p2p_msg.param_bitmap,
- CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER);
+ ret = set_parameter(subparams, &bd->id,
+ CDMA_SMS_SUBPARAM_ID_MESSAGE_ID,
+ sizeof(bd->id),
+ &bd->subparam_bitmap);
- simple_iter_init(&iter, pdu, len);
+ if (ret == FALSE) {
+ g_slist_foreach(subparams, (GFunc) free_param_item, NULL);
+ g_slist_free(subparams);
+ return FALSE;
+ }
- while (simple_iter_next(&iter) == TRUE) {
- rec_handler handler;
- enum cdma_sms_param_id rec_id;
- guint8 rec_len;
- const guint8 *rec_buf;
- void *uninitialized_var(dataobj);
+ switch (bd->id.msg_type) {
+ case CDMA_SMS_MSG_TYPE_RESERVED:
+ ret = FALSE;
+ break;
- rec_id = simple_iter_get_id(&iter);
- if (rec_id == CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER)
- continue;
+ case CDMA_SMS_MSG_TYPE_DELIVER:
+ decode_bearer_data_delivery(subparams, bd);
+ break;
- rec_len = simple_iter_get_length(&iter);
- rec_buf = simple_iter_get_data(&iter);
+ case CDMA_SMS_MSG_TYPE_SUBMIT:
+ case CDMA_SMS_MSG_TYPE_CANCEL:
+ decode_bearer_data_submit(subparams, bd);
+ break;
- handler = param_handler_for_id(rec_id, incoming, &dataobj);
- if (handler != NULL) {
- if (handler(rec_buf, rec_len, dataobj) == FALSE)
- return FALSE;
+ case CDMA_SMS_MSG_TYPE_DELIVER_ACK:
+ decode_bearer_data_deliver_ack(subparams, bd);
+ break;
- set_bitmap(&incoming->p2p_msg.param_bitmap, rec_id);
- }
+ case CDMA_SMS_MSG_TYPE_USER_ACK:
+ decode_bearer_data_user_ack(subparams, bd);
+ break;
+
+ case CDMA_SMS_MSG_TYPE_READ_ACK:
+ decode_bearer_data_read_ack(subparams, bd);
+ break;
+
+ case CDMA_SMS_MSG_TYPE_DELIVER_REPORT:
+ case CDMA_SMS_MSG_TYPE_SUBMIT_REPORT:
+ decode_bearer_data_report(subparams, bd);
+ break;
}
- /*
- * Originating Address is mandatory field,
- * Table 3.4.2.1-1 of C.S0015-B v2.0
- */
- if ((incoming->p2p_msg.param_bitmap &
- (1 << CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS)) == 0)
+ g_slist_foreach(subparams, (GFunc) free_param_item, NULL);
+ g_slist_free(subparams);
+ return ret;
+}
+
+static gboolean decode_p2p_sms(GSList *params, struct cdma_sms *sms)
+{
+ guint32 *bitmap;
+
+ if (params == NULL || sms == NULL)
+ return FALSE;
+
+ bitmap = &sms->p2p_msg.param_bitmap;
+
+ set_parameter(params, &sms->p2p_msg.teleservice_id,
+ CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER,
+ sizeof(sms->p2p_msg.teleservice_id),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.service_category,
+ CDMA_SMS_PARAM_ID_SERVICE_CATEGORY,
+ sizeof(sms->p2p_msg.service_category),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.addr,
+ CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS,
+ sizeof(sms->p2p_msg.addr),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.subaddr,
+ CDMA_SMS_PARAM_ID_ORIGINATING_SUBADDRESS,
+ sizeof(sms->p2p_msg.subaddr),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.addr,
+ CDMA_SMS_PARAM_ID_DESTINATION_ADDRESS,
+ sizeof(sms->p2p_msg.addr),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.subaddr,
+ CDMA_SMS_PARAM_ID_DESTINATION_SUBADDRESS,
+ sizeof(sms->p2p_msg.subaddr),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.reply_option,
+ CDMA_SMS_PARAM_ID_BEARER_REPLY_OPTION,
+ sizeof(sms->p2p_msg.reply_option),
+ bitmap);
+
+ set_parameter(params, &sms->p2p_msg.bd,
+ CDMA_SMS_PARAM_ID_BEARER_DATA,
+ sizeof(sms->p2p_msg.bd),
+ bitmap);
+
+ return TRUE;
+}
+
+static gboolean decode_broadcast_sms(GSList *params, struct cdma_sms *sms)
+{
+ if (params == NULL || sms == NULL)
+ return FALSE;
+
+ set_parameter(params, &sms->broadcast_msg.service_category,
+ CDMA_SMS_PARAM_ID_SERVICE_CATEGORY,
+ sizeof(sms->broadcast_msg.service_category),
+ NULL);
+
+ set_parameter(params, &sms->broadcast_msg.bd,
+ CDMA_SMS_PARAM_ID_BEARER_DATA,
+ sizeof(sms->broadcast_msg.bd),
+ NULL);
+
+ return TRUE;
+}
+
+static gboolean decode_ack_sms(GSList *params, struct cdma_sms *sms)
+{
+ void *value;
+
+ if (params == NULL || sms == NULL)
+ return FALSE;
+
+ value = get_param(params, CDMA_SMS_PARAM_ID_DESTINATION_ADDRESS);
+ if (value != NULL)
+ memcpy(&sms->ack_msg.daddr, value, sizeof(sms->ack_msg.daddr));
+
+ value = get_param(params, CDMA_SMS_PARAM_ID_DESTINATION_SUBADDRESS);
+ if (value != NULL)
+ memcpy(&sms->ack_msg.subaddr, value,
+ sizeof(sms->ack_msg.subaddr));
+
+ value = get_param(params, CDMA_SMS_PARAM_ID_CAUSE_CODE);
+ if (value != NULL)
+ memcpy(&sms->ack_msg.cause_code, value,
+ sizeof(sms->ack_msg.cause_code));
+ else
return FALSE;
return TRUE;
}
gboolean cdma_sms_decode(const guint8 *pdu, guint8 len,
- struct cdma_sms *incoming)
+ struct cdma_sms *sms)
{
- incoming->type = bit_field_unpack(pdu, 0, 8);
- pdu += 1;
- len -= 1;
+ GSList *params = NULL;
- switch (incoming->type) {
+ gboolean ret;
+
+ if (pdu == NULL || len == 0 || sms == NULL)
+ return FALSE;
+
+ memset(sms, 0, sizeof(struct cdma_sms));
+
+ sms->type = *pdu++;
+ len--;
+
+ ret = decode_params(pdu, len, ¶ms, FALSE);
+
+ if (ret == FALSE) {
+ g_slist_foreach(params, (GFunc) free_param_item, NULL);
+ g_slist_free(params);
+ return FALSE;
+ }
+
+ switch (sms->type) {
case CDMA_SMS_TP_MSG_TYPE_P2P:
- return cdma_sms_p2p_decode(pdu, len, incoming);
+ ret = decode_p2p_sms(params, sms);
+ break;
+
case CDMA_SMS_TP_MSG_TYPE_BCAST:
+ ret = decode_broadcast_sms(params, sms);
+ break;
+
case CDMA_SMS_TP_MSG_TYPE_ACK:
- /* TODO: Not supported yet */
- return FALSE;
+ ret = decode_ack_sms(params, sms);
+ break;
}
- return FALSE;
+ g_slist_foreach(params, (GFunc) free_param_item, NULL);
+ g_slist_free(params);
+ return ret;
+}
+
+const char *cdma_sms_address_to_string(const struct cdma_sms_address *addr)
+{
+ static char buf[CDMA_SMS_MAX_ADDR_FIELDS + 1];
+
+ if (addr->digit_mode == CDMA_SMS_DIGIT_MODE_4BIT_DTMF) {
+ if (dtmf_to_ascii(buf, addr->address,
+ addr->num_fields) == TRUE)
+ return buf;
+ else
+ return NULL;
+ } else {
+ if (addr->number_mode == CDMA_SMS_NUM_MODE_DIGIT) {
+ if (addr->digi_num_type ==
+ CDMA_SMS_DIGI_NUM_TYPE_INTERNATIONAL) {
+ sprintf(buf, "+%s", addr->address);
+ return buf;
+ }
+
+ return (char *)addr->address;
+ }
+
+ /* TODO: convert data network address */
+ return (char *)addr->address;
+ }
+}
+
+char *cdma_sms_decode_text(const struct cdma_sms_ud *ud)
+{
+ switch (ud->msg_encoding) {
+ case CDMA_SMS_MSG_ENCODING_OCTET:
+ case CDMA_SMS_MSG_ENCODING_EXTENDED_PROTOCOL_MSG:
+ case CDMA_SMS_MSG_ENCODING_7BIT_ASCII:
+ case CDMA_SMS_MSG_ENCODING_IA5:
+ case CDMA_SMS_MSG_ENCODING_UNICODE:
+ case CDMA_SMS_MSG_ENCODING_SHIFT_JIS:
+ case CDMA_SMS_MSG_ENCODING_KOREAN:
+ case CDMA_SMS_MSG_ENCODING_LATIN_HEBREW:
+ case CDMA_SMS_MSG_ENCODING_LATIN:
+ case CDMA_SMS_MSG_ENCODING_GSM_7BIT:
+ case CDMA_SMS_MSG_ENCODING_GSM_DATA_CODING:
+ return NULL; /* TODO */
+ }
+
+ return NULL;
}
diff --git a/src/cdma-smsutil.h b/src/cdma-smsutil.h
index d8c22c3..bdd8b3a 100644
--- a/src/cdma-smsutil.h
+++ b/src/cdma-smsutil.h
@@ -3,6 +3,7 @@
* oFono - Open Source Telephony
*
* Copyright (C) 2010-2011 Nokia Corporation. All rights reserved.
+ * Copyright (C) 2011 Wind river systems. All rights reserved.
*
* 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
@@ -20,6 +21,7 @@
*/
#define CDMA_SMS_MAX_ADDR_FIELDS 256
+#define CDMA_SMS_MAX_FIELDS 256
#define CDMA_SMS_UD_LEN 512
/* 3GPP2 C.S0015-B v2.0, Table 3.4-1 */
@@ -80,6 +82,11 @@ enum cdma_sms_numbering_plan {
CDMA_SMS_NUMBERING_PLAN_RESERVED = 15
};
+enum cdma_sms_subaddr_type {
+ CDMA_SMS_SUBADDR_TYPE_NASP = 0,
+ CDMA_SMS_SUBADDR_TYPE_USER_SPEC = 1,
+};
+
/* 3GPP2 C.S0015-B v2.0 Table 4.5.1-1 */
enum cdma_sms_msg_type {
CDMA_SMS_MSG_TYPE_RESERVED = 0,
@@ -196,6 +203,86 @@ enum cdma_sms_digit_mode {
CDMA_SMS_DIGIT_MODE_8BIT_ASCII = 1
};
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.9 */
+enum cdma_sms_priority {
+ CDMA_SMS_PRIORITY_NORMAL = 0,
+ CDMA_SMS_PRIORITY_INTERACTIVE = 1,
+ CDMA_SMS_PRIORITY_URGENT = 2,
+ CDMA_SMS_PRIORITY_EMERGENCY = 3,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.10 */
+enum cdma_sms_privacy {
+ CDMA_SMS_PRIVACY_NOT_RESTRICTED = 0,
+ CDMA_SMS_PRIVACY_RESTRICTED = 1,
+ CDMA_SMS_PRIVACY_CONFIDENTIAL = 2,
+ CDMA_SMS_PRIVACY_SECRET = 3,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.13 */
+enum cdma_sms_alert {
+ CDMA_SMS_ALERT_DEFAULT = 0,
+ CDMA_SMS_ALERT_LOW = 1,
+ CDMA_SMS_ALERT_MEDIUM = 2,
+ CDMA_SMS_ALERT_HIGH = 3,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.14 */
+enum cdma_sms_language_indicator {
+ CDMA_SMS_LANGUAGE_UNSPECIFIED = 0,
+ CDMA_SMS_LANGUAGE_ENGLISH = 1,
+ CDMA_SMS_LANGUAGE_FRENCH = 2,
+ CDMA_SMS_LANGUAGE_SPANISH = 3,
+ CDMA_SMS_LANGUAGE_JAPANESE = 4,
+ CDMA_SMS_LANGUAGE_KOREAN = 5,
+ CDMA_SMS_LANGUAGE_CHINESE = 6,
+ CDMA_SMS_LANGUAGE_HEBREW = 7,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.16 */
+enum cdma_sms_display_mode {
+ CDMA_SMS_DISPLAY_MODE_IMMEDIATE = 0,
+ CDMA_SMS_DISPLAY_MODE_DEFAULT = 1,
+ CDMA_SMS_DISPLAY_MODE_USER_INVOKE = 2,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.20 */
+enum cdma_sms_service_category_program_result {
+ CDMA_SMS_SCP_RESULT_SUCCESS = 0,
+ CDMA_SMS_SCP_RESULT_MEMORY_EXCEEDED = 1,
+ CDMA_SMS_SCP_RESULT_CATEGORY_EXCEEDED = 2,
+ CDMA_SMS_SCP_RESULT_ALREAY_PROGRAMMED = 3,
+ CDMA_SMS_SCP_RESULT_NOT_PREPROGRAMMED = 4,
+ CDMA_SMS_SCP_RESULT_INVALID_MAX_MESSAGES = 5,
+ CDMA_SMS_SCP_RESULT_INVALID_ALERT_OPTION = 6,
+ CDMA_SMS_SCP_RESULT_INVALID_SERVICE_CATEGORY_NAME = 7,
+ CDMA_SMS_SCP_RESULT_UNSPECIFIED_FAILURE = 8,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.21 */
+enum cdma_sms_error_report_class {
+ CDMA_SMS_ERROR_REPORT_NO_ERROR = 0,
+ CDMA_SMS_ERROR_REPORT_TEMPORARY = 2,
+ CDMA_SMS_ERROR_REPORT_PERMANENT = 3,
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.22 */
+enum cdma_sms_msg_status_code {
+ CDMA_SMS_MSG_STATUS_ACCEPTED = 0,
+ CDMA_SMS_MSG_STATUS_DEPOSITED = 1,
+ CDMA_SMS_MSG_STATUS_DELIVERED = 2,
+ CDMA_SMS_MSG_STATUS_CANCELLED = 3,
+ CDMA_SMS_MSG_STATUS_NW_CONGRESTION = 4,
+ CDMA_SMS_MSG_STATUS_NW_ERROR = 5,
+ CDMA_SMS_MSG_STATUS_CANCEL_FAILED = 6,
+ CDMA_SMS_MSG_STATUS_BLOCKED = 7,
+ CDMA_SMS_MSG_STATUS_TXT_TOO_LONG = 8,
+ CDMA_SMS_MSG_STATUS_DUPLICATED = 9,
+ CDMA_SMS_MSG_STATUS_INVALID_DEST = 10,
+ CDMA_SMS_MSG_STATUS_EXPIRED = 13,
+ CDMA_SMS_MSG_STATUS_UNKNOWN_ERROR = 63,
+};
+
/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.3 */
struct cdma_sms_address {
enum cdma_sms_digit_mode digit_mode;
@@ -209,6 +296,19 @@ struct cdma_sms_address {
guint8 address[CDMA_SMS_MAX_ADDR_FIELDS];
};
+/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.4 */
+struct cdma_sms_subaddress {
+ enum cdma_sms_subaddr_type type;
+ gboolean odd;
+ guint8 num_fields;
+ guint8 address[CDMA_SMS_MAX_ADDR_FIELDS];
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.5 */
+struct cdma_sms_bearer_reply_option {
+ guint8 reply_seq;
+};
+
/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.6 */
struct cdma_sms_cause_code {
guint8 reply_seq;
@@ -217,7 +317,7 @@ struct cdma_sms_cause_code {
};
/* 3GPP2 C.S0015-B v2.0 Section 4.5.1 */
-struct cdma_sms_identifier {
+struct cdma_sms_msg_id {
enum cdma_sms_msg_type msg_type;
guint16 msg_id;
gboolean header_ind;
@@ -226,25 +326,178 @@ struct cdma_sms_identifier {
/* 3GPP2 C.S0015-B v2.0 Section 4.5.2 */
struct cdma_sms_ud {
enum cdma_sms_msg_encoding msg_encoding;
+ enum cdma_sms_msg_type type;
guint8 num_fields;
- guint8 chari[CDMA_SMS_UD_LEN];
+ guint8 data[CDMA_SMS_UD_LEN];
};
-/*
- * 3GPP2 C.S0015-B v2.0 Table 4.3.4-1.
- * TODO: Not all subparameter records defined
- * and supported yet.
- */
-struct cdma_sms_wmt_deliver {
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.4 */
+struct cdma_sms_time {
+ guint16 year;
+ guint8 month;
+ guint8 day;
+ guint8 hour;
+ guint8 min;
+ guint8 sec;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.11 */
+struct cdma_sms_reply_option {
+ guint8 user_ack_req:1;
+ guint8 dak_req:1;
+ guint8 read_ack_req:1;
+ guint8 report_ack:1;
+ guint8 padding:4;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.19 */
+struct cdma_sms_category_specific_fields {
+ guint8 op_code;
+ guint16 category;
+ guint8 language;
+ guint8 max_msg;
+ enum cdma_sms_alert alart_option;
+ guint8 num_fields;
+ guint8 data[CDMA_SMS_MAX_FIELDS];
+};
+
+struct cdma_sms_serive_category_program_data {
+ enum cdma_sms_msg_encoding encoding;
+ guint8 fields_count;
+ struct cdma_sms_category_specific_fields fields[64];
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.20 */
+struct cdma_sms_serive_category_program_results {
+ guint16 category;
+ enum cdma_sms_service_category_program_result result;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.21 */
+struct cdma_sms_msg_status {
+ enum cdma_sms_error_report_class error;
+ enum cdma_sms_msg_status_code status;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.23 */
+struct cdma_sms_enhanced_vmn {
+ enum cdma_sms_priority priority;
+ gboolean pwd_required;
+ gboolean setup_required;
+ gboolean pwd_chg_required;
+ guint8 min_pwd_len;
+ guint8 max_pwd_len;
+ guint8 unheard_msgs;
+ gboolean almost_full;
+ gboolean full;
+ gboolean reply_allow;
+ gboolean fax_include;
+ guint16 vm_length;
+ guint8 retention_days;
+ guint16 msg_id;
+ guint16 mailbox_id;
+ struct cdma_sms_address access_number;
+ struct cdma_sms_address cli;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.5.24 */
+struct cdma_sms_enhanced_vmn_ack {
+ guint16 mailbox_id;
+ guint8 unheard_msgs;
+ guint8 del_acks_num;
+ guint8 play_acks_num;
+ guint16 da_id[8];
+ guint16 pa_id[8];
+};
+
+/* 3GPP2 C.S0015-B v2.0 Table 4.4.1-1. */
+struct cdma_sms_deliver {
struct cdma_sms_ud ud;
+ struct cdma_sms_time time_stamp;
+ union {
+ struct cdma_sms_time vp_absolute;
+ guint8 vp;
+ };
+ union {
+ struct cdma_sms_time ddt_absolute;
+ guint8 ddt;
+ };
+ enum cdma_sms_priority priority;
+ enum cdma_sms_privacy privacy;
+ struct cdma_sms_reply_option reply_option;
+ guint8 msg_num;
+ enum cdma_sms_alert alert;
+ enum cdma_sms_language_indicator language;
+ struct cdma_sms_address cb_number;
+ enum cdma_sms_display_mode display_mode;
+ struct cdma_sms_ud me_ud;
+ guint16 deposit_idx;
+ struct cdma_sms_serive_category_program_data scpd;
};
-/* 3GPP2 C.S0015-B v2.0 Section 4.5 */
+/* 3GPP2 C.S0015-B v2.0 Table 4.4.2-1. */
+struct cdma_sms_submit {
+ struct cdma_sms_ud ud;
+ union {
+ struct cdma_sms_time vp_absolute;
+ guint8 vp;
+ };
+ union {
+ struct cdma_sms_time ddt_absolute;
+ guint8 ddt;
+ };
+ enum cdma_sms_priority priority;
+ enum cdma_sms_privacy privacy;
+ struct cdma_sms_reply_option reply_option;
+ enum cdma_sms_alert alert;
+ enum cdma_sms_language_indicator language;
+ struct cdma_sms_address cb_number;
+ struct cdma_sms_ud me_ud;
+ guint16 deposit_idx;
+ struct cdma_sms_serive_category_program_results scpr[128];
+};
+
+struct cdma_sms_user_ack {
+ struct cdma_sms_ud ud;
+ guint8 response;
+ struct cdma_sms_time time_stamp;
+ struct cdma_sms_ud me_ud;
+ guint16 deposit_idx;
+};
+
+struct cdma_sms_deliver_ack {
+ struct cdma_sms_ud ud;
+ struct cdma_sms_time time_stamp;
+ struct cdma_sms_ud me_ud;
+ struct cdma_sms_msg_status status;
+};
+
+struct cdma_sms_read_ack {
+ struct cdma_sms_ud ud;
+ struct cdma_sms_time time_stamp;
+ struct cdma_sms_ud me_ud;
+ guint16 deposit_idx;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Table 4.4.7-1 & Table 4.4.8-1*/
+struct cdma_sms_report {
+ guint8 cause;
+ struct cdma_sms_ud ud;
+ enum cdma_sms_language_indicator language;
+ struct cdma_sms_ud me_ud;
+};
+
+/* 3GPP2 C.S0015-B v2.0 Section 4.4 */
struct cdma_sms_bearer_data {
guint32 subparam_bitmap;
- struct cdma_sms_identifier id;
+ struct cdma_sms_msg_id id;
union {
- struct cdma_sms_wmt_deliver wmt_deliver;
+ struct cdma_sms_deliver deliver;
+ struct cdma_sms_submit submit;
+ struct cdma_sms_user_ack user_ack;
+ struct cdma_sms_deliver_ack deliver_ack;
+ struct cdma_sms_read_ack read_ack;
+ struct cdma_sms_report report;
};
};
@@ -256,7 +509,10 @@ struct cdma_sms_bearer_data {
struct cdma_sms_p2p_msg {
guint32 param_bitmap;
enum cdma_sms_teleservice_id teleservice_id;
- struct cdma_sms_address oaddr;
+ enum cdma_sms_service_cat service_category;
+ struct cdma_sms_address addr;
+ struct cdma_sms_subaddress subaddr;
+ struct cdma_sms_bearer_reply_option reply_option;
struct cdma_sms_bearer_data bd;
};
@@ -273,6 +529,7 @@ struct cdma_sms_broadcast_msg {
*/
struct cdma_sms_ack_msg {
struct cdma_sms_address daddr;
+ struct cdma_sms_subaddress subaddr;
struct cdma_sms_cause_code cause_code;
};
diff --git a/unit/test-cdmasms.c b/unit/test-cdmasms.c
index 1d27cbb..e968d0b 100644
--- a/unit/test-cdmasms.c
+++ b/unit/test-cdmasms.c
@@ -91,10 +91,10 @@ static void test_wmt_deliver(gconstpointer data)
g_assert(s.p2p_msg.teleservice_id == CDMA_SMS_TELESERVICE_ID_WMT);
- addr = cdma_sms_address_to_string(&s.p2p_msg.oaddr);
+ addr = cdma_sms_address_to_string(&s.p2p_msg.addr);
check_text(addr, test->oaddr);
- message = cdma_sms_decode_text(&s.p2p_msg.bd.wmt_deliver.ud);
+ message = (char *)cdma_sms_decode_text(&s.p2p_msg.bd.deliver.ud);
check_text(message, test->text);
g_free(message);
--
1.7.5