FreeCalypso > hg > fc-magnetite
view src/aci2/aci/cmh_smsf.c @ 232:cbee8f31694a
l1_rf12.c: rf_850 Tx calchan bogon fixed
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 12 Mar 2017 20:58:28 +0000 |
parents | 93999a60b835 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS (6147) | Modul : CMH_SMSF +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module defines the functions used by the command | handler for the short message service. +----------------------------------------------------------------------------- */ #ifndef CMH_SMSF_C #define CMH_SMSF_C #endif #include "aci_all.h" /*==== INCLUDES ===================================================*/ #include "aci_cmh.h" #include "ati_cmd.h" #include "aci_cmd.h" #ifdef FAX_AND_DATA #include "aci_fd.h" #endif /* of #ifdef FAX_AND_DATA */ #include "aci.h" #include "aci_lst.h" #include "aci_mem.h" #include "psa.h" #include "psa_cc.h" #ifdef SIM_TOOLKIT #include "psa_sat.h" #endif #include "psa_sms.h" #include "psa_sim.h" #include "psa_mmi.h" #include "psa_util.h" #include "phb.h" #include "cmh.h" #include "cmh_sms.h" #include "pcm.h" #include "aci_lst.h" #if (defined (MFW) AND !defined (FF_MMI_RIV)) OR defined (_CONC_TESTING_) #include "conc_sms.h" #endif /* ##if (defined (MFW) AND !defined (FF_MMI_RIV)) OR defined (_CONC_TESTING_)*/ #ifdef UART #include "dti_conn_mng.h" #endif #include "cmh_sim.h" #ifndef _SIMULATION_ /* temporary solution to get ffs.h included without GPRS to be set ! */ #ifdef GPRS #include "ffs/ffs.h" #else #include "ffs/ffs.h" #undef GPRS #endif /* GPRS */ #include "ffs_coat.h" #endif /* !_SIMULATION_ */ #ifdef FF_CPHS #include "cphs.h" #endif /* FF_CPHS */ /*==== CONSTANTS ==================================================*/ #define SMS_CMH_YEAR_MAX (99) /* maximum value for year in */ /* absolute validity period */ #define SMS_CMH_YEAR_MIN (0) /* minimum value for year in */ /* absolute validity period */ #define SMS_CMH_MONTH_MAX (12) /* maximum value for month in */ /* absolute validity period */ #define SMS_CMH_MONTH_MIN (1) /* minimum value for month in */ /* absolute validity period */ #define SMS_CMH_DAY_MAX (31) /* maximum value for day in */ /* absolute validity period */ #define SMS_CMH_DAY_MIN (1) /* minimum value for day in */ /* absolute validity period */ #define SMS_CMH_HOUR_MAX (23) /* maximum value for hour in */ /* absolute validity period */ #define SMS_CMH_HOUR_MIN (0) /* minimum value for hour in */ /* absolute validity period */ #define SMS_CMH_MINUTE_MAX (59) /* maximum value for minute in */ /* absolute validity period */ #define SMS_CMH_MINUTE_MIN (0) /* minimum value for minute in */ /* absolute validity period */ #define SMS_CMH_SECOND_MAX (59) /* maximum value for second in */ /* absolute validity period */ #define SMS_CMH_SECOND_MIN (0) /* minimum value for second in */ /* absolute validity period */ #define SMS_CMH_TZ_MAX (47) /* maximum value for a time */ /* zone in absolute validity */ /* period */ #define SMS_CMH_TZ_MIN (-47) /* minimum value for a time */ /* zone in absolute validity */ /* period */ /* macro for converting a two digit BCD into an UBYTE */ #define BCD2UBYTE(bcd) (UBYTE)(10 * bcd[0] + bcd[1]) /* macro for testing whether any digit of a two digit */ /* BCD lies outside of a predefined value range */ #define NOTBCD(bcd) (bcd[0] > 9 OR\ bcd[1] > 9 ) #define L_MAX_UD 140 #define L_MAX_UD_CONC 134 /*==== TYPES ======================================================*/ /*==== EXPORT =====================================================*/ EXTERN T_ACI_LIST *set_prm_list; /*==== VARIABLES ==================================================*/ const char * const ffs_smsprfl_fname[] = { FFS_SMSPRFL_FNAME01, FFS_SMSPRFL_FNAME02, FFS_SMSPRFL_FNAME03, FFS_SMSPRFL_FNAME04 }; /*==== FUNCTIONS ==================================================*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : ACI_CMD | | STATE : code ROUTINE : aci_encodeVpenh | +--------------------------------------------------------------------+ PURPOSE : This function encodes a given T_ACI_VP_ENH type to a string. */ GLOBAL void aci_encodeVpenh ( CHAR* vpenh_str, T_ACI_VP_ENH* vpenh ) { UBYTE pos; /* functionality indicator */ utl_binToHex (&vpenh->func_ind, 1, vpenh_str); pos = 2; /* extension octet */ if (vpenh->func_ind & TP_VPF_ENH_EXT_BIT_MASK) { utl_binToHex (&vpenh->ext_oct, 1, vpenh_str+pos); pos += 2; } /* process validity period values */ if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_REL) { utl_binToHex (&vpenh->val.vpenh_relative, 1, vpenh_str+pos ); pos += 2; } else if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_SEC) { utl_binToHex (&vpenh->val.vpenh_seconds, 1, vpenh_str+pos ); pos += 2; } else if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_HRS) { vpenh_str[pos++] = vpenh->val.vpenh_hours.hour[1] + '0'; vpenh_str[pos++] = vpenh->val.vpenh_hours.hour[0] + '0'; vpenh_str[pos++] = vpenh->val.vpenh_hours.minute[1] + '0'; vpenh_str[pos++] = vpenh->val.vpenh_hours.minute[0] + '0'; vpenh_str[pos++] = vpenh->val.vpenh_hours.second[1] + '0'; vpenh_str[pos++] = vpenh->val.vpenh_hours.second[0] + '0'; } /* fill the rest with zeros */ while (pos < 14) { vpenh_str[pos++] = '0'; } /* string terminator */ vpenh_str[pos] = '\0'; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getNType | +-------------------------------------------------------------------+ PURPOSE : This function calculates the 'numbering type' out of the current 'type of numbering'. */ GLOBAL UBYTE cmhSMS_getNType ( T_ACI_TOA_TON ton ) { switch( ton ) { case( TON_International ): case( TON_National ): case( TON_NetSpecific ): case( TON_DedAccess ): case( TON_Alphanumeric ): case( TON_Abbreviated ): return (UBYTE)ton; default: return SMS_TON_UNKNOWN; } } GLOBAL BOOL cmhSMS_findPrflId ( UBYTE critrerium, void* elem ) { T_SMS_SET_PRM *compared = (T_SMS_SET_PRM*)elem; if ( compared->prflId == critrerium ) return TRUE; else return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getTon | +-------------------------------------------------------------------+ PURPOSE : This function calculates the 'type of numbering' out of the current 'numbering type'. */ GLOBAL T_ACI_TOA_TON cmhSMS_getTon ( UBYTE ntype ) { switch( ntype ) { case( SMS_TON_UNKNOWN ): case( SMS_TON_INTERNATIONAL ): case( SMS_TON_NATIONAL ): case( SMS_TON_NETWORK_SPEC ): case( SMS_TON_SUBSCRIBER ): case( SMS_TON_ALPHANUMERIC ): case( SMS_TON_ABBREVIATED ): return (T_ACI_TOA_TON)ntype; default: return TON_NotPresent; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getNPlan | +-------------------------------------------------------------------+ PURPOSE : This function calculates the 'numbering plan' out of the current 'numbering plan identification'. */ GLOBAL UBYTE cmhSMS_getNPlan ( T_ACI_TOA_NPI npi ) { switch( npi ) { case( NPI_IsdnTelephony ): case( NPI_Data ): case( NPI_Telex ): case( NPI_National ): case( NPI_Private ): return (UBYTE)npi; default: return NPI_Unknown; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getNpi | +-------------------------------------------------------------------+ PURPOSE : This function calculates the 'numbering plan identification' out of the current 'numbering plan'. */ GLOBAL T_ACI_TOA_NPI cmhSMS_getNpi ( UBYTE nplan ) { switch( nplan ) { case( SMS_TON_UNKNOWN ): case( SMS_NPI_ISDN ): case( SMS_NPI_X121 ): case( SMS_NPI_F69 ): case( SMS_NPI_NATIONAL ): case( SMS_NPI_PRIVATE ): return (T_ACI_TOA_NPI)nplan; default: return NPI_NotPresent; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getStatCmh | +-------------------------------------------------------------------+ PURPOSE : This function converts the message status from PSA type to CMH type. */ GLOBAL void cmhSMS_getStatCmh ( UBYTE inStat, T_ACI_SMS_STAT* outStat ) { switch( inStat & STAT_MASK ) { case( REC_UNREAD ): *outStat = SMS_STAT_RecUnread; break; case( REC_READ ): *outStat = SMS_STAT_RecRead; break; case( STO_UNSENT ): *outStat = SMS_STAT_StoUnsent; break; case( STO_SENT ): *outStat = SMS_STAT_StoSent; break; default: *outStat = SMS_STAT_NotPresent; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getStatPsa | +-------------------------------------------------------------------+ PURPOSE : This function converts the message status from CMH type to PSA type. */ GLOBAL BOOL cmhSMS_getStatPsa ( T_ACI_SMS_STAT inStat, UBYTE* outStat ) { switch( inStat ) { case( SMS_STAT_RecUnread ): *outStat = REC_UNREAD; break; case( SMS_STAT_RecRead ): *outStat = REC_READ; break; case( SMS_STAT_StoUnsent ): *outStat = STO_UNSENT; break; case( SMS_STAT_StoSent ): *outStat = STO_SENT; break; default : return (FALSE); } return ( TRUE ); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_isVpabsVld | +-------------------------------------------------------------------+ PURPOSE : This function is used to process whether the given absolute validity period is valid. Note: This function checks whether every individual time value is within a valid range. It does not check whether the whole expression is valid. */ GLOBAL BOOL cmhSMS_isVpabsVld ( T_ACI_VP_ABS* vpabs ) { if ( BCD2UBYTE ( vpabs -> year ) > SMS_CMH_YEAR_MAX OR BCD2UBYTE ( vpabs -> month ) < SMS_CMH_MONTH_MIN OR BCD2UBYTE ( vpabs -> month ) > SMS_CMH_MONTH_MAX OR BCD2UBYTE ( vpabs -> day ) < SMS_CMH_DAY_MIN OR BCD2UBYTE ( vpabs -> day ) > SMS_CMH_DAY_MAX OR BCD2UBYTE ( vpabs -> hour ) > SMS_CMH_HOUR_MAX OR BCD2UBYTE ( vpabs -> minute ) > SMS_CMH_MINUTE_MAX OR BCD2UBYTE ( vpabs -> second ) > SMS_CMH_SECOND_MAX OR vpabs -> timezone < SMS_CMH_TZ_MIN OR vpabs -> timezone > SMS_CMH_TZ_MAX OR NOTBCD ( vpabs -> year ) OR NOTBCD ( vpabs -> month ) OR NOTBCD ( vpabs -> day ) OR NOTBCD ( vpabs -> hour ) OR NOTBCD ( vpabs -> minute ) OR NOTBCD ( vpabs -> second ) ) return ( FALSE ); return ( TRUE ); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_isVpenhVld | +-------------------------------------------------------------------+ PURPOSE : This function is used to process whether the given enhanced validity period is valid. Note: This function checks whether every individual time value is within a valid range. It does not check whether the whole expression is valid. */ GLOBAL BOOL cmhSMS_isVpenhVld ( T_ACI_VP_ENH* vpenh ) { if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) > TP_VPF_ENH_HRS) { return FALSE; } if ((vpenh->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_HRS) { if ( BCD2UBYTE ( vpenh->val.vpenh_hours.minute ) > SMS_CMH_MINUTE_MAX OR BCD2UBYTE ( vpenh->val.vpenh_hours.second ) > SMS_CMH_SECOND_MAX OR NOTBCD ( vpenh->val.vpenh_hours.hour ) OR NOTBCD ( vpenh->val.vpenh_hours.minute ) OR NOTBCD ( vpenh->val.vpenh_hours.second ) ) { return ( FALSE ); } } return ( TRUE ); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setVpabsPsa | +-------------------------------------------------------------------+ PURPOSE : This function is used to copy the elements of the absolute validity period structure of the ACI to the corresponding structure of the PSA. Note: Copying of the structure elements might be dangerous when array size of time elements differ from MAX_VP_ABS_DIGIT due to changes in PSA declaration. */ GLOBAL void cmhSMS_setVpabsPsa ( T_tp_vp_abs* psaVp, T_ACI_VP_ABS* cmhVp ) { USHORT i; /* used for counting */ BOOL isNegative = ( cmhVp->timezone & 0x8000 ); SHORT tz = ( UBYTE ) cmhVp->timezone; for (i = 0; i < MAX_VP_ABS_DIGITS; i++) { psaVp -> year [i] = cmhVp -> year [i]; psaVp -> month [i] = cmhVp -> month [i]; psaVp -> day [i] = cmhVp -> day [i]; psaVp -> hour [i] = cmhVp -> hour [i]; psaVp -> minute[i] = cmhVp -> minute[i]; psaVp -> second[i] = cmhVp -> second[i]; } if ( isNegative ) { tz = -tz; psaVp -> tz_sign = 1; } else { psaVp -> tz_sign = 0; } psaVp -> tz_lsb = tz & 0x000F; psaVp -> tz_msb = tz & 0x00F0; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setVpenhPsa | +-------------------------------------------------------------------+ PURPOSE : This function is used to copy the elements of the enhanced validity period structure of the ACI to the corresponding structure of the PSA. */ GLOBAL void cmhSMS_setVpenhPsa ( T_tp_vp_enh* psaVp, T_ACI_VP_ENH* cmhVp ) { memset(psaVp, 0, sizeof(T_tp_vp_enh)); if (cmhVp->func_ind & TP_VPF_ENH_EXT_BIT_MASK) { psaVp->tp_ext = SMS_EXT_INCLUDED; psaVp->v_tp_rsrvd = 1; psaVp->tp_rsrvd = cmhVp->ext_oct; } if (cmhVp->func_ind & TP_VPF_ENH_SINGLE_SHOT_MASK) { psaVp->tp_ss = SMS_SS_SET; } if ((cmhVp->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_NOT_PRESENT) { psaVp->tvpf = SMS_TVPF_NOT_PRESENT; } else if ((cmhVp->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_REL) { psaVp->tvpf = SMS_TVPF_RELATIVE; psaVp->v_tp_vp_rel = 1; psaVp->tp_vp_rel = cmhVp->val.vpenh_relative; } else if ((cmhVp->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_SEC) { psaVp->tvpf = SMS_TVPF_SECONDS; psaVp->v_tp_vp_sec = 1; psaVp->tp_vp_sec = cmhVp->val.vpenh_seconds; } else if ((cmhVp->func_ind & TP_VPF_ENH_FORMAT_MASK) EQ TP_VPF_ENH_HRS) { psaVp->tvpf = SMS_TVPF_HOURS; psaVp->v_hour = 1; psaVp->hour[0] = cmhVp->val.vpenh_hours.hour[0]; psaVp->hour[1] = cmhVp->val.vpenh_hours.hour[1]; psaVp->v_minute = 1; psaVp->minute[0] = cmhVp->val.vpenh_hours.minute[0]; psaVp->minute[1] = cmhVp->val.vpenh_hours.minute[1]; psaVp->v_second = 1; psaVp->second[0] = cmhVp->val.vpenh_hours.second[0]; psaVp->second[1] = cmhVp->val.vpenh_hours.second[1]; } else { TRACE_EVENT("[ERR] cmhSMS_setVpenhPsa: wrong type of validity period format"); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setVpabsCmh | +-------------------------------------------------------------------+ PURPOSE : This function is used to copy the elements of the absolute validity period structure of the PSA to the corresponding structure of the ACI. Note: Copying of the structure elements might be dangerous when array size of time elements differ from MAX_VP_ABS_DIGIT due to changes in PSA declaration. */ GLOBAL void cmhSMS_setVpabsCmh ( T_ACI_VP_ABS* cmhVp, T_tp_vp_abs* psaVp ) { USHORT i; /* used for counting */ SHORT tz; for (i = 0; i < MAX_VP_ABS_DIGITS; i++) { cmhVp -> year [i] = psaVp -> year [i]; cmhVp -> month [i] = psaVp -> month [i]; cmhVp -> day [i] = psaVp -> day [i]; cmhVp -> hour [i] = psaVp -> hour [i]; cmhVp -> minute[i] = psaVp -> minute[i]; cmhVp -> second[i] = psaVp -> second[i]; } tz = ((psaVp->tz_msb & 0x07) * 10) + psaVp->tz_lsb; /* BCD */ if (psaVp->tz_sign) cmhVp -> timezone = -tz; else cmhVp -> timezone = tz; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setVpenhCmh | +-------------------------------------------------------------------+ PURPOSE : This function is used to copy the elements of the enhanced validity period structure of the PSA to the corresponding structure of the ACI. */ GLOBAL void cmhSMS_setVpenhCmh ( T_ACI_VP_ENH* cmhVp, T_tp_vp_enh* psaVp ) { memset(cmhVp, 0, sizeof(T_ACI_VP_ENH)); cmhVp->func_ind = psaVp->tvpf; if ((psaVp->tp_ext EQ SMS_EXT_INCLUDED) AND (psaVp->v_tp_rsrvd)) { cmhVp->func_ind |= TP_VPF_ENH_EXT_BIT_MASK; cmhVp->ext_oct = psaVp->tp_rsrvd; } if (psaVp->tp_ss EQ SMS_SS_SET) { cmhVp->func_ind |= TP_VPF_ENH_SINGLE_SHOT_MASK; } if (psaVp->tvpf EQ SMS_TVPF_NOT_PRESENT) { /* do nothing */ } else if ((psaVp->tvpf EQ SMS_TVPF_RELATIVE) AND (psaVp->v_tp_vp_rel)) { cmhVp->val.vpenh_relative = psaVp->tp_vp_rel; } else if ((psaVp->tvpf EQ SMS_TVPF_SECONDS) AND (psaVp->v_tp_vp_sec)) { cmhVp->val.vpenh_seconds = psaVp->tp_vp_sec; } else if (psaVp->tvpf EQ SMS_TVPF_HOURS) { if (psaVp->v_hour) { cmhVp->val.vpenh_hours.hour[0] = psaVp->hour[0]; cmhVp->val.vpenh_hours.hour[1] = psaVp->hour[1]; } if (psaVp->v_minute) { cmhVp->val.vpenh_hours.minute[0] = psaVp->minute[0]; cmhVp->val.vpenh_hours.minute[1] = psaVp->minute[1]; } if (psaVp->v_second) { cmhVp->val.vpenh_hours.second[0] = psaVp->second[0]; cmhVp->val.vpenh_hours.second[1] = psaVp->second[1]; } } else { TRACE_EVENT("[ERR] cmhSMS_setVpenhCmh: wrong type of validity period format"); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getAdrStr | +--------------------------------------------------------------------+ PURPOSE : This function is used to convert the service center address in BCD to the service center address as a string. */ GLOBAL UBYTE cmhSMS_getAdrStr ( CHAR* pStr, UBYTE maxIdx, UBYTE* pBcd, UBYTE numDigits ) { UBYTE bcdIdx; UBYTE strIdx = 0; memset(pStr, 0x00, maxIdx); for(bcdIdx = 0; bcdIdx < numDigits AND strIdx < maxIdx; bcdIdx++) { switch (pBcd[bcdIdx]) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: pStr[strIdx++] = pBcd[bcdIdx] + '0'; break; case BCD_ASTSK: pStr[strIdx++] = '*'; break; case BCD_PND: pStr[strIdx++] = '#'; break; case BCD_A: pStr[strIdx++] = 'A'; break; case BCD_B: pStr[strIdx++] = 'B'; break; case BCD_C: pStr[strIdx++] = 'C'; break; } } pStr[strIdx] = '\0'; return ( strIdx ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getAdrBcd | +--------------------------------------------------------------------+ PURPOSE : This function is used to convert the service center address as a string to the service center address in BCD. */ GLOBAL void cmhSMS_getAdrBcd ( UBYTE* pBcd, UBYTE* pNumDigits, UBYTE maxDigits, CHAR* pStr ) { UBYTE bcdIdx = 0; UBYTE strIdx; for(strIdx = 0; bcdIdx < maxDigits AND pStr[strIdx] NEQ '\0'; strIdx++) { switch (pStr[strIdx]) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': pBcd[bcdIdx++] = pStr[strIdx] - '0'; break; case '*': pBcd[bcdIdx++] = BCD_ASTSK; break; case '#': pBcd[bcdIdx++] = BCD_PND; break; case 'A': pBcd[bcdIdx++] = BCD_A; break; case 'B': pBcd[bcdIdx++] = BCD_B; break; case 'C': pBcd[bcdIdx++] = BCD_C; break; } } *pNumDigits = bcdIdx; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getMemCmh | +-------------------------------------------------------------------+ PURPOSE : This function converts the preferred memory from PSA type to CMH type. */ GLOBAL void cmhSMS_getMemCmh ( UBYTE inMem, T_ACI_SMS_STOR* outMem ) { switch( inMem ) { case( MEM_ME ): *outMem = SMS_STOR_Me; break; case( MEM_SM ): *outMem = SMS_STOR_Sm; break; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getMemPsa | +-------------------------------------------------------------------+ PURPOSE : This function converts the preferred memory from CMH type to PSA type. returns: TRUE if conversion was successfull, otherwise FALSE */ GLOBAL BOOL cmhSMS_getMemPsa ( T_ACI_SMS_STOR inMem, UBYTE* outMem ) { switch( inMem ) { case( SMS_STOR_Me ): *outMem = MEM_ME; break; case( SMS_STOR_Sm ): *outMem = MEM_SM; break; default : return ( FALSE ); } return ( TRUE ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getAlphabetPp | +--------------------------------------------------------------------+ PURPOSE : This function is used to extract the used alphabet out of the data coding scheme for point-to-point SMS. */ GLOBAL UBYTE cmhSMS_getAlphabetPp ( UBYTE dcs ) { UBYTE alphabet = 0; /* means 7 bit default alphabet */ switch (dcs & 0xF0) { case( 0x30 ): case( 0x20 ): alphabet = 0x01; /* compressed, counts as 8 bit data */ break; case( 0x10 ): case( 0x00 ): alphabet = (dcs & 0x0C) >> 2; if (alphabet EQ 3) alphabet = 0; /* reserved coding */ break; case( 0xE0 ): alphabet = 0x02; /* UCS2 */ break; case( 0xF0 ): alphabet = (dcs & 0x04) >> 2; break; } return alphabet; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_expdSmsPp | +-------------------------------------------------------------------+ PURPOSE : This function expands a point-to-point SMS from 7 to 8 bit. */ GLOBAL void cmhSMS_expdSmsPp ( UBYTE byte_offset, UBYTE dcs, UBYTE* source, UBYTE source_len, UBYTE* dest, UBYTE* dest_len ) { UBYTE alphabet; UBYTE bit_offset = 0; TRACE_FUNCTION ("cmhSMS_expdSmsPp ()"); alphabet = cmhSMS_getAlphabetPp ( dcs ); switch (alphabet) { case( 0 ): /* 7 bit alphabet */ if ( byte_offset % 7 NEQ 0 ) { bit_offset = 7 - ((byte_offset*8) % 7); } *dest_len = source_len - ((byte_offset*8+6)/7); /* adjust byte_offset to septets */ /* In 7-Bit mode we get number of septets but we need octets */ source_len = (source_len*7+7)/8; /* round up to next octet*/ source_len -= byte_offset; utl_cvt7To8 ( source, source_len, dest, bit_offset); break; default: /* 8 bit alphabet, UCS2, reserved */ *dest_len = source_len-byte_offset; memcpy ( (CHAR*) dest, (CHAR*)source, *dest_len ); break; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_rdcSmsPp | +-------------------------------------------------------------------+ PURPOSE : This function reduces a point-to-point SMS from 8 to 7 bit. */ GLOBAL void cmhSMS_rdcSmsPp ( UBYTE byte_offset, UBYTE dcs, UBYTE* source, UBYTE source_len, UBYTE* dest, UBYTE* dest_len ) { UBYTE data_len; UBYTE alphabet; UBYTE bit_offset = 0; TRACE_FUNCTION ("cmhSMS_rdcSmsPp ()"); if (source_len EQ 0) { *dest_len = source_len; return; } alphabet = cmhSMS_getAlphabetPp ( dcs ); switch (alphabet) { case( 0 ): /* 7 bit alphabet */ if ( byte_offset % 7 NEQ 0 ) { bit_offset = 7 - ((byte_offset*8) % 7); } data_len = MINIMUM (source_len, (SMS_MSG_LEN * 8) / 7); data_len = utl_cvt8To7 ( source, data_len, dest, bit_offset ); break; default: /* 8 bit alphabet, UCS2, reserved */ data_len = MINIMUM ( source_len, SMS_MSG_LEN ); memcpy ( ( CHAR * ) dest, ( CHAR * ) source, data_len ); break; } *dest_len = data_len; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMF_SMSF | | STATE : code ROUTINE : cmhSMS_getAlphabetCb | +--------------------------------------------------------------------+ PURPOSE : This function is used to extract the used alphabet out of the data coding scheme for cell broadcast SMS. */ GLOBAL UBYTE cmhSMS_getAlphabetCb ( UBYTE dcs ) { UBYTE alphabet = 0; /* means 7 bit default alphabet */ switch (dcs & 0xF0) { case( 0x10 ): if (dcs EQ 0x11) alphabet = 2; break; case( 0x70 ): case( 0x60 ): case( 0x50 ): case( 0x40 ): alphabet = (dcs & 0x0C) >> 2; /* According to 03.38, "Any reserved codings shall be assumed * to be the GSM 7 bit default alphabet by a receiving entity". */ if (alphabet EQ 3) alphabet = 0; break; case( 0xF0 ): alphabet = (dcs & 0x04) >> 2; break; } return alphabet; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_expdSmsCb | +--------------------------------------------------------------------+ PURPOSE : This function expands a cell broadcast SMS from 7 to 8 bit. */ GLOBAL void cmhSMS_expdSmsCb ( UBYTE dcs, UBYTE *source, UBYTE source_len, UBYTE *dest, UBYTE *dest_len ) { UBYTE alphabet; TRACE_FUNCTION ("cmhSMS_expdSmsCb()"); alphabet = cmhSMS_getAlphabetCb ( dcs ); switch (alphabet) { case( 0 ): /* 7 bit alphabet */ /* PATCH Add bit_offset parameter to function cvt7To8 */ /* utl_cvt7To8 ( source, source_len, dest ); */ utl_cvt7To8 ( source, source_len, dest, 0); /* PATCH END */ *dest_len = ( source_len * 8 ) / 7; break; default: /* 8 bit alphabet, UCS2, reserved */ memcpy ( ( CHAR * ) dest, ( CHAR * ) source, source_len ); *dest_len = source_len; break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setToaDef | +--------------------------------------------------------------------+ PURPOSE : This function sets the type of address to default values (when the first character of address is '+' or the first two characters are '0' default is 145 otherwise default is 129) */ GLOBAL CHAR* cmhSMS_setToaDef ( CHAR* number, UBYTE* ntype, UBYTE* nplan ) { *nplan = SMS_NPI_ISDN; if ( *number EQ '+' ) { *ntype = SMS_TON_INTERNATIONAL; return number+1; } else { *ntype = SMS_TON_UNKNOWN; return number; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setTimezone | +--------------------------------------------------------------------+ PURPOSE : Codes the timezone format used in entity SMS. */ GLOBAL UBYTE cmhSMS_setTimezone (SHORT timezone) { UBYTE local_tz = ( UBYTE ) timezone; BOOL isNegative = ( local_tz & 0x80 ); if ( isNegative ) local_tz = ~local_tz + 1; local_tz = ( local_tz / 10 ) + ( ( local_tz % 10 ) << 4 ); return ( ( isNegative ) ? local_tz | 0x08 : local_tz ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getTimezone | +--------------------------------------------------------------------+ PURPOSE : Decodes the timezone format used in entity SMS. */ GLOBAL SHORT cmhSMS_getTimezone (UBYTE timezone) { signed char local_tz; local_tz = ( timezone & 0x07 ) * 10 + ( ( timezone & 0xF0 ) >> 4 ); return ( SHORT ) (( timezone & 0x08 ) ? -local_tz : local_tz ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_setStorOcc | +--------------------------------------------------------------------+ PURPOSE : Fills the T_ACI_SMS_STOR_OCC structure with data from the shared parameter buffer. */ GLOBAL void cmhSMS_setStorOcc ( T_ACI_SMS_STOR_OCC* outMem, UBYTE inMem ) { cmhSMS_getMemCmh ( inMem, &outMem -> mem ); if ( outMem -> mem EQ SMS_STOR_Sm ) { outMem -> used = smsShrdPrm.aci_sms_parameter.simUsed; outMem -> total = smsShrdPrm.aci_sms_parameter.simTotal; } else { outMem -> used = smsShrdPrm.aci_sms_parameter.meUsed; outMem -> total = smsShrdPrm.aci_sms_parameter.meTotal; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_GetCmsFromSim | +-------------------------------------------------------------------+ PURPOSE : Mapping of SIM error code to ACI error code. */ GLOBAL T_ACI_CMS_ERR cmhSMS_GetCmsFromSim ( USHORT errCode ) { switch ( errCode ) { case SIM_NO_ERROR: return CMS_ERR_NotPresent; case SIM_CAUSE_PIN1_EXPECT: return CMS_ERR_SimPinReq; case SIM_CAUSE_PIN2_EXPECT: return CMS_ERR_SimPin2Req; case SIM_CAUSE_PUK1_EXPECT: case SIM_CAUSE_PIN1_BLOCKED: return CMS_ERR_SimPukReq; case SIM_CAUSE_PUK2_EXPECT: case SIM_CAUSE_PIN2_BLOCKED: return CMS_ERR_SimPuk2Req; case SIM_CAUSE_PUK1_BLOCKED: case SIM_CAUSE_PUK2_BLOCKED: return CMS_ERR_SimWrong; case SIM_CAUSE_UNKN_FILE_ID: case SIM_CAUSE_DNL_ERROR: return CMS_ERR_UnknownErr; case SIM_CAUSE_EF_INVALID: return CMS_ERR_OpNotSup; case SIM_CAUSE_ADDR_WRONG: return CMS_ERR_InValMemIdx; case SIM_CAUSE_CMD_INCONSIST: case SIM_CAUSE_MAX_INCREASE: case SIM_CAUSE_CHV_NOTSET: case SIM_CAUSE_CHV_VALIDATED: case SIM_CAUSE_ACCESS_PROHIBIT: return CMS_ERR_OpNotAllowed; case SIM_CAUSE_CARD_REMOVED: case SIM_CAUSE_DRV_NOCARD: return CMS_ERR_SimNotIns; case SIM_CAUSE_NO_SELECT: case SIM_CAUSE_CLA_WRONG: case SIM_CAUSE_INS_WRONG: case SIM_CAUSE_P1P2_WRONG: case SIM_CAUSE_P3_WRONG: case SIM_CAUSE_PARAM_WRONG: return CMS_ERR_MeFail; case SIM_CAUSE_SAT_BUSY: return CMS_ERR_SimBsy; case SIM_CAUSE_DRV_TEMPFAIL: return CMS_ERR_SimFail; default: if (GET_CAUSE_DEFBY(errCode) EQ DEFBY_CONDAT AND GET_CAUSE_ORIGSIDE(errCode) EQ ORIGSIDE_MS) { return CMS_ERR_UnknownErr; } return CMS_ERR_UnknownErr; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_GetCmsFromSms | +-------------------------------------------------------------------+ PURPOSE : Mapping of SMS causes (MNSMS.doc) to ACI error code. */ GLOBAL T_ACI_CMS_ERR cmhSMS_GetCmsFromSms ( USHORT errCode ) { switch ( errCode ) { case SMS_NO_ERROR: /* No error */ return CMS_ERR_NotPresent; case SMS_CAUSE_PARAM_WRONG: /* Wrong parameter in primitive */ case SMS_CAUSE_ENTITY_BUSY: /* Entity is busy */ return CMS_ERR_SimBsy; case SMS_CAUSE_OPER_NOT_ALLW: /* Operation not allowed */ return CMS_ERR_OpNotAllowed; case SMS_CAUSE_OPER_NOT_SUPP: /* Operation not supported */ return CMS_ERR_OpNotSup; case SMS_CAUSE_SIM_BUSY: /* SIM busy */ return CMS_ERR_SimBsy; default: break; } /* * The switch must be splitted because of a compiler bug * - asm files can not compiled * * TMS470 ANSI C Compiler Version 1.22e * * brz, 2004.02.14 */ switch(errCode) { case SMS_CAUSE_MEM_FAIL: /* Memory failure */ return CMS_ERR_MemFail; case SMS_CAUSE_INV_INDEX: /* Invalid memory index */ return CMS_ERR_InValMemIdx; case SMS_CAUSE_MEM_FULL: /* Memory full */ return CMS_ERR_MemFull; case SMS_CAUSE_NO_SERVICE: /* No network service */ return CMS_ERR_NoNetServ; case SMS_CAUSE_NET_TIMEOUT: /* Network timeout */ return CMS_ERR_NetTimeOut; case SMS_CAUSE_UNEXP_CNMA: /* No +CNMA acknowledgement expected */ return CMS_ERR_NoCnmaAckExpect; case SMS_CAUSE_OTHER_ERROR: /* Any other error */ return CMS_ERR_UnknownErr; default: return ((T_ACI_CMS_ERR) (errCode & 0xFF)); /* cmdCmsError(errCode) will figure out other error values from the first byte of the error code */ } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_ready | +-------------------------------------------------------------------+ PURPOSE : This function notifies SMS_READY to all sources. */ GLOBAL void cmhSMS_ready ( void ) { int idx; T_opl_field * ptr_opl; TRACE_FUNCTION ("cmhSMS_ready()"); smsShrdPrm.accessEnabled = TRUE; ptr_opl = cmhSIM_GetOPL(); ptr_opl->opl_status = FALSE; cmhSIM_UpdateOperatorName(NOT_PRESENT_16BIT); /* start EF_PNN and EF_OPL reading */ pb_start_build(FALSE); /* start phonebook reading, no guarantees */ percentCSTAT_indication(STATE_MSG_SMS, ENTITY_STATUS_Ready); for( idx = 0; idx < CMD_SRC_MAX; idx++ ) { R_AT( RAT_SMS_READY, idx )(); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_disableAccess | +-------------------------------------------------------------------+ PURPOSE : This function disables access to all SMS functions. */ GLOBAL void cmhSMS_disableAccess (void) { smsShrdPrm.accessEnabled = FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_checkSIM | +-------------------------------------------------------------------+ PURPOSE : This function checks if SMS is initialized. If not, the SIM state is checked. AN error code dependent of the SIM state is stored. */ GLOBAL BOOL cmhSMS_checkSIM (void) { if (smsShrdPrm.accessEnabled) return TRUE; /* SMS is accessible*/ /* *----------------------------------------------------------------- * check SIM status *----------------------------------------------------------------- */ switch (simShrdPrm.SIMStat) { case NO_VLD_SS: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimNotIns ); break; case SS_INV: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimFail ); break; /* case SS_BLKD: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimPukReq ); break; */ case SS_URCHB: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimWrong ); break; case SS_OK: switch (simShrdPrm.PINStat) { case PS_PIN1: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimPinReq); break; case PS_PIN2: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimPin2Req); break; case PS_PUK1: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimPukReq); break; case PS_PUK2: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimPuk2Req); break; default: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimBsy ); break; } break; default: ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_SimBsy ); break; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_checkAccess | +-------------------------------------------------------------------+ PURPOSE : This function checks if SMS is accessible. If an error condition is found, then *ret is set to either AT_FAIL or AT_BUSY, otherwise it remains unaffected. The error code is stored. */ GLOBAL BOOL cmhSMS_checkAccess (T_ACI_CMD_SRC srcId, T_ACI_RETURN *ret) { /* *----------------------------------------------------------------- * check command source *----------------------------------------------------------------- */ if(!cmh_IsVldCmdSrc (srcId) AND (srcId NEQ OWN_SAT)) { ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); TRACE_ERROR ("[cmhSMS_checkAccess]: Cmd Src not valid"); *ret = AT_FAIL; return FALSE; } /* *----------------------------------------------------------------- * check entity status *----------------------------------------------------------------- */ if( smsShrdPrm.smsEntStat.curCmd NEQ AT_CMD_NONE ) { ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); TRACE_ERROR ("[cmhSMS_checkAccess]: Entity is busy"); *ret = AT_BUSY; return FALSE; } /* *----------------------------------------------------------------- * check SMS access status *----------------------------------------------------------------- */ if (cmhSMS_checkSIM ()) return TRUE; TRACE_ERROR ("[cmhSMS_checkAccess]: Wrong SIM status"); *ret = AT_FAIL; return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getPrfRge | +-------------------------------------------------------------------+ PURPOSE : This function gets the number of available profiles for SMS related parameters. First, the SIM is checked. If there is no space, then PCM ist checked. */ GLOBAL SHORT cmhSMS_getPrfRge ( void ) { /* TEMPORARY, ONLY FOR TEST PURPOSES: Pretend that the SIM has no SMSP !!! */ /* smsShrdPrm.aci_sms_parameter.smsParamMaxRec = 0;*/ if (smsShrdPrm.aci_sms_parameter.smsParamMaxRec > 0) { return (SHORT)smsShrdPrm.aci_sms_parameter.smsParamMaxRec; } else { return (MAX_FFS_SMSPRFLS); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_ReadPrmFFS | +-------------------------------------------------------------------+ PURPOSE : This function reads one record of EF_SMSPRFL_ID from FFS. The processed parameters are controlled by bits in 'access'. */ static T_ACI_RETURN cmhSMS_ReadPrmFFS (T_ACI_CMD_SRC srcId, SHORT recNr, int access) { T_SMS_SET_PRM *pSMSSetPrm; /* points to SMS parameter set */ int i; T_SMS_SET_PRM *elem; T_ACI_FFS_SMSPRFL smsPrfl; #ifndef _SIMULATION_ T_FFS_RET ffs_ret; T_FFS_SIZE ffs_size; #endif TRACE_FUNCTION ("cmhSMS_ReadPrmFFS()"); #ifdef _SIMULATION_ smsPrfl.vldFlag = FFS_SMSPRFL_INVLD; /* trigger a failure since nothing can be read in simulation */ #else ffs_size = FFS_fread(ffs_smsprfl_fname[recNr-1], (void*)&smsPrfl, SIZE_FSS_SMSPRFL); /* Don't check FFS return for only specif ERRORS, as ACI will not know what ERROR FFS may send. So, it's walyws better to check for ERROR OK i.e EFFS_OK Considering this in mind the below condition is changes to do the same. */ if ( ffs_size < EFFS_OK ) { TRACE_EVENT_P1("error when reading FFS object \"%s\"", ffs_smsprfl_fname[recNr-1]); ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_MemFail ); return AT_FAIL; } #endif if ( smsPrfl.vldFlag EQ FFS_SMSPRFL_INVLD ) { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_OpNotAllowed ); return AT_FAIL; } if (access & ACI_PCM_ACCESS_SMSP) { if (srcId >= CMD_SRC_MAX) { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_UnknownErr ); return AT_FAIL; } else { if (set_prm_list EQ NULL) { set_prm_list = new_list(); } elem = find_element(set_prm_list, (UBYTE)recNr, cmhSMS_findPrflId); if (elem EQ NULL) { ACI_MALLOC(elem, sizeof(T_SMS_SET_PRM)); memset(elem, 0, sizeof(T_SMS_SET_PRM)); insert_list(set_prm_list, elem); } if (srcId <= CMD_SRC_NONE) { elem->numOfRefs = OWN_MAX; for (i=0; i < OWN_MAX; i++) { smsShrdPrm.pSetPrm[i] = (T_SMS_SET_PRM*) elem; } } else { smsShrdPrm.pSetPrm[srcId] = (T_SMS_SET_PRM*) elem; (smsShrdPrm.pSetPrm[srcId])->numOfRefs++; } } pSMSSetPrm = (T_SMS_SET_PRM*) elem; pSMSSetPrm->prflId = (UBYTE)recNr; #ifndef _SIMULATION_ /* *------------------------------------------------------------- * restore the service center address *------------------------------------------------------------- */ pSMSSetPrm->sca.c_num = MINIMUM (smsPrfl.CSCAlenSca, MAX_SMS_ADDR_DIG); memcpy ( pSMSSetPrm->sca.num, smsPrfl.CSCAsca, pSMSSetPrm->sca.c_num); pSMSSetPrm->sca.ton = smsPrfl.CSCAton; pSMSSetPrm->sca.npi = smsPrfl.CSCAnpi; pSMSSetPrm->sca.v_ton = TRUE; pSMSSetPrm->sca.v_npi = TRUE; /* *------------------------------------------------------------- * restore the text mode parameters *------------------------------------------------------------- */ pSMSSetPrm->vpRel = smsPrfl.CSMPvprel; memcpy ( &pSMSSetPrm->vpAbs, smsPrfl.CSMPvpabs, SIZE_FFS_SMSPRFL_VPABS ); memcpy ( &pSMSSetPrm->vpEnh, smsPrfl.CSMPvpenh, SIZE_FFS_SMSPRFL_VPENH ); pSMSSetPrm->msgType = smsPrfl.CSMPfo; pSMSSetPrm->pid = smsPrfl.CSMPpid; pSMSSetPrm->dcs = smsPrfl.CSMPdcs; #endif } #ifndef _SIMULATION_ if (access & ACI_PCM_ACCESS_CBMP) { /* *------------------------------------------------------------- * restore the cell broadcast message types and data coding * schemes *------------------------------------------------------------- */ smsShrdPrm.cbmPrm.cbmMode = smsPrfl.CSCBmode; { /* default setting */ memset (smsShrdPrm.cbmPrm.msgId, DEF_MID_RANGE, sizeof (smsShrdPrm.cbmPrm.msgId)); memset (smsShrdPrm.cbmPrm.dcsId, DEF_DCS_RANGE, sizeof(smsShrdPrm.cbmPrm.dcsId)); } for ( i = 0; i < MINIMUM(MAX_IDENTS,SIZE_FFS_SMSPRFL_MIDS/2); i++ ) { smsShrdPrm.cbmPrm.msgId[i] = ( USHORT )smsPrfl.CSCBmids[2*i] << 8; smsShrdPrm.cbmPrm.msgId[i] |= ( USHORT )smsPrfl.CSCBmids[2*i+1]; } memcpy ( smsShrdPrm.cbmPrm.dcsId, smsPrfl.CSCBdcss, MINIMUM(MAX_IDENTS,SIZE_FFS_SMSPRFL_DCSS) ); memcpy (smsShrdPrm.cbmPrm.IMSI, smsPrfl.IMSI, MAX_IMSI); } #endif return AT_CMPL; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_WritePrmFFS | +-------------------------------------------------------------------+ PURPOSE : This function writes one record of EF_SMSPRFL_ID to FFS. The processed parameters are controlled by bits in 'access'. */ static T_ACI_RETURN cmhSMS_WritePrmFFS (T_ACI_CMD_SRC srcId, SHORT recNr, int access) { T_SMS_SET_PRM *pSMSSetPrm; /* points to SMS parameter set */ T_ACI_FFS_SMSPRFL smsPrfl; int i; #ifndef _SIMULATION_ T_FFS_RET ffs_ret; T_FFS_SIZE ffs_size; #endif TRACE_FUNCTION ("cmhSMS_WritePrmFFS()"); if (access & ACI_PCM_ACCESS_SMSP) { if (srcId > CMD_SRC_NONE AND srcId < CMD_SRC_MAX) { pSMSSetPrm = smsShrdPrm.pSetPrm[srcId]; /* *------------------------------------------------------------- * save the service center address *------------------------------------------------------------- */ smsPrfl.CSCAlenSca = MINIMUM ( pSMSSetPrm->sca.c_num, SIZE_FFS_SMSPRFL_SCA ); memcpy ( smsPrfl.CSCAsca, pSMSSetPrm->sca.num, smsPrfl.CSCAlenSca ); i = (int)smsPrfl.CSCAlenSca; while ( i < SIZE_FFS_SMSPRFL_SCA ) smsPrfl.CSCAsca[i++] = 0xFF; smsPrfl.CSCAton = pSMSSetPrm->sca.ton; smsPrfl.CSCAnpi = pSMSSetPrm->sca.npi; /* *------------------------------------------------------------- * store the text mode parameters *------------------------------------------------------------- */ smsPrfl.CSMPfo = pSMSSetPrm->msgType; smsPrfl.CSMPvprel = pSMSSetPrm->vpRel; memcpy ( smsPrfl.CSMPvpabs, &pSMSSetPrm->vpAbs, SIZE_FFS_SMSPRFL_VPABS ); memcpy ( smsPrfl.CSMPvpenh, &pSMSSetPrm->vpEnh, SIZE_FFS_SMSPRFL_VPENH ); smsPrfl.CSMPpid = pSMSSetPrm->pid; smsPrfl.CSMPdcs = pSMSSetPrm->dcs; /* *------------------------------------------------------------- * set the valid flag *------------------------------------------------------------- */ smsPrfl.vldFlag = FFS_SMSPRFL_VLD; } else { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_UnknownErr ); return AT_FAIL; } } if (access & ACI_PCM_ACCESS_CBMP) { /* *------------------------------------------------------------- * save the cell broadcast message types *------------------------------------------------------------- */ smsPrfl.CSCBmode = smsShrdPrm.cbmPrm.cbmMode; { /* default setting */ memset (smsPrfl.CSCBmids, 0xFF, sizeof(smsPrfl.CSCBmids)); memset (smsPrfl.CSCBdcss, 0xFF, sizeof(smsPrfl.CSCBdcss)); } for ( i = 0; i < MINIMUM(MAX_IDENTS*2,SIZE_FFS_SMSPRFL_MIDS)-1; i += 2 ) { smsPrfl.CSCBmids[i] = (UBYTE)(smsShrdPrm.cbmPrm.msgId[i/2] >> 8); smsPrfl.CSCBmids[i+1] = (UBYTE)smsShrdPrm.cbmPrm.msgId[i/2]; } memcpy ( smsPrfl.CSCBdcss, smsShrdPrm.cbmPrm.dcsId, MINIMUM(MAX_IDENTS,SIZE_FFS_SMSPRFL_DCSS) ); /* * Save IMSI also in FFS */ memcpy (smsPrfl.IMSI, simShrdPrm.imsi.field, simShrdPrm.imsi.c_field); smsPrfl.vldFlag = FFS_SMSPRFL_VLD; } #ifndef _SIMULATION_ ffs_ret = FFS_mkdir(FFS_SMSPRFL_PATH); if (ffs_ret EQ EFFS_OK) { TRACE_EVENT_P1("FFS directory \"%s\" successfully created", FFS_SMSPRFL_PATH); } else if (ffs_ret EQ EFFS_EXISTS) { TRACE_EVENT_P1("FFS directory \"%s\" already exists", FFS_SMSPRFL_PATH); } else { TRACE_EVENT_P1("error when creating FFS directory \"%s\"", FFS_SMSPRFL_PATH); } ffs_ret = FFS_fwrite(ffs_smsprfl_fname[recNr-1], (void*)&smsPrfl, SIZE_FSS_SMSPRFL); if (ffs_ret NEQ EFFS_OK) { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_MemFail ); TRACE_EVENT_P1("error when writing FFS object \"%s\"", ffs_smsprfl_fname[recNr-1]); return AT_FAIL; } #endif return AT_CMPL; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_ReadParams | +-------------------------------------------------------------------+ PURPOSE : This function reads parameters from SIM and/or PCM. In case of AT command +CFUN the first record is read to be informed about storage capability of SIM. */ GLOBAL T_ACI_RETURN cmhSMS_ReadParams (T_ACI_CMD_SRC srcId, T_ACI_AT_CMD cmd, SHORT recNr) { T_ACI_RETURN ret = AT_CMPL; int access = 0; TRACE_FUNCTION ("cmhSMS_ReadParams()"); smsShrdPrm.smsEntStat.curCmd = cmd; smsShrdPrm.smsEntStat.entOwn = smsShrdPrm.owner = srcId; if (cmd EQ AT_CMD_CFUN) { /* initialization */ /* * Always read CSCB params from FFS so that previously stored mode and dcss * can also be restored from FFS */ access |= ACI_PCM_ACCESS_CBMP; /*if (!psaSIM_ChkSIMSrvSup( SRV_SMS_Parms ))*/ access |= ACI_PCM_ACCESS_SMSP; if (access NEQ 0) ret = cmhSMS_ReadPrmFFS (CMD_SRC_NONE, 1, access); if (psaSIM_ChkSIMSrvSup( SRV_SMS_Parms )) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_SMSP; ret = cmhSIM_ReadRecordEF (CMD_SRC_NONE, cmd, SIM_SMSP, 1, 255, NULL, cmhSMS_InitSMSP); } else if (psaSIM_ChkSIMSrvSup( SRV_CBMIdRnge )) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMIR; ret = cmhSIM_ReadTranspEF (CMD_SRC_NONE, cmd, SIM_CBMIR, 0, 255, NULL, cmhSMS_InitSMSP); } else if (psaSIM_ChkSIMSrvSup( SRV_CBM_Ident )) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMI; ret = cmhSIM_ReadTranspEF (CMD_SRC_NONE, cmd, SIM_CBMI, 0, 255, NULL, cmhSMS_InitSMSP); } #ifdef SIM_TOOLKIT else if ((psaSIM_ChkSIMSrvSup( SRV_DtaDownlCB )) AND smsShrdPrm.owner EQ OWN_SAT ) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMID; ret = cmhSIM_ReadTranspEF (CMD_SRC_NONE, cmd, SIM_CBMID, 0, 255, NULL, cmhSMS_InitSMSP); } #endif /* of SIM_TOOLKIT */ } else { /* TEMPORARY, ONLY FOR TEST PURPOSES: Pretend that the SIM has no SMSP !!! */ /* smsShrdPrm.aci_sms_parameter.smsParamMaxRec = 0; */ /* * Always read CSCB params from FFS so that previously stored mode and dcss * can also be restored from FFS */ /* normal operation */ access |= ACI_PCM_ACCESS_CBMP; /* if (smsShrdPrm.aci_sms_parameter.smsParamMaxRec EQ 0)*/ access |= ACI_PCM_ACCESS_SMSP; if (access NEQ 0) ret = cmhSMS_ReadPrmFFS (srcId, recNr, access); if (smsShrdPrm.aci_sms_parameter.smsParamMaxRec > 0) { if (recNr <= 0 OR recNr > (SHORT)smsShrdPrm.aci_sms_parameter.smsParamMaxRec) { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_InValMemIdx ); ret= AT_FAIL; } else { smsShrdPrm.prmRdSeq = SMS_READ_SIM_SMSP; return cmhSIM_ReadRecordEF (CMD_SRC_NONE, cmd, SIM_SMSP, (UBYTE)(recNr), smsShrdPrm.aci_sms_parameter.smsParamRecLen, NULL, cmhSMS_RdCnfCRES); } } if (smsShrdPrm.cbmPrm.cbmSIMmaxIdRge > 0) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMIR; return cmhSIM_ReadTranspEF (CMD_SRC_NONE, cmd, SIM_CBMIR, 0, smsShrdPrm.cbmPrm.cbmSIMmaxIdRge, NULL, cmhSMS_RdCnfCRES); } if (smsShrdPrm.cbmPrm.cbmSIMmaxId > 0) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMI; return cmhSIM_ReadTranspEF (CMD_SRC_NONE, cmd, SIM_CBMI, 0, smsShrdPrm.cbmPrm.cbmSIMmaxId, NULL, cmhSMS_RdCnfCRES); } } if (ret NEQ AT_EXCT) { smsShrdPrm.smsEntStat.curCmd = AT_CMD_NONE; smsShrdPrm.smsEntStat.entOwn = smsShrdPrm.owner = OWN_NONE; smsShrdPrm.cbmPrm.cbchOwner = srcId; psaMMI_Cbch(); smsShrdPrm.cbmPrm.cbchOwner = OWN_NONE; } return ret; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_WriteParams | +-------------------------------------------------------------------+ PURPOSE : This function reads parameters from SIM and/or PCM. In case of AT command +CFUN the first record is read to be informed about storage capability of SIM. */ GLOBAL T_ACI_RETURN cmhSMS_WriteParams (T_ACI_CMD_SRC srcId, T_ACI_AT_CMD cmd, SHORT recNr) { T_ACI_RETURN ret = AT_CMPL; int access = 0; UBYTE data[MAX_SIM_CMD]; TRACE_FUNCTION ("cmhSMS_WriteParams()"); smsShrdPrm.smsEntStat.curCmd = cmd; smsShrdPrm.smsEntStat.entOwn = smsShrdPrm.owner = srcId; /* TEMPORARY, ONLY FOR TEST PURPOSES: Pretend that the SIM has no SMSP !!! */ /* smsShrdPrm.aci_sms_parameter.smsParamMaxRec = 0; */ /* * Always write CSCB params to FFS so that mode and dcss * can later be restored from FFS */ access |= ACI_PCM_ACCESS_CBMP; /*if (smsShrdPrm.aci_sms_parameter.smsParamMaxRec EQ 0)*/ access |= ACI_PCM_ACCESS_SMSP; if (access NEQ 0) ret = cmhSMS_WritePrmFFS (srcId, recNr, access); if (smsShrdPrm.aci_sms_parameter.smsParamMaxRec > 0) { if (recNr <= 0 OR recNr > (SHORT)smsShrdPrm.aci_sms_parameter.smsParamMaxRec) { ACI_ERR_DESC( ACI_ERR_CLASS_Cms, CMS_ERR_InValMemIdx ); ret= AT_FAIL; } else { smsShrdPrm.prmRdSeq = SMS_READ_SIM_SMSP; cmhSMS_PutPrmSIM (srcId, data, (int)smsShrdPrm.aci_sms_parameter.smsParamRecLen); return cmhSIM_WriteRecordEF (CMD_SRC_NONE, cmd, SIM_SMSP, (UBYTE)(recNr), smsShrdPrm.aci_sms_parameter.smsParamRecLen, data, cmhSMS_WrCnfCSAS); } } if (smsShrdPrm.cbmPrm.cbmSIMmaxIdRge > 0) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMIR; cmhSMS_PutCbmirSIM (srcId, data, (int)smsShrdPrm.cbmPrm.cbmSIMmaxIdRge * 4); return cmhSIM_WriteTranspEF (CMD_SRC_NONE, cmd, SIM_CBMIR, 0, (UBYTE)(smsShrdPrm.cbmPrm.cbmSIMmaxIdRge * 4), data, cmhSMS_WrCnfCSAS); } if (smsShrdPrm.cbmPrm.cbmSIMmaxId > 0) { smsShrdPrm.prmRdSeq = SMS_READ_SIM_CBMI; cmhSMS_PutCbmiSIM (srcId, data, (int)smsShrdPrm.cbmPrm.cbmSIMmaxId * 2); return cmhSIM_WriteTranspEF (CMD_SRC_NONE, cmd, SIM_CBMI, 0, (UBYTE)(smsShrdPrm.cbmPrm.cbmSIMmaxId * 2), data, cmhSMS_WrCnfCSAS); } if (ret NEQ AT_EXCT) { smsShrdPrm.smsEntStat.curCmd = AT_CMD_NONE; smsShrdPrm.smsEntStat.entOwn = smsShrdPrm.owner = OWN_NONE; } return ret; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_GetPrmSIM | +-------------------------------------------------------------------+ PURPOSE : This function extracts the parameters of one record of EF(SMSP) read from SIM. */ GLOBAL BOOL cmhSMS_GetPrmSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int dataLen) { T_SMS_SET_PRM *pSMSSetPrm; /* points to SMS parameter set */ T_ACI_SMS_SIM_PARAMS *smsprm; TRACE_FUNCTION ("cmhSMS_GetPrmSIM ()"); if (data NEQ NULL) { pSMSSetPrm = smsShrdPrm.pSetPrm[srcId]; smsprm = (T_ACI_SMS_SIM_PARAMS *)&data[(dataLen <= MIN_SMS_PRM_LEN)? 0: dataLen - MIN_SMS_PRM_LEN]; if (smsprm->par_ind EQ NOT_PRESENT_8BIT) { /* ACI-SPR-16431: reset sca number */ pSMSSetPrm->sca.c_num = 0; memset(pSMSSetPrm->sca.num, 0xFF, sizeof(pSMSSetPrm->sca.num)); /* end of ACI-SPR-16431: reset sca number */ return TRUE; /* record is empty */ } if ((smsprm->par_ind & SIM_SMSP_V_SCA) EQ 0) { cmh_demergeTOA (smsprm->sca_ton_npi, &pSMSSetPrm->sca.ton, &pSMSSetPrm->sca.npi); pSMSSetPrm->sca.c_num = (UBYTE)cmh_unpackBCD (pSMSSetPrm->sca.num, smsprm->sca_addr, (USHORT)(smsprm->sca_length - 1)); pSMSSetPrm->sca.v_ton = TRUE; pSMSSetPrm->sca.v_npi = TRUE; } if ((smsprm->par_ind & SIM_SMSP_V_PID) EQ 0) pSMSSetPrm->pid = smsprm->pid; if ((smsprm->par_ind & SIM_SMSP_V_DCS) EQ 0) pSMSSetPrm->dcs = smsprm->dcs; if ((smsprm->par_ind & SIM_SMSP_V_VPREL) EQ 0) { pSMSSetPrm->vpRel = smsprm->vp_rel; pSMSSetPrm->msgType &= ~TP_VPF_MASK; pSMSSetPrm->msgType |= TP_VPF_RELATIVE; } else if ((pSMSSetPrm->msgType & TP_VPF_MASK) EQ TP_VPF_RELATIVE) pSMSSetPrm->msgType &= ~TP_VPF_MASK; return TRUE; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_PutPrmSIM | +-------------------------------------------------------------------+ PURPOSE : This function conbiness the parameters for one record of EF(SMSP) to be written to SIM. */ GLOBAL BOOL cmhSMS_PutPrmSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int maxDataLen) { T_SMS_SET_PRM *pSMSSetPrm; /* points to SMS parameter set */ T_ACI_SMS_SIM_PARAMS *smsprm; size_t datalen; TRACE_FUNCTION ("cmhSMS_PutPrmSIM ()"); if (data NEQ NULL) { pSMSSetPrm = smsShrdPrm.pSetPrm[srcId]; if (maxDataLen < MIN_SMS_PRM_LEN) { datalen = MIN_SMS_PRM_LEN; smsprm = (T_ACI_SMS_SIM_PARAMS *)data; } else { datalen = (size_t)maxDataLen; smsprm = (T_ACI_SMS_SIM_PARAMS *)&data[datalen - MIN_SMS_PRM_LEN]; } memset (data, NOT_PRESENT_8BIT, datalen); /* *------------------------------------------------------------- * set the service center address *------------------------------------------------------------- */ if (pSMSSetPrm->sca.c_num > 0) { smsprm->sca_ton_npi = cmh_mergeTOA (pSMSSetPrm->sca.ton, pSMSSetPrm->sca.npi); smsprm->sca_length = (UBYTE)cmh_packBCD (smsprm->sca_addr, pSMSSetPrm->sca.num, (USHORT)MINIMUM(pSMSSetPrm->sca.c_num, MAX_SMS_ADDR_DIG)) + 1; smsprm->par_ind &= ~SIM_SMSP_V_SCA; } /* *------------------------------------------------------------- * set PID, DCS and VP-REL *------------------------------------------------------------- */ smsprm->pid = pSMSSetPrm->pid; smsprm->par_ind &= ~SIM_SMSP_V_PID; smsprm->dcs = pSMSSetPrm->dcs; smsprm->par_ind &= ~SIM_SMSP_V_DCS; if ((pSMSSetPrm->msgType & TP_VPF_MASK) EQ TP_VPF_RELATIVE) { smsprm->vp_rel = pSMSSetPrm->vpRel; smsprm->par_ind &= ~SIM_SMSP_V_VPREL; } return TRUE; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_GetCbmirSIM | +-------------------------------------------------------------------+ PURPOSE : This function extracts the parameters of EF(CBMIR) read from SIM. */ GLOBAL BOOL cmhSMS_GetCbmirSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int dataLen) { T_ACI_CBM_SIM_MID_RANGE *mid_range; USHORT lower_mid, upper_mid; int mid_entry; TRACE_FUNCTION ("cmhSMS_GetCbmirSIM ()"); if (data NEQ NULL) { /* Please be aware that to keep simulation test cases as less changed as possible lets assume that IMSI and CBMs stored in the FFS and from SIM card are the same, since we cannot access FFS under SIMULATION*/ #ifndef _SIMULATION_ /* * The CSCB parameters read from FFS should be restored only if the same SIM * is inserted ( check IMSI to ensure the same SIM), otherwise reset the CSCB * parameters to default values */ if (memcmp (smsShrdPrm.cbmPrm.IMSI, simShrdPrm.imsi.field, simShrdPrm.imsi.c_field) NEQ 0) { smsShrdPrm.cbmPrm.cbmMode = CBCH_ACCEPT; memset (smsShrdPrm.cbmPrm.msgId, DEF_MID_RANGE, sizeof (smsShrdPrm.cbmPrm.msgId)); memset (smsShrdPrm.cbmPrm.dcsId, DEF_DCS_RANGE, sizeof(smsShrdPrm.cbmPrm.dcsId)); return FALSE; } #endif mid_range = (T_ACI_CBM_SIM_MID_RANGE *)data; mid_entry = 0; while (smsShrdPrm.cbmPrm.cbmFoundIds < MAX_IDENTS/2 AND mid_entry < dataLen) { lower_mid = (USHORT)mid_range->lowerLSB | ((USHORT)mid_range->lowerMSB << 8); upper_mid = (USHORT)mid_range->upperLSB | ((USHORT)mid_range->upperMSB << 8); mid_range++; mid_entry += 4; if (lower_mid NEQ NOT_PRESENT_16BIT OR upper_mid NEQ NOT_PRESENT_16BIT) { /* Please be aware that to keep simulation test cases as less changed as possible lets assume that CBMs stored in the FFS and from SIM card are the same, since we cannot access FFS under SIMULATION*/ #ifndef _SIMULATION_ /* * If the msg ids are same that in FFS and SIM, then restore else reset * to default values */ if (smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2] EQ lower_mid AND smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1] EQ upper_mid) { smsShrdPrm.cbmPrm.cbmFoundIds++; } else { smsShrdPrm.cbmPrm.cbmMode = CBCH_ACCEPT; memset (smsShrdPrm.cbmPrm.msgId, DEF_MID_RANGE, sizeof (smsShrdPrm.cbmPrm.msgId)); memset (smsShrdPrm.cbmPrm.dcsId, DEF_DCS_RANGE, sizeof(smsShrdPrm.cbmPrm.dcsId)); smsShrdPrm.cbmPrm.cbmFoundIds = 0; return FALSE; } #else /* Just for simulation - copy data, received from SIM */ smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2] = lower_mid; smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1] = upper_mid; smsShrdPrm.cbmPrm.cbmFoundIds++; #endif } } return TRUE; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_PutCbmirSIM | +-------------------------------------------------------------------+ PURPOSE : This function conbines the parameters of EF(CBMIR) to be written to SIM. */ GLOBAL BOOL cmhSMS_PutCbmirSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int maxDataLen) { T_ACI_CBM_SIM_MID_RANGE *mid_range; USHORT lower_mid, upper_mid; int mid_entry; TRACE_FUNCTION ("cmhSMS_PutCbmirSIM ()"); if (data NEQ NULL) { memset (data, NOT_PRESENT_8BIT, maxDataLen); mid_range = (T_ACI_CBM_SIM_MID_RANGE *)data; mid_entry = 0; while (smsShrdPrm.cbmPrm.cbmFoundIds < MAX_IDENTS/2 AND mid_entry < maxDataLen) { lower_mid = smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2]; upper_mid = smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1]; smsShrdPrm.cbmPrm.cbmFoundIds++; if (lower_mid NEQ NOT_PRESENT_16BIT OR upper_mid NEQ NOT_PRESENT_16BIT) { mid_range->lowerLSB = (UBYTE)lower_mid; mid_range->lowerMSB = (UBYTE)(lower_mid >> 8); mid_range->upperLSB = (UBYTE)upper_mid; mid_range->upperMSB = (UBYTE)(upper_mid >> 8); mid_range++; mid_entry += 4; } } return TRUE; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_GetCbmiSIM | +-------------------------------------------------------------------+ PURPOSE : This function extracts the parameters of one record of EF(SMSP) read from SIM. */ GLOBAL BOOL cmhSMS_GetCbmiSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int dataLen) { T_ACI_CBM_SIM_MID_LIST **mid_list; USHORT mid; int mid_entry; TRACE_FUNCTION ("cmhSMS_GetCbmiSIM ()"); if (data NEQ NULL) { /* Please be aware that to keep simulation test cases as less changed as possible lets assume that IMSI and CBMs stored in the FFS and from SIM card are the same, since we cannot access FFS under SIMULATION*/ #ifndef _SIMULATION_ /* * The CSCB parameters read from FFS should be restored only if the same SIM * is inserted ( check IMSI to ensure the same SIM), otherwise reset the CSCB * parameters to default values */ if (memcmp (smsShrdPrm.cbmPrm.IMSI, simShrdPrm.imsi.field, simShrdPrm.imsi.c_field) NEQ 0) { smsShrdPrm.cbmPrm.cbmMode = CBCH_ACCEPT; memset (smsShrdPrm.cbmPrm.msgId, DEF_MID_RANGE, sizeof (smsShrdPrm.cbmPrm.msgId)); memset (smsShrdPrm.cbmPrm.dcsId, DEF_DCS_RANGE, sizeof(smsShrdPrm.cbmPrm.dcsId)); return FALSE; } #endif mid_list = (T_ACI_CBM_SIM_MID_LIST **)&data; mid_entry = 0; while (smsShrdPrm.cbmPrm.cbmFoundIds < MAX_IDENTS/2 AND mid_entry < dataLen) { mid = (USHORT)(*mid_list)->LSB | ((USHORT)(*mid_list)->MSB << 8); data += 2; /* overcome TI alignment problem */ mid_entry += 2; if (mid NEQ NOT_PRESENT_16BIT) { /* Please be aware that to keep simulation test cases as less changed as possible lets assume that CBMs stored in the FFS and from SIM card are the same, since we cannot access FFS under SIMULATION*/ #ifndef _SIMULATION_ /* * If the msg ids are same that in FFS and SIM, then restore else reset * to default values */ if (smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2] EQ mid AND smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1] EQ mid) { smsShrdPrm.cbmPrm.cbmFoundIds++; } else { smsShrdPrm.cbmPrm.cbmMode = CBCH_ACCEPT; memset (smsShrdPrm.cbmPrm.msgId, DEF_MID_RANGE, sizeof (smsShrdPrm.cbmPrm.msgId)); memset (smsShrdPrm.cbmPrm.dcsId, DEF_DCS_RANGE, sizeof(smsShrdPrm.cbmPrm.dcsId)); smsShrdPrm.cbmPrm.cbmFoundIds = 0; return FALSE; } #else /* Just for simulation - copy data, received from SIM */ smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2] = smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1] = mid; smsShrdPrm.cbmPrm.cbmFoundIds++; #endif } } return TRUE; } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_PutCbmiSIM | +-------------------------------------------------------------------+ PURPOSE : This function conbines the parameters of EF(CBMI) to be written to SIM. */ GLOBAL BOOL cmhSMS_PutCbmiSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int maxDataLen) { T_ACI_CBM_SIM_MID_LIST **mid_list; USHORT lower_mid, upper_mid; UBYTE mid_entry; TRACE_FUNCTION ("cmhSMS_PutCbmiSIM ()"); if (data NEQ NULL) { memset (data, NOT_PRESENT_8BIT, maxDataLen); mid_list = (T_ACI_CBM_SIM_MID_LIST **)&data; mid_entry = 0; while (smsShrdPrm.cbmPrm.cbmFoundIds < MAX_IDENTS/2 AND mid_entry < maxDataLen) { lower_mid = smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2]; upper_mid = smsShrdPrm.cbmPrm.msgId[smsShrdPrm.cbmPrm.cbmFoundIds * 2 + 1]; smsShrdPrm.cbmPrm.cbmFoundIds++; if (lower_mid NEQ NOT_PRESENT_16BIT OR upper_mid NEQ NOT_PRESENT_16BIT) { while (lower_mid <= upper_mid AND mid_entry < maxDataLen) { (*mid_list)->LSB = (UBYTE)lower_mid; (*mid_list)->MSB = (UBYTE)(lower_mid >> 8); lower_mid++; data += 2; /* overcome TI alignment problem */ mid_entry += 2; } } } return TRUE; } return FALSE; } #ifdef SIM_TOOLKIT /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_FileUpdate | +-------------------------------------------------------------------+ PURPOSE : This function processes the primitive SIM_FILE_UPDATE_IND to update the SMS parameters stored on the SIM. */ GLOBAL BOOL cmhSMS_FileUpdate (int ref, T_SIM_FILE_UPDATE_IND *fu) { BOOL found = FALSE; int i; TRACE_FUNCTION ("cmhSMS_FileUpdate ()"); for (i = 0; i < (int)fu->val_nr; i++) { if (!found AND (fu->file_id[i] EQ SIM_SMSP OR fu->file_id[i] EQ SIM_CBMI OR fu->file_id[i] EQ SIM_CBMIR OR fu->file_id[i] EQ SIM_CBMID)) { found = TRUE; } if (fu->file_id[i] EQ SIM_SMS) { smsShrdPrm.aci_sms_parameter.simTotal = 0; smsShrdPrm.aci_sms_parameter.simUsed = 0; } } if (found) { smsShrdPrm.cbmPrm.cbmFoundIds = 0; /* new CBMI(R) */ if (cmhSMS_ReadParams (OWN_SAT, AT_CMD_CFUN, 1) EQ AT_EXCT) { smsShrdPrm.accessEnabled = FALSE; simShrdPrm.fuRef = ref; return FALSE; /* reading files */ } else return TRUE; /* nothing to do */ } else { simShrdPrm.fuRef = -1; /* nothing to do */ return TRUE; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_GetCbDtaDwnlSIM | +-------------------------------------------------------------------+ PURPOSE : This function extracts the parameters of CBMID record of EF(CBMID) read from SIM. */ GLOBAL BOOL cmhSMS_GetCbDtaDwnlSIM (T_ACI_CMD_SRC srcId, UBYTE *data, int dataLen) { T_ACI_CBM_SIM_MID_LIST **mid_list; USHORT mid; int mid_entry; TRACE_FUNCTION ("cmhSMS_GetCbDtaDwnlSIM ()"); if (data NEQ NULL) { smsShrdPrm.cbmPrm.CBDtaDwnlFoundIds = 0; memset (smsShrdPrm.cbmPrm.CBDtaDwnlIdent, NOT_PRESENT_8BIT, sizeof (smsShrdPrm.cbmPrm.CBDtaDwnlIdent)); mid_list = (T_ACI_CBM_SIM_MID_LIST **)&data; mid_entry = 0; while (smsShrdPrm.cbmPrm.CBDtaDwnlFoundIds < MAX_IDENTS_SAT AND mid_entry < dataLen) { mid = (USHORT)(*mid_list)->LSB | ((USHORT)(*mid_list)->MSB << 8); data += 2; /* overcome TI alignment problem */ mid_entry += 2; if (mid NEQ NOT_PRESENT_16BIT) { smsShrdPrm.cbmPrm.CBDtaDwnlIdent[smsShrdPrm.cbmPrm.CBDtaDwnlFoundIds] = mid; smsShrdPrm.cbmPrm.CBDtaDwnlFoundIds++; } } return TRUE; } return FALSE; } #endif /*of SIM_TOOLKIT */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_decodeMsg | +--------------------------------------------------------------------+ PURPOSE : decodes a SM in two steps */ GLOBAL UBYTE* cmhSMS_decodeMsg (T_sms_sdu *sms_sdu, T_rp_addr* rp_addr, UBYTE vt_mti) { UBYTE ccdRet; UBYTE direction; UBYTE recover_from_error; BUF_tpdu sim_buf; /* source for the second decoding */ TRACE_FUNCTION("cmhSMS_decodeMsg ()"); if( sms_sdu->l_buf EQ 0) { TRACE_EVENT("empty SDU: no decoding"); return(NULL); } CCD_START; { MCAST( sim_pdu, SIM_PDU ); /* sim_pdu points to _decodedMsg */ /*memset( sim_pdu, 0, sizeof (T_SIM_PDU) ); */ /* decoding outer layer */ ccdRet = ccd_decodeMsg ( CCDENT_SMS, BOTH /* doesn't work with DOWNLINK!!! */, (T_MSGBUF *) sms_sdu, (UBYTE *) _decodedMsg, /* target */ SMS_VT_SIM_PDU); if ( (ccdRet NEQ ccdOK) OR (!sim_pdu->v_tpdu) OR (_decodedMsg[0] NEQ SMS_VT_SIM_PDU) ) { TRACE_EVENT_P1("CCD Decoding Error: %d", ccdRet); CCD_END; return NULL; } memcpy(rp_addr, &sim_pdu->rp_addr, sizeof(T_rp_addr) ); memcpy(&sim_buf, &sim_pdu->tpdu, sizeof(BUF_tpdu) ); /*memset( _decodedMsg, 0, sizeof (T_TP_SUBMIT) ); */ if (vt_mti EQ SMS_VT_SUBMIT) { /* for decoding of SMS-SUBMIT (in response to +CMGR, +CMGL) */ direction = UPLINK; } else { direction = DOWNLINK; } /* decoding inner layer */ ccdRet = ccd_decodeMsg ( CCDENT_SMS, direction, (T_MSGBUF *) &sim_buf, (UBYTE *) _decodedMsg, /* target */ vt_mti ); if (ccdRet EQ ccdWarning) recover_from_error = TRUE; /* Try to recover if a ccdWarning occoured */ else recover_from_error = FALSE; if ((ccdRet EQ ccdError) OR (ccdRet EQ ccdWarning)) { UBYTE ccd_err; USHORT parlist [6]; TRACE_EVENT_P1 ("ccd_decodeMsg(): %02x", ccdRet); /* * get the first error */ ccd_err = ccd_getFirstError (CCDENT_SMS, parlist); /* * Error Handling */ do { #ifndef NTRACE /* save some ROM */ char *errstr; switch (ccd_err) { case ERR_NO_MORE_ERROR: errstr= "the end of the error list is reached";break; case ERR_INVALID_CALC: errstr= "calculation of the element repeat value failed";break; case ERR_PATTERN_MISMATCH:errstr= "a bit pattern was not expected";break; case ERR_COMPREH_REQUIRED:errstr= "check for comprehension required failed";break; case ERR_IE_NOT_EXPECTED: errstr= "an information element was not expected";break; case ERR_IE_SEQUENCE: errstr= "wrong sequence of information elements";break; case ERR_MAX_IE_EXCEED: errstr= "maximum amount of repeatable information elements has exceeded";break; case ERR_MAX_REPEAT: errstr= "a repeatable element occurs too often in the message";break; case ERR_MAND_ELEM_MISS: errstr= "a mandatory information element is missing";break; case ERR_INVALID_MID: errstr= "the message ID is not correct";break; case ERR_INVALID_TYPE: errstr= "the information element is not a spare padding";break; case ERR_EOC_TAG_MISSING: errstr= "indefinite length is specified for the ASN.1-BER but the end tag is missing";break; case ERR_INTERNAL_ERROR: errstr= "an internal CCD error occured ";break; default: errstr= "unknown error";break; } if (ccdRet EQ ccdError) { TRACE_EVENT_P2 ("ERR: %u %s", ccd_err, errstr); } else if (ccdRet EQ ccdWarning) { TRACE_EVENT_P2 ("WRN: %u %s", ccd_err, errstr); } #endif /* NTRACE */ if (ccdRet EQ ccdWarning) { switch (ccd_err) { case ERR_PATTERN_MISMATCH: /* recoverable warnings */ case ERR_COMPREH_REQUIRED: case ERR_INTERNAL_ERROR: break; default: recover_from_error = FALSE; /* in all other cases reset the recover flag */ } } ccd_err = ccd_getNextError (CCDENT_SMS, parlist); }while (ccd_err NEQ ERR_NO_MORE_ERROR); } if ( (ccdRet EQ ccdError) OR ((ccdRet EQ ccdWarning) AND (recover_from_error EQ FALSE)) OR /* not possible to recover */ (_decodedMsg[0] NEQ vt_mti) ) { TRACE_EVENT_P1("CCD Decoding Error Stage 2: %d", ccdRet); CCD_END; return NULL; } else if ((ccdRet EQ ccdWarning) AND (recover_from_error EQ TRUE)) { TRACE_EVENT ("recovered from warning"); } } CCD_END; return _decodedMsg; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_codeMsg | +--------------------------------------------------------------------+ PURPOSE : encodes a SM in two steps */ GLOBAL void cmhSMS_codeMsg (T_sms_sdu *sms_sdu, UBYTE tp_vt_mti, T_rp_addr* sc_addr, UBYTE tp_mti, UBYTE* decoded_pdu ) { BUF_tpdu sim_buf; /* target for first coding */ UBYTE direction; TRACE_FUNCTION ("cmhSMS_codeMsg()"); CCD_START; { UBYTE ccdRet; MCAST( sim_pdu, SIM_PDU ); /* source of outer encoding */ memset( sim_pdu, 0, sizeof (T_SIM_PDU) ); /* target of outer encoding */ /* memset( sms_sdu, 0, sizeof (T_sms_sdu) ); */ sms_sdu->o_buf = 0; sms_sdu->l_buf = SIM_PDU_LEN << 3; sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; sim_pdu->tp_mti = tp_mti; /* service center address exists */ if (sc_addr) { memcpy(&sim_pdu->rp_addr, sc_addr, sizeof(T_rp_addr)); sim_pdu->rp_addr.v_ton = 1; sim_pdu->rp_addr.v_npi = 1; } /* pdu data exists */ if (decoded_pdu) { /* target of inner encoding */ /* memset(sim_buf, 0, sizeof(BUF_tpdu)); */ sim_buf.o_tpdu = 0; sim_buf.l_tpdu = (sizeof(BUF_tpdu)) << 3; if (tp_vt_mti EQ SMS_VT_DELIVER) { /* for encoding of SMS-DELIVER (only in +CMGW) */ direction = DOWNLINK; } else { direction = UPLINK; } /* encoding inner layer */ ccdRet = ccd_codeMsg (CCDENT_SMS, direction, (T_MSGBUF *) &sim_buf, /* target */ (UBYTE *) decoded_pdu, tp_vt_mti); if ( ccdRet NEQ ccdOK ) { TRACE_EVENT_P1("CCD Coding Error: %d", ccdRet); CCD_END; return; } if (sim_buf.l_tpdu EQ 0) { TRACE_EVENT("Encoded length is zero"); } memcpy(&sim_pdu->tpdu, &sim_buf, sizeof(BUF_tpdu)); sim_pdu->v_tpdu = 1; /* set validy flag */ } /* encoding outer layer */ ccdRet = ccd_codeMsg (CCDENT_SMS, UPLINK, (T_MSGBUF *) sms_sdu, /* target */ (UBYTE *) sim_pdu, SMS_VT_SIM_PDU); if ( ccdRet NEQ ccdOK ) { TRACE_EVENT_P1("CCD Coding Error: %d", ccdRet); CCD_END; return; } if (sms_sdu->l_buf EQ 0) { TRACE_EVENT("Encoded length is zero"); } } CCD_END; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_cpyDeliver | +--------------------------------------------------------------------+ PURPOSE : converts a SMS-DELIVER message to the T_ACI_CMGL_SM structure */ GLOBAL BOOL cmhSMS_cpyDeliver ( T_ACI_CMGL_SM * sm, T_sms_sdu * sms_sdu ) { T_rp_addr rp_addr; UBYTE* message; T_TP_DELIVER *sms_deliver; UBYTE alphabet; TRACE_FUNCTION("cmhSMS_cpyDeliver()"); message = cmhSMS_decodeMsg(sms_sdu, &rp_addr, SMS_VT_DELIVER); if (message EQ NULL) { sm->stat = SMS_STAT_Invalid; return (FALSE); } if ( message[0] NEQ SMS_VT_DELIVER) { TRACE_EVENT_P1("wrong VTI = %x", message[0]); } sms_deliver = (T_TP_DELIVER*)message; /* *----------------------------------------------------------------- * process originator address *----------------------------------------------------------------- */ if (sms_deliver->tp_oa.ton EQ SMS_TON_ALPHANUMERIC) { UBYTE i,j = 0; UBYTE dest_len; CHAR address_buf[MAX_SMS_ADDR_DIG/2]; for (i = 0 ; i < sms_deliver->tp_oa.digits ; i=i+2) { address_buf[j] = (UBYTE)(sms_deliver->tp_oa.num[i+1] << 4) + (UBYTE)(sms_deliver->tp_oa.num[i]); j++; } dest_len = utl_cvt7To8 ( (UBYTE*)address_buf, j, (UBYTE*)sm->adress, 0); sm -> adress[dest_len] = '\0'; } else cmhSMS_getAdrStr ( sm -> adress, MAX_SMS_NUM_LEN - 1, sms_deliver->tp_oa.num, sms_deliver->tp_oa.digits ); sm -> toa.ton = cmhSMS_getTon ( sms_deliver->tp_oa.ton ); sm -> toa.npi = cmhSMS_getNpi ( sms_deliver->tp_oa.npi ); /* *----------------------------------------------------------------- * process service center address *----------------------------------------------------------------- */ cmhSMS_getAdrStr ( sm -> sca, MAX_SMS_NUM_LEN - 1, rp_addr.num, rp_addr.c_num); sm -> tosca.ton = cmhSMS_getTon ( rp_addr.ton ); sm -> tosca.npi = cmhSMS_getNpi ( rp_addr.npi ); /* *----------------------------------------------------------------- * process alphanumerical phonebook entry *----------------------------------------------------------------- */ psaCC_phbMfwSrchNumPlnTxt ( sm -> adress, &sm -> alpha ); /* *----------------------------------------------------------------- * process first octet *----------------------------------------------------------------- */ sm -> fo = sms_sdu->buf[sms_sdu->buf[0] + 1]; /* *----------------------------------------------------------------- * process protocol identifier *----------------------------------------------------------------- */ sm -> pid = sms_deliver->tp_pid; /* *----------------------------------------------------------------- * process data coding scheme *----------------------------------------------------------------- */ sm -> dcs = sms_deliver->tp_dcs; /* *----------------------------------------------------------------- * process short message data, expanding from 7 to 8 bit *----------------------------------------------------------------- */ if (sms_deliver->v_tp_ud) { /* user data */ cmhSMS_expdSmsPp ( 0, sms_deliver->tp_dcs, sms_deliver->tp_ud.data, sms_deliver->tp_ud.length, sm -> data.data, &sm->data.len ); sm->udh.len = 0; } else { alphabet = cmhSMS_getAlphabetPp ( sms_deliver->tp_dcs ); /* user data header */ memcpy (sm->udh.data, sms_deliver->tp_udh_inc.tp_udh.data, sms_deliver->tp_udh_inc.tp_udh.c_data); sm->udh.len = sms_deliver->tp_udh_inc.tp_udh.c_data; /* user data (only user data can be 7bit data!!!) */ cmhSMS_expdSmsPp ( (UBYTE)(sm->udh.len+1), sms_deliver->tp_dcs, sms_deliver->tp_udh_inc.data, sms_deliver->tp_udh_inc.length, /* ACI-SPR-9440 */ sm->data.data, &sm->data.len ); /* 7-bit data */ if (alphabet EQ 0x00) { sm->data.len = sms_deliver->tp_udh_inc.length - ((sm->udh.len+1)*8)/7; /* minus space for the fill bits */ if (((sm->udh.len+1)*8)%7 NEQ 0) sm->data.len--; } /* 8-bit data */ else { sm->data.len = sms_deliver->tp_udh_inc.length-(sm->udh.len+1); } } /* *----------------------------------------------------------------- * process service center time stamp *----------------------------------------------------------------- */ sm -> vp_rel = 0; memset ( &sm->vp_enh, 0, sizeof(T_ACI_VP_ENH) ); cmhSMS_setVpabsCmh ( &sm -> scts, (T_tp_vp_abs*) &sms_deliver->tp_scts ); return (TRUE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_cpySubmit | +--------------------------------------------------------------------+ PURPOSE : converts a SMS-SUBMIT message to the T_ACI_CMGL_SM structure */ GLOBAL BOOL cmhSMS_cpySubmit ( T_ACI_CMGL_SM * sm, T_sms_sdu * sms_sdu ) { T_rp_addr rp_addr; UBYTE* message; T_TP_SUBMIT *sms_submit; UBYTE alphabet; TRACE_FUNCTION("cmhSMS_cpySubmit()"); message = cmhSMS_decodeMsg(sms_sdu, &rp_addr, SMS_VT_SUBMIT); if (message EQ NULL) { sm->stat = SMS_STAT_Invalid; return (FALSE); } if ( message[0] NEQ SMS_VT_SUBMIT) { TRACE_EVENT_P1("wrong VTI = %x", message[0]); } sms_submit = (T_TP_SUBMIT*)message; /* *----------------------------------------------------------------- * process recepient address *----------------------------------------------------------------- */ if (sms_submit->tp_da.ton EQ SMS_TON_ALPHANUMERIC) { UBYTE i,j = 0; UBYTE dest_len; CHAR address_buf[MAX_SMS_ADDR_DIG/2]; for (i = 0 ; i < sms_submit->tp_da.digits ; i=i+2) { address_buf[j] = (UBYTE)(sms_submit->tp_da.num[i+1] << 4) + (UBYTE)(sms_submit->tp_da.num[i]); j++; } dest_len = utl_cvt7To8 ( (UBYTE*)address_buf, j, (UBYTE*)sm->adress, 0); sm -> adress[dest_len] = '\0'; } else cmhSMS_getAdrStr ( sm -> adress, MAX_SMS_NUM_LEN - 1, sms_submit->tp_da.num, sms_submit->tp_da.digits ); sm -> toa.ton = cmhSMS_getTon ( sms_submit->tp_da.ton ); sm -> toa.npi = cmhSMS_getNpi ( sms_submit->tp_da.npi ); /* *----------------------------------------------------------------- * process service center address *----------------------------------------------------------------- */ cmhSMS_getAdrStr ( sm -> sca, MAX_SMS_NUM_LEN - 1, rp_addr.num, rp_addr.c_num); sm -> tosca.ton = cmhSMS_getTon ( rp_addr.ton ); sm -> tosca.npi = cmhSMS_getNpi ( rp_addr.npi ); /* *----------------------------------------------------------------- * process alphanumerical phonebook entry *----------------------------------------------------------------- */ psaCC_phbMfwSrchNumPlnTxt ( sm -> adress, &sm -> alpha ); /* *----------------------------------------------------------------- * process first octet *----------------------------------------------------------------- */ sm -> fo = sms_sdu->buf[sms_sdu->buf[0] + 1]; /* *----------------------------------------------------------------- * process protocol identifier *----------------------------------------------------------------- */ sm -> pid = sms_submit->tp_pid; /* *----------------------------------------------------------------- * process data coding scheme *----------------------------------------------------------------- */ sm -> dcs = sms_submit->tp_dcs; /* *----------------------------------------------------------------- * process short message data, expanding from 7 to 8 bit *----------------------------------------------------------------- */ if (sms_submit->v_tp_ud) { /* user data */ cmhSMS_expdSmsPp ( 0, sms_submit->tp_dcs, sms_submit->tp_ud.data, sms_submit->tp_ud.length, /* ACI-SPR-9440 */ sm->data.data, &sm->data.len ); sm->udh.len = 0; } else { alphabet = cmhSMS_getAlphabetPp ( sms_submit->tp_dcs ); /* user data header */ memcpy (sm->udh.data, sms_submit->tp_udh_inc.tp_udh.data, sms_submit->tp_udh_inc.tp_udh.c_data); sm->udh.len = sms_submit->tp_udh_inc.tp_udh.c_data; /* user data (only user data can be 7bit data!!!) */ cmhSMS_expdSmsPp ( (UBYTE)(sm->udh.len+1), sms_submit->tp_dcs, sms_submit->tp_udh_inc.data, sms_submit->tp_udh_inc.length, /* ACI-SPR-9440 */ sm->data.data, &sm->data.len ); /* 7-bit data */ if (alphabet EQ 0x00) { sm->data.len = sms_submit->tp_udh_inc.length - ((sm->udh.len+1)*8)/7; /* minus space for the fill bits */ if (((sm->udh.len+1)*8)%7 NEQ 0) sm->data.len--; } /* 8-bit data */ else { sm->data.len = sms_submit->tp_udh_inc.length-(sm->udh.len+1); } } /* *----------------------------------------------------------------- * process validity period *----------------------------------------------------------------- */ if (sms_submit->v_tp_vp_abs) { cmhSMS_setVpabsCmh ( &sm->scts, &sms_submit->tp_vp_abs ); sm -> vp_rel = 0; memset ( &sm->vp_enh, 0, sizeof(T_ACI_VP_ENH) ); } else if (sms_submit->v_tp_vp_enh) { cmhSMS_setVpenhCmh ( &sm->vp_enh, &sms_submit->tp_vp_enh ); sm -> vp_rel = 0; memset ( &sm->scts, 0, sizeof(T_ACI_VP_ABS) ); } else { sm -> vp_rel = sms_submit->tp_vp_rel; memset ( &sm -> scts, 0, sizeof(T_ACI_VP_ABS) ); memset ( &sm -> vp_enh, 0, sizeof(T_ACI_VP_ENH) ); } return (TRUE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_cpyMsgInd | +--------------------------------------------------------------------+ PURPOSE : handles a message indication */ GLOBAL BOOL cmhSMS_cpyMsgInd ( T_ACI_CMGL_SM * sm, T_MNSMS_MESSAGE_IND * mnsms_message_ind) { BOOL ret = FALSE; TRACE_FUNCTION("cmhSMS_cpyMsgInd()"); /* *----------------------------------------------------------------- * decode SMS-DELIVER or SMS-SUBMIT *----------------------------------------------------------------- */ /* * ACI-SPR-17004: set RFU bits of status to 0 if present since these * should be ignored in a GSM session (GSM 11.11 section 9.3) */ cmhSMS_removeStatusRFUBits( &mnsms_message_ind->status ); switch (mnsms_message_ind->status) { case SMS_RECORD_REC_UNREAD: case SMS_RECORD_REC_READ: ret = cmhSMS_cpyDeliver ( sm, &mnsms_message_ind->sms_sdu ); break; case SMS_RECORD_STO_UNSENT: case SMS_RECORD_STO_SENT: /* ACI-SPR-17003: Handle unsupported statuses */ case SMS_RECORD_STAT_UNRCVD: case SMS_RECORD_STAT_UNSTRD: case SMS_RECORD_STAT_STRD: ret = cmhSMS_cpySubmit ( sm, &mnsms_message_ind->sms_sdu ); break; /* 21.Mar.2003 currently not used by SMS entity */ /* * case SMS_RECORD_INVALID: * ret = FALSE; * break; */ default: TRACE_EVENT("incorrect status"); } /* *----------------------------------------------------------------- * process status (convert from PSA type to CMH type) *----------------------------------------------------------------- */ if (sm->stat NEQ SMS_STAT_Invalid) { cmhSMS_getStatCmh ( mnsms_message_ind->status, &sm -> stat ); } /* *----------------------------------------------------------------- * process message reference *----------------------------------------------------------------- */ sm -> msg_ref = mnsms_message_ind->rec_num; /* *----------------------------------------------------------------- * process tp_status *----------------------------------------------------------------- */ sm ->tp_status = -1; return (ret); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_cpyReadCnf | +--------------------------------------------------------------------+ PURPOSE : handles a read confirmation */ GLOBAL BOOL cmhSMS_cpyReadCnf ( T_ACI_CMGL_SM * sm, T_MNSMS_READ_CNF * mnsms_read_cnf ) { BOOL ret = FALSE; TRACE_FUNCTION("cmhSMS_cpyReadCnf()"); /* * ACI-SPR-17004: set RFU bits of status to 0 if present since these * should be ignored in a GSM session (GSM 11.11 section 9.3) */ cmhSMS_removeStatusRFUBits( &mnsms_read_cnf->status ); switch (mnsms_read_cnf->status) { case SMS_RECORD_REC_UNREAD: case SMS_RECORD_REC_READ: ret = cmhSMS_cpyDeliver ( sm, &mnsms_read_cnf->sms_sdu ); break; case SMS_RECORD_STO_UNSENT: case SMS_RECORD_STO_SENT: /* ACI-SPR-17003: Handle unsupported statuses */ case SMS_RECORD_STAT_UNRCVD: case SMS_RECORD_STAT_UNSTRD: case SMS_RECORD_STAT_STRD: ret = cmhSMS_cpySubmit ( sm, &mnsms_read_cnf->sms_sdu ); break; /* 21.Mar.2003 currently not used by SMS entity */ /* * case SMS_RECORD_INVALID: * ret = FALSE; * break; */ default: TRACE_EVENT("incorrect status"); } /* *----------------------------------------------------------------- * process status (PSA format -> CMH format) *----------------------------------------------------------------- */ if (sm->stat NEQ SMS_STAT_Invalid) { cmhSMS_getStatCmh ( mnsms_read_cnf->status, &sm -> stat ); } /* *----------------------------------------------------------------- * process message reference *----------------------------------------------------------------- */ sm -> msg_ref = mnsms_read_cnf->rec_num; /* *----------------------------------------------------------------- * process tp_status *----------------------------------------------------------------- */ sm ->tp_status = -1; return (ret); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_cpyStatInd | +--------------------------------------------------------------------+ PURPOSE : handles a status indication */ GLOBAL BOOL cmhSMS_cpyStatInd ( T_ACI_CDS_SM * sm, T_MNSMS_STATUS_IND *mnsms_status_ind ) { T_rp_addr rp_addr; UBYTE* message; T_TP_STATUS *sms_status; TRACE_FUNCTION("cmhSMS_cpyStatInd()"); message = cmhSMS_decodeMsg(&mnsms_status_ind->sms_sdu, &rp_addr, SMS_VT_STATUS); if (message EQ NULL) { return (FALSE); } if ( message[0] NEQ SMS_VT_STATUS) { TRACE_EVENT_P1("wrong VTI = %x", message[0]); } sms_status = (T_TP_STATUS*)message; /* *----------------------------------------------------------------- * process message type *----------------------------------------------------------------- */ sm -> fo = mnsms_status_ind->sms_sdu.buf[mnsms_status_ind->sms_sdu.buf[0]+1]; /* *----------------------------------------------------------------- * process message reference *----------------------------------------------------------------- */ sm -> msg_ref = sms_status->tp_mr; /* *----------------------------------------------------------------- * process recipient address *----------------------------------------------------------------- */ cmhSMS_getAdrStr ( sm->addr, MAX_SMS_ADDR_DIG - 1, sms_status->tp_ra.num, sms_status->tp_ra.digits); sm->toa.ton = cmhSMS_getTon ( sms_status->tp_ra.ton ); sm->toa.npi = cmhSMS_getNpi ( sms_status->tp_ra.npi ); /* *----------------------------------------------------------------- * process service center time stamp *----------------------------------------------------------------- */ cmhSMS_setVpabsCmh ( &sm->vpabs_scts, (T_tp_vp_abs*) &sms_status->tp_scts ); /* *----------------------------------------------------------------- * process discharge time *----------------------------------------------------------------- */ cmhSMS_setVpabsCmh ( &sm->vpabs_dt, (T_tp_vp_abs*) &sms_status->tp_dt ); /* *----------------------------------------------------------------- * process status *----------------------------------------------------------------- */ sm -> tp_status = sms_status->tp_st; return (TRUE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_getPhbEntry | +--------------------------------------------------------------------+ PURPOSE : gets phone book entry from coded SM */ GLOBAL void cmhSMS_getPhbEntry( UBYTE *buf, T_ACI_PB_TEXT *alpha, T_ACI_SMS_STAT status ) { UBYTE *p_data; UBYTE sca_len; UBYTE nplan; UBYTE no_bcd; UBYTE bcd[MAX_SMS_ADDR_DIG]; CHAR addr[MAX_SMS_ADDR_DIG+1]; /* for '\0' */ USHORT octets; alpha->len = 0; p_data = &buf[0]; sca_len = buf[0]; switch (status) { case SMS_STAT_RecUnread: case SMS_STAT_RecRead: if ((*(p_data+sca_len+1) & TP_MTI_MASK) EQ TP_MTI_SMS_STATUS_REP) { p_data++; } p_data += (sca_len+1) + 1; /* sms-deliver */ break; case SMS_STAT_StoUnsent: case SMS_STAT_StoSent: p_data += (sca_len+1) + 2; /* sms-submit */ break; default: return; } /* process originator/destination address */ no_bcd = *p_data++; no_bcd = MINIMUM(no_bcd, MAX_SMS_ADDR_DIG); nplan = *p_data++ & 0x0F; /* npi */ octets = (no_bcd+1)/2; no_bcd = (UBYTE)cmh_unpackBCD (bcd, p_data, octets); if (nplan EQ 0x05) /* VO patch - if (patch) else ... */ { UBYTE i,j = 0; for (i = 0 ; i < no_bcd; i=i+2) { addr[j] = (UBYTE)(bcd[i+1] << 4) + (UBYTE)(bcd[i]); j++; } addr[j] = '\0'; } else { cmhSMS_getAdrStr ( addr, MAX_SMS_ADDR_DIG, bcd, no_bcd ); } /* *----------------------------------------------------------------- * process alphanumerical phonebook entry *----------------------------------------------------------------- */ psaCC_phbMfwSrchNumPlnTxt ( addr, alpha ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_codeDelRep | +--------------------------------------------------------------------+ PURPOSE : codes RP-ACK for SMS-DELIVER-REPORT (without PID, DCS, UD) */ GLOBAL void cmhSMS_codeDelRep(T_sms_sdu *sms_sdu, T_rp_addr *sc_addr) { UBYTE sca_len; /* SCA len incl. length byte and toa */ UBYTE sca_buf[MAX_SMS_ADDR_DIG/2 + 2]; sca_len = CodeRPAddress( sca_buf, sc_addr->c_num, sc_addr->ton, sc_addr->npi, sc_addr->num ); sms_sdu->l_buf = (sca_len+2)<<3; sms_sdu->o_buf = 0; memcpy ( sms_sdu->buf, sca_buf, sca_len); memset ( sms_sdu->buf+sca_len, 0, 2); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : CodeRPAddress | +--------------------------------------------------------------------+ PURPOSE : converts address (in BCD format) to semi-octet representation (including address-length, ton and npi), for RP addresses (e.g SCA) returns number of octets including address-length, ton and npi */ GLOBAL UBYTE CodeRPAddress( UBYTE *buf, UBYTE numDigits, UBYTE ton, UBYTE npi, UBYTE *bcd ) { UBYTE length; if (numDigits EQ 0) { length = 1; *buf = 0x00; } else { *buf++ = (numDigits+1)/2 + 1; *buf++ = (ton << 4) + npi + 0x80; length = (UBYTE)cmh_packBCD ( buf, bcd, numDigits ); /* add length of length field, ton and npi */ length += 2; } return length; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : CodeTPAddress | +--------------------------------------------------------------------+ PURPOSE : converts address (in BCD format) to semi-octet representation (including address-length, ton and npi), for TP addresses (e.g OA or DA) returns number of octets including including address-length, ton and npi */ GLOBAL UBYTE CodeTPAddress( UBYTE *buf, UBYTE numDigits, UBYTE ton, UBYTE npi, UBYTE *bcd ) { UBYTE length; *buf++ = numDigits; *buf++ = (ton << 4) + npi + 0x80; length = (UBYTE)cmh_packBCD ( buf, bcd, numDigits ); /* add length of length field, to and npi */ length += 2; return length; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : DecodeRPAddress | +--------------------------------------------------------------------+ PURPOSE : converts RP address (SC address) from semi-octet representation to address in BCD format (including address-length, ton and npi) returns number of processed octets in buf */ GLOBAL UBYTE DecodeRPAddress(UBYTE *c_num, UBYTE *ton, UBYTE *npi, UBYTE *bcd, UBYTE *buf) { UBYTE sca_length; /* sca length is lenth in bytes plus TOA-octet */ UBYTE processed_octets; sca_length = *buf++; *ton = (*buf & 0x70)>>4; *npi = *buf++ & 0x0F; *c_num = (UBYTE)cmh_unpackBCD (bcd, buf, (USHORT)(sca_length-1)); processed_octets = (*c_num+1)/2 + 2; return processed_octets; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : CMH_SMSF | | STATE : code ROUTINE : DecodeTPAddress | +--------------------------------------------------------------------+ PURPOSE : converts TP address (DA, OA)from semi-octet representation to address in BCD format (including address-length, ton and npi) returns number of processed octets in buf */ GLOBAL UBYTE DecodeTPAddress(UBYTE *c_num, UBYTE *ton, UBYTE *npi, UBYTE *bcd, UBYTE *buf) { UBYTE digits; UBYTE processed_octets; digits = *buf++; *ton = (*buf & 0x70)>>4; *npi = *buf++ & 0x0F; *c_num = (UBYTE)cmh_unpackBCD (bcd, buf, (USHORT)((digits+1)/2)); processed_octets = (*c_num+1)/2 + 2; return processed_octets; } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_fillTpSubmit | +--------------------------------------------------------------------+ PURPOSE : fills a T_TP_SUBMIT */ GLOBAL void cmhSMS_fillTpSubmit (T_TP_SUBMIT* tp_submit, T_ACI_CMD_SRC srcId, UBYTE msgType, UBYTE mr, T_tp_da* da_addr, T_ACI_SM_DATA* data, UBYTE septets, T_ACI_UDH_DATA* udh ) { T_SMS_SET_PRM * pSMSSetPrm; /* points to SMS parameter set */ UBYTE alphabet; TRACE_FUNCTION ("cmhSMS_fillTpSubmit()"); pSMSSetPrm = smsShrdPrm.pSetPrm[srcId]; memset(tp_submit, 0, sizeof(T_TP_SUBMIT)); tp_submit->tp_vt_mti = SMS_VT_SUBMIT; tp_submit->tp_rp = (msgType & TP_RP_MASK) ? 1 : 0; tp_submit->tp_mti = SMS_SUBMIT; tp_submit->tp_mr = mr; tp_submit->tp_srr = (msgType & TP_SRR_MASK) ? 1 : 0; if (da_addr->digits NEQ 0x00) memcpy(&tp_submit->tp_da, da_addr, sizeof(T_tp_da)); tp_submit->tp_pid = pSMSSetPrm -> pid; tp_submit->tp_dcs = pSMSSetPrm -> dcs; switch (msgType & VPF_MASK) { case VPF_RELATIVE: /* validity period relative */ tp_submit->v_tp_vp_rel = 1; tp_submit->tp_vpf = SMS_VPF_RELATIVE; tp_submit->tp_vp_rel = pSMSSetPrm -> vpRel; break; case VPF_ABSOLUTE: /* validity period absolute */ tp_submit->v_tp_vp_abs = 1; tp_submit->tp_vpf = SMS_VPF_ABSOLUTE; memcpy(&tp_submit->tp_vp_abs, &pSMSSetPrm -> vpAbs, sizeof(T_tp_vp_abs)); break; case VPF_ENHANCED: /* validity period enhanced */ tp_submit->v_tp_vp_enh = 1; tp_submit->tp_vpf = SMS_VPF_ENHANCED; memcpy(&tp_submit->tp_vp_enh, &pSMSSetPrm -> vpEnh, sizeof(T_tp_vp_enh)); break; default: /* validity period not present */ break; } alphabet = cmhSMS_getAlphabetPp ( pSMSSetPrm -> dcs ); if ((udh) AND (udh->len)) { tp_submit->tp_udhi = 1; tp_submit->v_tp_udh_inc = 1; tp_submit->tp_udh_inc.tp_udh.c_data = udh->len; memcpy(tp_submit->tp_udh_inc.tp_udh.data, udh->data, udh->len); /* copy user data */ if ((data) AND (data->len)) { tp_submit->tp_udh_inc.c_data = data->len; memcpy(tp_submit->tp_udh_inc.data, data->data, data->len); } /* 7-bit data */ if (alphabet EQ 0x00) { tp_submit->tp_udh_inc.length = septets + (((udh->len+1)*8)/7); /* space for the fill bits */ if (((udh->len+1)*8)%7 NEQ 0) { tp_submit->tp_udh_inc.length++; if ((data EQ NULL) OR (data->len EQ 0)) { tp_submit->tp_udh_inc.c_data = 1; tp_submit->tp_udh_inc.data[0] = 0; /* redundant */ } } } /* 8-bit data */ else { tp_submit->tp_udh_inc.length = tp_submit->tp_udh_inc.c_data+udh->len+1; /* UDH length should be also added */ } } else { /* validity flag set for both normal SMS and empty SMS */ tp_submit->v_tp_ud = 1; if ((data) AND (data->len)) { tp_submit->tp_ud.length = septets; tp_submit->tp_ud.c_data = data->len; memcpy(tp_submit->tp_ud.data, data->data, data->len); } else { /* enters when zero character SMS to be sent */ } } } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_fillTpDeliver | +--------------------------------------------------------------------+ PURPOSE : fills a T_TP_DELIVER (only used by +CMGW) */ GLOBAL void cmhSMS_fillTpDeliver (T_TP_DELIVER* tp_deliver, T_ACI_CMD_SRC srcId, UBYTE msgType, T_tp_oa* oa_addr, T_ACI_SM_DATA* data, UBYTE septets, T_ACI_UDH_DATA* udh ) { T_SMS_SET_PRM * pSMSSetPrm; /* points to SMS parameter set */ UBYTE alphabet; TRACE_FUNCTION ("cmhSMS_fillTpDeliver()"); pSMSSetPrm = smsShrdPrm.pSetPrm[srcId]; memset(tp_deliver, 0, sizeof(T_TP_DELIVER)); tp_deliver->tp_vt_mti = SMS_VT_DELIVER; tp_deliver->tp_rp = (msgType & TP_RP_MASK) ? 1 : 0; tp_deliver->tp_mti = SMS_DELIVER; if (oa_addr->digits NEQ 0x00) memcpy(&tp_deliver->tp_oa, oa_addr, sizeof(T_tp_oa)); tp_deliver->tp_pid = pSMSSetPrm -> pid; tp_deliver->tp_dcs = pSMSSetPrm -> dcs; memcpy(&tp_deliver->tp_scts, &pSMSSetPrm -> vpAbs, sizeof(T_tp_scts)); if ((data) AND (data->len)) { alphabet = cmhSMS_getAlphabetPp ( pSMSSetPrm -> dcs ); if ((udh) AND (udh->len)) { tp_deliver->tp_udhi = 1; tp_deliver->v_tp_udh_inc = 1; tp_deliver->tp_udh_inc.tp_udh.c_data = udh->len; memcpy(tp_deliver->tp_udh_inc.tp_udh.data, udh->data, udh->len); /* copy user data */ tp_deliver->tp_udh_inc.c_data = data->len; memcpy(tp_deliver->tp_udh_inc.data, data->data, data->len); /* 7-bit data */ if (alphabet EQ 0x00) { tp_deliver->tp_udh_inc.length = septets + (((udh->len+1)*8)/7); /* space for the fill bits */ if (((udh->len+1)*8)%7 NEQ 0) tp_deliver->tp_udh_inc.length++; } /* 8-bit data */ else { tp_deliver->tp_udh_inc.length = tp_deliver->tp_udh_inc.c_data; } } else { tp_deliver->v_tp_ud = 1; tp_deliver->tp_ud.length = septets; tp_deliver->tp_ud.c_data = data->len; memcpy(tp_deliver->tp_ud.data, data->data, data->len); } } else /* if ((data) AND (data->len)) */ { tp_deliver->v_tp_ud = 1; tp_deliver->tp_ud.length = 0; } } /* +--------------------------------------------------------------------+ | PROJECT : MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_fillTpCommand | +--------------------------------------------------------------------+ PURPOSE : fills a T_TP_COMMAND */ GLOBAL void cmhSMS_fillTpCommand ( T_TP_COMMAND* tp_command, UBYTE fo, UBYTE ct, UBYTE mr, UBYTE pid, UBYTE mn, T_tp_da* da_addr, T_ACI_CMD_DATA* data, T_ACI_UDH_DATA* udh) { TRACE_FUNCTION ("cmhSMS_fillTpCommand()"); memset(tp_command, 0, sizeof(T_TP_COMMAND)); tp_command->tp_vt_mti = SMS_VT_COMMAND; tp_command->tp_srr = (fo & TP_SRR_MASK) ? 1 : 0; tp_command->tp_mti = SMS_COMMAND; tp_command->tp_mr = mr; tp_command->tp_pid = pid; tp_command->tp_ct = ct; tp_command->tp_mn = mn; if (da_addr->digits NEQ 0x00) memcpy(&tp_command->tp_da, da_addr, sizeof(T_tp_da)); if ((data) AND (data->len)) { if ((udh) AND (udh->len)) { tp_command->tp_udhi = 1; tp_command->v_tp_cdh_inc = 1; tp_command->tp_cdh_inc.tp_udh.c_data = udh->len; memcpy(tp_command->tp_cdh_inc.tp_udh.data, udh->data, udh->len); tp_command->tp_cdh_inc.c_data = data->len; memcpy(tp_command->tp_cdh_inc.data, data->data, data->len); } else { tp_command->v_tp_cd = 1; tp_command->tp_cd.c_data = data->len; memcpy(tp_command->tp_cd.data, data->data, data->len); } } else { /* command length field must be present */ tp_command->v_tp_cd = 1; tp_command->tp_cd.c_data = 0; } } #ifdef FF_CPHS /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_check_voice_mail_ind| +----------------------------------------------------------------------+ PURPOSE : */ LOCAL BOOL cmhSMS_check_voice_mail_ind( T_TP_DELIVER *sms_deliver ) { TRACE_FUNCTION("cmhSMS_check_voice_mail_ind()"); if ( sms_deliver->tp_oa.digits NEQ 4 OR sms_deliver->tp_oa.ton NEQ SMS_TON_ALPHANUMERIC ) { TRACE_EVENT_P2("no vmi -> oa... digits:%d ton:%d", sms_deliver->tp_oa.digits, sms_deliver->tp_oa.ton); return FALSE; } switch (sms_deliver->tp_dcs & 0xF0) { case SMS_DCS_GRP_DEF: case SMS_DCS_GRP_CLASS: if ( (sms_deliver->tp_dcs & 0xF) EQ 0 OR (sms_deliver->tp_dcs & 0xF) EQ 0xC ) { break; /* GSM Default Alphabet */ } /* no break, if FALSE */ /*lint -fallthrough*/ case SMS_DCS_GRP_COMPR: case SMS_DCS_GRP_CLASS_COMPR: case SMS_DCS_GRP_MW_STORE_UCS2: TRACE_EVENT_P1("no vmi -> dcs: %d", sms_deliver->tp_dcs); return FALSE; /* no GSM Default Alphabet */ case SMS_DCS_DATA_CLASS: if (sms_deliver->tp_dcs & 0x4) { TRACE_EVENT_P1("no vmi -> dcs: %d", sms_deliver->tp_dcs); return FALSE; /* no GSM Default Alphabet */ } } if (!sms_deliver->v_tp_ud) { TRACE_EVENT("no vmi -> no ud"); return FALSE; /* not only text present */ } if ( ( sms_deliver->tp_ud.length NEQ 1 ) OR ( (sms_deliver->tp_ud.data[0] & 0x7F) NEQ ' ') ) { TRACE_EVENT_P2("no vmi -> ud... length:%d data[0]:%d", sms_deliver->tp_ud.length, sms_deliver->tp_ud.data[0]); return FALSE; /* no single space */ } TRACE_FUNCTION ("CPHS VWI: send to cphs module"); return TRUE; } /* +-------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_voice_mail_ind_get_line| +-------------------------------------------------------------------------+ PURPOSE : */ LOCAL void cmhSMS_voice_mail_ind_get_data( T_TP_DELIVER *sms_deliver, UBYTE *flag_set, T_CPHS_LINES *line ) { TRACE_FUNCTION("cmhSMS_voice_mail_ind_get_line()"); /* get flag set, which is send in the first bit of the first byte of the originating address number. Due to the decoding each byte of the originating address number is now splitted into 2 bytes, so that the first 4 bits of the former first byte can be found in byte 1 */ *flag_set = sms_deliver->tp_oa.num[0] & 0x1; /* line is coded in character 1 bit 1 of GSM originating address. the originating address of T_TP_DELIVER is allready decoded so that this information is to be found in byte 3 of the originating address number */ if (sms_deliver->tp_oa.num[2] & 0x1) { *line = CPHS_LINE2; } else { *line = CPHS_LINE1; } } /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_voice_mail_ind | +----------------------------------------------------------------------+ PURPOSE : */ GLOBAL BOOL cmhSMS_voice_mail_ind( T_sms_sdu *sms_sdu) { T_TP_DELIVER *sms_deliver; T_rp_addr rp_addr; T_CPHS_LINES line; UBYTE flag_set; UBYTE *message; TRACE_FUNCTION("cmhSMS_voice_mail_ind()"); /* check if cphs is active */ /* check if indication is voice mail indication */ if ( sms_sdu ) { message = cmhSMS_decodeMsg(sms_sdu, &rp_addr, SMS_VT_DELIVER); if (message EQ NULL) return FALSE; if ( message[0] NEQ SMS_VT_DELIVER) { TRACE_EVENT_P1("wrong VTI = %x", message[0]); } sms_deliver = (T_TP_DELIVER*)message; if ( cphs_check_status() EQ CPHS_OK ) { if ( cmhSMS_check_voice_mail_ind(sms_deliver) ) { cmhSMS_voice_mail_ind_get_data(sms_deliver, &flag_set, &line); cphs_voice_mail_ind(flag_set, line); return TRUE; } } } return FALSE; } #endif /* FF_CPHS*/ /* +----------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | ROUTINE : cmhSMS_resetMtDsCnmiParam | +----------------------------------------------------------------------+ PURPOSE : this function resets the <mt> and <ds> parameter for the SMS acknowledge in Phase2+ mode (+CNMA). */ GLOBAL void cmhSMS_resetMtDsCnmiParam(void) { smsShrdPrm.mtHndl = 0; /* reset <mt> and <ds> param in error case */ smsShrdPrm.srHndl = 0; smsShrdPrm.CNMImt = 0; smsShrdPrm.CNMIds = 0; { /* inform the SMS entity about the parameter changes */ PALLOC (mnsms_configure_req, MNSMS_CONFIGURE_REQ); /* fill in primitive parameter: command request */ mnsms_configure_req -> pref_mem_3 = smsShrdPrm.mem3; mnsms_configure_req -> mt = smsShrdPrm.mtHndl; mnsms_configure_req -> ds = smsShrdPrm.srHndl; mnsms_configure_req -> mhc = (smsShrdPrm.CSMSservice NEQ CSMS_SERV_GsmPh2Plus) ? SMS_MHC_PH2 : SMS_MHC_PH2PLUS; mnsms_configure_req->v_cmms_mode = FALSE; mnsms_configure_req->v_tmms_val = FALSE; PSENDX (SMS, mnsms_configure_req); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSS | | STATE : code ROUTINE : sAT_PlusCMGWPdu | +-------------------------------------------------------------------+ PURPOSE : This is the internal function which is responsible for storing messages into the mobile station or SIM card. AT command which is responsible for writing a short message to memory in PDU mode. */ GLOBAL BOOL cmhSMS_storePduToSim( T_ACI_CMD_SRC srcId, UBYTE stat, T_ACI_SM_DATA *pdu ) { T_ACI_RETURN ret; TRACE_FUNCTION ("cmhSMS_storePduToSim()"); /* check if command executable */ if(!cmhSMS_checkAccess (srcId, &ret)) { return FALSE; } { PALLOC (mnsms_store_req, MNSMS_STORE_REQ); mnsms_store_req -> mem_type = smsShrdPrm.mem2; mnsms_store_req -> rec_num = CMGW_IDX_FREE_ENTRY; mnsms_store_req -> condx = SMS_CONDX_OVR_NON; mnsms_store_req -> status = stat; if ( (pdu->len > 0) AND (pdu->len <= SIM_PDU_LEN) ) { mnsms_store_req->sms_sdu.l_buf = pdu->len * 8; mnsms_store_req->sms_sdu.o_buf = 0; memcpy (mnsms_store_req->sms_sdu.buf, pdu->data, pdu->len); } else { TRACE_FUNCTION ("cmhSMS_storePduToSim() : wrong PDU len"); PFREE (mnsms_store_req); return FALSE; } PSENDX (SMS, mnsms_store_req); } smsShrdPrm.smsEntStat.curCmd = AT_CMD_CMGW; smsShrdPrm.smsEntStat.entOwn = smsShrdPrm.owner = srcId; smsShrdPrm.uiInternalSmsStorage = srcId; return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_removeStatusRFUBits | +--------------------------------------------------------------------+ PURPOSE : ACI-SPR-17004: Method for removing of SMS RFU status bits as defined by GSM 11.11 section 9.3 */ GLOBAL void cmhSMS_removeStatusRFUBits ( UBYTE* status ) { TRACE_FUNCTION("cmhSMS_removeStatusRFUBits()"); /* See GSM 11.11 section 10.5.3 for position of RFU bits in status */ /* test the pattern of the three lowest bits, match for "101" */ if ((*status & 0x07) EQ 0x05) { /* set the highest three bits to 0 */ *status &= 0x1F; } else { /* set the highest five bits to 0 */ *status &= 0x07; } } /* +-------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhSMS_convertDeliverStatusToACI| +-------------------------------------------------------------------------+ PURPOSE : converts the SMS delivery status to ACI CPRSM status. */ GLOBAL T_ACI_CPRSM_MOD cmhSMS_convertDeliverStatusToACI ( UBYTE status ) { T_ACI_CPRSM_MOD mode; TRACE_FUNCTION("cmhSMS_convertDeliverStatusToACI()"); switch (status) { case SMS_DELIVER_STATUS_PAUSE: mode = CPRSM_MOD_Pause; break; case SMS_DELIVER_STATUS_RESUME: mode = CPRSM_MOD_Resume; break; default: mode = CPRSM_MOD_NotPresent; } return mode; } /*==== EOF ========================================================*/