FreeCalypso > hg > freecalypso-sw
diff gsm-fw/g23m-gsm/sms/sms_tlf.c @ 673:2f7df7a314f8
gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 28 Sep 2014 23:20:04 +0000 |
parents | |
children | 2d8cb1c85e01 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gsm-fw/g23m-gsm/sms/sms_tlf.c Sun Sep 28 23:20:04 2014 +0000 @@ -0,0 +1,3565 @@ +/* ++----------------------------------------------------------------------------- +| Project : GSM-F&D (8411) +| Modul : SMS_TLF ++----------------------------------------------------------------------------- +| 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 Modul defines the functions for the transfer layer +| capability of the module Short Message Service. ++----------------------------------------------------------------------------- +*/ + +#ifndef SMS_TLF_C +#define SMS_TLF_C + +#define ENTITY_SMS + +/*==== INCLUDES ===================================================*/ + +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include "typedefs.h" +#include "pcm.h" +#include "vsi.h" +#include "custom.h" +#include "gsm.h" +#include "message.h" +#include "ccdapi.h" +#include "prim.h" +#include "cus_sms.h" +#include "cnf_sms.h" +#include "mon_sms.h" +#include "pei.h" +#include "tok.h" +#include "sms.h" +#include "gdi.h" +#include "sms_em.h" + +/*==== EXPORT ======================================================*/ + +/*==== PRIVAT ======================================================*/ + +static const UBYTE ref_nr_23430[] = { + 0xE, 0x3, 0x8, 0x7, 0x9, 0x5, 0xE, 0x3, 0x7}; + +/*==== VARIABLES ===================================================*/ + +/* Implements Measure#32: Row 84, 96, 87, 89, 95, 97, 104, 109 & 113 */ +const char * const ef_sms_id = EF_SMS_ID; + +/*==== FUNCTIONS ===================================================*/ + +/* Implements Measure# 14 */ +/* ++---------------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_send_sim_update_req | ++---------------------------------------------------------------------------+ + + PURPOSE : This routine process SIM update request and SMS memo resume request + +*/ + + +LOCAL void tl_send_sim_update_req(UBYTE trans_data, USHORT offset) +{ + GET_INSTANCE_DATA; + UBYTE sim_acc_ix; + TRACE_FUNCTION("tl_send_sim_update_req()"); + /* + * update sim notification flag + */ + if (sms_data->sim_phase >= PHASE_2_SIM) + { + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + PALLOC (update_req, SIM_UPDATE_REQ); + + update_req->source = SRC_SMS; + update_req->req_id = sim_acc_ix; + update_req->v_path_info = FALSE; + update_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMSS; + update_req->length = 1; + update_req->trans_data[0] = trans_data; + update_req->offset = offset; + + PSENDX (SIM, update_req); + + if(sms_data->inst == INST_MO) + tl_set_access_fifo (ACCESS_BY_MMI); + else + tl_set_access_fifo (ACCESS_BY_NET); + } + } +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_get_octet_len | +| ROUTINE : tl_adjust_message_len | ++--------------------------------------------------------------------+ + + PURPOSE : Derive the number of octets of TP-User-Data and the whole + message regarding the Data Coding Scheme. +*/ + +LOCAL BOOL tl_udl_count_septet (UBYTE dcs) +{ + BOOL isSeptet = TRUE; + + switch (dcs & 0xF0) + { + case 0x00: + case 0x10: + if ((dcs & 0xC) EQ 0x4 OR /* 8-bit data */ + (dcs & 0xC) EQ 0x8) /* UCS2 data */ + isSeptet = FALSE; + break; + case 0x20: /* compressed data */ + case 0x30: /* compressed data */ + case 0xE0: /* UCS2 data */ + isSeptet = FALSE; + break; + case 0xF0: + if ((dcs & 0x4) NEQ 0) /* 8-bit data */ + isSeptet = FALSE; + break; + } + return isSeptet; +} + +LOCAL USHORT tl_get_octet_len (USHORT tp_udl, UBYTE dcs) +{ + if (tl_udl_count_septet (dcs)) /* convert number of septets */ + return (USHORT)((tp_udl + 1) * 7 / 8); + + return tp_udl; +} + +GLOBAL void tl_adjust_message_len (UBYTE tp_vt_mti, BUF_tpdu *tpdu) +{ + USHORT oct_len, pre_len; + UBYTE dcs; + UBYTE *tp_data, *tp_msg; + + if (tp_vt_mti EQ SMS_VT_SIM_PDU) + { + pre_len = tpdu->b_tpdu[0] + 1; + tp_msg = &tpdu->b_tpdu[pre_len]; + switch (*tp_msg & 0x3) + { + case SMS_SUBMIT: + tp_vt_mti = SMS_VT_SUBMIT; + break; + case SMS_DELIVER: + tp_vt_mti = SMS_VT_DELIVER; + break; + case SMS_STATUS_REPORT: + tp_vt_mti = SMS_VT_STATUS; + break; + default: + return; + } + } + else + { + pre_len = 0; + tp_msg = &tpdu->b_tpdu[0]; + } + switch (tp_vt_mti) + { + case SMS_VT_SUBMIT: + oct_len = (tp_msg[2] + 1)/2; + tp_data = &tp_msg[5 + oct_len]; + dcs = *tp_data; + + switch ((tp_msg[0] >> 3) & 0x3) /* TP-VPF */ + { /* point to TP-UDL */ + case SMS_VPF_RELATIVE: + tp_data += 2; + oct_len += 8; + break; + case SMS_VPF_ENHANCED: + case SMS_VPF_ABSOLUTE: + tp_data += 8; + oct_len += 14; + break; + default: + tp_data++; + oct_len += 7; + break; + } + oct_len += tl_get_octet_len (*tp_data, dcs); + tpdu->l_tpdu = (oct_len + pre_len) << 3; + break; + case SMS_VT_DELIVER: + oct_len = (tp_msg[1] + 1)/2; + tp_data = &tp_msg[4 + oct_len]; + dcs = *tp_data; + tp_data += 8; /* point to TP-UDL */ + oct_len += (13 + tl_get_octet_len (*tp_data, dcs)); + tpdu->l_tpdu = (oct_len + pre_len) << 3; + break; + case SMS_VT_STATUS: + oct_len = (tp_msg[2] + 1)/2 + 19; + tp_data = &tp_msg[oct_len]; /* tp_data points to PI */ + if(*tp_data NEQ NOT_PRESENT_8BIT) + { + dcs = *(tp_data+2); + tp_data += 3; /* point to TP-UDL */ + oct_len += (3 + tl_get_octet_len (*tp_data, dcs)); + tpdu->l_tpdu = (oct_len + pre_len) << 3; + } + else + { + tpdu->l_tpdu = (oct_len + pre_len) << 3; + } + break; + default: + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_establish_connection | ++--------------------------------------------------------------------+ + + PURPOSE : Initiate the Establishment of a new connection + +*/ +GLOBAL void tl_establish_connection ( + BOOL incr /* true if reference nr increment needed */) +{ + GET_INSTANCE_DATA; + UBYTE ti; + TRACE_FUNCTION ("tl_establish_connection()"); + + /* + * new instance + */ + GET_NEW_SMS_INSTANCE(0); + /* + * increment TI + */ + ti = csf_get_new_mo_ti(); +#if defined (GPRS) + /* + * Set downlink according to prefs, + * in case of LL it has to be checked first if up + */ + if ( ( (sms_data->mo_dst_pref EQ GPRS_SMS_GPRS_PREF) || + (sms_data->mo_dst_pref EQ GPRS_SMS_GPRS_ONLY) ) /*&& + ( sms_data->llc_flow NEQ SMS_LLC_UNKNOWN )*/ ) + { + SMS_INST.downlink = SMS_DOWNLINK_LL_CHECK; + TRACE_EVENT("downlink = SMS_DOWNLINK_LL_CHECK"); + } + else + { + SMS_INST.downlink = SMS_DOWNLINK_MMSMS; + TRACE_EVENT("downlink = SMS_DOWNLINK_MMSMS"); + } +#endif /* GPRS */ + if (incr) + { + /* + * increment reference + */ + ++SMS_INST.tp_mr; + /* + * SIM_UPDATE_REQ + */ + tl_build_sim_update_req(); + } + TRACE_EVENT_P2("TI=%u TP_MR=%u", ti, SMS_INST.tp_mr); + /* + * RL_ESTABLISH_REQ + */ + rl_establish_req(ti); +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_build_status_rep | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_BUILD_STATUS_REP. + +*/ + +GLOBAL void tl_build_status_rep (T_rp_data_dl *rp_data_dl, + T_MNSMS_STATUS_IND *status_ind) +{ + T_SIM_PDU *sim_pdu; + + TRACE_FUNCTION ("tl_build_status_rep()"); + + memset (&status_ind->sms_sdu, 0, sizeof(T_sms_sdu)); + + if (rp_data_dl NEQ NULL) + { + MALLOC (sim_pdu, sizeof(T_SIM_PDU)); + + sim_pdu->rp_addr = rp_data_dl->rp_addr; + sim_pdu->tpdu = rp_data_dl->rp_user_data.tpdu; + sim_pdu->tp_mti = SMS_STATUS_REPORT; + sim_pdu->v_tpdu = TRUE; + sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; + + ccd_codeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)&status_ind->sms_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU); + + MFREE (sim_pdu); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_modify_submit | ++--------------------------------------------------------------------+ + + PURPOSE : The SM taken from storage (rec_data) is modified with + certain values from parameter 'sms_sdu' according to + parameter 'modify'. The resulting message is returned in + parameter 'sim_pdu'. +*/ + +LOCAL void tl_translate_mt_to_mo (T_TP_SUBMIT *submit, + T_TP_DELIVER *deliver) +{ + submit->tp_vt_mti = SMS_VT_SUBMIT; + submit->tp_udhi = deliver->tp_udhi; + submit->tp_mti = SMS_SUBMIT; + submit->tp_mr = NOT_PRESENT_8BIT; + submit->tp_pid = deliver->tp_pid; + submit->tp_dcs = deliver->tp_dcs; + if ((submit->v_tp_ud = deliver->v_tp_ud) NEQ 0) + { + submit->tp_ud = deliver->tp_ud; + submit->v_tp_udh_inc = FALSE; + } + else if (submit->v_tp_udh_inc= deliver->v_tp_udh_inc) + submit->tp_udh_inc= deliver->tp_udh_inc; +} + +GLOBAL BOOL tl_modify_submit (T_SIM_PDU *sim_pdu, + UBYTE modify, + T_sms_sdu *sms_sdu, + UBYTE *rec_data) +{ + T_TP_SUBMIT *submit; + T_sms_sdu *rec_sdu; + union { + T_TP_SUBMIT *submit; + T_TP_DELIVER *deliver; + } rec_msg; + T_rp_addr rp_addr; + + TRACE_FUNCTION ("tl_modify_submit()"); + + if (modify >= SMS_MODIFY_ALL) + return TRUE; /* ignore message from storage */ + + if ((rec_data[0] & 1) EQ SMS_RECORD_FREE) + return FALSE; /* empty or invalid record */ + + if (ccd_decodeMsg (CCDENT_SMS, BOTH, (T_MSGBUF *)sms_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU) EQ ccdError) + return FALSE; + + rp_addr = sim_pdu->rp_addr; /* keep SCA */ + + MALLOC (submit, sizeof(T_TP_SUBMIT)); + memset (submit, 0, sizeof(T_TP_SUBMIT)); + + if (ccd_decodeMsg (CCDENT_SMS, UPLINK, (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)submit, SMS_VT_SUBMIT) EQ ccdError) + { + MFREE (submit); + return FALSE; + } + MALLOC (rec_sdu, sizeof(T_sms_sdu)); + + rec_sdu->o_buf = 0; + rec_sdu->l_buf = SIM_PDU_LEN<<3; + memcpy (rec_sdu->buf, &rec_data[1], SIM_PDU_LEN); + tl_adjust_message_len (SMS_VT_SIM_PDU, (BUF_tpdu *)rec_sdu); + + if (ccd_decodeMsg (CCDENT_SMS, BOTH, (T_MSGBUF *)rec_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU) EQ ccdError) + { + MFREE (rec_sdu); + return FALSE; + } + MFREE (rec_sdu); + + switch (modify) + { + case SMS_MODIFY_SCA: + sim_pdu->rp_addr = rp_addr; /* SCA from SUBMIT_REQ */ + /*FALLTHROUGH*/ /*lint -fallthrough*/ + case SMS_MODIFY_NON: + switch (rec_data[0] & 7) + { + case SMS_RECORD_REC_UNREAD: + case SMS_RECORD_REC_READ: + if (sim_pdu->tp_mti NEQ SMS_DELIVER OR !sim_pdu->v_tpdu) + { + MFREE (submit); + return FALSE; + } + MALLOC (rec_msg.deliver, sizeof(T_TP_DELIVER)); + memset (rec_msg.deliver, 0, sizeof(T_TP_DELIVER)); + + if (ccd_decodeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)rec_msg.deliver, + SMS_VT_DELIVER) EQ ccdError) + { + MFREE (rec_msg.deliver); + return FALSE; + } + tl_translate_mt_to_mo (submit, rec_msg.deliver); + memcpy (&submit->tp_da, &rec_msg.deliver->tp_oa, + sizeof(T_tp_da)); + MFREE (rec_msg.deliver); + + sim_pdu->tpdu.o_tpdu = 0; + sim_pdu->tpdu.l_tpdu = TPDU_BIT_LEN; + if (ccd_codeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)submit, SMS_VT_SUBMIT) NEQ ccdOK) + { + MFREE (submit); + return FALSE; + } + MFREE (submit); + break; + /* sim_pdu shall contain a SMS_SUBMIT message */ + default: + MFREE (submit); + if (sim_pdu->tp_mti NEQ SMS_SUBMIT OR !sim_pdu->v_tpdu) + { + return FALSE; + } + break; + } + break; + + case SMS_MODIFY_TPOA_SCA: + sim_pdu->rp_addr = rp_addr; /* SCA from SUBMIT_REQ */ + /* no break */ + case SMS_MODIFY_TPOA: + switch (rec_data[0] & 7) + { + case SMS_RECORD_REC_UNREAD: + case SMS_RECORD_REC_READ: + if (sim_pdu->tp_mti NEQ SMS_DELIVER OR !sim_pdu->v_tpdu) + { + MFREE (submit); + return FALSE; + } + MALLOC (rec_msg.deliver, sizeof(T_TP_DELIVER)); + memset (rec_msg.deliver, 0, sizeof(T_TP_DELIVER)); + + if (ccd_decodeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)rec_msg.deliver, + SMS_VT_DELIVER) EQ ccdError) + { + MFREE (rec_msg.deliver); + return FALSE; + } + tl_translate_mt_to_mo (submit, rec_msg.deliver); + MFREE (rec_msg.deliver); + + sim_pdu->tpdu.o_tpdu = 0; + sim_pdu->tpdu.l_tpdu = TPDU_BIT_LEN; + if (ccd_codeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)submit, SMS_VT_SUBMIT) NEQ ccdOK) + { + MFREE (submit); + return FALSE; + } + MFREE (submit); + break; + /* sim_pdu shall contain a SMS_SUBMIT message */ + default: + if (sim_pdu->tp_mti NEQ SMS_SUBMIT OR !sim_pdu->v_tpdu) + { + MFREE (submit); + return FALSE; + } + MALLOC (rec_msg.submit, sizeof(T_TP_SUBMIT)); + memset (rec_msg.submit, 0, sizeof(T_TP_SUBMIT)); + + if (ccd_decodeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)rec_msg.submit, + SMS_VT_SUBMIT) EQ ccdError) + { + MFREE (rec_msg.submit); + MFREE (submit); + return FALSE; + } + rec_msg.submit->tp_da = submit->tp_da; + MFREE (submit); + + sim_pdu->tpdu.o_tpdu = 0; + sim_pdu->tpdu.l_tpdu = TPDU_BIT_LEN; + if (ccd_codeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)rec_msg.submit, SMS_VT_SUBMIT) NEQ ccdOK) + { + MFREE (rec_msg.submit); + return FALSE; + } + MFREE (rec_msg.submit); + break; + } + break; + + default: + MFREE (submit); + break; + } + sim_pdu->tp_mti = SMS_SUBMIT; + tl_adjust_message_len (SMS_VT_SUBMIT, &sim_pdu->tpdu); + return TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_prepare_submit | ++--------------------------------------------------------------------+ + + PURPOSE : Fills 'cp_data' with required parameters and returns TRUE. + If the parameter check fails nothing is changed and + FALSE is returned. + +*/ + +GLOBAL BOOL tl_prepare_submit ( + T_SIM_PDU *sim_pdu, + T_U_CP_DATA *cp_data) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("tl_prepare_submit()"); + + if (sim_pdu->tp_mti EQ SMS_SUBMIT AND sim_pdu->v_tpdu) + { + // ++SMS_INST.tp_mr; + sim_pdu->tpdu.b_tpdu[1] = SMS_INST.tp_mr; + + SMS_TP_REF_RET(sms_data) = SMS_INST.tp_mr; + + cp_data->cp_user_data_ul.v_rp_error = FALSE; + cp_data->cp_user_data_ul.v_rp_ack = FALSE; + memset (&cp_data->cp_user_data_ul.rp_data_ul, 0, + sizeof (T_rp_data_ul)); + + memcpy (&cp_data->cp_user_data_ul.rp_data_ul.rp_addr, + &sim_pdu->rp_addr, sizeof (T_rp_addr)); + cp_data->cp_user_data_ul.rp_data_ul.rp_user_data.tp_mti + = sim_pdu->tp_mti; + memcpy (&cp_data->cp_user_data_ul.rp_data_ul.rp_user_data.tpdu, + &sim_pdu->tpdu, sizeof (BUF_tpdu)); + cp_data->cp_user_data_ul.rp_data_ul.rp_user_data.v_tpdu + = TRUE; + cp_data->cp_user_data_ul.v_rp_data_ul = TRUE; + + return TRUE; + } + + TRACE_EVENT ("tl_prepare_submit() failed"); + + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_init_complete | ++--------------------------------------------------------------------+ + + PURPOSE : tasks at initialisation (sim read record loop) completion + + DESCRIPTION: - set init_done flag + - send smma message if necessary + - send report indication to user if applicable + +*/ +GLOBAL void tl_init_complete (void) +{ + GET_INSTANCE_DATA; + BOOL notification_flag; + BOOL memory_available; + BOOL mem_avail_msg; + + TRACE_FUNCTION ("tl_init_complete()"); + + /* + * check whether memory available message must be sent + */ + mem_avail_msg = FALSE; + notification_flag = !sms_data->mem_cap_avail; + + if ( (notification_flag == TRUE) AND + (sms_data->pr_cntrl.delivery_state == SMS_DELIVER_STATUS_RESUME) ) + { + memory_available = (tl_get_free_space (MEM_SM) OR + tl_get_free_space (MEM_ME)); + if (memory_available == TRUE) + { + /* + * initiate the sending of memory available message + */ + mem_avail_msg = TRUE; + GET_MO_INSTANCE(sms_data); + /* + * TL state transition TL_ESTABLISH + * EST state transition EST_SMMA + */ + SMS_INST_SET_STATE (STATE_TL, TL_ESTABLISH); + SET_STATE (STATE_EST, EST_SMMA); + /* + * 1st shot + */ + SMS_INST.retrans = FALSE; + /* + * establish connection + */ + tl_establish_connection(FALSE); + } + } + if (mem_avail_msg == FALSE) + { +#ifdef GPRS + cp_send_getunitdata_req (); +#endif + /* + * set state: READY + */ + sms_data->ent_state = SMS_STATE_READY; + /* + * report ind to user + */ + tl_mnsms_report_ind (SMS_STATE_READY); + } + /* + * init done + */ + sms_data->init_done = TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_convert_sim_error | ++--------------------------------------------------------------------+ + + PURPOSE : Converts a SIM error to the appropriate SMS failure code. + +*/ + +GLOBAL USHORT tl_convert_sim_error (USHORT sim_error) +{ +#if 0 + switch (sim_error) + { + case SIM_INVALID_PIN_1: + return SMS_ERR_SIM_PIN1_REQ; + case SIM_INVALID_PUK_1: + return SMS_ERR_SIM_PUK1_REQ; + case SIM_INVALID_PIN_2: + return SMS_ERR_SIM_PIN2_REQ; + case SIM_INVALID_PUK_2: + return SMS_ERR_SIM_PUK2_REQ; + case SIM_INVALID_OFFSET: + return SMS_ERR_INV_INDEX; + case SIM_FATAL_ERROR: + return SMS_ERR_SIM_MISSING; + default: + return SMS_ERR_SIM_FAIL; + } +#else + return sim_error; // prelimary +#endif +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_convert_mo_to_mem | ++--------------------------------------------------------------------+ + + PURPOSE : Prepare a MO-SM to be stored. + +*/ + +GLOBAL BOOL tl_convert_mo_to_mem (T_MMSMS_DATA_REQ *data_req, + UBYTE *data) +{ + T_SIM_PDU *sim_pdu; + T_sms_sdu *sms_sdu; + MCAST (cp_data, U_CP_DATA); + + TRACE_FUNCTION ("tl_convert_mo_to_mem()"); + + data_req->sdu.l_buf -= 8; // point to CP message type! + data_req->sdu.o_buf += 8; + if (ccd_decodeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&data_req->sdu, + (UBYTE *)cp_data, NOT_PRESENT_8BIT) EQ ccdError) + { + return FALSE; + } + if (cp_data->msg_type NEQ U_CP_DATA OR + cp_data->cp_user_data_ul.rp_mti NEQ RP_DATA_UL) + { + return FALSE; + } + MALLOC (sim_pdu, sizeof(T_SIM_PDU)); + MALLOC (sms_sdu, sizeof(T_sms_sdu)); + sms_sdu->o_buf = 0; + sms_sdu->l_buf = SIM_PDU_LEN<<3; + + sim_pdu->rp_addr = cp_data->cp_user_data_ul.rp_data_ul.rp_addr; + sim_pdu->tpdu = cp_data->cp_user_data_ul.rp_data_ul.rp_user_data.tpdu; + sim_pdu->tp_mti = SMS_SUBMIT; + sim_pdu->v_tpdu = TRUE; + sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; + + ccd_codeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)sms_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU); + + /* set status byte */ + data[0] = SMS_RECORD_STO_SENT; + memcpy (&data[1], sms_sdu->buf, sms_sdu->l_buf >> 3); + memset (&data[(sms_sdu->l_buf >> 3) + 1], NOT_PRESENT_8BIT, + (SIZE_EF_SMS-1) - (sms_sdu->l_buf >> 3)); + + MFREE (sim_pdu); + MFREE (sms_sdu); +// CCD_END; + return TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_convert_mt_to_mem | ++--------------------------------------------------------------------+ + + PURPOSE : Prepare a MT-SM to be stored. + +*/ + +GLOBAL void tl_convert_mt_to_mem (T_rp_data_dl *rp_data_dl, + UBYTE *data) +{ + T_SIM_PDU *sim_pdu; + T_sms_sdu *sms_sdu; + + TRACE_FUNCTION ("tl_convert_mt_to_mem()"); + + MALLOC (sim_pdu, sizeof(T_SIM_PDU)); + MALLOC (sms_sdu, sizeof(T_sms_sdu)); + sms_sdu->o_buf = 0; + sms_sdu->l_buf = SIM_PDU_LEN<<3; + + sim_pdu->rp_addr = rp_data_dl->rp_addr; + sim_pdu->tpdu = rp_data_dl->rp_user_data.tpdu; + sim_pdu->tp_mti = SMS_DELIVER; + sim_pdu->v_tpdu = TRUE; + sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; + + ccd_codeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)sms_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU); + + data[0] = SMS_RECORD_REC_UNREAD; + memcpy (&data[1], sms_sdu->buf, sms_sdu->l_buf >> 3); + memset (&data[(sms_sdu->l_buf >> 3) + 1], NOT_PRESENT_8BIT, + (SIZE_EF_SMS-1) - (sms_sdu->l_buf >> 3)); + + MFREE (sim_pdu); + MFREE (sms_sdu); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_get_free_space | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the first not used record for SMS messages. + Returns the index of the first free record in the + range 1..max_record, if no free record exists 0 is returned. + +*/ + +GLOBAL UBYTE tl_get_free_space (UBYTE mem_type) +{ + UBYTE i; + GET_INSTANCE_DATA; + + T_BACKUP * backup; + + TRACE_FUNCTION ("tl_get_free_space()"); + + if (mem_type EQ MEM_ME) + backup = &SMS_ME_PROP(sms_data); + else if (mem_type EQ MEM_SM) + backup = &SMS_SIM_PROP(sms_data); + else + return 0; + + for (i = 1; i <= backup->max_record; i++) + { + if ((tl_get_status (backup, i-1) & 1) EQ 0) + return i; + } + return 0; +} + + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_find_first | ++--------------------------------------------------------------------+ + + PURPOSE : Checks availability of SMS memory on SIM or ME memory. + +*/ + +GLOBAL void tl_find_first (UBYTE mem_type) +{ + GET_INSTANCE_DATA; + + TRACE_FUNCTION ("tl_find_first()"); + + if (mem_type EQ MEM_SM) + { + /* + * Start with index 1 on SIM card + */ + tl_set_access_fifo (ACCESS_BY_MMI); + SET_STATE (STATE_MMI, MMI_FIND_FIRST); + tl_sim_read_record_req (1); + sms_data->sim_backup.any_valid = FALSE; + } + else + { + USHORT max_record; + UBYTE version; + UBYTE *sim_msg; + MALLOC (sim_msg, SIZE_EF_SMS); + + sms_data->me_backup.any_valid = FALSE; + /* + * look at Mobile Memory + */ +/* Implements Measure#32: Row 84 */ + if (pcm_ReadRecord ((UBYTE *)ef_sms_id, 1, SIZE_EF_SMS, + sim_msg, &version, &max_record) EQ PCM_OK) + { + if (max_record > MAX_RECORD_ME) + max_record = MAX_RECORD_ME; + else if (max_record EQ 0) + max_record = 1; + + sms_data->me_backup.max_record = (UBYTE)max_record; + if (tl_find_status_pid (MEM_ME, 1, sim_msg, + &sms_data->me_backup)) + { + tl_message_ind_from_sim (MEM_ME, 1, (UBYTE)max_record, sim_msg); + } + } + else + { + /* + * No SMS in mobile memory + */ + sms_data->me_backup.max_record = 0; + } + MFREE (sim_msg); + } +} +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_find_next | ++--------------------------------------------------------------------+ + + PURPOSE : Creates a copy of the status and protocol identifier + for the next entry. + +*/ + +GLOBAL void tl_find_next (UBYTE mem_type, UBYTE index) +{ + GET_INSTANCE_DATA; + + TRACE_FUNCTION ("tl_find_next()"); + + if (mem_type EQ MEM_SM) + { + /* + * Start with index on SIM card + */ + tl_set_access_fifo (ACCESS_BY_MMI); + SET_STATE (STATE_MMI, MMI_FIND_NEXT); + tl_sim_read_record_req (index); + } + else + { + USHORT max_record; + UBYTE version; + UBYTE *sim_msg; + MALLOC (sim_msg, SIZE_EF_SMS); + + /* + * look at Mobile Memory + */ +/* Implements Measure#32: Row 86 */ + if (pcm_ReadRecord ((UBYTE *)ef_sms_id, index, SIZE_EF_SMS, + sim_msg, &version, &max_record) EQ PCM_OK) + { + if (tl_find_status_pid (MEM_ME, index, sim_msg, + &sms_data->me_backup)) + tl_message_ind_from_sim (MEM_ME, index, (UBYTE)max_record, sim_msg); + } + else + { + /* + * declare only the successfull records + * from previous attempts as available + */ + sms_data->me_backup.max_record = index - 1; + } + MFREE (sim_msg); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_get_pid_dcs | ++--------------------------------------------------------------------+ + + PURPOSE : Gets TP-PID and/or TP-DCS from any message type. + If something is not available, nothing is written to + *pid and *dcs. +*/ + +GLOBAL void tl_get_pid_dcs (UBYTE status, + T_sms_sdu *sms_sdu, + UBYTE *pid, + UBYTE *dcs) +{ + UBYTE *ptr; + int step, rpl; + + TRACE_FUNCTION ("tl_get_pid_dcs()"); + + ptr = &sms_sdu->buf[rpl = sms_sdu->buf[0] + 1]; /* points to TP-MTI */ + switch (status) + { + case SMS_RECORD_STO_UNSENT: + case SMS_RECORD_STO_SENT: /* MO-SM */ + switch (*ptr & 3) + { + case SMS_SUBMIT: + ptr += (*(ptr + 2) + 1) / 2 + 4; + if (pid NEQ NULL) + *pid = *ptr; + if (dcs NEQ NULL) + *dcs = *(ptr + 2); + break; + + case SMS_COMMAND: + if (pid NEQ NULL) + *pid = *(ptr + 2); + break; + + default: + break; + } + break; + + case SMS_RECORD_REC_UNREAD: + case SMS_RECORD_REC_READ: /* MT-SM */ + switch (*ptr & 3) + { + case SMS_DELIVER: + ptr += (*(ptr + 1) + 1) / 2 + 3; + if (pid NEQ NULL) + *pid = *ptr; + if (dcs NEQ NULL) + *dcs = *(ptr + 2); + break; + + case SMS_STATUS_REPORT: + if ((step = (*(ptr + 2) + 1) / 2 + 19) + rpl < (sms_sdu->l_buf >> 3)) + { + ptr += step; /* TP-PI */ + if (pid NEQ NULL AND *ptr & 1) + *pid = *(ptr + 1); + if (dcs NEQ NULL AND *ptr & 2) + *dcs = *(ptr + 2); + } + break; + + default: + break; + } + break; + + default: + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_find_status_pid | ++--------------------------------------------------------------------+ + + PURPOSE : Calculates status and protocol identifier of a SMS + record and stores the values. Returns TRUE, when a + valid message is recognized. +*/ + +GLOBAL BOOL tl_find_status_pid (UBYTE mem_type, + UBYTE index, + UBYTE * data, + T_BACKUP * backup) +{ + UBYTE *ptr; + BOOL is_valid = FALSE; + + TRACE_FUNCTION ("tl_find_status_pid()"); + + /* + * Store status and clear pid + */ + tl_store_status (backup, index-1, data[0]); + tl_store_pid (backup, index-1, 0); + + /* + * mobile terminated message (bit 3 = 0) and used (bit 1 = 1) + * check first byte with mask 00000101 = bit 3+1 = 5 must + * be 1, that means bit 3 = 0 and bit 1 = 1. + * skip service centre address and set to message type + */ + ptr = &data[1] + data[1] + 1; + + switch (data[0] & 5) + { + case 1: // MT-SM + /* + * check message type to be a SMS-DELIVER + */ + if ((*ptr & 3) EQ SMS_DELIVER) + { + /* + * skip message type and originator address, + * *(ptr+1) contains the number of digits of the + * originator address. The term (*p+1)/2 indicates + * the number of bytes used for the digits. Plus 3 for + * message type, the length field and TON/NPI field. + */ + ptr += (*(ptr + 1) + 1) / 2 + 3; + + /* + * store protocol identifier + */ + tl_store_pid (backup, index-1, *ptr); + + /* + * valid message found + */ + backup->any_valid = TRUE; + is_valid = TRUE; + } + else if((*ptr & 3) EQ SMS_STATUS_REPORT) + { + /* + * Indicate that valid Status Report message is found in ME or SIM. + * No need to store status & pid as only reading and delelting of + * Status Report Message is allowed and not replacing of the message. + * + */ + backup->any_valid = TRUE; + is_valid = TRUE; + } + else + { + /* + * consider the record as free + */ + tl_store_status (backup, index-1, 0); + } + break; + + case 5: // MO-SM + /* + * mobile originated messages are not to be replaced, + * but it is checked whether there is really a SMS-SUBMIT + * stored on the SIM + */ + if ((*ptr & 3) NEQ SMS_SUBMIT) + { + /* + * consider the record as free + */ + tl_store_status (backup, index-1, 0); + } + else + { + /* + * valid message found + */ + backup->any_valid = TRUE; + is_valid = TRUE; + } + break; + + default: + break; + } + return is_valid; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_cphs_voice_mail | ++--------------------------------------------------------------------+ + + PURPOSE : Checking whether a CPHS Voice Mail Indication is + given, which shall not be stored. +*/ +#ifdef FF_CPHS +LOCAL BOOL tl_cphs_voice_mail (T_TP_DELIVER *sms_deliver) +{ + if (sms_deliver->tp_oa.digits NEQ 4 OR + sms_deliver->tp_oa.ton NEQ SMS_TON_ALPHANUMERIC) + return FALSE; + + switch (sms_deliver->tp_dcs & 0xF0) + { + case SMS_DCS_GRP_DEF: + case SMS_DCS_GRP_CLASS: + if ((sms_deliver->tp_dcs & 0xC) EQ 0 OR + (sms_deliver->tp_dcs & 0xC) EQ 0xC) + break; /* GSM Default Alphabet */ + /*FALLTHROUGH*/ /*lint -fallthrough*/ + case SMS_DCS_GRP_COMPR: + case SMS_DCS_GRP_CLASS_COMPR: + case SMS_DCS_GRP_MW_STORE_UCS2: + return FALSE; /* no GSM Default Alphabet */ + case SMS_DCS_DATA_CLASS: + if (sms_deliver->tp_dcs & 0x4) + return FALSE; /* no GSM Default Alphabet */ + } + if (!sms_deliver->v_tp_ud) + return FALSE; /* not only text present */ + + if (sms_deliver->tp_ud.length NEQ 1 OR + (sms_deliver->tp_ud.data[0] & 0x7F) NEQ ' ') + return FALSE; /* no single space */ + + TRACE_FUNCTION ("CPHS VMS: do not store"); + + return TRUE; +} +#endif +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_network_on_sim | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the PLMN code as part of the IMSI and notices + whether a certain network operator is present. +*/ +#ifdef FF_SMS_NW_RCG_SIM +GLOBAL void tl_check_network_on_sim (UBYTE *data) +{ + GET_INSTANCE_DATA; + if (data NEQ NULL AND data[0] >= 3 AND + (data[1] & 0xF7) EQ 0x21 /* ignore parity bit */ + AND data[2] EQ 0x43 AND data[3] EQ 0x03) + SMS_NETWORK(sms_data) = NW_SIM_23430; + else + SMS_NETWORK(sms_data) = NW_SIM_NONE; +} +#endif +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_handle_23430 | ++--------------------------------------------------------------------+ + + PURPOSE : Special handling of an income Short Message according to + specifications of operator 23430 +*/ +#ifdef FF_SMS_23430 +GLOBAL BOOL tl_handle_23430 (T_TP_DELIVER *sms_deliver) +{ + GET_INSTANCE_DATA; + UBYTE record; + + if (SMS_NETWORK(sms_data) NEQ NW_SIM_23430) + return FALSE; + + if ((sms_deliver->tp_dcs EQ 0 OR sms_deliver->tp_dcs EQ 0xF2) + AND (int)sms_deliver->tp_oa.digits EQ sizeof(ref_nr_23430) + AND sms_deliver->tp_oa.ton EQ SMS_TON_ALPHANUMERIC + AND memcmp (sms_deliver->tp_oa.num, ref_nr_23430, + sizeof(ref_nr_23430)) EQ 0) + { + record = tl_get_free_space (MEM_SM); + if (record) + { + tl_store_status (&SMS_SIM_PROP(sms_data), record-1, SIM_SMS_PENDING); + tl_sim_conv_update_req (record, SMS_RP_RCVD(sms_data)); + + tl_set_access_fifo (ACCESS_BY_NET); + SET_STATE (STATE_NET, NET_23430_WRITE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + } + else + { + tl_sms_memo_exceeded (FALSE); + } + return TRUE; /* the message has been handled */ + } + switch (sms_deliver->tp_dcs & 0xF0) + { + case SMS_DCS_GRP_CLASS: + case SMS_DCS_GRP_CLASS_COMPR: + case SMS_DCS_DATA_CLASS: + if ((sms_deliver->tp_dcs & 3) EQ 2 AND /* Class 2 */ + ((sms_deliver->v_tp_ud AND sms_deliver->tp_ud.length EQ 0) OR + (sms_deliver->v_tp_udh_inc AND sms_deliver->tp_udh_inc.length EQ 0))) + { + if (tl_get_free_space (MEM_SM) NEQ 0) + rl_report_req_ack (NULL); + else + tl_sms_memo_exceeded (FALSE); + return TRUE; /* the message has been handled */ + } + break; + default: + break; + } + return FALSE; /* no SIM specific message */ +} +#endif +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_store_special_sms | ++--------------------------------------------------------------------+ + + PURPOSE : Checking the presence of a special message indication + requiring the message to be stored. +*/ + +LOCAL BOOL tl_store_special_sms (T_TP_DELIVER *sms_deliver) +{ + UBYTE *udh; + int udh_len; + + if (!sms_deliver->tp_udhi OR + !sms_deliver->v_tp_udh_inc) + return FALSE; + + udh = &sms_deliver->tp_udh_inc.tp_udh.data[0]; + udh_len = (int)sms_deliver->tp_udh_inc.tp_udh.c_data; + + while (udh_len > 0) + { + if (udh[0] EQ 0x01) /* tag Special Message Indication? */ + { + if (udh[2] & 0x80) /* storing required? */ + { + TRACE_FUNCTION ("tl_store_special_sms: found"); + return TRUE; + } + } + udh_len -= (int)udh[1] + 2; + udh += udh[1] + 2; /* next tag */ + } + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_handle_message | ++--------------------------------------------------------------------+ + + PURPOSE : Standard handling of an income Short Message according to + GSM 03.40 and 03.38 +*/ + +/* + * DISPLAY display + * MEM_ME store in ME + * MEM_SM store in SIM + * NOTHING do nothing + */ + +static const UBYTE me_table_A [5][7] = +{ /* mt no class class 0 class 1 class 2 class 3 discard store */ + /* 0 */ { MEM_ME, MEM_ME, MEM_ME, MEM_SM, MEM_ME, MEM_ME, MEM_ME }, + /* 1 */ { MEM_ME, DISPLAY, MEM_ME, MEM_SM, MEM_ME, MEM_ME, MEM_ME }, + /* 2 */ { DISPLAY, DISPLAY, DISPLAY, MEM_SM, DISPLAY, DISPLAY, MEM_ME }, + /* 3 */ { MEM_ME, DISPLAY, MEM_ME, MEM_SM, DISPLAY, MEM_ME, MEM_ME }, + /* 4 */ { MEM_ME, DISPLAY, MEM_ME, MEM_SM, MEM_SM, DISPLAY, MEM_ME } +}; + +static const UBYTE me_table_B [5][7] = +{ /* mt no class class 0 class 1 class 2 class 3 discard store */ + /* 0 */ { MEM_SM, DISPLAY, MEM_SM, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 1 */ { MEM_SM, IGNORE, MEM_SM, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 2 */ { NOTHING, IGNORE, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING }, + /* 3 */ { MEM_SM, IGNORE, MEM_SM, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 4 */ { MEM_SM, IGNORE, MEM_SM, NOTHING, MEM_ME, NOTHING, MEM_SM } +}; + +static const UBYTE sm_table_A [5][7] = +{ /* mt no class class 0 class 1 class 2 class 3 discard store */ + /* 0 */ { MEM_SM, MEM_SM, MEM_SM, MEM_SM, MEM_SM, MEM_SM, MEM_SM }, + /* 1 */ { MEM_SM, DISPLAY, MEM_SM, MEM_SM, MEM_SM, MEM_SM, MEM_SM }, + /* 2 */ { DISPLAY, DISPLAY, DISPLAY, MEM_SM, DISPLAY, DISPLAY, MEM_SM }, + /* 3 */ { MEM_SM, DISPLAY, MEM_SM, MEM_SM, DISPLAY, MEM_SM, MEM_SM }, + /* 4 */ { MEM_SM, DISPLAY, MEM_ME, MEM_SM, MEM_SM, DISPLAY, MEM_SM } +}; + +static const UBYTE sm_table_B [5][7] = +{ /* mt no class class 0 class 1 class 2 class 3 discard store */ + /* 0 */ { MEM_ME, DISPLAY, MEM_ME, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 1 */ { MEM_ME, IGNORE, MEM_ME, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 2 */ { NOTHING, IGNORE, NOTHING, NOTHING, NOTHING, NOTHING, NOTHING }, + /* 3 */ { MEM_ME, IGNORE, MEM_ME, NOTHING, NOTHING, DISPLAY, NOTHING }, + /* 4 */ { MEM_ME, IGNORE, MEM_SM, NOTHING, MEM_ME, NOTHING, MEM_ME } +}; + +GLOBAL void tl_handle_message (T_TP_DELIVER *sms_deliver) +{ + GET_INSTANCE_DATA; + UBYTE dcs_class; + UBYTE record; + UBYTE data[SIZE_EF_SMS]; + + TRACE_FUNCTION ("tl_handle_message()"); + + if (sms_data->pr_cntrl.delivery_state == SMS_DELIVER_STATUS_PAUSE) + { + /* user has blocked message receiption */ + TRACE_EVENT("User has paused MT message delivery"); + + tl_sms_memo_pause(); + + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + return; + } + +#ifdef FF_CPHS + if (SMS_CPHS(sms_data) AND tl_cphs_voice_mail (sms_deliver)) + dcs_class = 5; /* discard message */ + else +#endif + if (tl_store_special_sms (sms_deliver)) + dcs_class = 6; /* store message */ + else if (sms_deliver->tp_pid EQ SMS_PID_ME_DOWNLOAD) + dcs_class = 1 + 1; /* class 1 */ + else if (sms_deliver->tp_pid EQ SMS_PID_SIM_DOWNLOAD) + dcs_class = 2 + 1; /* class 2 */ + else switch (sms_deliver->tp_dcs & 0xF0) + { + case SMS_DCS_GRP_CLASS: + case SMS_DCS_GRP_CLASS_COMPR: + case SMS_DCS_DATA_CLASS: + dcs_class = (sms_deliver->tp_dcs & 3) + 1; + break; + case SMS_DCS_GRP_MW_DISCD: + dcs_class = 5; /* discard message */ + break; + case SMS_DCS_GRP_MW_STORE: + case SMS_DCS_GRP_MW_STORE_UCS2: + dcs_class = 6; /* store message */ + break; + default: + dcs_class = 0; // no class + break; + } + + if (sms_data->mem3 EQ MEM_ME) + { + sms_data->use_mem_a = me_table_A [sms_data->mt][dcs_class]; + sms_data->use_mem_b = me_table_B [sms_data->mt][dcs_class]; + } + else + { + sms_data->use_mem_a = sm_table_A [sms_data->mt][dcs_class]; + sms_data->use_mem_b = sm_table_B [sms_data->mt][dcs_class]; + } + + /* + * try alternative A + */ + switch (sms_data->use_mem_a) + { + case DISPLAY: + /* + * Only display of the message + */ + + TRACE_EVENT("TABLE A: DISPLAY"); + + SMS_EM_DISPLAY_MT_SHORT_MESSAGE; + + tl_message_ind_from_net (NOT_PRESENT_8BIT, 0, 0, + SMS_RP_RCVD(sms_data)); + { + if (SMS_MT_ACK_MODE(sms_data) NEQ SMS_MHC_PH2PLUS) + { + rl_report_req_ack (NULL); + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + } + } + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + return; + + case MEM_ME: + /* + * memory type is mobile memory + */ + + TRACE_EVENT("TABLE A: MEM_ME"); + + record = tl_get_free_space (MEM_ME); + if (record NEQ 0) + { + tl_convert_mt_to_mem (SMS_RP_RCVD(sms_data), data); + /* + * store in mobile memory + */ +/* Implements Measure#32: Row 87 */ + if (pcm_WriteRecord ((UBYTE *)ef_sms_id, record, + SIZE_EF_SMS, data) NEQ PCM_OK) + break; + /* + * update status byte and protocol identifier + */ + tl_store_status (&SMS_ME_PROP(sms_data), record-1, SMS_RECORD_REC_UNREAD); + tl_store_pid (&SMS_ME_PROP(sms_data), record-1, sms_deliver->tp_pid); + /* + * send indication to MMI + */ + tl_message_ind_from_net (MEM_ME, record, + sms_data->me_backup.max_record, + SMS_RP_RCVD(sms_data)); + /* + * acknowledge to the infrastructure + */ + rl_report_req_ack (NULL); + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + return; + } + break; + + case MEM_SM: + /* + * memory type is SIM card + */ + + TRACE_EVENT("TABLE A: MEM_SM"); + + record = tl_get_free_space (MEM_SM); + if (record) + { + tl_store_status (&SMS_SIM_PROP(sms_data), record-1, SIM_SMS_PENDING); + tl_sim_conv_update_req (record, SMS_RP_RCVD(sms_data)); + + tl_set_access_fifo (ACCESS_BY_NET); + SET_STATE (STATE_NET, NET_WRITE); + return; + } + break; + } + /* + * try alternative B + */ + switch (sms_data->use_mem_b) + { + case DISPLAY: + /* + * Only display of the message + */ + + TRACE_EVENT("TABLE B: DISPLAY"); + + tl_message_ind_from_net (NOT_PRESENT_8BIT, 0, 0, + sms_data->rp_data_dl); + { + if (SMS_MT_ACK_MODE(sms_data) NEQ SMS_MHC_PH2PLUS) + { + rl_report_req_ack (NULL); + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + } + } + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + + case MEM_ME: + /* + * memory type is mobile memory + */ + + TRACE_EVENT("TABLE B: MEM_ME"); + + record = tl_get_free_space (MEM_ME); + if (record) + { + tl_convert_mt_to_mem (SMS_RP_RCVD(sms_data), data); + /* + * store in mobile memory + */ +/* Implements Measure#32: Row 89 */ + if (pcm_WriteRecord ((UBYTE *)ef_sms_id, record, + SIZE_EF_SMS, data) EQ PCM_OK) + { + /* + * update status byte + */ + tl_store_status (&SMS_ME_PROP(sms_data), record-1, SMS_RECORD_REC_UNREAD); + tl_store_pid (&SMS_ME_PROP(sms_data), record-1, sms_deliver->tp_pid); + /* + * send indication to MMI + */ + tl_message_ind_from_net (MEM_ME, record, + sms_data->me_backup.max_record, + SMS_RP_RCVD(sms_data)); + /* + * acknowledge to the infrastructure + */ + rl_report_req_ack (NULL); + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + SET_STATE (STATE_NET, NET_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + } + } + if (tl_get_free_space (MEM_SM)) /* SIM memory available? */ + { + /* + * RP_ERROR => + */ + rl_report_req_error (SMS_RP_CS_PROTOCOL_ERROR, NULL); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + + /* + * free instance + */ + // FREE_SMS_INSTANCE (SMS_INST.ti); + } + else + { + /* change mem_cap_avail flag on SIM and return error */ + tl_sms_memo_exceeded (FALSE); + } + + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + SET_STATE (STATE_NET, NET_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + + case MEM_SM: + /* + * memory type is SIM card + */ + + TRACE_EVENT("TABLE B: MEM_SM"); + + record = tl_get_free_space (MEM_SM); + if (record) + { + tl_store_status (&SMS_SIM_PROP(sms_data), record-1, SIM_SMS_PENDING); + tl_sim_conv_update_req (record, SMS_RP_RCVD(sms_data)); + + tl_set_access_fifo (ACCESS_BY_NET); + SET_STATE (STATE_NET, NET_WRITE); + break; + } + if (tl_get_free_space (MEM_ME)) /* other memory available? */ + { + /* + * RP_ERROR => + */ + rl_report_req_error (SMS_RP_CS_PROTOCOL_ERROR, NULL); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + + /* + * free instance + */ + // FREE_SMS_INSTANCE (SMS_INST.ti); + } + else + { + /* change mem_cap_avail flag on SIM and return error */ + tl_sms_memo_exceeded (FALSE); + } + + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + SET_STATE (STATE_NET, NET_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + + case IGNORE: + + TRACE_EVENT("TABLE B: IGNORE"); + + rl_report_req_ack (NULL); + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + + default: /* other memory available? */ + + TRACE_EVENT("TABLE B: OTHER?"); + + if (tl_get_free_space (MEM_ME) OR tl_get_free_space (MEM_SM)) + { + /* + * RP_ERROR => + */ + rl_report_req_error (SMS_RP_CS_PROTOCOL_ERROR, NULL); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + /* + * free instance + */ + // FREE_SMS_INSTANCE (SMS_INST.ti); + } + else + { + /* change mem_cap_avail flag on SIM and return error */ + tl_sms_memo_exceeded (FALSE); + } + + SMS_INST_SET_STATE (STATE_TL, TL_IDLE); + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + break; + } + sms_data->use_mem_b = NOTHING; // not reached if alternative B in progress +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sms_reserve_req_id | ++--------------------------------------------------------------------+ + + PURPOSE : Finds a free entry in for SIM accesses and reserves it for use. +*/ + +GLOBAL BOOL tl_sms_reserve_req_id (UBYTE *acc_ix_ptr) +{ + GET_INSTANCE_DATA; + UBYTE sim_acc_ix; + + + for (sim_acc_ix = 0; + sim_acc_ix < SMS_MAX_SIM_ACCESS AND sms_data->sms_sim_access_info[sim_acc_ix].entry_used; + ++sim_acc_ix); + + if (sim_acc_ix < SMS_MAX_SIM_ACCESS) + { + *acc_ix_ptr = sim_acc_ix; + sms_data->sms_sim_access_info[sim_acc_ix].entry_used = TRUE; + return TRUE; + } + else + { + TRACE_ERROR("SMS SIM Access entries used up"); + return FALSE; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_build_sim_update_req | ++--------------------------------------------------------------------+ + + PURPOSE : Build and send the SIM_UPDATE_REQ. + +*/ + +GLOBAL void tl_build_sim_update_req (void) +{ + GET_INSTANCE_DATA; + + TRACE_FUNCTION ("tl_build_sim_update_req()"); + + /* Implements Measure# 14 */ + tl_send_sim_update_req (SMS_INST.tp_mr, 0); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TL | +| STATE : code ROUTINE : tl_message_ind_from_net | ++--------------------------------------------------------------------+ + + PURPOSE : Builds from SIM data and sends the primitive + MNSMS_MESSAGE_IND to ACI. A NULL pointer for parameter + 'data' generates an empty indication, which shall + interpreted as existent but empty memory. +*/ + +GLOBAL void tl_message_ind_from_net (UBYTE mem_type, + UBYTE record, + UBYTE max_record, + T_rp_data_dl *rp_data_dl) +{ + T_SIM_PDU *sim_pdu; + + TRACE_FUNCTION ("tl_message_ind_from_net"); + + if (rp_data_dl NEQ NULL) + { + PALLOC (message_ind, MNSMS_MESSAGE_IND); + MALLOC (sim_pdu, sizeof(T_SIM_PDU)); + message_ind->sms_sdu.o_buf = 0; + message_ind->sms_sdu.l_buf = SIM_PDU_LEN<<3; + + message_ind->status = SMS_RECORD_REC_UNREAD; + message_ind->mem_type = mem_type; + message_ind->rec_num = record; + message_ind->rec_max = max_record; + + SMS_EM_STORE_MT_MESSAGE; + + sim_pdu->rp_addr = rp_data_dl->rp_addr; + sim_pdu->tpdu = rp_data_dl->rp_user_data.tpdu; + sim_pdu->tp_mti = SMS_DELIVER; + sim_pdu->v_tpdu = TRUE; + sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; + + ccd_codeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)&message_ind->sms_sdu, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU); + + PSENDX (MMI, message_ind); + MFREE (sim_pdu); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TL | +| STATE : code ROUTINE : tl_message_ind_from_sim | ++--------------------------------------------------------------------+ + + PURPOSE : Builds from SIM data and sends the primitive + MNSMS_MESSAGE_IND to ACI. A NULL pointer for parameter + 'data' generates an empty indication, which shall + interpreted as existent but empty memory. +*/ + +GLOBAL void tl_message_ind_from_sim (UBYTE mem_type, + UBYTE record, + UBYTE max_record, + UBYTE *data) +{ + PALLOC (message_ind, MNSMS_MESSAGE_IND); + + TRACE_FUNCTION ("tl_message_ind_from_sim"); + + memset (message_ind, 0, sizeof (T_MNSMS_MESSAGE_IND)); + message_ind->mem_type = mem_type; + message_ind->rec_max = max_record; + + if (data NEQ NULL) + { + message_ind->rec_num = record; + message_ind->status = data[0]; + memcpy (message_ind->sms_sdu.buf, &data[1], SIZE_EF_SMS-1); + message_ind->sms_sdu.l_buf = (SIZE_EF_SMS-1) << 3; + tl_adjust_message_len (SMS_VT_SIM_PDU, (BUF_tpdu *)&message_ind->sms_sdu); + } + PSENDX (MMI, message_ind); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_read_access_fifo | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_READ_ACCESS_FIFO. + +*/ + +GLOBAL UBYTE tl_read_access_fifo (void) +{ + GET_INSTANCE_DATA; + UBYTE id; + + TRACE_FUNCTION ("tl_read_access_fifo()"); + + if (sms_data->access_fifo [1] NEQ ACCESS_EMPTY) + { + id = sms_data->access_fifo [1]; + sms_data->access_fifo [1] = ACCESS_EMPTY; + } + else + { + id = sms_data->access_fifo [0]; + sms_data->access_fifo [0] = ACCESS_EMPTY; + } + + return id; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_read_me_memory | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_READ_ME_MEMORY. + +*/ + +GLOBAL void tl_read_me_memory (USHORT rec_num, + UBYTE status) +{ + GET_INSTANCE_DATA; + int index; + + TRACE_FUNCTION ("tl_read_me_memory()"); + + if (rec_num <= SMS_ME_PROP(sms_data).max_record) + { + SMS_REC_STATUS(sms_data) = tl_check_status_value (status); + if (rec_num EQ SMS_RECORD_NOT_EXIST) + { + /* + * find first record of given status + */ + index = tl_search_record (&SMS_ME_PROP(sms_data), 1, + SMS_REC_STATUS(sms_data)); + } + else + index = (int)rec_num; + + if ((index NEQ SMS_RECORD_NOT_EXIST) AND + (tl_get_status (&SMS_ME_PROP(sms_data), index-1) & 1)) + { + USHORT max_record; + UBYTE misc; + UBYTE sim_msg[SIZE_EF_SMS]; + /* + * valid index + */ +/* Implements Measure#32: Row 84 */ + if (pcm_ReadRecord ((UBYTE *)ef_sms_id, (USHORT)index, SIZE_EF_SMS, + sim_msg, &misc, &max_record) NEQ PCM_OK) + { + tl_mnsms_read_cnf (MEM_ME, (UBYTE)rec_num, + NULL, SMS_CAUSE_MEM_FAIL); + SMS_ME_PROP(sms_data).max_record = 0; + return; + } + tl_store_status (&SMS_ME_PROP(sms_data), index-1, sim_msg[0]); + if (sim_msg[0] & 1) + { + + SMS_EM_READ_SHORT_MESSAGE; + + switch (sim_msg[0] & 7) + { + case SMS_RECORD_REC_UNREAD: + /* + * entry is changeable + */ + switch (SMS_READ_MODE(sms_data)) + { + case READ_STATUS_CHANGE: + sim_msg[0] = SMS_RECORD_REC_READ; +/* Implements Measure#32: Row 84 */ + pcm_WriteRecord ((UBYTE *)ef_sms_id, (USHORT)index, + SIZE_EF_SMS, sim_msg); + tl_store_status (&SMS_ME_PROP(sms_data), index-1, sim_msg[0]); + tl_mnsms_read_cnf (MEM_ME, (UBYTE)index, + NULL, SIM_NO_ERROR); + break; + + default: + misc = sim_msg[0]; + sim_msg[0] = SMS_RECORD_REC_READ; +/* Implements Measure#32: Row 84 */ + pcm_WriteRecord ((UBYTE *)ef_sms_id, (USHORT)index, + SIZE_EF_SMS, sim_msg); + tl_store_status (&SMS_ME_PROP(sms_data), index-1, sim_msg[0]); + sim_msg[0] = misc; + /*FALLTHROUGH*/ /*lint -fallthrough*/ + case READ_PREVIEW: + tl_mnsms_read_cnf (MEM_ME, (UBYTE)index, + sim_msg, SIM_NO_ERROR); + break; + } + break; + + case SMS_RECORD_STO_SENT: + case SMS_RECORD_STO_UNSENT: + /* + * no status change for STORE_UNSENT! + */ + if (SMS_READ_MODE(sms_data) EQ READ_STATUS_CHANGE) + { + tl_mnsms_read_cnf (MEM_ME, (UBYTE)rec_num, + NULL, SMS_CAUSE_OPER_NOT_ALLW); + return; + } + /*FALLTHROUGH*/ /*lint -fallthrough*/ + default: + /* + * Status Change is obsolete + */ + tl_mnsms_read_cnf (MEM_ME, (UBYTE)index, + sim_msg, SIM_NO_ERROR); + break; + } + return; + } + } + } + else + index = (int)rec_num; + /* + * index is wrong or other error + */ + tl_mnsms_read_cnf (MEM_ME, (UBYTE)index, NULL, + (USHORT)((SMS_ME_PROP(sms_data).max_record EQ 0)? + SMS_CAUSE_MEM_FAIL: SMS_CAUSE_INV_INDEX)); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_read_sim_memory | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_READ_SIM_MEMORY. + +*/ + +GLOBAL void tl_read_sim_memory ( + USHORT rec_num, + UBYTE status) +{ + GET_INSTANCE_DATA; + int index; + + TRACE_FUNCTION ("tl_read_sim_memory()"); + + if (rec_num <= (USHORT)SMS_SIM_PROP(sms_data).max_record) + { + SMS_REC_STATUS(sms_data) = tl_check_status_value (status); + if (rec_num EQ SMS_RECORD_NOT_EXIST) + { + /* + * find first record of given status + */ + index = tl_search_record (&SMS_SIM_PROP(sms_data), 1, + SMS_REC_STATUS(sms_data)); + } + else + index = (int)rec_num; + + if ((index NEQ SMS_RECORD_NOT_EXIST) AND + (tl_get_status (&SMS_SIM_PROP(sms_data), index-1) & 1)) + { + /* + * valid index + */ + if (SMS_READ_MODE(sms_data) EQ READ_STATUS_CHANGE) + { + switch (tl_get_status (&SMS_SIM_PROP(sms_data), index-1) & 7) + { + case SMS_RECORD_REC_UNREAD: + /* + * entry is changeable + */ + break; + + case SMS_RECORD_STO_SENT: + case SMS_RECORD_STO_UNSENT: + /* + * no status change for STORE_UNSENT! + */ + tl_mnsms_read_cnf (MEM_SM, (UBYTE)rec_num, + NULL, SMS_CAUSE_OPER_NOT_ALLW); + return; + + default: + /* + * Status Change is obsolete + */ + tl_mnsms_read_cnf (MEM_SM, (UBYTE)rec_num, + NULL, SIM_NO_ERROR); + return; + } + } + SMS_SEL_REC(sms_data) = (UBYTE)index; + tl_set_access_fifo (ACCESS_BY_MMI); + SET_STATE (STATE_MMI, MMI_READ); + SMS_INST_SET_STATE (STATE_TL, TL_OTHER); + tl_sim_read_record_req ((UBYTE)index); + return; + } + } + /* + * index is wrong or other error + */ + tl_mnsms_read_cnf (MEM_SM, (UBYTE)rec_num, NULL, + (USHORT)((SMS_SIM_PROP(sms_data).max_record EQ 0)? + SMS_CAUSE_MEM_FAIL: SMS_CAUSE_INV_INDEX)); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sim_read_req | ++--------------------------------------------------------------------+ + + PURPOSE : Prepares and sends the primitive SIM_READ_REQ to read a + binary file from SIM. +*/ + +GLOBAL void tl_sim_read_req (USHORT datafield, + UBYTE length) +{ + GET_INSTANCE_DATA; + + UBYTE sim_acc_ix; + + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + + PALLOC (sim_read_req, SIM_READ_REQ); + sim_read_req->source = SRC_SMS; + sim_read_req->req_id = sim_acc_ix; + sim_read_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = datafield; + sim_read_req->v_path_info = FALSE; + sim_read_req->offset = 0; + sim_read_req->length = length; + sim_read_req->max_length = 0; + PSENDX (SIM, sim_read_req); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sim_read_record_req | ++--------------------------------------------------------------------+ + + PURPOSE : Prepares and sends the primitive SIM_READ_RECORD_REQ to + read the given record from EF(SMS). +*/ + +GLOBAL void tl_sim_read_record_req (UBYTE record) +{ + GET_INSTANCE_DATA; + + UBYTE sim_acc_ix; + + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + + PALLOC (sim_read_record_req, SIM_READ_RECORD_REQ); + + sim_read_record_req->source = SRC_SMS; + sim_read_record_req->req_id = sim_acc_ix; + sim_read_record_req->v_path_info = FALSE; + sim_read_record_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMS; + sim_read_record_req->record = + sms_data->sms_sim_access_info[sim_acc_ix].rec_num = record; + sim_read_record_req->length = SIM_LENGTH_SMS_RECORD; + + PSENDX (SIM, sim_read_record_req); + } + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sim_update_req | ++--------------------------------------------------------------------+ + + PURPOSE : Prepares and sends the primitive SIM_READ_UPDATE_REQ to + update the given record of EF(SMS). Parameter 'status' is + written to the first byte of the record, the remaining + bytes are filled with the parameter '*data'. When parameter + 'data' is NULL, then the remaining bytes are filled with + pattern NOT_PRESENT_8BIT (0xFF). +*/ + +GLOBAL void tl_sim_update_req (UBYTE record, + UBYTE status, + UBYTE *data) +{ + GET_INSTANCE_DATA; + + UBYTE sim_acc_ix; + + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + PALLOC (update_record_req, SIM_UPDATE_RECORD_REQ); + update_record_req->source = SRC_SMS; + update_record_req->req_id = sim_acc_ix; + update_record_req->v_path_info = FALSE; + update_record_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMS; + update_record_req->record = + sms_data->sms_sim_access_info[sim_acc_ix].rec_num = record; + + update_record_req->length = SIM_LENGTH_SMS_RECORD; + if (data NEQ NULL) + { + update_record_req->linear_data[0] = status; + memcpy (&update_record_req->linear_data[1], + data, SIM_LENGTH_SMS_RECORD-1); + } + else + { + update_record_req->linear_data[0] = SMS_RECORD_FREE; + memset (&update_record_req->linear_data[1], + NOT_PRESENT_8BIT, SIM_LENGTH_SMS_RECORD-1); + } + PSENDX (SIM, update_record_req); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sim_conv_update_req | ++--------------------------------------------------------------------+ + + PURPOSE : Prepares and sends the primitive SIM_READ_UPDATE_REQ to + update the given record of EF(SMS). The data is extracted + from the RP-DATA IE. +*/ + +GLOBAL void tl_sim_conv_update_req (UBYTE record, + T_rp_data_dl *rp_data_dl) +{ + GET_INSTANCE_DATA; + + UBYTE sim_acc_ix; + + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + PALLOC (update_record_req, SIM_UPDATE_RECORD_REQ); + update_record_req->source = SRC_SMS; + update_record_req->req_id = sim_acc_ix; + update_record_req->v_path_info = FALSE; + update_record_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMS; + update_record_req->record = + sms_data->sms_sim_access_info[sim_acc_ix].rec_num = record; + update_record_req->length = SIM_LENGTH_SMS_RECORD; + tl_convert_mt_to_mem (rp_data_dl, + update_record_req->linear_data); + + PSENDX (SIM, update_record_req); + } + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_replace_entry | ++--------------------------------------------------------------------+ + + PURPOSE : Compares the service centre address and the originator + address for two sms messages during replace procedure. + +*/ + +GLOBAL BOOL tl_check_replace_entry (UBYTE /*T_TP_DELIVER*/ *sms_addr, + UBYTE /*T_TP_DELIVER*/ *sms_storage) +{ + TRACE_FUNCTION ("tl_check_replace_entry()"); + + /* + * skip service centre address + */ + sms_storage += *sms_storage + 1; + /* + * check TP-MTI + */ + if ((sms_storage[0] & 0x3) NEQ SMS_DELIVER) + { + return FALSE; + } + /* + * compare originator address and protocol identifier + */ + if (memcmp (sms_addr, &sms_storage[1], (*sms_addr + 1) / 2 + 3) EQ 0) + { + return TRUE; + } + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_replace_message | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the ME and SIM memory for replacing a short message. + If protocol identifier, service centre address and + originator address are equal the message will be replaced. + Else normal handling is processed. + +*/ + +GLOBAL void tl_replace_message (T_TP_DELIVER *sms_deliver) +{ + GET_INSTANCE_DATA; + int i; + + TRACE_FUNCTION ("tl_replace_message()"); + + /* + * first check mobile memory + */ + i = tl_check_mt_pid (&sms_data->me_backup, 1, sms_deliver->tp_pid); + { + if (i > 0) /* possible record found */ + { + USHORT max_record; + UBYTE version; + UBYTE data[SIZE_EF_SMS]; + /* + * look at Mobile Memory + */ +/* Implements Measure#32: Row 84 */ + if (pcm_ReadRecord ((UBYTE *)ef_sms_id, (USHORT)i, SIZE_EF_SMS, + data, &version, &max_record) EQ PCM_OK) + { + if (tl_check_replace_entry (&SMS_RP_RCVD(sms_data)->rp_user_data.tpdu.b_tpdu[1], + &data[1])) + { + /* + *record shall be replaced, store new one + */ + tl_convert_mt_to_mem (sms_data->rp_data_dl, data); + +/* Implements Measure#32: Row 84 */ + pcm_WriteRecord ((UBYTE *)ef_sms_id, (USHORT)i, + SIZE_EF_SMS, data); + /* + * send indication to MMI + */ + tl_message_ind_from_net (MEM_ME, (UBYTE)i, + SMS_ME_PROP(sms_data).max_record, + SMS_RP_RCVD(sms_data)); + /* + * acknowledge to the infrastructure + */ + rl_report_req_ack (NULL); + + SMS_EM_REPLACE_SMS_IN_ME; + + MFREE (SMS_RP_RCVD(sms_data)); + SMS_RP_RCVD(sms_data) = NULL; + return; + } + } + } + } + + /* + * now look at the SIM card + */ + + i = tl_check_mt_pid (&sms_data->sim_backup, 1, sms_deliver->tp_pid); + if (i > 0) + { + tl_set_access_fifo (ACCESS_BY_NET); + SET_STATE (STATE_NET, NET_READ); + tl_sim_read_record_req ((UBYTE)i); + } + else + { + tl_handle_message (sms_deliver); + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_replace_pid | ++--------------------------------------------------------------------+ + + PURPOSE : This function checks whether a given PID for a replacement + message could match the entry described by backup and index. +*/ + +LOCAL BOOL tl_check_replace_pid (T_BACKUP *backup, + unsigned index, + UBYTE pid) + +{ + if (backup->pid_field EQ NULL) + return TRUE; /* Maybe of replacement type, further checks needed */ + return ((backup->pid_field[index >> 3] & (1 << (index & 0x7))) NEQ 0); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_store_pid | ++--------------------------------------------------------------------+ + + PURPOSE : This function stores the information wheter the given + MT PID is of the replacement type in compressed form. + +*/ + +GLOBAL void tl_store_pid (T_BACKUP *backup, + unsigned index, + UBYTE pid) +{ + UBYTE mask; + +#ifdef WIN32 + if (backup->mem_type EQ MEM_ME) + assert (index < MAX_RECORD_ME); + else if (backup->mem_type EQ MEM_SM) + assert (index < MAX_RECORD_SIM); +#endif /* #ifdef WIN32 */ + + if (backup->pid_field EQ NULL) + return; /* No caching here */ + + mask = 1 << (index & 0x7); + + switch (pid) + { + case SMS_PID_REP_SM_TYPE_1: + case SMS_PID_REP_SM_TYPE_2: + case SMS_PID_REP_SM_TYPE_3: + case SMS_PID_REP_SM_TYPE_4: + case SMS_PID_REP_SM_TYPE_5: + case SMS_PID_REP_SM_TYPE_6: + case SMS_PID_REP_SM_TYPE_7: + case SMS_PID_RET_CALL_MSG: + backup->pid_field[index >> 3] |= mask; + break; + default: + backup->pid_field[index >> 3] &= ~mask; + break; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_store_status | ++--------------------------------------------------------------------+ + + PURPOSE : This function stores the status into the backup data + in compressed form. + +*/ + +GLOBAL void tl_store_status (T_BACKUP *backup, + unsigned index, + UBYTE status) +{ +#ifdef WIN32 + if (backup->mem_type EQ MEM_ME) + assert (index < MAX_RECORD_ME); + else if (backup->mem_type EQ MEM_SM) + assert (index < MAX_RECORD_SIM); +#endif /* #ifdef WIN32 */ + + if (backup->status_field EQ NULL) + return; /* No caching here */ + + backup->status_field[index] = status; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_get_status | ++--------------------------------------------------------------------+ + + PURPOSE : This function gets the status. For the asynchronous + interface to the SIM the presence of backup data is + mandatory, for the synchronous (and fast) interface + to the FFS the presence of backup data is optional. + +*/ + +GLOBAL UBYTE tl_get_status (T_BACKUP *backup, + unsigned index) +{ + USHORT max_record; + UBYTE version; + +#ifdef WIN32 + if (backup->mem_type EQ MEM_ME) + assert (index < MAX_RECORD_ME); + else if (backup->mem_type EQ MEM_SM) + assert (index < MAX_RECORD_SIM); +#endif /* #ifdef WIN32 */ + + switch (backup->mem_type) + { + case MEM_ME: + if (backup->status_field EQ NULL) + { + UBYTE status = SMS_RECORD_FREE; + UBYTE *sim_msg; + MALLOC (sim_msg, SIZE_EF_SMS); +/* Implements Measure#32: Row 84 */ + if (pcm_ReadRecord ((UBYTE *)ef_sms_id, (USHORT)(index + 1), SIZE_EF_SMS, + sim_msg, &version, &max_record) EQ PCM_OK) + status = sim_msg[0]; + MFREE (sim_msg); + return status; + } + /*FALLTHROUGH*/ /*lint -fallthrough*/ + case MEM_SM: + return backup->status_field[index]; + + default: + return SMS_RECORD_FREE; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_mt_pid | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the memory for replacing candidates. + If protocol identifier and status (mt message) are okay + the index of the record is returned. + +*/ + +GLOBAL int tl_check_mt_pid (T_BACKUP *backup, + unsigned index, + UBYTE pid) + +{ + int i; + + for (i = (int)index; i <= (int)backup->max_record; i++) + { + if (((tl_get_status (backup, i - 1) & 5) EQ 1) AND /* mt message */ + tl_check_replace_pid (backup, i - 1, pid)) /* replacement type pid */ + return i; + } + return 0; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_status_value | ++--------------------------------------------------------------------+ + + PURPOSE : Checks and maps the parameter <status> according to the + following rule: + - SMS_RECORD_REC_UNREAD as is + - SMS_RECORD_REC_READ as is + - SMS_RECORD_STO_UNSENT as is + - SMS_RECORD_STO_SENT as is + - SMS_RECORD_STAT_UNRCVD to SMS_RECORD_STO_SENT + - SMS_RECORD_STAT_UNSTRD to SMS_RECORD_STO_SENT + - SMS_RECORD_STAT_STRD to SMS_RECORD_STO_SENT + - any other value to NOT_PRESENT_8BIT + In conjunction with 'tl_search_record' a memory location + with comparable properties can be found +*/ + +GLOBAL UBYTE tl_check_status_value (UBYTE status) +{ + switch (status) + { + case SMS_RECORD_REC_UNREAD: + case SMS_RECORD_REC_READ: + case SMS_RECORD_STO_UNSENT: + case SMS_RECORD_STO_SENT: + return status; + case SMS_RECORD_STAT_UNRCVD: + case SMS_RECORD_STAT_UNSTRD: + case SMS_RECORD_STAT_STRD: + return SMS_RECORD_STO_SENT; + default: + break; + } + return NOT_PRESENT_8BIT; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_search_record | ++--------------------------------------------------------------------+ + + PURPOSE : Searches the memory for the next message with the given + status. + The following codes for parameter <status> are supported: + - SMS_RECORD_FREE: next free record + - SMS_RECORD_REC_UNREAD + - SMS_RECORD_REC_READ + - SMS_RECORD_STO_UNSENT + - SMS_RECORD_STO_SENT: next record with any sent message + - NOT_PRESENT_8BIT: any occupied record + The index of the record is returned. +*/ + +GLOBAL int tl_search_record (T_BACKUP *backup, + USHORT index, + UBYTE status) +{ + int i; + + TRACE_FUNCTION ("tl_search_record()"); + + for (i = (int)index; i <= (int)backup->max_record; i++) + { + if (status EQ NOT_PRESENT_8BIT) + { /* next occupied record */ + if ((tl_get_status (backup, i - 1) & 1) NEQ SMS_RECORD_FREE) + return i; + } + else if ((status & 1) EQ SMS_RECORD_FREE) + { /* next free record */ + if ((tl_get_status (backup, i - 1) & 1) EQ SMS_RECORD_FREE) + return i; + } + else if ((status & 7) EQ (tl_get_status (backup, i - 1) & 7)) + return i; + } + return 0; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_search_record_for_delete| ++--------------------------------------------------------------------+ + + PURPOSE : Searches the SMS DataBase for the next message to be deleted with the given + status. + The following codes for parameter <status> are supported: + - CMGD_DEL_INDEX delete message only for the index given + - CMGD_DEL_READ + - CMGD_DEL_READ_SENT + - CMGD_DEL_READ_SENT_UNSENT + - CMGD_DEL_ALL next occupied record + The index of the record is returned. +*/ + +GLOBAL UBYTE tl_search_record_for_delete (T_BACKUP *backup, + UBYTE index, + UBYTE status) +{ + UBYTE i; + UBYTE file_status; + + TRACE_FUNCTION ("tl_search_record_for_delete()"); + + for (i = index; i <= backup->max_record; i++) + { + file_status = backup->status_field[i - 1] & 7; + switch(status) + { + case CMGD_DEL_ALL: + { + if ((file_status & 1) NEQ SMS_RECORD_FREE) + { + return i; + } + break; + } + case CMGD_DEL_READ: + { + if (file_status EQ SMS_RECORD_REC_READ) + { + return i; + } + break; + } + case CMGD_DEL_READ_SENT: + { + if (file_status EQ SMS_RECORD_REC_READ || + file_status EQ SMS_RECORD_STO_SENT) + { + return i; + } + break; + } + case CMGD_DEL_READ_SENT_UNSENT: + { + if (file_status EQ SMS_RECORD_REC_READ || + file_status EQ SMS_RECORD_STO_SENT || + file_status EQ SMS_RECORD_STO_UNSENT) + { + return i; + } + break; + } + } + } + return SMS_RECORD_NOT_EXIST; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_set_access_fifo | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_SET_ACCESS_FIFO. + +*/ + +GLOBAL void tl_set_access_fifo (UBYTE access) +{ + GET_INSTANCE_DATA; + + TRACE_FUNCTION ("tl_set_access_fifo()"); + + sms_data->access_fifo[1] = sms_data->access_fifo[0]; + sms_data->access_fifo[0] = access; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sms_memo_exceeded | ++--------------------------------------------------------------------+ + + PURPOSE : Checks the SIM memory availability. If an update of + EF(SMSS) is required, then TRUE is returned. If the memory + has become full, then the appropriate RP-ERROR is generated. +*/ + +GLOBAL BOOL tl_sms_memo_exceeded (BOOL avail) +{ + GET_INSTANCE_DATA; + BOOL sim_update = FALSE; + UBYTE sim_acc_ix; + + TRACE_FUNCTION ("tl_sms_memo_exceeded()"); + + if ((sms_data->sim_phase >= 2) AND (sms_data->mem_cap_avail NEQ avail)) + { + + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + PALLOC (update_req, SIM_UPDATE_REQ); + update_req->source = SRC_SMS; + update_req->req_id = sim_acc_ix; + update_req->v_path_info = FALSE; + update_req->datafield = sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMSS; + update_req->length = 1; + update_req->trans_data[0] = (avail)? 0xFF: 0xFE; + update_req->offset = 1; + + PSENDX (SIM, update_req); + + if(sms_data->inst == INST_MO) + tl_set_access_fifo (ACCESS_BY_MMI); + else + tl_set_access_fifo (ACCESS_BY_NET); + + sim_update = TRUE; + } + } + if (!(sms_data->mem_cap_avail = avail)) + { + /* + * RP_ERROR => + */ + rl_report_req_error (SMS_RP_CS_MEM_CAP_EXCEEDED, NULL); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + /* + * no memory + */ + } + + /* inform the ACI about SIM-full/avail via SMS error indication */ + tl_mnsms_error_ind(avail ? SMS_CAUSE_MEM_AVAIL : SMS_CAUSE_MEM_FULL); + + return sim_update; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sms_memo_pause | ++--------------------------------------------------------------------+ + + PURPOSE : used for <<user intiated memory full condition>> (by the + MNSMS_PAUSE_REQ). + - update sim notification flag (if not done already) + - send RP-ERROR (MEM_CAPAPCITY_EXCEEDED) to network + - release connection +*/ + +GLOBAL void tl_sms_memo_pause (void) +{ + GET_INSTANCE_DATA; + UBYTE sim_acc_ix; + TRACE_FUNCTION ("tl_sms_memo_pause()"); + + /* + * generate RP_ERROR(MEM_CAP_EXCEEDED) + */ + rl_report_req_error (SMS_RP_CS_MEM_CAP_EXCEEDED, + NULL); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + /* + * update sim notification flag if necessary + */ + if(sms_data->pr_cntrl.mem_full_sent EQ FALSE) + { + sms_data->pr_cntrl.mem_full_sent = TRUE; + + if (sms_data->sim_phase >= 2) + { + if (tl_sms_reserve_req_id(&sim_acc_ix)) + { + PALLOC (update_req, SIM_UPDATE_REQ); + update_req->req_id = sim_acc_ix; + update_req->v_path_info = FALSE; + update_req->source = SRC_SMS; + update_req->datafield = + sms_data->sms_sim_access_info[sim_acc_ix].datafield = SIM_SMSS; + update_req->length = 1; + update_req->trans_data[0] = 0xFE; /* Notification Flag = TRUE */ + update_req->offset = 1; + PSENDX (SIM, update_req); + if(sms_data->inst == INST_MO) + tl_set_access_fifo (ACCESS_BY_MMI); + else + tl_set_access_fifo (ACCESS_BY_NET); + } + + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sms_memo_resume | ++--------------------------------------------------------------------+ + + PURPOSE : used for release of <<user intiated memory full condition>> + (by the MNSMS_RESUME_REQ). + - update sim notification flag (set to false) +*/ + +GLOBAL void tl_sms_memo_resume (void) +{ + + TRACE_FUNCTION ("tl_sms_memo_resume()"); + + /* Implements Measure# 14 */ + tl_send_sim_update_req(0xFF, 1); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_mnsms_report_ind | ++--------------------------------------------------------------------+ + + PURPOSE : Processing the function TL_MNSMS_REPORT_IND. + +*/ + +GLOBAL void tl_mnsms_report_ind (UBYTE ent_state) +{ + PALLOC (report_ind, MNSMS_REPORT_IND); + + report_ind->state = ent_state; + + /* + * Disable the v_cmms_mode flag as we are not sending current value of the + * mode value for CMMS operation. + */ + + report_ind->v_cmms_mode = FALSE; + + PSENDX (MMI, report_ind); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_pause | ++--------------------------------------------------------------------+ + + PURPOSE : execute sms delivery pause + + DESCRIPTION: set marker for pause so that the next incoming sms + will be responded with RP_ERROR (Cause: Memory + Capacity Exceeded). +*/ +GLOBAL void tl_pause (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("tl_pause()"); + + if (sms_data->pr_cntrl.delivery_state NEQ SMS_DELIVER_STATUS_PAUSE) + { + sms_data->pr_cntrl.delivery_state = SMS_DELIVER_STATUS_PAUSE; + sms_data->pr_cntrl.mem_full_sent = FALSE; + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_resume | ++--------------------------------------------------------------------+ + + PURPOSE : execute sms delivery resumption + + DESCRIPTION: reset marker for pause and initiate the sending of + memory available message (SMMA) to network + to indicate that we can receive sms again. +*/ +GLOBAL void tl_resume (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("tl_resume()"); + + if ( sms_data->pr_cntrl.delivery_state != SMS_DELIVER_STATUS_PAUSE ) + { + tl_mnsms_resume_cnf(SMS_NO_ERROR); + return; + } + + if ( sms_data->pr_cntrl.mem_full_sent == FALSE ) + { + sms_data->pr_cntrl.delivery_state = SMS_DELIVER_STATUS_RESUME; + tl_mnsms_resume_cnf(SMS_NO_ERROR); + return; + } + + if (GET_STATE (STATE_MMI) NEQ MMI_IDLE) + { + TRACE_ERROR("Unable to process resume request"); + tl_mnsms_resume_cnf(SMS_CAUSE_ENTITY_BUSY); + return; + } + + GET_MO_INSTANCE(sms_data); + /* + * TL state transition TL_ESTABLISH + * EST state transition EST_SMMA + * MMI state transition MMI_RESUME + * + */ + SET_STATE (STATE_MMI, MMI_RESUME); + SET_STATE (STATE_EST, EST_SMMA); + SMS_INST_SET_STATE (STATE_TL, TL_ESTABLISH); + /* + * 1st shot + */ + SMS_INST.retrans = FALSE; + /* + * establish connection + */ + tl_establish_connection(FALSE); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_query_deliver_status | ++--------------------------------------------------------------------+ + + PURPOSE : handle sms status query for deliver state + +*/ +GLOBAL void tl_query_deliver_status (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("tl_query_deliver_status()"); + + tl_mnsms_query_cnf(SMS_QUERY_DELIVER_STATUS,sms_data->pr_cntrl.delivery_state); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_concat_check | ++--------------------------------------------------------------------+ + + PURPOSE : check for concatenated sms + +*/ +GLOBAL BOOL tl_concat_check ( T_sms_sdu *sms_sdu) +{ + BYTE ccd_result; + T_SIM_PDU *sim_pdu; + T_TP_SUBMIT *submit; + T_SMS_PDU_IE_HDR *ie_hdr; + T_SMS_PDU_CONCAT_8BIT_HDR *concat_8_hdr; + /* T_SMS_PDU_CONCAT_16BIT_HDR *concat_16_hdr; */ + T_SMS_CONCAT_HDR *concat_hdr = NULL; + + MALLOC (sim_pdu, sizeof(*sim_pdu)); + MALLOC (submit, sizeof(*submit)); + + //CCD_START; + /* + * CCD: SMS SDU -> SIM PDU + */ + ccd_result = ccd_decodeMsg (CCDENT_SMS, + BOTH, + (T_MSGBUF *)sms_sdu, + (UBYTE *)sim_pdu, + SMS_VT_SIM_PDU); + if (ccd_result NEQ ccdOK) + { + /* + * error understanding the sdu + */ + TRACE_ERROR ("ccd error decoding sim pdu"); + /* + * give up + */ + // CCD_END; + MFREE (sim_pdu); + MFREE (submit); + return FALSE; + } + if (sim_pdu->tp_mti NEQ SMS_SUBMIT) + { + /* + * error understanding the sdu + */ + TRACE_ERROR ("error not a <submit> in sim pdu"); + /* + * give up + */ + // CCD_END; + MFREE (sim_pdu); + MFREE (submit); + return FALSE; + } + /* + * CCD: SIM PDU -> SUBMIT + */ + ccd_result = ccd_decodeMsg (CCDENT_SMS, + UPLINK, + (T_MSGBUF *)&sim_pdu->tpdu, + (UBYTE *)submit, + SMS_VT_SUBMIT); + if (ccd_result NEQ ccdOK) + { + /* + * error understanding the sdu + */ + TRACE_ERROR ("ccd error decoding submit"); +//TISH, patch for ASTec32699,OMAPS00135322 +//start + if (ccd_result NEQ ccdWarning) + { + /* + * give up + */ + // CCD_END; + MFREE (sim_pdu); + MFREE (submit); + return FALSE; + } +//end + } + if (submit->tp_udhi EQ SMS_UDHI_INCLUDED) + { + TRACE_EVENT("UDH INCLUDED"); + + ie_hdr = (T_SMS_PDU_IE_HDR *)((UBYTE *)&submit->tp_udh_inc.tp_udh.data[0]); + + if (ie_hdr->iei EQ 0x00 ) /* SMS_IEI_CONC_8BIT */ + { + /* + * Concatenation header for 8 bit ref nr + */ + concat_8_hdr = (T_SMS_PDU_CONCAT_8BIT_HDR *) + ((UBYTE *)&submit->tp_udh_inc.tp_udh.data[2]); + TRACE_EVENT_P3("Concatenated: Ref %#x Seq %u Of %u", + concat_8_hdr->ref_nr, + concat_8_hdr->seq_nr, + concat_8_hdr->max_nr); + /* + * safe contents of header in common header structure + */ + MALLOC (concat_hdr, sizeof(*concat_hdr)); + concat_hdr->ref_nr = concat_8_hdr->ref_nr; + concat_hdr->seq_nr = concat_8_hdr->seq_nr; + concat_hdr->max_nr = concat_8_hdr->max_nr; + } + else + { + TRACE_ERROR ("could not find concat header"); + } + } + // CCD_END; + /* + * concat control + */ + tl_concat_cntrl(concat_hdr); + /* + * clean up + */ + if (concat_hdr) + MFREE(concat_hdr); + MFREE (sim_pdu); + MFREE (submit); + return TRUE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_concat_cntrl | ++--------------------------------------------------------------------+ + + PURPOSE : control of concatenated sms + +*/ +GLOBAL void tl_concat_cntrl ( + T_SMS_CONCAT_HDR *concat_hdr /* may be NULL */) +{ + GET_INSTANCE_DATA; + if (sms_data->concat_cntrl.concatenation EQ FALSE) + { + /* + * Concatenation currently not active + */ + if (concat_hdr EQ NULL) + { + /* + * nothing to be done + */ + return; + } + else + { + if ((concat_hdr->seq_nr EQ 1) AND + (concat_hdr->seq_nr < concat_hdr->max_nr)) + { + /* + * begin of concatenation series + */ + TRACE_EVENT("concatenation series begin"); + sms_data->concat_cntrl.concatenation = TRUE; + sms_data->concat_cntrl.release_pending = FALSE; + sms_data->concat_cntrl.nr = *concat_hdr; + } + else + { + TRACE_ERROR("concatenation series implausible nr"); + } + } + } + else + { + /* + * Concatenation currently active + */ + if (concat_hdr EQ NULL) + { + TRACE_ERROR("concatenation series ends unexpected"); + sms_data->concat_cntrl.release_pending = TRUE; + sms_data->concat_cntrl.end = TRUE; + } + else if ((concat_hdr->seq_nr == concat_hdr->max_nr) AND + (concat_hdr->seq_nr EQ sms_data->concat_cntrl.nr.seq_nr+1)) + { + TRACE_EVENT("concatenation series end"); + sms_data->concat_cntrl.release_pending = TRUE; + sms_data->concat_cntrl.end = TRUE; + sms_data->concat_cntrl.nr = *concat_hdr; + } + else if (concat_hdr->seq_nr EQ sms_data->concat_cntrl.nr.seq_nr+1) + { + /* + * plausible + */ + TRACE_EVENT("concatenation series continued"); + sms_data->concat_cntrl.release_pending = TRUE; + sms_data->concat_cntrl.end = FALSE; + sms_data->concat_cntrl.nr = *concat_hdr; + } + else + { + TRACE_ERROR("concatenation series implausible nr"); + sms_data->concat_cntrl.release_pending = TRUE; + sms_data->concat_cntrl.end = TRUE; + sms_data->concat_cntrl.nr = *concat_hdr; + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_check_class_2 | ++--------------------------------------------------------------------+ + + PURPOSE : Checks whether the data coding scheme is class 2. + +*/ + +#ifdef SIM_TOOLKIT +GLOBAL UBYTE tl_check_class_2 (UBYTE dcs) +{ + TRACE_FUNCTION ("tl_class_check()"); + + /* + * check 00x1xx10 + */ + if ((dcs & 0xD3) EQ 0x12) + return TRUE; + + /* + * check 1111xx10 + */ + if ((dcs & 0xF3) EQ 0xF2) + return TRUE; + + return FALSE; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_build_envelope_sms_download | ++--------------------------------------------------------------------+ + + PURPOSE : Builds an envelope command to the SIM card for SMS + download. + +*/ + +GLOBAL BOOL tl_build_envelope_sms_download (T_rp_data_dl *rp_data_dl) +{ + GET_INSTANCE_DATA; + int ber_len, tpdu_len; + int start_addr, start_tpdu; + T_stk_cmd *stk_cmd; + UBYTE *env; + + MCAST (sim_pdu, SIM_PDU); + PALLOC (sim_toolkit_req, SIM_TOOLKIT_REQ); + + TRACE_FUNCTION ("tl_build_envelope_sms_download()"); + + if (rp_data_dl EQ NULL) + { + PFREE (sim_toolkit_req); + return FALSE; + } + /* + * make SIM PDU + */ + sim_pdu->rp_addr = rp_data_dl->rp_addr; + sim_pdu->tpdu = rp_data_dl->rp_user_data.tpdu; + sim_pdu->tp_mti = SMS_DELIVER; + sim_pdu->v_tpdu = TRUE; + sim_pdu->tp_vt_mti = SMS_VT_SIM_PDU; + + MALLOC (stk_cmd, sizeof(T_stk_cmd)); + stk_cmd->o_cmd = 0; + stk_cmd->l_cmd = MAX_STK_CMD<<3; + + ccd_codeMsg (CCDENT_SMS, DOWNLINK, + (T_MSGBUF *)stk_cmd, + (UBYTE *)sim_pdu, SMS_VT_SIM_PDU); + /* + * calculate variable length items of ENVELOPE + */ + ber_len = 4; /* length of TLV device id */ + /* + * find RP-ADDR (Service Centre) in SIM_PDU + */ + start_addr = (int)stk_cmd->o_cmd >> 3; + /* position of RP-ADDR length */ + ber_len += (int)stk_cmd->cmd[start_addr] + 2; + /* add length of TLV address */ + /* + * find TPDU in SIM PDU + */ + start_tpdu = start_addr + (int)stk_cmd->cmd[start_addr] + 1; + /* skip RP-Orig Address */ + tpdu_len = ((int)stk_cmd->l_cmd >> 3) - start_tpdu; + /* length of RP-User-Data */ + + ber_len += tpdu_len + 2; /* add length of TLV SMS-TPDU */ + if (tpdu_len >= 128) /* 2 byte length coding required? */ + ber_len++; /* adjust */ + /* + * prepare the primitive + */ + sim_toolkit_req -> source = SRC_SMS; + sim_toolkit_req -> req_id = 0; + + sim_toolkit_req -> stk_cmd.o_cmd = 0; + /* + * BER-TLV Envelope SMS-PP Download + */ + env = sim_toolkit_req -> stk_cmd.cmd; + *env++ = 0xD1; + if (ber_len >= 128) /* 2 byte length coding required */ + { + *env++ = 0x81; + sim_toolkit_req -> stk_cmd.l_cmd = (USHORT)((ber_len + 3) << 3); + } + else + sim_toolkit_req -> stk_cmd.l_cmd = (USHORT)((ber_len + 2) << 3); + *env++ = (UBYTE)ber_len; + /* + * TLV Device Identities + */ + *env++ = 0x82; /* Tag */ + *env++ = 2; /* Length */ + *env++ = 0x83; /* Source Network */ + *env++ = 0x81; /* Destination SIM */ + /* + * TLV Address + */ + *env++ = 0x06; /* address tag, optional */ + memcpy (env, &stk_cmd->cmd[start_addr], /* copy length and content of RP-Orig Address */ + stk_cmd->cmd[start_addr] + 1); + env += stk_cmd->cmd[start_addr] + 1; /* tag plus content */ + /* + * env now points to the tag of the TLV SMS-TPDU + */ + *env++ = 0x8B; /* SMS TPDU tag, mandatory */ + if (tpdu_len >= 128) + *env++ = 0x81; + *env++ = (UBYTE)tpdu_len; + memcpy (env, &stk_cmd->cmd[start_tpdu], /* copy content of TPDU */ + tpdu_len); + /* + * Send to SIM card + */ + PSENDX (SIM, sim_toolkit_req); + MFREE (stk_cmd); + /* + * Set instance to assign answer from SIM card. + */ + tl_set_access_fifo (ACCESS_BY_NET); + SET_STATE (STATE_NET, NET_WRITE); + + return TRUE; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_sim_toolkit_confirm | ++--------------------------------------------------------------------+ + + PURPOSE : Getting the terminal response to a SMS - Download. + +*/ + +GLOBAL void tl_sim_toolkit_confirm (T_SIM_TOOLKIT_CNF *toolkit_cnf) +{ + GET_INSTANCE_DATA; + T_rp_user_data *rp_ud; + union { + T_TP_DLVR_REP_ACK *ack; + T_TP_DLVR_REP_ERR *err; + } dlvr_rep; + + TRACE_FUNCTION ("tl_sim_toolkit_confirm()"); + + CCD_START; + + switch (toolkit_cnf->cause) + { + case SIM_NO_ERROR: + /* + * The SIM responds with "90 00", the ME shall acknowledge the receipt + * of the short message to the network using an RP-ACK message. + * + * or + * + * The SIM responds with "9F XX", the ME shall use the GET RESPONSE + * command to the response data. The response data will be supplied by + * the ME in the TP-User-Data Element of the RP-ACK message. It will be + * send back to the network. The values of protocol identifier and data + * coding scheme in RP-ACK shall be as in the original message. + */ + { + if (toolkit_cnf->stk_cmd.l_cmd > 0) + { + MALLOC (rp_ud, sizeof(T_rp_user_data)); + MALLOC (dlvr_rep.ack, sizeof(T_TP_DLVR_REP_ACK)); + + dlvr_rep.ack->tp_vt_mti = SMS_VT_DLVR_REP_ACK; + dlvr_rep.ack->tp_udhi = SMS_UDHI_NOT_INCLUDED; + dlvr_rep.ack->tp_mti = SMS_DELIVER_REPORT; + dlvr_rep.ack->v_tp_udh_inc = FALSE; + memcpy (dlvr_rep.ack->tp_ud.data, + &toolkit_cnf->stk_cmd.cmd[toolkit_cnf->stk_cmd.o_cmd >> 3], + (size_t)(toolkit_cnf->stk_cmd.l_cmd >> 3)); + dlvr_rep.ack->tp_ud.c_data = (UBYTE)(toolkit_cnf->stk_cmd.l_cmd >> 3); + dlvr_rep.ack->tp_ud.length = (tl_udl_count_septet (SMS_DCS(sms_data)))? + (UBYTE)(dlvr_rep.ack->tp_ud.c_data * 8 / 7): + dlvr_rep.ack->tp_ud.c_data; + dlvr_rep.ack->tp_ext = SMS_EXT_NOT_INCLUDED; + dlvr_rep.ack->v_tp_ud = TRUE; + dlvr_rep.ack->tp_udl_p = SMS_UD_INCLUDED; + dlvr_rep.ack->tp_dcs = SMS_DCS(sms_data); + dlvr_rep.ack->v_tp_dcs = TRUE; + dlvr_rep.ack->tp_dcs_p = SMS_DCS_INCLUDED; + dlvr_rep.ack->tp_pid = SMS_PID(sms_data); + dlvr_rep.ack->v_tp_pid = TRUE; + dlvr_rep.ack->tp_pid_p = SMS_PID_INCLUDED; + + rp_ud->tpdu.o_tpdu = 0; + rp_ud->tpdu.l_tpdu = TPDU_BIT_LEN; + rp_ud->v_tpdu = (ccd_codeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&rp_ud->tpdu, + (UBYTE *)dlvr_rep.ack, + SMS_VT_DLVR_REP_ACK) EQ ccdOK); + rp_ud->tp_mti = SMS_DELIVER_REPORT; + MFREE (dlvr_rep.ack); + } + else + rp_ud = NULL; + + rl_report_req_ack (rp_ud); + SET_STATE (STATE_NET, NET_IDLE); + + SMS_EM_RECEIVE_SIM_TOOLKIT_DATA_DOWNLOAD; + + if (rp_ud NEQ NULL) + { + MFREE (rp_ud); + } + } + break; + + case SIM_CAUSE_SAT_BUSY: + /* + * The SIM responds with "93 00", the ME shall either retry the command or + * send back an RP-ERROR message to the network with the TP-FCS value + * indicating "SIM Application Toolkit Busy). + */ + { + MALLOC (rp_ud, sizeof(T_rp_user_data)); + + rp_ud->tpdu.l_tpdu = 40; /* 5 bytes */ + rp_ud->tpdu.o_tpdu = 0; + + rp_ud->tpdu.b_tpdu[0] = SMS_DELIVER_REPORT; /* MTI, no UDHI */ + rp_ud->tpdu.b_tpdu[1] = SMS_FCS_SAT_BUSY; /* SAT busy */ + rp_ud->tpdu.b_tpdu[2] = 0x03; /* PI: DCS and PID will follow, no UD */ + rp_ud->tpdu.b_tpdu[3] = SMS_PID(sms_data); /* set PID */ + rp_ud->tpdu.b_tpdu[4] = SMS_DCS(sms_data); /* set DCS */ + + rp_ud->tp_mti = SMS_DELIVER_REPORT; + rp_ud->v_tpdu = TRUE; + + /* + * RP_ERROR + */ + rl_report_req_error (SMS_RP_CS_PROTOCOL_ERROR, rp_ud); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + SET_STATE (STATE_NET, NET_IDLE); + + MFREE (rp_ud); + } + break; + + case SIM_CAUSE_DNL_ERROR: + /* + * The ME has indicated in TERMINAL PROFILE that it supports the status + * word "9E XX" and if the SIM responds with "9E XX", the ME shall use + * the GET RESPONSE command to get the response data. The response data + * from the SIM will be supplied by the ME in the TP-User data element + * of the RP-ERROR message. It will be sent back to the network. The + * values of protocol identifier and data coding scheme in RP-ERROR + * shall be as in the original message. The value of TP-FCS element + * of the RP-ERROR shall be "SIM data download error". + */ + { + MALLOC (rp_ud, sizeof(T_rp_user_data)); + MALLOC (dlvr_rep.err, sizeof(T_TP_DLVR_REP_ERR)); + + dlvr_rep.err->tp_vt_mti = SMS_VT_DLVR_REP_ERR; + dlvr_rep.err->tp_udhi = SMS_UDHI_NOT_INCLUDED; + dlvr_rep.err->tp_mti = SMS_DELIVER_REPORT; + dlvr_rep.err->tp_fcs = SMS_FCS_SAT_DNL_ERROR; + dlvr_rep.err->v_tp_udh_inc = FALSE; + memcpy (dlvr_rep.err->tp_ud.data, + &toolkit_cnf->stk_cmd.cmd[toolkit_cnf->stk_cmd.o_cmd >> 3], + (size_t)(toolkit_cnf->stk_cmd.l_cmd >> 3)); + dlvr_rep.err->tp_ud.c_data = (UBYTE)(toolkit_cnf->stk_cmd.l_cmd >> 3); + dlvr_rep.err->tp_ud.length = (tl_udl_count_septet (SMS_DCS(sms_data)))? + (UBYTE)(dlvr_rep.err->tp_ud.c_data * 8 / 7): + dlvr_rep.err->tp_ud.c_data; + dlvr_rep.err->tp_ext = SMS_EXT_NOT_INCLUDED; + dlvr_rep.err->v_tp_ud = TRUE; + dlvr_rep.err->tp_udl_p = SMS_UD_INCLUDED; + dlvr_rep.err->tp_dcs = SMS_DCS(sms_data); + dlvr_rep.err->v_tp_dcs = TRUE; + dlvr_rep.err->tp_dcs_p = SMS_DCS_INCLUDED; + dlvr_rep.err->tp_pid = SMS_PID(sms_data); + dlvr_rep.err->v_tp_pid = TRUE; + dlvr_rep.err->tp_pid_p = SMS_PID_INCLUDED; + + rp_ud->tpdu.o_tpdu = 0; + rp_ud->tpdu.l_tpdu = TPDU_BIT_LEN; + rp_ud->v_tpdu = (ccd_codeMsg (CCDENT_SMS, UPLINK, + (T_MSGBUF *)&rp_ud->tpdu, + (UBYTE *)dlvr_rep.err, + SMS_VT_DLVR_REP_ERR) EQ ccdOK); + rp_ud->tp_mti = SMS_DELIVER_REPORT; + MFREE (dlvr_rep.err); + + /* + * RP_ERROR + */ + rl_report_req_error (SMS_RP_CS_PROTOCOL_ERROR, rp_ud); + /* + * RL_RELEASE_REQ ==> + */ + rl_release_req(SMS_INST.ti); + SET_STATE (STATE_NET, NET_IDLE); + MFREE (rp_ud); + } + break; + + default: + break; + } + CCD_END; +} +#endif + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8410) MODULE : SMS_TLF | +| STATE : code ROUTINE : tl_cmms_start | ++--------------------------------------------------------------------+ + + PURPOSE : Function used for starting the Timer TMMS and continuing + the CMMS mode. + +*/ + +GLOBAL void tl_cmms_start(void) +{ + TRACE_FUNCTION ("tl_cmms_start()"); + + if(sms_timer_check(TMMS)) + { + sms_timer_stop(TMMS); + } + sms_timer_start(TMMS); +} + + +#endif