FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/llc/llc_us.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/llc/llc_us.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,1252 @@ +/* ++----------------------------------------------------------------------------- +| Project : +| Modul : ++----------------------------------------------------------------------------- +| 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 is part of the entity LLC and implements all +| functions to handles the incoming process internal signals as +| described in the SDL-documentation (U-statemachine) ++----------------------------------------------------------------------------- +*/ + +#ifndef LLC_US_C +#define LLC_US_C +#endif + +#define ENTITY_LLC + +/*==== INCLUDES =============================================================*/ + +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gprs.h" +#include "gsm.h" /* to get a lot of macros */ +#include "cnf_llc.h" /* to get cnf-definitions */ +#include "mon_llc.h" /* to get mon-definitions */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "llc.h" /* to get the global entity definitions */ +#include "llc_f.h" + +#include "llc_uf.h" /* to get local U functions */ +#include "llc_ul.h" /* to get local U labels */ +#include "llc_t200s.h" /* to get signal interface to T200 */ +#include "llc_txs.h" /* to get signal interface to TX */ +#include "llc_llmes.h" /* to get signal interface to LLME */ + +/*==== CONST ================================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +/*==== PUBLIC FUNCTIONS =====================================================*/ + + + +/* ++------------------------------------------------------------------------------ +| Function : sig_llme_u_assign_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_LLME_U_ASSIGN_REQ +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_llme_u_assign_req (void) +{ + TRACE_ISIG( "sig_llme_u_assign_req" ); + + switch (GET_STATE(U)) + { + case U_TLLI_UNASSIGNED: + u_init_sapi(); + SET_STATE (U, U_ADM); + break; + default: + TRACE_ERROR( "SIG_LLME_U_ASSIGN_REQ unexpected" ); + break; + } +} /* sig_llme_u_assign_req() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : sig_llme_u_unassign_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_LLME_U_UNASSIGN_REQ +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_llme_u_unassign_req (void) +{ + TRACE_ISIG( "sig_llme_u_unassign_req" ); + + switch (GET_STATE(U)) + { + case U_TLLI_UNASSIGNED: + TRACE_ERROR( "SIG_LLME_U_UNASSIGN_REQ unexpected" ); + break; + + default: + sig_u_t200_stop_req(); + SET_STATE (U, U_TLLI_UNASSIGNED); + break; + } +} /* sig_llme_u_unassign_req() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : sig_rx_u_data_ind ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_RX_U_DATA_IND +| +| Parameters : ll_unitdata_ind - a valid pointer to an LL-UNITDATA-IND +| primitive +| command - contains the command within the primitive +| cr_bit - setting of the C/R bit +| pf_bit - setting of the P/F bit +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_rx_u_data_ind (T_LL_UNITDATA_IND *ll_unitdata_ind, + T_COMMAND command, + T_BIT cr_bit, + T_BIT pf_bit) +{ + BOOL reset_received; + BOOL xid_ind; + BOOL rc_xid_valid; + BOOL l3p_outstanding; + + + TRACE_ISIG( "sig_rx_u_data_ind" ); + + /* + * Set TLLI for current transaction. + */ + llc_data->u->current_tlli = ll_unitdata_ind->tlli; + + switch (GET_STATE(U)) + { + case U_ADM: + if (cr_bit EQ SGSN_COMMAND) + { + /* + * Label ADM_COMMAND + */ + switch (command) + { + case U_SABM: /* COMMAND ADM */ + /* + * Label ADM_SABM + */ + if (pf_bit EQ 1) + { + if ( (llc_data->current_sapi EQ LL_SAPI_1) || + (llc_data->current_sapi EQ LL_SAPI_7) ) + { + /* + * ABM not possible on SAPI 1 and 7 + */ + PFREE (ll_unitdata_ind); + + u_send_dm (pf_bit); + } + else /* current_sapi is one of 3, 5, 9, or 11 */ + { + rc_xid_valid = u_check_xid (&(ll_unitdata_ind->sdu), + cr_bit, command); + + PFREE (ll_unitdata_ind); + + if (rc_xid_valid) + { + /* + * No check needed, reset_received cannot be TRUE + * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless + * (LL_ESTABLISH_IND contains N201-U/I). + */ + u_eval_xid (cr_bit, &reset_received, &xid_ind); + + /* + * Check XID/SABM collision issue - XID command shall + * be treated as not transmitted. + */ + if (llc_data->u->xid_pending) + { + llc_data->u->xid_pending = FALSE; + + sig_u_t200_stop_req(); + } + + /* + * Label S_EST_IND + */ + u_label_s_est_ind (pf_bit); + } + } + } + else /* pf_bit is not set */ + { + PFREE (ll_unitdata_ind); + } + break; + + case U_XID: /* COMMAND ADM */ + /* + * Label XID + */ + u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + case U_DISC: /* COMMAND ADM */ + PFREE (ll_unitdata_ind); + if (pf_bit EQ 1) + { + u_send_dm (pf_bit); + } + break; + + default: + if (pf_bit EQ 1) + { + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + } + else + { + PFREE (ll_unitdata_ind); + } + break; + } + } + else /* SGSN_RESPONSE */ + { + /* + * Label ADM_RESPONSE + */ + switch (command) + { + case U_UA: /* RESPONSE ADM */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI); + break; + + case U_DM: /* RESPONSE ADM */ + PFREE (ll_unitdata_ind); + break; + + case U_XID: /* RESPONSE ADM */ + /* + * Label XIDRES + */ + u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + case U_FRMR: /* RESPONSE ADM */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED); + break; + + default: + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + break; + } + } + break; /* U_ADM */ + + case U_LOCAL_ESTABLISHMENT: + if (cr_bit EQ SGSN_COMMAND) + { + /* + * Label LEST_COMMAND + */ + switch (command) + { + case U_SABM: /* COMMAND LOCAL_ESTABLISHMENT */ + /* + * Label LEST_SABM + */ + + if (pf_bit EQ 1) + { + rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu, cr_bit, + command); + + PFREE (ll_unitdata_ind); + + if (rc_xid_valid) + { + if ((llc_data->decoded_l3_xid.valid EQ TRUE) AND + !(llc_data->u->xid_tag_sent & (0x00000001L << XID_LAYER_3))) + { + /* + * No check needed, reset_received cannot be TRUE + * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless + * (LL_ESTABLISH_IND contains N201-U/I). + */ + u_eval_xid (cr_bit, &reset_received, &xid_ind); + + /* + * Label S_EST_IND + */ + u_label_s_est_ind (pf_bit); + } + } + } + else /* pf_bit is not set */ + { + PFREE (ll_unitdata_ind); + } + break; + + case U_DISC: /* COMMAND LOCAL_ESTABLISHMENT */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + PALLOC (ll_release_ind, LL_RELEASE_IND); + + ll_release_ind->sapi = llc_data->current_sapi; +#ifdef LL_2to1 + ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc; + ll_release_ind->ps_cause.value.llc_cause = LL_RELCS_NORMAL; +#else + ll_release_ind->cause = LL_RELCS_NORMAL; +#endif + + TRACE_1_OUT_PARA("s:%d", ll_release_ind->sapi); + PSEND (hCommSNDCP, ll_release_ind); + + u_send_dm (1); + + SET_STATE (U, U_ADM); + } + break; + + case U_XID: /* COMMAND LOCAL_ESTABLISHMENT */ + /* + * Label XID_SABM_SEND + */ + u_label_xid_sabm_send (ll_unitdata_ind, cr_bit, pf_bit); + break; + + default: + if (pf_bit EQ 1) + { + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + } + else + { + PFREE (ll_unitdata_ind); + } + break; + } + } + else /* SGSN_RESPONSE */ + { + /* + * Label LEST_RESPONSE + */ + switch (command) + { + case U_UA: /* RESPONSE LOCAL_ESTABLISHMENT */ + /* + * Label LEST_UA + */ + + if (pf_bit EQ 1) + { + rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu, + cr_bit, command); + + if (rc_xid_valid) + { + l3p_outstanding = (llc_data->u->xid_tag_sent & (0x1L << XID_LAYER_3)) ? TRUE : FALSE; + + /* + * An UA response frame should only be handled if the XID L3 + * para are included or not same as requested. Else ignore it! + */ + if (llc_data->decoded_l3_xid.valid == l3p_outstanding) + { + /* + * <R.LLC.ABMEST_R.A.018> + */ + sig_u_t200_stop_req(); + + /* + * If an XID parameter is not included in the response and + * if it was included in the request, the requested value is + * implicit accepted. + */ + u_handle_optimization (); + + /* + * Reset_received cannot be TRUE, otherwise + * frame would not be valid + */ + u_eval_xid (cr_bit, &reset_received, &xid_ind); + + PFREE (ll_unitdata_ind); + + if (llc_data->u->release_requested == TRUE) + { + /* + * Do not send any establish confirmation to L3 and start + * release procedure + */ + llc_data->u->retransmission_counter = 0; + + SET_STATE (U, U_LOCAL_RELEASE); + + /* + * Send GRLC_DATA_REQ (DISC), start T200. + */ + u_send_disc(); + } + else + { + if (llc_data->u->ind_cnf_establishment EQ IND_ESTABLISHMENT) + { + u_send_ll_establish_ind (); + + SET_STATE (U, U_ESTABLISH_RES_PENDING); + + /* + * start ABM (re-)establish when establish response is received + */ + } + else /* CNF_ESTABLISHMENT */ + { + u_send_ll_establish_cnf (); + + SET_STATE (U, U_ABM); + + /* + * inform LLME about (re-)establischment + */ + sig_u_llme_abmest_ind(); + } + } + } + else + { + PFREE (ll_unitdata_ind); + } + } + else + { + PFREE (ll_unitdata_ind); + + /* + * request T200 to let the timer manually expire, + * thus retransmitting the frame immediately + */ + sig_u_t200_expire_req (); + + /* SET_STATE (U, SAME_STATE); */ + } + } + else /* pf_bit == 0 */ + { + PFREE (ll_unitdata_ind); + + u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI); + + /* SET_STATE (U, SAME_STATE); */ + } + break; + + case U_DM: /* RESPONSE LOCAL_ESTABLISHMENT */ + /* + * Label LEST_DM + */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + sig_u_t200_stop_req(); + + if (llc_data->u->release_requested == TRUE) + { + u_send_ll_release_cnf (); + } + else + { + u_send_ll_release_ind (LL_RELCS_DM_RECEIVED); + } + + SET_STATE (U, U_ADM); + } + break; + + case U_XID: /* RESPONSE LOCAL_ESTABLISHMENT */ + /* + * Label XIDRES + */ + u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + case U_FRMR: /* RESPONSE LOCAL_ESTABLISHMENT */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED); + break; + + default: + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + break; + } + } + break; /* U_LOCAL_ESTABLISHMENT */ + + case U_ABM: + if (cr_bit EQ SGSN_COMMAND) + { + /* + * Label ABM_COMMAND + */ + switch (command) + { + case U_SABM: /* COMMAND ABM */ + /* + * Label ABM_REEST_PEER + */ + if (pf_bit EQ 1) + { + u_send_llgmm_status_ind (LLGMM_ERRCS_PEER_REEST); + + rc_xid_valid = u_check_xid (&ll_unitdata_ind->sdu, + cr_bit, command); + + PFREE (ll_unitdata_ind); + + if (rc_xid_valid) + { + /* + * No check needed, reset_received cannot be TRUE + * (<R.LLC.XID_INVA.A.003>) and xid_ind is meaningless + * (LL_ESTABLISH_IND contains N201-U/I). + */ + u_eval_xid (cr_bit, &reset_received, &xid_ind); + + /* + * Label S_EST_IND + */ + u_label_s_est_ind (pf_bit); + } + } + else /* pf_bit == 0 */ + { + PFREE (ll_unitdata_ind); + } + break; + + case U_DISC: /* COMMAND ABM */ + /* + * Label ABM_DISC + */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + PALLOC (ll_release_ind, LL_RELEASE_IND); + + ll_release_ind->sapi = llc_data->current_sapi; +#ifdef LL_2to1 + ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc; + ll_release_ind->ps_cause.value.llc_cause = LL_RELCS_NORMAL; +#else + ll_release_ind->cause = LL_RELCS_NORMAL; +#endif + TRACE_1_OUT_PARA("s:%d", ll_release_ind->sapi); + PSEND (hCommSNDCP, ll_release_ind); + + SET_STATE (U, U_ADM); + + sig_u_llme_abmrel_ind(); + + /* + * Send UA response without XID information field (= FALSE). + */ + u_send_ua (pf_bit, FALSE); + } + break; + + case U_XID: /* COMMAND ABM */ + /* + * Label XID + */ + u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + default: + if (pf_bit EQ 1) + { + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL_ABM; + + /* + * Label FRMR_COND_REEST + */ + u_label_frmr_cond_reest (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + } + else + { + PFREE (ll_unitdata_ind); + } + break; + } + } + else /* SGSN_RESPONSE */ + { + /* + * Label ABM_RESPONSE + */ + switch (command) + { + case U_UA: /* RESPONSE ABM */ + /* + * Label ABM_UA + */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI); + break; + + case U_DM: /* RESPONSE ABM */ + /* + * Label ABM_DM + */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + u_send_llgmm_status_ind (LLGMM_ERRCS_DM1_RECEIVED); + } + else /* pf_bit == 0 */ + { + u_send_llgmm_status_ind (LLGMM_ERRCS_DM0_RECEIVED_REEST); + + llc_data->u->retransmission_counter = 0; + + /* + * Send LL_ESTABLISH_IND after successful establishment. + */ + llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT; + + SET_STATE (U, U_LOCAL_ESTABLISHMENT); + + sig_u_llme_abmrel_ind(); + + /* + * Re-establishment procedure: send GRLC_DATA_REQ (SABM), + * start T200. + */ + u_send_sabm(); + } + break; + + case U_XID: /* RESPONSE ABM */ + /* + * Label XIDRES + */ + u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + case U_FRMR: /* RESPONSE ABM */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED); + break; + + default: + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL_ABM; + + /* + * Label FRMR_COND_REEST + */ + u_label_frmr_cond_reest (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + break; + } + } + break; /* U_ABM */ + + case U_LOCAL_RELEASE: + if (cr_bit EQ SGSN_COMMAND) + { + /* + * Label LREL_COMMAND + */ + switch (command) + { + case U_SABM: /* COMMAND LOCAL_RELEASE */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + /* + * Send DM response with F bit set to 1. + */ + u_send_dm (1); + } + break; + + case U_DISC: /* COMMAND LOCAL_RELEASE */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + /* + * Send UA response with F bit set to 1, but without information + * field (= FALSE). + */ + u_send_ua (1, FALSE); + } + break; + + case U_XID: /* COMMAND LOCAL_RELEASE */ + /* + * Label XID + */ + u_label_xid (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + default: + if (pf_bit EQ 1) + { + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + } + else + { + PFREE (ll_unitdata_ind); + } + break; + } + } + else /* SGSN_RESPONSE */ + { + /* + * Label LREL_RESPONSE + */ + switch (command) + { + case U_UA: /* RESPONSE LOCAL_RELEASE */ + /* + * no break! + */ + case U_DM: /* RESPONSE LOCAL_RELEASE */ + /* + * Label LREL_UA_DM + */ + PFREE (ll_unitdata_ind); + + if (pf_bit EQ 1) + { + SET_STATE (U, U_ADM); + + sig_u_t200_stop_req(); + + u_send_ll_release_cnf(); + } + else /* pf_bit == 0 */ + { + if (command EQ U_UA) + { + u_send_llgmm_status_ind (LLGMM_ERRCS_MULT_ASS_TLLI); + } + } + break; + + case U_XID: /* RESPONSE LOCAL_RELEASE */ + /* + * Label XIDRES + */ + u_label_xidres (ll_unitdata_ind, command, cr_bit, pf_bit); + break; + + case U_FRMR: /* RESPONSE LOCAL_RELEASE */ + PFREE (ll_unitdata_ind); + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_RECEIVED); + break; + + default: + llc_data->u->frmr_reason = FRMR_UNDEFINED_CTRL; + + /* + * Label FRMR_COND + */ + u_label_frmr_cond (ll_unitdata_ind, cr_bit, + llc_data->u->frmr_reason); + break; + } + } + break; /* U_LOCAL_RELEASE */ + + default: + PFREE (ll_unitdata_ind); + TRACE_ERROR( "SIG_RX_U_DATA_IND unexpected" ); + break; + } +} /* sig_rx_u_data_ind() */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_rx_u_frmr_ind ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_RX_U_FRMR_IND +| +| Parameters : ll_unitdata_ind - valid pointer to the frame that caused the +| frame rejection condition +| pdu_type - type of frame +| frmr_ctrl_length - length of frame control field, if known +| cr_bit - C/R bit setting of frame +| frmr_reason - reason of frame rejection condition +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_rx_u_frmr_ind (T_LL_UNITDATA_IND *ll_unitdata_ind, + T_PDU_TYPE pdu_type, + USHORT frmr_ctrl_length, + T_BIT cr_bit, + UBYTE frmr_reason) +{ + TRACE_ISIG( "sig_rx_u_frmr_ind" ); + + /* + * Set TLLI for current transaction. + */ + llc_data->u->current_tlli = ll_unitdata_ind->tlli; + + switch (GET_STATE (U)) + { + case U_ADM: + case U_LOCAL_ESTABLISHMENT: + case U_ESTABLISH_RES_PENDING: + case U_REMOTE_ESTABLISHMENT: + /* + * No break! + */ + case U_LOCAL_RELEASE: + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND); + + u_send_frmr (ll_unitdata_ind, pdu_type, frmr_ctrl_length, + llc_data->sapi->vs, llc_data->sapi->vr, + cr_bit, frmr_reason); + + PFREE (ll_unitdata_ind); + break; + case U_ABM: + u_send_llgmm_status_ind (LLGMM_ERRCS_FRMR_COND_REEST); + + SET_STATE (U, U_LOCAL_ESTABLISHMENT); + + /* + * Set bit W4 in frmr_reason to indicate ABM mode. + */ + frmr_reason |= FRMR_W4; + + u_send_frmr (ll_unitdata_ind, pdu_type, frmr_ctrl_length, + llc_data->sapi->vs, llc_data->sapi->vr, + cr_bit, frmr_reason); + + sig_u_llme_abmrel_ind(); + + PFREE (ll_unitdata_ind); + + llc_data->u->retransmission_counter = 0; + + /* + * Send LL_ESTABLISH_IND after successful establishment. + */ + llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT; + + /* + * Re-establishment procedure: send GRLC_DATA_REQ (SABM), start T200. + */ + u_send_sabm(); + break; + default: + PFREE (ll_unitdata_ind); + TRACE_ERROR( "SIG_RX_U_FRMR_IND unexpected" ); + break; + } + +} /* sig_rx_u_frmr_ind() */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_t200_u_expired_ind ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_T200_U_EXPIRED_IND +| +| Parameters : grlc_data_req - a valid pointer to the frame (primitive) that +| is associated with the timer +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_t200_u_expired_ind +( +#ifndef LL_DESC + T_LL_UNITDATA_REQ *ll_unitdesc_req, +#else + T_LL_UNITDESC_REQ *ll_unitdesc_req, +#endif + UBYTE cause, + T_EXPIRY_MODE_TYPE mode +) +{ + UBYTE u_state; + + TRACE_ISIG( "sig_t200_u_expired_ind" ); + + /* + * Set TLLI for current transaction. + */ + llc_data->u->current_tlli = llc_data->tlli_new; + + u_state = GET_STATE(U); + switch (u_state) + { + case U_LOCAL_ESTABLISHMENT: + /* + * First check if an L3 release requested is pendling + */ + if (llc_data->u->release_requested == TRUE) + { + /* + * Do not restart timer. Send the release confirm. + */ +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + + u_send_ll_release_cnf(); + + SET_STATE (U, U_ADM); + } + else + { + /* + * Increment retransmission_counter. + */ + llc_data->u->retransmission_counter++; + + if (llc_data->u->retransmission_counter <= *(llc_data->n200)) + { + /* + * T200 has to be started before the primitive is sent to TX, because + * the primitive is copied by t200_start() and it may not be valid + * anymore after sending to TX. + */ + sig_u_t200_start_req (ll_unitdesc_req, cause); + + sig_u_tx_data_req (ll_unitdesc_req, cause); + } + else /* retransmission_counter exceeds N200 */ + { +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + + /* + * Label LEST_N200 + */ + + u_send_llgmm_status_ind (LLGMM_ERRCS_SABM_NO_PEER_RES); + + if (mode == EXPIRY_TIMED) + { + u_send_ll_release_ind (LL_RELCS_NO_PEER_RES); + } + else /* EXPIRY_REQUESTED */ + { + /* + * <R.LLC.ABMEST_R.A.015> + * vs. <R.LLC.ABMEST_R.A.030> + */ + u_send_ll_release_ind (LL_RELCS_INVALID_XID); + } + + SET_STATE (U, U_ADM); + } + } + break; /* U_LOCAL_ESTABLISHMENT */ + + case U_LOCAL_RELEASE: + /* + * First check if an L3 release requested is pendling + */ + if (llc_data->u->release_requested == TRUE) + { + /* + * Do not restart timer. Send the release confirm. + */ +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + + u_send_ll_release_cnf(); + + SET_STATE (U, U_ADM); + } + else + { + /* + * Increment retransmission_counter. + */ + llc_data->u->retransmission_counter++; + + if (llc_data->u->retransmission_counter <= *(llc_data->n200)) + { + /* + * T200 has to be started before the primitive is sent to TX, because + * the primitive is copied by t200_start() and it may not be valid + * anymore after sending to TX. + */ + sig_u_t200_start_req (ll_unitdesc_req, cause); + sig_u_tx_data_req (ll_unitdesc_req, cause); + } + else /* retransmission_counter exceeds N200 */ + { +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + + SET_STATE (U, U_ADM); + + u_send_llgmm_status_ind (LLGMM_ERRCS_DISC_NO_PEER_RES); + u_send_ll_release_cnf (); + } + } + break; + + case U_ADM: + case U_ABM: + llc_data->u->retransmission_counter++; + if (llc_data->u->retransmission_counter <= *(llc_data->n200)) + { + /* If T200 expires and needs to send SABM the state should + * be set properly + */ + if (u_state == U_ADM AND + llc_data->u->xid_pending NEQ TRUE ) + { + SET_STATE (U,U_LOCAL_ESTABLISHMENT); + } + /* + * T200 has to be started before the primitive is sent to TX, because + * the primitive is copied by t200_start() and it may not be valid + * anymore after sending to TX. + */ + sig_u_t200_start_req (ll_unitdesc_req, cause); + sig_u_tx_data_req (ll_unitdesc_req, cause); + + /* SET_STATE (U, SAME_STATE); */ + } + else + { +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + + /* + * Label XIDSENT_N200 + */ + + u_send_llgmm_status_ind (LLGMM_ERRCS_XID_NO_PEER_RES); + + if (llc_data->u->xid_pending) + { + llc_data->u->xid_pending = FALSE; + } + + if (u_state == U_ADM) + { + if (llc_data->u->xid_tag_sent & (0x00000001L << XID_LAYER_3)) + { + if (mode == EXPIRY_TIMED) + { + u_send_ll_status_ind (LL_ERRCS_NO_PEER_RES); + } + else /* EXPIRY_REQUESTED */ + { + u_send_ll_status_ind (LL_ERRCS_INVALID_XID); + } + } + + /* SET_STATE (U, SAME_STATE); */ + } + else /* U_ABM */ + { + if (mode == EXPIRY_TIMED) + { + u_send_ll_release_ind (LL_RELCS_NO_PEER_RES); + } + else /* EXPIRY_REQUESTED */ + { + /* + * <R.LLC.XIDNEG_O.A.016> + * vs. <R.LLC.XIDNEG_O.A.022> + */ + u_send_ll_release_ind (LL_RELCS_INVALID_XID); + } + + SET_STATE (U, U_ADM); + + sig_u_llme_abmrel_ind(); + } + } + break; + + default: +#ifdef LL_DESC + llc_cl_desc3_free((T_desc3*)ll_unitdesc_req->desc_list3.first); +#endif /* LL_DESC */ + PFREE (ll_unitdesc_req); + TRACE_ERROR( "SIG_T200_U_EXPIRED_IND unexpected" ); + break; + } +} /* sig_t200_u_expired_ind() */ + + +/* ++------------------------------------------------------------------------------ +| Function : sig_llme_u_reest_req ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_LLME_U_REEST_REQ +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_llme_u_reest_req ( void ) +{ + TRACE_FUNCTION( "sig_llme_u_reest_req" ); + + switch (GET_STATE(U)) + { + case U_ABM: + llc_data->u->retransmission_counter = 0; + + /* + * Send LL_ESTABLISH_IND after successful re-establishment. + */ + llc_data->u->ind_cnf_establishment = IND_ESTABLISHMENT; + + SET_STATE (U, U_LOCAL_ESTABLISHMENT); + + /* + * Send GRLC_DATA_REQ (SABM), start T200. + */ + u_send_sabm(); + break; + + default: + TRACE_ERROR( "SIG_LLME_U_REEST_REQ unexpected" ); + break; + } + +} /* sig_llme_u_reest_req() */ + +/* ++------------------------------------------------------------------------------ +| Function : sig_irx_u_no_frame_expected_ind ++------------------------------------------------------------------------------ +| Description : Handles the internal signal SIG_IRX_U_NO_FRAME_EXPECTED_IND +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void sig_irx_u_no_frame_expected_ind ( void ) +{ + TRACE_FUNCTION( "sig_irx_u_no_frame_expected_ind" ); + + switch (GET_STATE(U)) + { + case U_ADM: + /* + * An LLE shall transmit a DM resonse to any valid command received + * that it cannot action: GSM 04.64 Ver 6.7.0 Chapter 6.4.1.4 + * Upon receiption of an I+S frame in ADM state, the MS shall send + * a DM response with F bit set 0. + */ + u_send_dm (0); + break; + + case U_LOCAL_ESTABLISHMENT: + case U_ESTABLISH_RES_PENDING: + case U_REMOTE_ESTABLISHMENT: + /* + * Ignore S- and I/S-frames received while ABM establishment. Do + * not send any response: GSM 04.64 Ver 6.7.0 Chapter 8.5.1.1 + */ + break; + + case U_LOCAL_RELEASE: + /* + * Ignore S- and I/S-frames received while ABM termination. Do + * not send any response: GSM 04.64 Ver 6.7.0 Chapter 8.5.2.1 + */ + break; + + case U_ABM: + default: + TRACE_ERROR( "SIG_IRX_U_NO_FRAME_EXPECTED_IND unexpected" ); + break; + } + +} /* sig_irx_u_no_frame_expected_ind() */ +