FreeCalypso > hg > freecalypso-sw
view gsm-fw/g23m-gsm/sms/sms_tlf.c @ 962:f4da3071dd61
doc/High-speed-serial write-up and Linux kernel patch added
author | Mychaela Falconia <falcon@ivan.Harhan.ORG> |
---|---|
date | Fri, 06 Nov 2015 21:46:05 +0000 |
parents | 2d8cb1c85e01 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | 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 #include "config.h" #include "fixedconf.h" #include "condat-features.h" #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