FreeCalypso > hg > fc-magnetite
view src/g23m-gsm/cc/cc_est.c @ 382:7bdd370f6f59
doc/Voice-pseudo-modem: minor fixes
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 13 Jan 2018 21:47:32 +0000 |
parents | 27a4235405c6 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS (6147) | Modul : CC_EST +----------------------------------------------------------------------------- | 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 establishment | phase of the call control process of the component CC. +----------------------------------------------------------------------------- */ #ifndef CC_EST_C #define CC_EST_C #define ENTITY_CC /*==== INCLUDES ===================================================*/ #include <string.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 "cnf_cc.h" #include "mon_cc.h" #include "pei.h" #include "tok.h" #include "cc.h" #include "cc_em.h" /*==== EXPORT =====================================================*/ /*==== PROTOTYPE ==================================================*/ /* Implements Measure# 19 */ LOCAL void cc_send_release_cmp (USHORT cause); LOCAL void cc_send_mncc_release_ind (UBYTE ti, USHORT cause); /*==== PRIVAT =====================================================*/ /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_init | +--------------------------------------------------------------------+ PURPOSE : Initialisation of CC data. */ GLOBAL void cc_init (void) { #ifdef OPTION_MULTIPLE_INSTANCES USHORT i; TRACE_FUNCTION ("cc_init()"); for (i=0;i<MAX_INSTANCES;i++) cc_init_data (&data_base[i]); } #else TRACE_FUNCTION ("cc_init()"); cc_init_data (); #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_init_data | +--------------------------------------------------------------------+ PURPOSE : Initializes the data for one instance. */ GLOBAL void cc_init_data (void) { GET_INSTANCE_DATA; USHORT i; TRACE_FUNCTION ("cc_init_data()"); memset (cc_data, 0, sizeof (T_CC_DATA)); /* No SETUP / EMERGENCY SETUP pending */ cc_data->stored_setup = NULL; /* No CCBS SETUP pending */ cc_data->stored_ccbs_setup = NULL; cc_data->channel_mode = NAS_CHM_SIG_ONLY; for (i=0;i<MAX_CC_CALLS;i++) { cc_data->stored_ti_values[i] = NOT_PRESENT_8BIT; } cc_csf_ms_cap (); /* * Initialise single numbering scheme */ cc_data->sns_bcpara.bearer_serv = MNCC_BEARER_SERV_SPEECH; cc_data->sns_mode = MNCC_SNS_MODE_VOICE; /* * Initialise connection element for MTC */ cc_data->conn_elem = MNCC_CONN_ELEM_NON_TRANS; /* * Initialize setup_reattempt_ti to not present */ cc_data->setup_reattempt_ti = NOT_PRESENT_8BIT; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_configure_req | +--------------------------------------------------------------------+ PURPOSE : Configuration of bearer capabilities and subaddress by man machine interface. */ static const UBYTE def_modem_type [8] = { MNCC_MT_V21, /* user rate 300 Baud -> modem type V.21 */ MNCC_MT_V22, /* user rate 1200 Baud -> modem type V.22 */ MNCC_MT_V22_BIS, /* user rate 2400 Baud -> modem type V.22bis */ MNCC_MT_V32, /* user rate 4800 Baud -> modem type V32 */ MNCC_MT_V32, /* user rate 9600 Baud -> modem type V32 */ MNCC_MT_V32, /* 12k transparent, not supported now by ACI */ MNCC_MT_V23, /* user rate 12k/75 Baud -> modem type V23 */ MNCC_MT_V21, /* user rate 14.4 kBaud -> modem type V21 ??? */ }; GLOBAL void cc_mncc_configure_req (T_MNCC_CONFIGURE_REQ * config) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_mncc_configure_req()"); /* * store own subadress if available * * NOTE: T_called_party_sub is the wrong type here in MNCC_CONFIGURE_REQ, * this should have been T_calling_party_sub as this is that what * the subaddress is used for in the uplink SETUP message later. * Doesn't really matter here as the types are identical, it's * just somewhat confusing and could be occasionally be changed. */ if (config->called_party_sub.c_subaddr) { cc_data->my_party_subaddr.v_tos = TRUE; cc_data->my_party_subaddr.tos = config->called_party_sub.tos; cc_data->my_party_subaddr.v_odd_even = TRUE; cc_data->my_party_subaddr.odd_even = config->called_party_sub.odd_even; cc_data->my_party_subaddr.c_subaddr = config->called_party_sub.c_subaddr; memcpy (cc_data->my_party_subaddr.subaddr, config->called_party_sub.subaddr, config->called_party_sub.c_subaddr); } else memset (&cc_data->my_party_subaddr, 0, sizeof (T_M_CC_called_subaddr)); /* * Store CTM support */ cc_data->ctm_ena = config->ctm_ena; /* * Store Single Numbering Scheme BC parameter and mode * if available */ if (config->sns_mode NEQ NOT_PRESENT_8BIT) { /* * Store Connection Element for MTC * Note that setting conditionally on sns_mode NEQ NOT_PRESENT_8BIT is * possible because ACI always sets sns_mode to something different from * NOT_PRESENT_8BIT when it sends an MNCC_CONFIGURE_REQ. * For future proof use of MNCC_CONFIGURE_REQ (e.g. only subaddress is valid!) * it is convenient and correct to consider parameters only if they * are valid. */ cc_data->conn_elem = config->bcpara.conn_elem; cc_data->sns_mode = config->sns_mode; if (cc_data->sns_mode EQ MNCC_SNS_MODE_VOICE) { memset (&cc_data->sns_bcpara, 0 /*NOT_PRESENT_8BIT*/, sizeof (T_MNCC_bcpara)); cc_data->sns_bcpara.bearer_serv = (cc_data->ctm_ena EQ MNCC_CTM_ENABLED)? MNCC_BEARER_SERV_SPEECH_CTM: MNCC_BEARER_SERV_SPEECH; } else memcpy (&cc_data->sns_bcpara, &config->bcpara, sizeof (T_MNCC_bcpara)); /* * Set modem type to default values for single numbering scheme */ switch (cc_data->sns_bcpara.bearer_serv) { case MNCC_BEARER_SERV_FAX: cc_data->sns_bcpara.modem_type = M_CC_MT_NONE; break; case MNCC_BEARER_SERV_SPEECH: case MNCC_BEARER_SERV_AUX_SPEECH: case MNCC_BEARER_SERV_SPEECH_CTM: case MNCC_BEARER_SERV_AUX_SPEECH_CTM: break; default: cc_data->sns_bcpara.modem_type = def_modem_type[config->bcpara.rate-1]; if (config->bcpara.modem_type == MNCC_MT_V34) { cc_data->sns_bcpara.modem_type = MNCC_MT_V34; } break; } } /* * define connection element if a preferred one is set by MMI */ if (cc_data->sns_bcpara.conn_elem EQ MNCC_CONN_ELEM_TRANS_PREF) { /* * check only if transparent asynchronous data services are supported */ if (FldGet(cc_data->mscap.datCap1, AsySup)) cc_data->sns_bcpara.conn_elem = M_CC_CE_TRANSPA; else cc_data->sns_bcpara.conn_elem = M_CC_CE_RLP; } /* * define connection element if a preferred one is set by MMI */ if (cc_data->sns_bcpara.conn_elem EQ MNCC_CONN_ELEM_NON_TRANS_PREF) { /* * check only if non-transparent asynchronous data services are supported */ if (FldGet (cc_data->mscap.datCap1, RLPSup)) cc_data->sns_bcpara.conn_elem = M_CC_CE_RLP; else cc_data->sns_bcpara.conn_elem = M_CC_CE_TRANSPA; } PFREE (config); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_prompt_rsp | +--------------------------------------------------------------------+ PURPOSE : A new transaction identifier during network initiated mobile origination call establishment was assigned by upper layers. Under normal conditions this causes the emmission of an MMCC_DATA_REQ (START CC) */ GLOBAL void cc_mncc_prompt_res (T_MNCC_PROMPT_RES * prompt) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_mncc_prompt_rsp()"); /* Check parameters */ if (prompt->ti >= 7) { /* Invalid transaction identifier */ /* Implements Measure# 36, 48 */ cc_send_mncc_release_ind (prompt->ti, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, M_CC_CAUSE_INVALID_TI)); PFREE (prompt); return; } /* Assign ti and allocate a free entry in the call data */ cc_data->ti = prompt->ti; cc_data->index_ti = srv_define_ti(); if (cc_data->index_ti EQ NOT_PRESENT_8BIT) { /* * No call instance available */ /* Implements Measure# 36, 48 */ cc_send_mncc_release_ind (prompt->ti, MNCC_CAUSE_MAX_NO_CALLS_REACHED); PFREE (prompt); return; } /* Send MMCC_PROMPT_RSP */ { PALLOC (prompt_rsp, MMCM_PROMPT_RES); // T_MMCM_ESTABLISH_REQ prompt_rsp->ti = prompt->ti; PSENDX (MM, prompt_rsp); } /* Send MMCC_DATA_REQ (START CC) */ CCD_START; { MCAST (start_cc, U_START_CC); cc_build_start_cc (start_cc); for_start_cc (start_cc); } CCD_END; /* Start Timer T332 */ TIMERSTART (T332, T332_VALUE); PFREE (prompt); /* Next state is WAIT FOR NETWORK INFO (U0.3) */ cc_set_state (M_CC_CS_03); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_prompt_rej | +--------------------------------------------------------------------+ PURPOSE : A new transaction identifier during network initiated mobile origination call establishment could not be assigned by upper layers. MM is informed by MMCC_PROMPT_REJ. */ GLOBAL void cc_mncc_prompt_rej (T_MNCC_PROMPT_REJ * prompt) { TRACE_FUNCTION ("cc_mncc_prompt_rej()"); PFREE (prompt); { PALLOC (reject, MMCM_PROMPT_REJ); PSENDX (MM, reject); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_setup_req | +--------------------------------------------------------------------+ PURPOSE : Starting of mobile originated call. */ GLOBAL void cc_mncc_setup_req (T_MNCC_SETUP_REQ * setup) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_mncc_setup_req()"); cc_data->index_ti = srv_convert_ti (setup->ti); if (cc_data->index_ti NEQ NOT_PRESENT_8BIT) { /* * Transaction identifier already present, this means, we know this ti * and CC is not in M_CC_CS_0 state. This is okay for M_CC_CS_06 (CCBS), * for every other state this is an internal failure. */ switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_06: /* RECALL present */ /* * Don't use the setup parametes from ACI, instead use * the stored SETUP message in CC. */ cc_data->progress_desc[cc_data->index_ti] = NOT_PRESENT_8BIT; /* No ugly CC setup reattempts here */ cc_data->setup_attempts = MAX_SETUP_ATTEMPTS; cc_data->setup_reattempt_ti = NOT_PRESENT_8BIT; /* Send stored SETUP message to network and forget it */ for_pd (cc_data->stored_ccbs_setup); cc_data->stored_ccbs_setup = NULL; /* Set parameters in cc_data */ cc_data->call_type [cc_data->index_ti] = CALL_TYPE_MOC; /* initialize disconnect collision flag */ cc_data->disc_coll [cc_data->index_ti] = FALSE; cc_data->t308_counter [cc_data->index_ti] = 0; cc_reset_dtmf (); /* Start T303 */ TIMERSTART (T303, T303_VALUE); /* Next state is CALL INIT */ cc_set_state (M_CC_CS_1); break; default: /* The ti is already in use and it is not CCBS recall */ { PALLOC (rel, MNCC_RELEASE_IND); rel->ti = setup->ti; rel->cause = M_CC_CAUSE_INVALID_TI; rel->c_raw_cause = 0; PSENDX (MMI, rel); } break; } PFREE (setup); return; } if (setup->ti >= 7) { /* * Invalid transaction identifier */ /* Implements Measure# 36, 48 */ cc_send_mncc_release_ind (setup->ti, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, M_CC_CAUSE_INVALID_TI)); PFREE (setup); return; } /* * ti is valid here and not already in use */ cc_data->ti = setup->ti; cc_data->index_ti = srv_define_ti (); if (cc_data->index_ti EQ NOT_PRESENT_8BIT) { /* * No call instance available */ /* Implements Measure# 36, 48 */ cc_send_mncc_release_ind (setup->ti, MNCC_CAUSE_MAX_NO_CALLS_REACHED); PFREE (setup); return; } /* * Security check: if bcpara indicates not present, * set service to speech */ if (setup->bcpara.bearer_serv EQ NOT_PRESENT_8BIT) { setup->bcpara.bearer_serv = (cc_data->ctm_ena EQ MNCC_CTM_ENABLED)? MNCC_BEARER_SERV_SPEECH_CTM: MNCC_BEARER_SERV_SPEECH; } /* * Security check: if prio indicates emergency call, * set service to speech or speech with CTM */ if (setup->prio NEQ MNCC_PRIO_NORM_CALL) { switch (setup->bcpara.bearer_serv) { case MNCC_BEARER_SERV_SPEECH: case MNCC_BEARER_SERV_SPEECH_CTM: break; case MNCC_BEARER_SERV_AUX_SPEECH_CTM: setup->bcpara.bearer_serv = MNCC_BEARER_SERV_SPEECH_CTM; break; default: setup->bcpara.bearer_serv = MNCC_BEARER_SERV_SPEECH; break; } } if (cc_check_capabilities (&setup->bcpara) EQ FALSE OR cc_check_capabilities ((T_MNCC_bcpara *)&setup->bcpara2) EQ FALSE) { /* * MS doesn't support the requested services. */ PALLOC ( rel, MNCC_RELEASE_IND); rel->ti = setup->ti; rel->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, M_CC_CAUSE_BEARER_NOT_IMPLEM); rel->c_raw_cause = 0; PSENDX (MMI, rel); srv_free_ti (); PFREE (setup); } else { PALLOC (est, MMCM_ESTABLISH_REQ); /* T_MMCM_ESTABLISH_REQ */ cc_build_bc (&cc_data->bc1, &cc_data->serv1, &setup->bcpara); cc_data->ri = setup->ri; cc_data->bcpara1 = setup->bcpara; memcpy (&cc_data->bcpara2, &setup->bcpara2, sizeof (T_MNCC_bcpara)); if (cc_data->ri EQ NOT_PRESENT_8BIT) cc_data->serv2 = NOT_PRESENT_8BIT; else cc_build_bc (&cc_data->bc2, &cc_data->serv2, (T_MNCC_bcpara *)&setup->bcpara2); memcpy (&cc_data->bcpara2, &setup->bcpara2, sizeof (T_MNCC_bcpara)); est->org_entity = NAS_ORG_ENTITY_CC; est->ti = setup->ti; /* Set establ_serv according to chosen bearer capability */ switch (cc_data->bcpara1.bearer_serv) { case MNCC_BEARER_SERV_SPEECH: est->estcs = MMCM_ESTCS_MOB_ORIG_SPCH; break; case MNCC_BEARER_SERV_ASYNC: if (cc_data->bcpara1.conn_elem == MNCC_CONN_ELEM_TRANS || cc_data->bcpara1.conn_elem == MNCC_CONN_ELEM_TRANS_PREF) { est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; } else { est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; } break; case MNCC_BEARER_SERV_FAX: est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; break; default: est->estcs = MMCM_ESTCS_MOB_ORIG_SPCH; break; } switch (cc_data->serv1) { case MNCC_SERV_DATA: if (FldGet(cc_data->mscap.datCap2, DHRSup)) { /* * Halfrate support for data */ switch (setup->bcpara.rate) { case M_CC_UR_0_3_KBIT: case M_CC_UR_1_2_KBIT: case M_CC_UR_2_4_KBIT: case M_CC_UR_4_8_KBIT: case M_CC_UR_1_2_KBIT_V23: est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; break; default: est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; break; } } else est->estcs = MMCM_ESTCS_MOB_ORIG_DATA; break; default: /* SERV_SPEECH */ if (setup->prio EQ MNCC_PRIO_NORM_CALL) est->estcs = MMCM_ESTCS_MOB_ORIG_SPCH; else est->estcs = MMCM_ESTCS_EMERGE; break; } /* Data solely needed for possible redial attempt */ cc_data->estcs = est->estcs; cc_data->setup_attempts = 0; srv_free_stored_setup (); cc_data->progress_desc[cc_data->index_ti] = NOT_PRESENT_8BIT; cc_data->call_type [cc_data->index_ti] = CALL_TYPE_MOC; // PATCH LE 10.04.00 // initialize disconnect collision flag cc_data->disc_coll [cc_data->index_ti] = FALSE; // END PATCH LE 10.04.00 cc_data->t308_counter [cc_data->index_ti] = 0; cc_reset_dtmf (); CCD_START; if (setup->prio EQ MNCC_PRIO_NORM_CALL) { MCAST (setup_msg, U_SETUP); cc_build_setup (setup_msg, setup); for_setup (setup_msg); } else { MCAST (emergency_setup_msg, U_EMERGE_SETUP); cc_build_emergency_setup (emergency_setup_msg); for_emergency_setup (emergency_setup_msg); } CCD_END; cc_set_state (M_CC_CS_01); for_est_req (est); TIMERSTART (T303, T303_VALUE); PFREE (setup); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_alert_req | +--------------------------------------------------------------------+ PURPOSE : The mobile side indicates alerting. */ GLOBAL void cc_mncc_alert_req (T_MNCC_ALERT_REQ * alert) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_mncc_alert_req()"); if ((cc_data->index_ti = srv_convert_ti (alert->ti)) EQ NOT_PRESENT_8BIT) { PFREE (alert); return; } switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_9: CCD_START; { MCAST (alert_msg, U_ALERT); cc_build_alert (alert_msg); cc_set_state (M_CC_CS_7); for_alert (alert_msg); } CCD_END; EM_CC_ALERTING_SENT; PFREE (alert); break; default: PFREE (alert); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_setup_res | +--------------------------------------------------------------------+ PURPOSE : The mobile side indicates call acceptance. */ GLOBAL void cc_mncc_setup_res (T_MNCC_SETUP_RES * setup_res) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_mncc_setup_res()"); if ((cc_data->index_ti = srv_convert_ti (setup_res->ti)) EQ NOT_PRESENT_8BIT) { PFREE (setup_res); return; } switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_7: case M_CC_CS_9: CCD_START; { MCAST (connect, U_CONNECT); cc_build_connect (connect); cc_set_state (M_CC_CS_8); TIMERSTART (T313, T313_VALUE); for_connect (connect); } CCD_END; EM_CC_CONNECT_SENT; PFREE (setup_res); break; default: PFREE (setup_res); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_alert | +--------------------------------------------------------------------+ PURPOSE : Processing an incoming alert message. */ GLOBAL void cc_alert (T_D_ALERT * alert) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_alert()"); EM_CC_ALERTING_RECEIVED; switch (cc_data->state[cc_data->index_ti]) { /* * CS_0 is handled by the formatter */ case M_CC_CS_1: case M_CC_CS_3: if (cc_check_error_flag ()) { PALLOC (alert_ind, MNCC_ALERT_IND); TIMERSTOP (TIMER_CC); if (alert->v_progress) { cc_data->progress_desc[cc_data->index_ti] = alert->progress.progress_desc; } cc_build_mncc_alert_ind (alert, alert_ind); PSENDX (MMI, alert_ind); cc_build_facility_ind (MNCC_FAC_IN_ALERT, alert->v_facility, &alert->facility); cc_build_user_user_ind (MNCC_USER_IN_ALERT, alert->v_user_user, &alert->user_user); CCD_END; srv_free_stored_setup (); cc_set_state (M_CC_CS_4); } break; default: CCD_END; /* Implements Measure# 3 and streamline encoding */ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_call_proceeding | +--------------------------------------------------------------------+ PURPOSE : Processing an incoming call proceed message. */ GLOBAL void cc_call_proceeding (T_D_CALL_PROCEED * proceed) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_call_proceeding()"); EM_CC_CALL_PROCEEDING_RECEIVED; switch (cc_data->state[cc_data->index_ti]) { /* * CS_0 is handled by the formatter */ case M_CC_CS_1: if (cc_check_error_flag ()) { TIMERSTOP (TIMER_CC); /* timer T303 */ if (cc_moc_compatibility (proceed) EQ OKAY) { PALLOC (proceed_ind, MNCC_CALL_PROCEED_IND); cc_build_mncc_proceed_ind (proceed, proceed_ind); PSENDX (MMI, proceed_ind); cc_build_facility_ind (MNCC_FAC_IN_CALL_PROCEED, proceed->v_facility, &proceed->facility); if (proceed->v_progress) { cc_data->progress_desc[cc_data->index_ti] = proceed->progress.progress_desc; } CCD_END; /* * - start T310 unless the CALL PROCEEDING message contains a progress indicator IE * specifying progress description #1, #2, Ph2 handling is not done yet (#64), see * also issue 4967 * - start T310 unless a PROGRESS message with #1, 2, 64 has been * received, this is achieved by remembering the progress description in cc_data * - the case when 1. PROGRESS and 2. CALL PROCEEDING with e.g. #4 is handled by * interpreting 5.2.1.1.3 of 04.08 in the manner that a 2nd progress description * superseeds the first one. See also issue 4965 / CC-FIX-4965. */ /* start T310 with Ph2 unless progress description value #1, #2 or #64 has been received */ { UBYTE prog_desc = cc_data->progress_desc[cc_data->index_ti]; if ((prog_desc NEQ MNCC_PROG_NO_END_TO_END_PLMN) AND (prog_desc NEQ MNCC_PROG_DEST_NON_PLMN) AND (prog_desc NEQ MNCC_PROG_QUEUEING)) { TIMERSTART (T310, T310_VALUE); } } if (proceed->v_progress AND proceed->progress.v_progress_desc AND proceed->progress.progress_desc EQ M_CC_PROG_INBAND_AVAIL) { /* * Avoid more call establishment attempts if there was * inband announcement heard by the user. * The user should have no way to realize that more than one * call attempt may be taken by CC. */ cc_data->setup_attempts = MAX_SETUP_ATTEMPTS; } cc_set_state (M_CC_CS_3); } else /* bearer capability check on CALL PROCEEDING failed */ { CCD_END; CCD_START; { MCAST (disconnect, U_DISCONNECT); PALLOC (rej_ind, MNCC_REJECT_IND); rej_ind->ti = cc_data->ti; /* * GSM 04.08 does not specify what to do / which cause to use; * Condat decided to use normal call clearing with cause #88 */ rej_ind->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST); PSENDX (MMI, rej_ind); cc_build_disconnect (disconnect, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST), NULL, MNCC_SS_VER_NOT_PRES); cc_set_state (M_CC_CS_11); for_disconnect (disconnect); } CCD_END; TIMERSTART (T305, T305_VALUE); } } break; default: CCD_END; /* Implements Measure# 3 and streamline encoding */ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_connect | +--------------------------------------------------------------------+ PURPOSE : Processing an incoming connect message. */ GLOBAL void cc_connect (T_D_CONNECT * connect) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_connect()"); switch (cc_data->state[cc_data->index_ti]) { /* * CS_0 is handled by the formatter */ case M_CC_CS_1: case M_CC_CS_3: case M_CC_CS_4: if (cc_check_error_flag ()) { PALLOC (setup_cnf, MNCC_SETUP_CNF); TIMERSTOP (TIMER_CC); if (connect->v_progress) { cc_data->progress_desc[cc_data->index_ti] = connect->progress.progress_desc; } cc_build_mncc_setup_cnf (connect, setup_cnf); PSENDX (MMI, setup_cnf); cc_build_facility_ind (MNCC_FAC_IN_CONNECT, connect->v_facility, &connect->facility); cc_build_user_user_ind (MNCC_USER_IN_CONNECT, connect->v_user_user, &connect->user_user); CCD_END; CCD_START; { MCAST (connect_ack, B_CONNECT_ACK); connect_ack->msg_type = B_CONNECT_ACK; for_connect_ack (connect_ack); } CCD_END; srv_free_stored_setup (); cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; cc_data->mpty_state[cc_data->index_ti] = M_CC_MPTY_IDLE; cc_set_state (M_CC_CS_10); } EM_CC_CONNECT_RECEIVED; break; default: /* Implements Measure# 3 and streamline encoding */ CCD_END; cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_connect_ack | +--------------------------------------------------------------------+ PURPOSE : Processing an incoming connect acknowledge message. */ GLOBAL void cc_connect_ack (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_connect_ack()"); switch (cc_data->state[cc_data->index_ti]) { /* * CS_0 is handled by the formatter */ case M_CC_CS_8: if (cc_check_error_flag ()) { PALLOC (setup_comp, MNCC_SETUP_COMPL_IND); CCD_END; TIMERSTOP (TIMER_CC); setup_comp->ti = cc_data->ti; setup_comp->cause = MNCC_CAUSE_SUCCESS; PSENDX (MMI, setup_comp); cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; cc_data->mpty_state[cc_data->index_ti] = M_CC_MPTY_IDLE; cc_set_state (M_CC_CS_10); EM_CC_CONNECT_ACKNOWLEDGE_RECEIVED; } break; default: CCD_END; /* Implements Measure# 3 and streamline encoding */ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_progress | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming progress message. */ GLOBAL void cc_progress (T_D_PROGRESS * progress) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_progress()"); switch (cc_data->state[cc_data->index_ti]) { /* * CS_0 is handled by the formatter */ case M_CC_CS_1: case M_CC_CS_3: case M_CC_CS_4: case M_CC_CS_6: case M_CC_CS_7: case M_CC_CS_8: case M_CC_CS_9: case M_CC_CS_11: case M_CC_CS_12: case M_CC_CS_19: if (cc_check_error_flag ()) { PALLOC (progress_ind, MNCC_PROGRESS_IND); TIMERSTOP (TIMER_CC); /* Progress indicator IE here is mandatory IE, so no * checks for presence need to be done here */ cc_data->progress_desc[cc_data->index_ti] = progress->progress.progress_desc; cc_build_mncc_progress_ind (progress, progress_ind); PSENDX (MMI, progress_ind); cc_build_user_user_ind (MNCC_USER_IN_PROGRESS, progress->v_user_user, &progress->user_user); CCD_END; } EM_CC_PROGRESS_RECEIVED; break; default: CCD_END; /* Implements Measure# 3 and streamline encoding */ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_cc_establishment | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming CC ESTABLISHMENT message. Because the only interesting part in this message is the setup container, only the decoded SETUP message is delivered here. */ GLOBAL void cc_cc_establishment (T_U_SETUP * setup) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_cc_establishment()"); switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_03: /* WAIT FOR NW INFO */ /* Check errors delivered by formatter */ switch (cc_data->error) { case M_CC_CAUSE_INVALID_MAND_INFO: case M_CC_CAUSE_COND_INFO_ELEM: CCD_END; /* Implements Measure# 7 and streamline encoding*/ cc_send_status (cc_data->error); return; default: /* No error until now */ /* Stop TIMER T332 */ TIMERSTOP (TIMER_CC); if (cc_data->stored_ccbs_setup NEQ NULL) { /* * There is only room for one stored CCBS SETUP message * for all instances. In case this is already occupied, * the call is released with cause "user busy". * In this case the CCBS recall is not lost, but suspended * by the network until the mobile becomes idle. */ CCD_END; /* Send RELEASE COMPLETE */ CCD_START; { MCAST (rel_com, U_RELEASE_COMP); cc_build_release_complete (rel_com, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_USER_BUSY)); for_release_complete (rel_com); } CCD_END; /* Inform MMI */ { PALLOC (release, MNCC_RELEASE_IND); release->ti = cc_data->ti; release->cause = MNCC_CAUSE_MAX_NO_RECALLS_REACHED; release->c_raw_cause = 0; PSENDX (MMI, release); } /* Release MM connection */ for_rel_req (); /* Next state is NULL */ cc_set_state (M_CC_CS_0); return; } /* Check bearer capabilities, do basic recall alignment */ if (cc_basic_service_align (setup) EQ ERROR) { /* Incompatible bearer capabilities. Clear call. */ CCD_END; /* Implements Measure# 19 */ cc_send_release_cmp (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST)); return; } /* * "If the CC Capabilities in the Setup Container IE is different * to that supported by the mobile station, the mobile station * shall modify the CC Capabilities in the SETUP message to indicate * the true capabilities of the mobile station" [GSM 04.08 5.2.3.2] */ setup->call_ctrl_cap = cc_data->call_ctrl_cap; /* Struct copy */ /* * Handle facility alignment * ("Simple recall alignment", * "Advanced recall alignment" and * "Recall alignment not essential"). */ /* "Simple recall alignment" handled automatically, do nothing */ if (setup->v_fac_adv) { /* Advanced recall alignment not supported. Reject call. */ CCD_END; /* Implements Measure# 19 */ cc_send_release_cmp (CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_FACILITY_REJECT)); return; } /* * The recall alignment not essential facility IE * need not be handled directly here, it is simply * an optional IE which was ignored by CCD. * The only handling we do is to delete the SS-Version * indicator if there are no remaining facility elements. */ if (!setup->v_facility) setup->v_ss_version = FALSE; /* Store coded setup message in cc_data */ { /* No assumtions made about length of this foreign message */ PALLOC_SDU (data, MMCM_DATA_REQ, M_CC_L3MAX << 3); data->sdu.o_buf = CC_ENCODE_OFFSET; ccd_codeMsg (CCDENT_CC, UPLINK, (T_MSGBUF *) &data->sdu, (UBYTE *) setup, NOT_PRESENT_8BIT); cc_data->stored_ccbs_setup = data; } CCD_END; /* Send MMCC_DATA_REQ (CC EST. CONFIRMED) */ CCD_START; { MCAST (est_cnf, U_CC_EST_CONF); if (cc_count_active_connections () EQ 0) cc_build_cc_est_confirm (est_cnf, CAUSE_MAKE(DEFBY_CONDAT, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, NOT_PRESENT_8BIT)); else cc_build_cc_est_confirm (est_cnf, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_USER_BUSY)); for_cc_est_confirm (est_cnf); } CCD_END; /* Start TIMER T335 */ TIMERSTART (T335, T335_VALUE); /* Enter the "CC-establishment confirmed" state */ cc_set_state (M_CC_CS_05); break; } break; default: /* Message not compatible with protocol state */ CCD_END; /* Implements Measure# 3 and streamline encoding */ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_recall | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming recall message. */ GLOBAL void cc_recall (T_D_RECALL * recall) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_recall"); switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_05: /* CC ESTABLISHMENT CONFIRMED */ switch(cc_data->error) { case M_CC_CAUSE_INVALID_MAND_INFO: case M_CC_CAUSE_COND_INFO_ELEM: CCD_END; /* Implements Measure# 7 and streamline encoding*/ cc_send_status (cc_data->error); return; default: /* Stop Timer T335 */ TIMERSTOP (TIMER_CC); { T_U_SETUP * setup; UBYTE result; PALLOC (fac_ind, MNCC_FACILITY_IND); /* Process facility element. may be not present */ fac_ind->ti = cc_data->ti; fac_ind->fac_context = MNCC_FAC_IN_RECALL; fac_ind->fac_inf.l_fac = recall->facility.c_fac << 3; fac_ind->fac_inf.o_fac = 0; memcpy (fac_ind->fac_inf.fac, recall->facility.fac, recall->facility.c_fac); { PALLOC (rec_ind, MNCC_RECALL_IND); /* T_MNCC_RECALL_IND */ rec_ind->ti = cc_data->ti; rec_ind->rcl_type = recall->recall_type.rcl_type; CCD_END; /* * Unpack coded setup container. * Conserving memory, so already processed parameters are * processed for a second time now. No errors expected. */ assert (cc_data->stored_ccbs_setup NEQ NULL); CCD_START; result = ccd_decodeMsg (CCDENT_CC, UPLINK, (T_MSGBUF *) &cc_data->stored_ccbs_setup->sdu, (UBYTE *) _decodedMsg, NOT_PRESENT_8BIT); assert (result EQ ccdOK); setup = (T_U_SETUP *)_decodedMsg; result = cc_basic_service_align (setup); assert (result NEQ ERROR); /* Process repeat indicator, BC I and BC II */ rec_ind->ri = cc_data->neg_ri; memcpy (&rec_ind->bcpara, &cc_data->neg_bcpara1, sizeof (T_MNCC_bcpara)); memcpy (&rec_ind->bcpara2, &cc_data->neg_bcpara2, sizeof (T_MNCC_bcpara)); /* Process called party address */ rec_ind->called_party.ton = setup->ul_called_num.ton; rec_ind->called_party.npi = setup->ul_called_num.npi; rec_ind->called_party.c_called_num = setup->ul_called_num.c_num; memcpy (rec_ind->called_party.called_num, setup->ul_called_num.num, setup->ul_called_num.c_num); /* Process called party subaddress */ if (setup->v_called_subaddr) { rec_ind->called_party_sub.tos = setup->called_subaddr.tos; rec_ind->called_party_sub.odd_even = setup->called_subaddr.odd_even; rec_ind->called_party_sub.c_subaddr = setup->called_subaddr.c_subaddr; memcpy (rec_ind->called_party_sub.subaddr, setup->called_subaddr.subaddr, MNCC_SUB_LENGTH); } else { rec_ind->called_party_sub.tos = MNCC_TOS_NOT_PRES; rec_ind->called_party_sub.c_subaddr = 0; } CCD_END; /* Send MNCC_RECALL_IND */ PSENDX (MMI, rec_ind); } /* Handle MNCC_FACILITY_IND */ if (fac_ind->fac_inf.l_fac) { PSENDX (MMI, fac_ind); } else PFREE (fac_ind); /* Next state is RECALL PRESENT */ cc_set_state (M_CC_CS_06); } break; } break; /* esac CS_05 */ default: CCD_END; /* Message not compatible with protocol state */ /* Implements Measure# 3 and streamline encoding*/ cc_send_status (MNCC_CAUSE_MESSAGE_TYPE_INCOMPAT); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_setup | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming setup message. */ GLOBAL void cc_setup (T_D_SETUP * setup) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_setup()"); switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_0: if (cc_data->ti < 8) { /* * This values are reserved for mobile originated calls. */ CCD_END; for_rel_req (); break; } switch (cc_data->error) { case M_CC_CAUSE_INVALID_MAND_INFO: case M_CC_CAUSE_COND_INFO_ELEM: CCD_END; CCD_START; { MCAST (rel_com, U_RELEASE_COMP); cc_build_release_complete (rel_com, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, cc_data->error)); for_release_complete (rel_com); } CCD_END; for_rel_req (); break; default: switch (cc_compatibility_check (setup)) { case BAD_SUBADDRESS: CCD_END; CCD_START; { MCAST (rel_com, U_RELEASE_COMP); cc_build_release_complete (rel_com, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_NO_ROUTE)); for_release_complete (rel_com); } CCD_END; for_rel_req (); cc_set_state (M_CC_CS_0); break; case ERROR: CCD_END; CCD_START; { MCAST (rel_com, U_RELEASE_COMP); cc_build_release_complete (rel_com, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST)); for_release_complete (rel_com); } CCD_END; for_rel_req (); cc_set_state (M_CC_CS_0); break; case OKAY: case NEGOTIATION: { PALLOC (setup_ind, MNCC_SETUP_IND); cc_data->progress_desc[cc_data->index_ti] = NOT_PRESENT_8BIT; if (setup->v_progress) { cc_data->progress_desc[cc_data->index_ti] = setup->progress.progress_desc; } cc_data->call_type [cc_data->index_ti] = CALL_TYPE_MTC; // PATCH LE 10.04.00 // initialize disconnect collision flag cc_data->disc_coll [cc_data->index_ti] = FALSE; // END PATCH LE 10.04.00 cc_build_mncc_setup_ind (setup, setup_ind); PSENDX (MMI, setup_ind); cc_build_facility_ind (MNCC_FAC_IN_SETUP, setup->v_facility, &setup->facility); cc_build_user_user_ind (MNCC_USER_IN_SETUP, setup->v_user_user, &setup->user_user); CCD_END; CCD_START; { MCAST (call_cnf, U_CALL_CONF); if (cc_count_active_connections () EQ 0) cc_build_call_confirm (call_cnf, CAUSE_MAKE(DEFBY_CONDAT, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, NOT_PRESENT_8BIT)); else cc_build_call_confirm (call_cnf, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_USER_BUSY)); for_call_confirm (call_cnf); } CCD_END; cc_set_state (M_CC_CS_9); EM_CC_MM_CONNECTION_ESTABLISHED_MT; break; } default: CCD_END; break; } break; } break; default: CCD_END; break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_sync_ind | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming sync indication from mobility management. */ GLOBAL void cc_sync_ind (T_MMCM_SYNC_IND * mmcm_sync) { GET_INSTANCE_DATA; PALLOC ( mncc_sync, MNCC_SYNC_IND ); TRACE_FUNCTION ("cc_sync_ind()"); cc_data->channel_type = mmcm_sync->sync_info.ch_info.ch_type; cc_data->channel_mode = mmcm_sync->sync_info.ch_info.ch_mode; mncc_sync->ti = mmcm_sync->ti; mncc_sync->ch_info.ch_mode = mmcm_sync->sync_info.ch_info.ch_mode; mncc_sync->ch_info.ch_type = mmcm_sync->sync_info.ch_info.ch_type; mncc_sync->cause = MNCC_CAUSE_CHANNEL_SYNC; PSENDX (MMI, mncc_sync); PFREE (mmcm_sync); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_est_cnf | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming establish confirm from mobility management. */ GLOBAL void cc_est_cnf (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_est_cnf()"); switch (cc_data->state[cc_data->index_ti]) { case M_CC_CS_01: { /* * As CC may potentially do some ugly things like * MAX_SETUP_ATTEMPTS > 1, we cannot use the stored * SETUP or EMERGENCY SETUP message, but have to copy. */ PALLOC_SDU (data, MMCM_DATA_REQ, cc_data->stored_setup->sdu.l_buf); data->sdu.l_buf = cc_data->stored_setup->sdu.l_buf; data->sdu.o_buf = cc_data->stored_setup->sdu.o_buf; memcpy (&data->sdu.buf[data->sdu.o_buf >> 3], &cc_data->stored_setup->sdu.buf[data->sdu.o_buf >> 3], data->sdu.l_buf >> 3); /* Forward the SETUP or EMERGENCY SETUP message to MM */ for_pd (data); } cc_set_state (M_CC_CS_1); srv_use_stored_prim (); break; default: break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_reest_cnf | +--------------------------------------------------------------------+ PURPOSE : Processing of an incoming re-establish confirm from mobility management. */ GLOBAL void cc_reest_cnf (void) { GET_INSTANCE_DATA; PALLOC (sync, MNCC_SYNC_IND); TRACE_FUNCTION ("cc_reest_cnf()"); switch (cc_data->state[cc_data->index_ti]) { case CS_101: sync->ti = cc_data->ti; sync->cause = MNCC_CAUSE_REEST_FINISHED; sync->ch_info.ch_mode = NOT_PRESENT_8BIT; sync->ch_info.ch_type = NOT_PRESENT_8BIT; PSENDX (MMI, sync); cc_set_state (M_CC_CS_10); srv_use_stored_prim (); break; case CS_261: sync->ti = cc_data->ti; sync->cause = MNCC_CAUSE_REEST_FINISHED; sync->ch_info.ch_mode = NOT_PRESENT_8BIT; sync->ch_info.ch_type = NOT_PRESENT_8BIT; PSENDX (MMI, sync); TIMERSTART (T323, T323_VALUE); cc_set_state (M_CC_CS_26); srv_use_stored_prim (); break; default: PFREE (sync); break; } } #ifdef SIM_TOOLKIT /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_mncc_bearer_cap_req | +--------------------------------------------------------------------+ PURPOSE: Checks the compatibility of bearer capabilities. Bearer capabilities in coded form are tranformed to parameter form and vice versa. */ GLOBAL void cc_mncc_bearer_cap_req (T_MNCC_BEARER_CAP_REQ * bc_req) { PALLOC (bc_conf, MNCC_BEARER_CAP_CNF); TRACE_FUNCTION ("cc_mncc_bearer_cap_req()"); /* Copy input parameters */ bc_conf->req_id = bc_req->req_id; bc_conf->bc_mod = bc_req->bc_mod; /* Set default values to no bcpara to set valid values in case cc_bearer_cap_decode returns OKAY */ memset (&bc_conf->bcpara2, 0, sizeof (T_MNCC_bcpara)); bc_conf->bcpara2.bearer_serv = MNCC_BEARER_SERV_NOT_PRES; if (bc_req->bc_mod EQ MNCC_BC_MOD_DECODE) { /* Transform coded form into parameter form */ /* Copy input parameters */ bc_conf->bcconf = bc_req->bcconf; bc_conf->bcconf2 = bc_req->bcconf2; if (cc_bearer_cap_decode(&bc_req->bcconf, &bc_conf->bcpara) EQ ERROR) { /* Bearer capabilities not supported */ PFREE (bc_req); bc_conf->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST); PSENDX (MMI, bc_conf); return; } if (cc_bearer_cap_decode((T_MNCC_bcconf *)&bc_req->bcconf2, (T_MNCC_bcpara *)&bc_conf->bcpara2) EQ ERROR) { /* Bearer capabilities not supported */ PFREE (bc_req); bc_conf->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST); PSENDX (MMI, bc_conf); return; } } else { /* Transform parameter form into coded form */ /* Copy input parameters */ bc_conf->bcpara = bc_req->bcpara; bc_conf->bcpara2 = bc_req->bcpara2; if (cc_bearer_cap_code(&bc_req->bcpara, &bc_conf->bcconf) EQ ERROR) { /* Bearer capabilities not supported */ PFREE (bc_req); bc_conf->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST); PSENDX (MMI, bc_conf); return; } if (cc_bearer_cap_code((T_MNCC_bcpara *)&bc_req->bcpara2, (T_MNCC_bcconf *)&bc_conf->bcconf2) EQ ERROR) { /* Bearer capabilities not supported */ PFREE (bc_req); bc_conf->cause = CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, MNCC_CAUSE_INCOMPAT_DEST); PSENDX (MMI, bc_conf); return; } } bc_conf->cause = MNCC_CAUSE_SUCCESS; /* Positive result */ PSENDX (MMI, bc_conf); PFREE (bc_req); } #endif /*SIM_TOOLKIT */ /* Implements Measure# 3 and streamline encoding*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_send_status | +--------------------------------------------------------------------+ PURPOSE : Calls CCD Start and then cc_build_and_send_status for sending status message */ GLOBAL void cc_send_status (USHORT cause) { TRACE_FUNCTION ("cc_send_status()"); CCD_START; { MCAST (status, B_STATUS); cc_build_status (status, CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_CC_ORIGINATING_ENTITY, cause)); for_status (status); } CCD_END; } /* Implements Measure# 19 */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_send_release_cmp | +--------------------------------------------------------------------+ PURPOSE : Send release complete message. */ LOCAL void cc_send_release_cmp (USHORT cause) { GET_INSTANCE_DATA; TRACE_FUNCTION ("cc_send_release_cmp()"); /* Send RELEASE COMPLETE */ CCD_START; { MCAST (rel_com, U_RELEASE_COMP); cc_build_release_complete (rel_com, cause); for_release_complete (rel_com); } CCD_END; /* Inform MMI */ { PALLOC (release, MNCC_RELEASE_IND); release->ti = cc_data->ti; release->cause = cause; release->c_raw_cause = cause; PSENDX (MMI, release); } /* Release MM connection */ for_rel_req (); /* Next state is NULL */ cc_set_state (M_CC_CS_0); } /* Implements Measure# 36, 48 */ /* +--------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CC_EST | | STATE : code ROUTINE : cc_send_mncc_release_ind | +--------------------------------------------------------------------------+ PURPOSE : Send release complete message with cause invalid ti. */ LOCAL void cc_send_mncc_release_ind(UBYTE ti, USHORT cause) { TRACE_FUNCTION ("cc_send_mncc_release_ind"); { PALLOC (release, MNCC_RELEASE_IND); release->ti = ti; release->cause = cause; release->c_raw_cause = 0; PSENDX (MMI, release); } } #endif