From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============8101587677430499073==" MIME-Version: 1.0 From: Lei Yu Subject: [PATCH v2, 3/7] cdma-sms: Add CDMA SMS Support Date: Tue, 21 Dec 2010 16:02:25 -0800 Message-ID: <1292976149-15598-4-git-send-email-lei.2.yu@nokia.com> In-Reply-To: List-Id: To: ofono@ofono.org --===============8101587677430499073== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable --- Makefile.am | 3 +- src/cdma-smsutil.c | 484 ++++++++++++++++++++++++++++++++++++++++++++++++= ++++ src/cdma-smsutil.h | 264 ++++++++++++++++++++++++++++ 3 files changed, 750 insertions(+), 1 deletions(-) create mode 100644 src/cdma-smsutil.c create mode 100644 src/cdma-smsutil.h diff --git a/Makefile.am b/Makefile.am index aa00016..e85f522 100644 --- a/Makefile.am +++ b/Makefile.am @@ -319,7 +319,8 @@ src_ofonod_SOURCES =3D $(gdbus_sources) $(builtin_sourc= es) src/ofono.ver \ src/radio-settings.c src/stkutil.h src/stkutil.c \ src/nettime.c src/stkagent.c src/stkagent.h \ src/simfs.c src/simfs.h src/audio-settings.c \ - src/smsagent.c src/smsagent.h src/ctm.c + src/smsagent.c src/smsagent.h src/ctm.c \ + src/cdma-smsutil.c = src_ofonod_LDADD =3D $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ @CAPNG_LIBS= @ -ldl = diff --git a/src/cdma-smsutil.c b/src/cdma-smsutil.c new file mode 100644 index 0000000..b80002c --- /dev/null +++ b/src/cdma-smsutil.c @@ -0,0 +1,484 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2010 Nokia Corporation. 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 U= SA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +#include + +#include "cdma-smsutil.h" + +/* + * Mapping from binary DTMF code to the digit it represents. + * As defined in Table 2.7.1.3.2.4-4 of 3GPP2 C.S0005-E v2.0. + * Note, 0 is NOT a valid value and not mapped to + * any valid DTMF digit. + */ +const char cdma_sms_dtmf_digits[13] =3D {0, '1', '2', '3', '4', '5', '6', = '7', + '8', '9', '0', '*', '#'}; + + +/* Unpacks the byte stream. */ +static guint32 bit_field_unpack(const guint8 *buf, guint32 offset, + guint32 nbit) +{ + guint32 val =3D 0; + guint32 byteIndex; + guint32 remainder; + + if (buf =3D=3D NULL) + return 0; + + byteIndex =3D offset >> 3; + remainder =3D (offset & 0x7); + + if (remainder !=3D 0) { + /* + * The field to be unpacked does not start at the byte + * boundary. Retrieve those bits first. + */ + guint32 mask; + + mask =3D (1 << (8 - remainder)) - 1; + val =3D buf[byteIndex] & mask; + + /* The field is within current byte */ + if (nbit < (8 - remainder)) + return (val >> (8 - remainder - nbit)); + + /* The field at least spans till end of the byte. */ + nbit -=3D (8 - remainder); + byteIndex++; + } + + /* Unpack rest of the bits in the field in 8-bit chunk. */ + while (nbit >=3D 8) { + val =3D (val << 8) | buf[byteIndex]; + nbit -=3D 8; + byteIndex++; + } + + /* If still some left, unpack the last remaining bits. */ + if (nbit > 0) + val =3D (val << nbit) | (buf[byteIndex] >> (8 - nbit)); + + return val; +} + +/* Convert CDMA DTMF digits into a string */ +static gboolean cdma_sms_dtmf_to_ascii(char *buf, const char *addr, + guint8 num_fields) +{ + guint8 index; + guint8 value; + + if (buf =3D=3D NULL || addr =3D=3D NULL) + return FALSE; + + for (index =3D 0; index < num_fields; index++) { + if ((addr[index] <=3D 0) || (addr[index] > 12)) + return FALSE; /* Invalid digit in address field */ + + value =3D (guint8) addr[index]; + buf[index] =3D cdma_sms_dtmf_digits[value]; + } + + buf[index] =3D 0; /* Make it NULL terminated string */ + + return TRUE; +} + +char *cdma_sms_address_to_string(const struct cdma_sms_address *addr) +{ + char *buf; + + if (addr =3D=3D NULL) + return NULL; + + if (addr->digit_mode !=3D DTMF_4_BIT) + return NULL; /* TODO: Only support DTMF_4_BIT currently */ + + buf =3D g_new(char, addr->num_fields + 1); + if (buf =3D=3D NULL) + return NULL; + + if (!cdma_sms_dtmf_to_ascii(buf, addr->address, addr->num_fields)) { + g_free(buf); + return NULL; + } + + return buf; +} + +/* Decode Address parameter record */ +static gboolean cdma_sms_decode_addr(const unsigned char *buf, int len, + struct cdma_sms_address *addr) +{ + guint32 bit_offset =3D 0; + guint8 chari_len; + guint32 total_num_bits =3D len * 8; + guint8 index; + + if (len <=3D 0 || buf =3D=3D NULL || addr =3D=3D NULL) + return FALSE; + + addr->digit_mode =3D (enum cdma_sms_digit_mode) + bit_field_unpack(buf, 0, 1); + bit_offset +=3D 1; + addr->number_mode =3D (guint8) bit_field_unpack(buf, bit_offset, 1); + bit_offset +=3D 1; + + if (addr->digit_mode =3D=3D CODE_8_BIT) { + addr->number_type =3D (guint8) + bit_field_unpack(buf, bit_offset, 3); + bit_offset +=3D 3; + + if (addr->number_mode =3D=3D 0) { + if (bit_offset + 4 > total_num_bits) + return FALSE; + + addr->number_plan =3D (enum cdma_sms_numbering_plan) + bit_field_unpack(buf, bit_offset, 4); + bit_offset +=3D 4; + } + } + + if ((bit_offset + 8) > total_num_bits) + return FALSE; + + addr->num_fields =3D (guint8) bit_field_unpack(buf, bit_offset, 8); + bit_offset +=3D 8; + + if (addr->digit_mode =3D=3D DTMF_4_BIT) + chari_len =3D 4; + else + chari_len =3D 8; + + if ((bit_offset + chari_len * addr->num_fields) > total_num_bits) + return FALSE; + + for (index =3D 0; index < addr->num_fields; index++) { + addr->address[index] =3D (char) bit_field_unpack(buf, + bit_offset, + chari_len); + bit_offset +=3D chari_len; + } + + return TRUE; +} + +char *cdma_sms_decode_text(struct cdma_sms_ud *ud) +{ + char *buf; + + if (ud =3D=3D NULL) + return NULL; + + /* TODO: Only support MSG_ENCODING_7BIT_ASCII currently */ + if (ud->msg_encoding !=3D MSG_ENCODING_7BIT_ASCII) + return NULL; + + buf =3D g_new(char, ud->num_fields + 1); + if (buf =3D=3D NULL) + return NULL; + + memcpy(buf, ud->chari, ud->num_fields); + buf[ud->num_fields] =3D 0; /* Make it NULL terminated string */ + + return buf; +} + +/* Decode User Data */ +static gboolean cdma_sms_decode_ud(const unsigned char *buf, int len, + struct cdma_sms_ud *ud) +{ + guint32 bit_offset =3D 0; + guint8 chari_len =3D 0; + guint32 total_num_bits =3D len * 8; + guint8 index; + enum cdma_sms_message_encoding msg_encoding; + + if (buf =3D=3D NULL || ud =3D=3D NULL) + return FALSE; + + if (total_num_bits < 13) + return FALSE; + + msg_encoding =3D (enum cdma_sms_message_encoding) + bit_field_unpack(buf, bit_offset, 5); + ud->msg_encoding =3D msg_encoding; + bit_offset +=3D 5; + + if (ud->msg_encoding =3D=3D MSG_ENCODING_EXTENDED_PROTOCOL_MSG || + ud->msg_encoding =3D=3D MSG_ENCODING_GSM_DATA_CODING) { + /* Skip message type field */ + /* TODO: Add support for message type field */ + bit_offset +=3D 8; + } + + if (bit_offset + 8 > total_num_bits) + return FALSE; + + ud->num_fields =3D (guint8) bit_field_unpack(buf, bit_offset, 8); + bit_offset +=3D 8; + + switch (msg_encoding) { + case MSG_ENCODING_OCTET: + chari_len =3D 8; + break; + case MSG_ENCODING_EXTENDED_PROTOCOL_MSG: + return FALSE; /* TODO */ + case MSG_ENCODING_7BIT_ASCII: + case MSG_ENCODING_IA5: + chari_len =3D 7; + break; + case MSG_ENCODING_UNICODE: + case MSG_ENCODING_SHIFT_JIS: + case MSG_ENCODING_KOREAN: + return FALSE; /* TODO */ + case MSG_ENCODING_LATIN_HEBREW: + case MSG_ENCODING_LATIN: + chari_len =3D 8; + break; + case MSG_ENCODING_GSM_7BIT: + chari_len =3D 7; + break; + case MSG_ENCODING_GSM_DATA_CODING: + return FALSE; /* TODO */ + } + + if (chari_len =3D=3D 0) + return FALSE; + + if (bit_offset + chari_len * ud->num_fields > total_num_bits) + return FALSE; + + for (index =3D 0; index < ud->num_fields; index++) { + ud->chari[index] =3D (guint8) bit_field_unpack(buf, + bit_offset, + chari_len); + bit_offset +=3D chari_len; + } + + return TRUE; +} + +/* Decode Message Identifier */ +static gboolean cdma_sms_decode_message_id(const unsigned char *buf, int l= en, + struct cdma_sms_identifier *id) +{ + guint32 bit_offset =3D 0; + + if (buf =3D=3D NULL || id =3D=3D NULL) + return FALSE; + + if (len !=3D 3) + return FALSE; + + id->msg_type =3D (enum cdma_sms_msg_type) + bit_field_unpack(buf, bit_offset, 4); + bit_offset +=3D 4; + id->msg_id =3D (guint16) bit_field_unpack(buf, bit_offset, 16); + bit_offset +=3D 16; + id->header_ind =3D (gboolean) bit_field_unpack(buf, bit_offset, 1); + + return TRUE; +} + +/* Decode Bearer Data */ +static gboolean cdma_sms_decode_bearer_data(const unsigned char *buf, int = len, + struct cdma_sms_bearer_data *bearer_data) +{ + gboolean ret =3D TRUE; + enum cdma_sms_subparam_id subparam_id; + guint8 subparam_len; + + if (buf =3D=3D NULL || bearer_data =3D=3D NULL) + return FALSE; + + while (len !=3D 0) { + + if (len < 2) + return FALSE; + + subparam_id =3D (enum cdma_sms_subparam_id) + bit_field_unpack(buf, 0, 8); + buf +=3D 1; + subparam_len =3D (guint8) bit_field_unpack(buf, 0, 8); + buf +=3D 1; + + len -=3D 2; + + if (len < subparam_len) + return FALSE; + + switch (subparam_id) { + case CDMA_SMS_SUBPARAM_ID_MESSAGE_ID: + ret =3D cdma_sms_decode_message_id(buf, subparam_len, + &bearer_data->id); + set_bitmap(&bearer_data->subparam_bitmap, + CDMA_SMS_SUBPARAM_ID_MESSAGE_ID); + break; + case CDMA_SMS_SUBPARAM_ID_USER_DATA: + ret =3D cdma_sms_decode_ud(buf, subparam_len, + &bearer_data->ud); + set_bitmap(&bearer_data->subparam_bitmap, + CDMA_SMS_SUBPARAM_ID_USER_DATA); + break; + 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: + /* + * TODO: Ignore any unsupported parameter. + * Also ignore any un-recognized parameter for + * future standard revision. + */ + break; + } + + if (ret =3D=3D FALSE) + return FALSE; + + len -=3D subparam_len; + buf +=3D subparam_len; + } + + return TRUE; +} + +static gboolean cdma_sms_p2p_decode(const unsigned char *pdu, int len, + struct cdma_sms *incoming) +{ + gboolean ret =3D TRUE; + enum cdma_sms_param_id rec_id; + guint8 rec_len; + + if (pdu =3D=3D NULL || incoming =3D=3D NULL) + return FALSE; + + while (len !=3D 0) { + + if (len <=3D 2) + return FALSE; + + rec_id =3D (enum cdma_sms_param_id) bit_field_unpack(pdu, 0, 8); + pdu +=3D 1; + rec_len =3D (guint8) bit_field_unpack(pdu, 0, 8); + pdu +=3D 1; + + len -=3D 2; + + if (len < rec_len) + return FALSE; + + switch (rec_id) { + case CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER: + incoming->p2p_msg.teleservice_id =3D + (enum cdma_sms_teleservice_id) + bit_field_unpack(pdu, 0, 16); + set_bitmap(&incoming->p2p_msg.param_bitmap, + CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER); + break; + case CDMA_SMS_PARAM_ID_SERVICE_CATEGORY: + break; /* TODO */ + case CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS: + ret =3D cdma_sms_decode_addr(pdu, rec_len, + &incoming->p2p_msg.oaddr); + set_bitmap(&incoming->p2p_msg.param_bitmap, + CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS); + break; + 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: + break; /* TODO */ + case CDMA_SMS_PARAM_ID_BEARER_DATA: + ret =3D cdma_sms_decode_bearer_data(pdu, rec_len, + &incoming->p2p_msg.bearer_data); + set_bitmap(&incoming->p2p_msg.param_bitmap, + CDMA_SMS_PARAM_ID_BEARER_DATA); + break; + } + + if (!ret) + return FALSE; + + len -=3D rec_len; + pdu +=3D rec_len; + } + + return TRUE; +} + +gboolean cdma_sms_decode(const unsigned char *pdu, int len, + struct cdma_sms *incoming) +{ + gboolean ret =3D FALSE; + + if ((len =3D=3D 0) || (pdu =3D=3D NULL) || (incoming =3D=3D NULL)) + return FALSE; + + incoming->type =3D (enum cdma_sms_tp_msg_type) + bit_field_unpack(pdu, 0, 8); + pdu +=3D 1; + len -=3D 1; + + switch (incoming->type) { + case CDMA_SMS_P2P: + ret =3D cdma_sms_p2p_decode(pdu, len, incoming); + break; + case CDMA_SMS_BCAST: + case CDMA_SMS_ACK: + /* TODO: Not supported yet */ + ret =3D FALSE; + break; + } + + return ret; +} diff --git a/src/cdma-smsutil.h b/src/cdma-smsutil.h new file mode 100644 index 0000000..bfe2abb --- /dev/null +++ b/src/cdma-smsutil.h @@ -0,0 +1,264 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2010 Nokia Corporation. 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 + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 U= SA + * + */ + +/* 3GPP2 C.S0015-B v2.0, Table 3.4-1 */ +enum cdma_sms_tp_msg_type { + CDMA_SMS_P2P =3D 0, + CDMA_SMS_BCAST =3D 1, + CDMA_SMS_ACK =3D 2 +}; + +/* 3GPP2 X.S0004-550-E, Section 2.256 */ +enum cdma_sms_teleservice_id { + TELESERVICE_CMT91 =3D 4096, + TELESERVICE_WPT =3D 4097, + TELESERVICE_WMT =3D 4098, + TELESERVICE_VMN =3D 4099, + TELESERVICE_WAP =3D 4100, + TELESERVICE_WEMT =3D 4101, + TELESERVICE_SCPT =3D 4102, + TELESERVICE_CATPT =3D 4103 +}; + +/* 3GPP2 C.S0005-E v2.0 Table 2.7.1.3.2.4-2 */ +enum cdma_sms_digi_number_type { + CDMA_SMS_NUM_TYPE_UNKNOWN =3D 0, + CDMA_SMS_NUM_TYPE_INTERNATIONAL_NUMBER =3D 1, + CDMA_SMS_NUM_TYPE_NATIONAL_NUMBER =3D 2, + CDMA_SMS_NUM_TYPE_NETWORK_SPECIFIC_NUMBER =3D 3, + CDMA_SMS_NUM_TYPE_SUBSCRIBER_NUMBER =3D 4, + /* Reserved 5 */ + CDMA_SMS_NUM_TYPE_ABBREVIATED_NUMBER =3D 6 + /* Reserved 7 */ +}; + +/* 3GPP2 C.S0015-B v2.0 Table 3.4.3.3-1 */ +enum cdma_sms_data_network_number_type { + CDMA_SMS_NETWORK_NUM_TYPE_UNKNOWN =3D 0, + CDMA_SMS_NETWORK_TYPE_INTERNET_PROTOCOL =3D 1, + CDMA_SMS_NETWORK_TYPE_INTERNET_EMAIL_ADDRESS =3D 2, + /* All Other Values Reserved */ +}; + +/* 3GPP2 C.S0005-E v2.0 Table 2.7.1.3.2.4-3 */ +enum cdma_sms_numbering_plan { + CDMA_SMS_NUMBERING_PLAN_UNKNOWN =3D 0, + CDMA_SMS_NUMBERING_PLAN_ISDN =3D 1, + CDMA_SMS_NUMBERING_PLAN_DATA =3D 3, + CDMA_SMS_NUMBERING_PLAN_TELEX =3D 4, + CDMA_SMS_NUMBERING_PLAN_PRIVATE =3D 9, + CDMA_SMS_NUMBERING_PLAN_RESERVED =3D 15 +}; + +/* 3GPP2 C.S0015-B v2.0 Table 4.5.1-1 */ +enum cdma_sms_msg_type { + CDMA_SMS_RESERVED =3D 0, + CDMA_SMS_DELIVER =3D 1, + CDMA_SMS_SUBMIT =3D 2, + CDMA_SMS_CANCEL =3D 3, + CDMA_SMS_DELIVER_ACK =3D 4, + CDMA_SMS_USER_ACK =3D 5, + CDMA_SMS_READ_ACK =3D 6, +}; + +/* C.R1001-G_v1.0 Table 9.1-1 */ +enum cdma_sms_message_encoding { + MSG_ENCODING_OCTET =3D 0, + MSG_ENCODING_EXTENDED_PROTOCOL_MSG =3D 1, + MSG_ENCODING_7BIT_ASCII =3D 2, + MSG_ENCODING_IA5 =3D 3, + MSG_ENCODING_UNICODE =3D 4, + MSG_ENCODING_SHIFT_JIS =3D 5, + MSG_ENCODING_KOREAN =3D 6, + MSG_ENCODING_LATIN_HEBREW =3D 7, + MSG_ENCODING_LATIN =3D 8, + MSG_ENCODING_GSM_7BIT =3D 9, + MSG_ENCODING_GSM_DATA_CODING =3D 10 +}; + +/* 3GPP2 C.S0015-B v2.0 Table 3.4.3-1 */ +enum cdma_sms_param_id { + CDMA_SMS_PARAM_ID_TELESERVICE_IDENTIFIER =3D 0x00, + CDMA_SMS_PARAM_ID_SERVICE_CATEGORY =3D 0x01, + CDMA_SMS_PARAM_ID_ORIGINATING_ADDRESS =3D 0x02, + CDMA_SMS_PARAM_ID_ORIGINATING_SUBADDRESS =3D 0x03, + CDMA_SMS_PARAM_ID_DESTINATION_ADDRESS =3D 0x04, + CDMA_SMS_PARAM_ID_DESTINATION_SUBADDRESS =3D 0x05, + CDMA_SMS_PARAM_ID_BEARER_REPLY_OPTION =3D 0x06, + CDMA_SMS_PARAM_ID_CAUSE_CODE =3D 0x07, + CDMA_SMS_PARAM_ID_BEARER_DATA =3D 0x08 +}; + +/* 3GPP2 C.S0015-B v2.0 Table 4.5-1 */ +enum cdma_sms_subparam_id { + CDMA_SMS_SUBPARAM_ID_MESSAGE_ID =3D 0x00, + CDMA_SMS_SUBPARAM_ID_USER_DATA =3D 0x01, + CDMA_SMS_SUBPARAM_ID_USER_RESPONSE_CODE =3D 0x02, + CDMA_SMS_SUBPARAM_ID_MC_TIME_STAMP =3D 0x03, + CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_ABSOLUTE =3D 0x04, + CDMA_SMS_SUBPARAM_ID_VALIDITY_PERIOD_RELATIVE =3D 0x05, + CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_ABSOLUTE =3D 0x06, + CDMA_SMS_SUBPARAM_ID_DEFERRED_DELIVERY_TIME_RELATIVE =3D 0x07, + CDMA_SMS_SUBPARAM_ID_PRIORITY_INDICATOR =3D 0x08, + CDMA_SMS_SUBPARAM_ID_PRIVACY_INDICATOR =3D 0x09, + CDMA_SMS_SUBPARAM_ID_REPLY_OPTION =3D 0x0A, + CDMA_SMS_SUBPARAM_ID_NUMBER_OF_MESSAGES =3D 0x0B, + CDMA_SMS_SUBPARAM_ID_ALERT_ON_MESSAGE_DELIVERY =3D 0x0C, + CDMA_SMS_SUBPARAM_ID_LANGUAGE_INDICATOR =3D 0x0D, + CDMA_SMS_SUBPARAM_ID_CALL_BACK_NUMBER =3D 0x0E, + CDMA_SMS_SUBPARAM_ID_MESSAGE_DISPLAY_MODE =3D 0x0F, + CDMA_SMS_SUBPARAM_ID_MULTIPLE_ENCODING_USER_DATA =3D 0x10, + CDMA_SMS_SUBPARAM_ID_MESSAGE_DEPOSIT_INDEX =3D 0x11, + CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_DATA =3D 0x12, + CDMA_SMS_SUBPARAM_ID_SERVICE_CATEGORY_PROGRAM_RESULT =3D 0x13, + CDMA_SMS_SUBPARAM_ID_MESSAGE_STATUS =3D 0x14, + CDMA_SMS_SUBPARAM_ID_TP_FAILURE_CAUSE =3D 0x15, + CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN =3D 0x16, + CDMA_SMS_SUBPARAM_ID_ENHANCED_VMN_ACK =3D 0x17 +}; + +/* 3GPP2 C.R1001-G Table 9.3.1-1 */ +enum cdma_sms_service_category { + SERVICE_CAT_EMERGENCY_BROADCAST =3D 1, + SERVICE_CAT_ADMINISTRATIVE =3D 2, + SERVICE_CAT_MAINTENANCE =3D 3, + SERVICE_CAT_GENERALNEWSLOCAL =3D 4, + SERVICE_CAT_GENERALNEWSREGIONAL =3D 5, + SERVICE_CAT_GENERALNEWSNATIONAL =3D 6, + SERVICE_CAT_GENERALNEWSINTERNATIONAL =3D 7, + SERVICE_CAT_BUSINESSFINALNEWSLOCAL =3D 8, + SERVICE_CAT_BUSINESSFINALNEWSREGIONAL =3D 9, + SERVICE_CAT_BUSINESSFINALNEWSNATIONAL =3D 10, + SERVICE_CAT_BUSINESSFINALNEWSINTNL =3D 11, + SERVICE_CAT_SPORTSNEWSLOCAL =3D 12, + SERVICE_CAT_SPORTSNEWSREGIONAL =3D 13, + SERVICE_CAT_SPORTSNEWSNATIONAL =3D 14, + SERVICE_CAT_SPORTSNEWSINTERNATIONAL =3D 15, + SERVICE_CAT_ENTERTAINMENTNEWSLOCAL =3D 16, + SERVICE_CAT_ENTERTAINMENTNEWSREGIONAL =3D 17, + SERVICE_CAT_ENTERTAINMENTNEWSNATIONAL =3D 18, + SERVICE_CAT_ENTERTAINMENTNEWSINTERNATIONAL =3D 19, + SERVICE_CAT_ENTERTAINMENTNEWSLOCALWEATHER =3D 20, + SERVICE_CAT_AREATRAFFICREPORTS =3D 21, + SERVICE_CAT_LOCALAIRTPORTFLIGHTSCHEDULES =3D 22, + SERVICE_CAT_RESTURANTS =3D 23, + SERVICE_CAT_LODGINGS =3D 24, + SERVICE_CAT_RETAILDIRECTORYADVERTISEMENTS =3D 25, + SERVICE_CAT_ADVERTISEMENTS =3D 26, + SERVICE_CAT_STOCKQUOTES =3D 27, + SERVICE_CAT_EMPLOYMENTOPPORTUNITIES =3D 28, + SERVICE_CAT_MEDICALHEALTHHOSPITALS =3D 29, + SERVICE_CAT_TECHNOLOGYNEWS =3D 30, + SERVICE_CAT_MULTICATEGORY =3D 31, + SERVICE_CAT_CAPT =3D 32 +}; + +enum cdma_sms_digit_mode { + DTMF_4_BIT =3D 0, + CODE_8_BIT =3D 1 +}; + +/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.3 */ +struct cdma_sms_address { + enum cdma_sms_digit_mode digit_mode; + guint8 number_mode; + guint8 number_type; + enum cdma_sms_numbering_plan number_plan; + guint8 num_fields; + char address[256]; +}; + +/* 3GPP2 C.S0015-B v2.0 Section 3.4.3.6 */ +struct cdma_sms_cause_code { + guint8 reply_seq; + guint8 error_class; + guint8 cause_code; +}; + +/* 3GPP2 C.S0015-B v2.0 Section 4.5.1 */ +struct cdma_sms_identifier { + enum cdma_sms_msg_type msg_type; + guint16 msg_id; + gboolean header_ind; +}; + +/* 3GPP2 C.S0015-B v2.0 Section 4.5.2 */ +struct cdma_sms_ud { + enum cdma_sms_message_encoding msg_encoding; + guint8 num_fields; + guint8 chari[512]; +}; + +/* 3GPP2 C.S0015-B v2.0 Section 4.5 */ +struct cdma_sms_bearer_data { + guint32 subparam_bitmap; + struct cdma_sms_identifier id; + struct cdma_sms_ud ud; +}; + +/* 3GPP2 C.S0015-B v2.0 Table 3.4.2.1-1. */ +struct cdma_sms_p2p_msg { + guint32 param_bitmap; + enum cdma_sms_teleservice_id teleservice_id; + struct cdma_sms_address oaddr; + struct cdma_sms_bearer_data bearer_data; +}; + +/* 3GPP2 C.S0015-B v2.0 Table 3.4.2.2-1 */ +struct cdma_sms_broadcast_msg { + enum cdma_sms_service_category service_category; + struct cdma_sms_bearer_data bearer_data; +}; + +/* 3GPP2 C.S0015-B v2.0 Table 3.4.2.3-1 */ +struct cdma_sms_ack_msg { + struct cdma_sms_address daddr; + struct cdma_sms_cause_code cause_code; +}; + +/* 3GPP2 C.S0015-B v2.0 Section 3.4.1 */ +struct cdma_sms { + enum cdma_sms_tp_msg_type type; + union { + struct cdma_sms_p2p_msg p2p_msg; + struct cdma_sms_broadcast_msg broadcast_msg; + struct cdma_sms_ack_msg ack_msg; + }; +}; + +static inline gboolean check_bitmap(guint32 bitmap, guint32 pos) +{ + guint32 mask =3D 0x1 << pos; + return bitmap & mask ? TRUE : FALSE; +} + +static inline void set_bitmap(guint32 *bitmap, guint32 pos) +{ + if (bitmap =3D=3D NULL) + return; + + *bitmap =3D *bitmap | (1 << pos); +} + +gboolean cdma_sms_decode(const unsigned char *pdu, int len, + struct cdma_sms *out); +char *cdma_sms_decode_text(struct cdma_sms_ud *ud); +char *cdma_sms_address_to_string(const struct cdma_sms_address *addr); -- = 1.7.0.4 --===============8101587677430499073==--