FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/sndcp/sndcp_mgf.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/sndcp/sndcp_mgf.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,6120 @@ +/* ++----------------------------------------------------------------------------- +| Project : GPRS (8441) +| Modul : sndcp_mgf.c ++----------------------------------------------------------------------------- +| 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 SNDCP and implements all +| procedures and functions as described in the +| SDL-documentation (MG-statemachine) ++----------------------------------------------------------------------------- +*/ + + +#define ENTITY_SNDCP + +/*==== INCLUDES =============================================================*/ + +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gsm.h" /* to get a lot of macros */ +#include "prim.h" /* to get the definitions of used SAP and directions */ + +#include "dti.h" + +#include "sndcp.h" /* to get the global entity definitions */ +#include "sndcp_f.h" /* to get the functions to access the global arrays*/ + +#include "sndcp_cias.h" /* to get the signals to service cia */ +#include "sndcp_nds.h" /* to get the signals to service nd */ +#include "sndcp_nus.h" /* to get the signals to service nu */ +#include "sndcp_nuf.h" +#include "sndcp_sus.h" /* to get the signals to service su */ +#include "sndcp_suas.h" /* to get the signals to service su */ +#include "sndcp_sds.h" /* to get the signals to service sd */ +#include "sndcp_sdas.h" /* to get the signals to service sda */ + +#include "sndcp_mgf.h" /* to get ths file */ +#include "sndcp_nup.h" /* nu_sn_[unit]data_req is called from + sig_callback().*/ + +#include <string.h> + +/*==== CONST ================================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +LOCAL void mg_get_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE* dntt); + +LOCAL void mg_get_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL* used); + +LOCAL void mg_get_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE* state); + +LOCAL void mg_get_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE* stat); + +LOCAL void mg_get_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE* stat); + +LOCAL void mg_get_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE* state); + +LOCAL void mg_set_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL used); + +LOCAL void mg_set_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE stat); + +LOCAL void mg_set_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE dntt); + +LOCAL void mg_set_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL rej); + +LOCAL void mg_set_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE state); + +LOCAL void mg_set_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL used); + +LOCAL void mg_set_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE stat); + +LOCAL void mg_set_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE pntt); + +LOCAL void mg_set_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL rej); + +LOCAL void mg_set_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE state); + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_dcomp_dntt ++------------------------------------------------------------------------------ +| Description : The procedures indicates the dntt assigned to a given dcomp +| for a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dcomp UBYTE, +| IN/OUT dntt UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE* dntt) +{ + TRACE_FUNCTION( "mg_get_sapi_dcomp_dntt" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *dntt = sndcp_data->mg.sapi_dcomp_dntt_ra[sapi_index][dcomp]; + } +} /* mg_get_sapi_dcomp_dntt() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_dntt_nsapi ++------------------------------------------------------------------------------ +| Description : The procedure informs if a given nsapi uses a given dntt on a +| given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN nsapi UBYTE, +| IN/OUT used BOOL +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL* used) +{ + TRACE_FUNCTION( "mg_get_sapi_dntt_nsapi" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *used = sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][dntt][nsapi]; + } +} /* mg_get_sapi_dntt_nsapi() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_dcomp_state ++------------------------------------------------------------------------------ +| Description : The procedures informs about the state of a given dcomp on a +| given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dcomp UBYTE, +| IN/OUT stat UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE* stat) +{ + TRACE_FUNCTION( "mg_get_sapi_dcomp_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *stat = sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp]; + } +} /* mg_get_sapi_dcomp_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_dntt_state ++------------------------------------------------------------------------------ +| Description : The procedures informs about the state of a given data +| compression entity on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN/OUT state UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE* state) +{ + TRACE_FUNCTION( "mg_get_sapi_dntt_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *state = sndcp_data->mg.sapi_dntt_state_ra[sapi_index][dntt]; + } + + + +} /* mg_get_sapi_dntt_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_pcomp_state ++------------------------------------------------------------------------------ +| Description : The procedures informs about the state of a given pcomp on a +| given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pcomp UBYTE, +| IN/OUT stat UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE* stat) +{ + TRACE_FUNCTION( "mg_get_sapi_pcomp_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *stat = sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp]; + } +} /* mg_get_sapi_pcomp_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_pntt_state ++------------------------------------------------------------------------------ +| Description : The procedures informs about the state of a given header +| compression entity on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN/OUT state UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_get_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE* state) +{ + TRACE_FUNCTION( "mg_get_sapi_pntt_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *state = sndcp_data->mg.sapi_pntt_state_ra[sapi_index][pntt]; + } +} /* mg_get_sapi_pntt_state() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_check_sense_bitwise ++------------------------------------------------------------------------------ +| Description : Checks, if "small" is bitwise smaller than or equal to "big" +| +| Parameters : USHORT small, big, BOOL wrong is set to TRUE, if small > big +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_ushort_sense_bitwise (USHORT small, + USHORT big, + BOOL* wrong) { + UBYTE bit = 0; + TRACE_FUNCTION( "mg_check_sense_bitwise" ); + *wrong = TRUE; + for (bit = 0; bit < 8 * sizeof(USHORT); bit++) { + if ((small & (1 << bit)) > (big & (1 << bit))) { + return; + } + } + *wrong = FALSE; +} /* mg_check_sense_bitwise() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_check_sense_bitwise ++------------------------------------------------------------------------------ +| Description : Checks, if "small" is bitwise smaller than "big" +| +| Parameters : UBYTE small, big, BOOL wrong is set to TRUE, if small > big +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_ubyte_sense_bitwise (UBYTE small, + UBYTE big, + BOOL* wrong) { + UBYTE bit = 0; + TRACE_FUNCTION( "mg_check_sense_bitwise" ); + *wrong = TRUE; + for (bit = 0; bit < 8 * sizeof(UBYTE); bit++) { + if ((small & (1 << bit)) > (big & (1 << bit))) { + return; + } + } + *wrong = FALSE; +} /* mg_check_sense_bitwise() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_decode_v42 ++------------------------------------------------------------------------------ +| Description : decodes the v42 part of given sdu to given xid block +| +| Parameters : source sdu, +| index in sdu, +| field index in sdu (sub index in compression fields, +| destination xid block, +| success ok +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_decode_v42 (T_sdu* sdu, + USHORT* index, + USHORT* field_index, + T_XID_BLOCK* xid_block, + BOOL* ok, + UBYTE p_bit) { +#define CHECK_XID_BUFFER_LEN2 if (*index + *field_index >= ((sdu->l_buf) >> 3)) return + + USHORT field_length = 0; + TRACE_FUNCTION( "mg_decode_v42" ); + *ok = FALSE; + + /* + * Set field_index to length of field octet. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + field_length = sdu->buf[*index + *field_index]; + /* + * NSAPIS parameter and followers omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_DATA_P_1_NSAPIS_OM) { + *ok = TRUE; + return; + } + } else { + if (field_length == MG_DATA_P_0_NSAPIS_OM) { + *ok = TRUE; + return; + } + } + /* + * If p bit set to 1, set field_index to dcomp field. + */ + if (p_bit == SNDCP_P_BIT_1) { + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.dcomp = + ((USHORT)sdu->buf[*index + *field_index]) >> 4; + } + /* + * Set field_index to MSB of applicable nsapis short. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.nsapis = + ((USHORT)sdu->buf[*index + *field_index]) << 8; + xid_block->v42.nsapis_set = TRUE; + /* + * Set field_index to LSB of applicable nsapis short. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.nsapis += + ((USHORT)sdu->buf[*index + *field_index]); + /* + * P0 parameter and followers omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_DATA_P_1_P0_OM) { + *ok = TRUE; + return; + } + } else { + if (field_length == MG_DATA_P_0_P0_OM) { + *ok = TRUE; + return; + } + } + /* + * Set field_index to p0. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.p0 = + sdu->buf[*index + *field_index]; + xid_block->v42.p0_set = TRUE; + /* + * P1 parameter and followers omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_DATA_P_1_P1_OM) { + *ok =TRUE; + return; + } + } else { + if (field_length == MG_DATA_P_0_P1_OM) { + *ok =TRUE; + return; + } + } + /* + * Set field_index to MSB of p1. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.p1 = + ((USHORT)sdu->buf[*index + *field_index]) << 8; + xid_block->v42.p1_set = TRUE; + /* + * Set field_index to LSB of p1. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.p1 += + ((USHORT)sdu->buf[*index + *field_index]); + /* + * P2 parameter and followers omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_DATA_P_1_P2_OM) { + *ok = TRUE; + return; + } + } else { + if (field_length == MG_DATA_P_0_P2_OM) { + *ok = TRUE; + return; + } + } + /* + * Set field_index to p2. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN2; + xid_block->v42.p2 = + sdu->buf[*index + *field_index]; + xid_block->v42.p2_set = TRUE; + + /* + * If length of v42 field is longer than specified, ignore the rest. + */ + while (*field_index < field_length) { + CHECK_XID_BUFFER_LEN2; + (*field_index)++; + } + + *ok = TRUE; + +} /* mg_decode_v42() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_decode_vj ++------------------------------------------------------------------------------ +| Description : decodes the vj part of given sdu to given xid block +| +| Parameters : source sdu, +| index in sdu, +| field index in sdu (sub index in compression fields, +| destination xid block, +| success ok +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_decode_vj (T_sdu* sdu, + USHORT* index, + USHORT* field_index, + T_XID_BLOCK* xid_block, + BOOL* ok, + UBYTE p_bit) { +#define CHECK_XID_BUFFER_LEN3 if (*index + *field_index >= ((sdu->l_buf) >> 3)) return + + USHORT field_length = 0; + TRACE_FUNCTION( "mg_decode_vj" ); + + /* + * Set field_index to length of field octet. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN3; + field_length = sdu->buf[*index + *field_index]; + /* + * NSAPIS parameter and followers omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_HEADER_P_1_NSAPIS_OM) { + *ok = TRUE; + return; + } + } else { + if (field_length == MG_HEADER_P_0_NSAPIS_OM) { + *ok = TRUE; + return; + } + } + /* + * If p bit set to 1, set field_index to dcomp field. + */ + if (p_bit == SNDCP_P_BIT_1) { + (*field_index)++; + CHECK_XID_BUFFER_LEN3; + xid_block->vj.pcomp1 = + ((USHORT)sdu->buf[*index + *field_index]) >> 4; + xid_block->vj.pcomp2 = + ((USHORT)sdu->buf[*index + *field_index]) & 0xf; + } + + /* + * Set field_index to MSB of applicable nsapis short. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN3; + xid_block->vj.nsapis = + ((USHORT)sdu->buf[*index + *field_index]) << 8; + xid_block->vj.nsapis_set = TRUE; + /* + * Set field_index to LSB of applicable nsapis short. + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN3; + xid_block->vj.nsapis += + ((USHORT)sdu->buf[*index + *field_index]); + /* + * S0_M_1 parameter omitted? + */ + if (p_bit == SNDCP_P_BIT_1) { + if (field_length == MG_HEADER_P_1_S0_M_1_OM) { + *ok = TRUE; + return; + } + } else { + if (field_length == MG_HEADER_P_0_S0_M_1_OM) { + *ok = TRUE; + return; + } + } + /* + * Set field_index to "s0 - 1" Parameter + */ + (*field_index)++; + CHECK_XID_BUFFER_LEN3; + xid_block->vj.s0_m_1 = sdu->buf[*index + *field_index]; + xid_block->vj.s0_m_1_set = TRUE; + + /* + * If length of vj field is longer than specified, ignore the rest. + */ + while (*field_index < field_length) { + CHECK_XID_BUFFER_LEN3; + (*field_index)++; + } + + + *ok = TRUE; + +} /* mg_decode_vj() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_detect_mode_clash ++------------------------------------------------------------------------------ +| Description : Unacknowledged and acknowledged contexts may not share the same +| compressor entity. This procdure detects possible violations of that rule. +| +| Parameters : the set of nsapis given as USHORT bit mask, +| violation detected, TRUE if at least 1 acknowledged and 1 +| unacknowledged context share the same compressor. +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_detect_mode_clash (USHORT nsapis, BOOL* vio) +{ + UBYTE nsapi = 0; + BOOL unack_found = FALSE; + BOOL ack_found = FALSE; + BOOL ack = FALSE; + TRACE_FUNCTION( "mg_detect_mode_clash" ); + /* + * Find affected nsapis. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((nsapis & (1 << nsapi)) > 0) { + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack) { + ack_found = TRUE; + } else { + unack_found = TRUE; + } + } + } + *vio = unack_found && ack_found; + + +} /* mg_detect_mode_clash() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_respond_if_nec ++------------------------------------------------------------------------------ +| Description : All nsapis connected to the given sapi +| that are in state MG_ACT are sent an +| SNSM_ACTIVATE_RES. +| +| Parameters : sapi +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_respond_if_nec (UBYTE sapi) { + UBYTE nsapi = 0; + UBYTE sapi_index = 0; +#ifdef SNDCP_UPM_INCLUDED + BOOL ack = FALSE; +#endif /* SNDCP_UPM_INCLUDED */ + + TRACE_FUNCTION( "mg_respond_if_nec" ); + + sndcp_get_sapi_index(sapi, &sapi_index); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + USHORT nsapi_state = MG_IDLE; + USHORT sapi_state = MG_IDLE; + UBYTE local_sapi = 0; + sndcp_get_nsapi_state(nsapi, &nsapi_state); + sndcp_get_nsapi_sapi(nsapi, &local_sapi); + sndcp_get_sapi_state(local_sapi, &sapi_state); + if (((nsapi_state & MG_ACT) > 0) + && + ((sapi_state & MG_XID) == 0) + && + ((sapi_state & MG_EST) == 0) + && + (local_sapi == sapi)) { + + /* + * Open DTI connection. + */ +#ifndef SNDCP_UPM_INCLUDED + mg_dti_open(nsapi); +#else + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack) { + nu_ready_ind_if_nec(nsapi); + } else { + nu_unitready_ind_if_nec(nsapi); + } +#endif + + mg_send_snsm_activate_res(nsapi); + /* + * Set nsapi state to MG_IDLE. + */ + sndcp_unset_nsapi_state (nsapi, MG_ACT); + } + + if (((nsapi_state & MG_DEACT) > 0) + && + ((sapi_state & MG_XID) == 0) + && + ((sapi_state & MG_REL) == 0) + && + (local_sapi == sapi)) { + +#ifdef SNDCP_UPM_INCLUDED + PALLOC(snsm_deactivate_res, SN_DEACTIVATE_CNF); +#else + PALLOC(snsm_deactivate_res, SNSM_DEACTIVATE_RES); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Now the NSAPI is not in use anymore: + */ + sndcp_set_nsapi_used(nsapi, FALSE); + sndcp_set_nsapi_ack(nsapi, FALSE); + + snsm_deactivate_res->nsapi = nsapi; + sndcp_unset_nsapi_state(nsapi, MG_DEACT); +#ifdef SNDCP_UPM_INCLUDED + PSEND(hCommUPM, snsm_deactivate_res); +#else + PSEND(hCommSM, snsm_deactivate_res); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + } + + } + +} /* mg_respond_if_nec */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_ntt_comp ++------------------------------------------------------------------------------ +| Description : Sets ntt and comp values acc. to req_xid_block. +| +| Parameters : UBYTE sapi, BOOL is this a renegotiation? +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_ntt_comp (UBYTE sapi) { + UBYTE sapi_index = 0; + UBYTE nsapi = 0; + TRACE_FUNCTION( "mg_set_ntt_comp" ); + sndcp_get_sapi_index(sapi, &sapi_index); + + if (sndcp_data->mg.req_xid_block[sapi_index].v42.is_set) { + mg_set_sapi_dntt_state(sapi, + sndcp_data->mg.req_xid_block[sapi_index].v42.ntt, + MG_SELECTED); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis & (1 << nsapi)) + > 0) { + mg_set_sapi_dntt_nsapi(sapi, + sndcp_data->mg.req_xid_block[sapi_index].v42.ntt, + nsapi, + TRUE); + } + } + mg_set_sapi_dcomp_state(sapi, + sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp, + MG_SELECTED); + mg_set_sapi_dcomp_dntt(sapi, + sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp, + sndcp_data->mg.req_xid_block[sapi_index].v42.ntt); + } + if (sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) { + mg_set_sapi_pntt_state(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt, + MG_SELECTED); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis & (1 << nsapi)) + > 0) { + mg_set_sapi_pntt_nsapi(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt, + nsapi, + TRUE); + } + } + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1, + MG_SELECTED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2, + MG_SELECTED); + mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1, + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt); + mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2, + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt); + } + + +} /* mg_set_ntt_comp() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_dntt_nsapi ++------------------------------------------------------------------------------ +| Description : The procedure stores the info that a given nsapi uses a given +| dntt on a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN nsapi UBYTE, +| IN used BOOL +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_dntt_nsapi (UBYTE sapi, UBYTE dntt, UBYTE nsapi, BOOL used) +{ + TRACE_FUNCTION( "mg_set_sapi_dntt_nsapi" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][dntt][nsapi] = used; + } +} /* mg_set_sapi_dntt_nsapi() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_dcomp_state ++------------------------------------------------------------------------------ +| Description : The procedures sets the state of a given dcomp on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dcomp UBYTE, +| IN stat UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_dcomp_state (UBYTE sapi, UBYTE dcomp, UBYTE stat) +{ + TRACE_FUNCTION( "mg_set_sapi_dcomp_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp] = stat; + } +} /* mg_set_sapi_dcomp_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_dcomp_dntt ++------------------------------------------------------------------------------ +| Description : The procedures sets the dntt assigned to a given dcomp +| for a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dcomp UBYTE, +| IN dntt UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_dcomp_dntt (UBYTE sapi, UBYTE dcomp, UBYTE dntt) +{ + TRACE_FUNCTION( "mg_set_sapi_dcomp_dntt" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_dcomp_dntt_ra[sapi_index][dcomp] = dntt; + } +} /* mg_set_sapi_dcomp_dntt() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_dntt_rej ++------------------------------------------------------------------------------ +| Description : The procedures stores if a given data +| compression entity on a given SAPI is to be rejected in +| LL_XID_REQ because it cannot be set up. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN rej BOOL +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL rej) +{ + TRACE_FUNCTION( "mg_set_sapi_dntt_rej" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][dntt] = rej; + } +} /* mg_set_sapi_dntt_rej() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_dntt_state ++------------------------------------------------------------------------------ +| Description : The procedures sets the state of a given data +| compression entity on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN state UBYTE +| Note : sapi dntt rej will be set ti FALSE if state is UNASSIGNED +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_dntt_state (UBYTE sapi, UBYTE dntt, UBYTE state) +{ + TRACE_FUNCTION( "mg_set_sapi_dntt_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_dntt_state_ra[sapi_index][dntt] = state; + + if (state == MG_UNASSIGNED) { + mg_set_sapi_dntt_rej(sapi, dntt, FALSE); + } + } +} /* mg_set_sapi_dntt_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_pntt_nsapi ++------------------------------------------------------------------------------ +| Description : The procedure stores the info that a given nsapi uses a given +| pntt on a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN nsapi UBYTE, +| IN used BOOL +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL used) +{ + TRACE_FUNCTION( "mg_set_sapi_pntt_nsapi" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][pntt][nsapi] = used; + } +} /* mg_set_sapi_pntt_nsapi() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_pcomp_state ++------------------------------------------------------------------------------ +| Description : The procedures sets the state of a given pcomp on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pcomp UBYTE, +| IN stat UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_pcomp_state (UBYTE sapi, UBYTE pcomp, UBYTE stat) +{ + TRACE_FUNCTION( "mg_set_sapi_pcomp_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp] = stat; + } +} /* mg_set_sapi_pcomp_state() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_pcomp_pntt ++------------------------------------------------------------------------------ +| Description : The procedures sets the pntt assigned to a given pcomp +| for a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pcomp UBYTE, +| IN pntt UBYTE +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE pntt) +{ + TRACE_FUNCTION( "mg_set_sapi_pcomp_pntt" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_pcomp_pntt_ra[sapi_index][pcomp] = pntt; + } +} /* mg_get_sapi_pcomp_pntt() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_pntt_rej ++------------------------------------------------------------------------------ +| Description : The procedures stores if a given data +| compression entity on a given SAPI is to be rejected in +| LL_XID_REQ because it cannot be set up. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN rej BOOL +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL rej) +{ + TRACE_FUNCTION( "mg_set_sapi_pntt_rej" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][pntt] = rej; + } +} /* mg_set_sapi_pntt_rej() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_sapi_pntt_state ++------------------------------------------------------------------------------ +| Description : The procedures sets the state of a given header +| compression entity on a given SAPI. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN state UBYTE +| Note : sapi pntt rej will be set ti FALSE if state is UNASSIGNED +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_sapi_pntt_state (UBYTE sapi, UBYTE pntt, UBYTE state) +{ + TRACE_FUNCTION( "mg_set_sapi_pntt_state" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_data->mg.sapi_pntt_state_ra[sapi_index][pntt] = state; + + if (state == MG_UNASSIGNED) { + mg_set_sapi_pntt_rej(sapi, pntt, FALSE); + } + } +} /* mg_set_sapi_pntt_state() */ + +#ifndef NCONFIG +/* ++------------------------------------------------------------------------------ +| Function : mg_config_delay ++------------------------------------------------------------------------------ +| Description : after config prim DELAY each new context activation will be +| computed with a delay. +| +| Parameters : delay in milliseconds +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_config_delay (USHORT millis) +{ + + TRACE_FUNCTION("mg_config_delay"); + + sndcp_data->millis = millis; + +} /* mg_config_delay() */ +#endif + + +/* ++------------------------------------------------------------------------------ +| Function : mg_reset_compressors ++------------------------------------------------------------------------------ +| Description : All compressors used by this nsapi are reset. +| +| Parameters : nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_reset_compressors (UBYTE nsapi) +{ + BOOL compressed = FALSE; + TRACE_FUNCTION( "mg_reset_compressors" ); + + sndcp_is_nsapi_data_compressed(nsapi, &compressed); + if (compressed) { + /* + * Must be added when data compression is added. + */ + } + + sndcp_is_nsapi_header_compressed(nsapi, &compressed); + if (compressed) { + UBYTE sapi = 0; + UBYTE sapi_index = 0; + /* + * This is implementation dependent and only works as long as only 1 + * header compressor is used in cia service. + */ + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_sapi_index(sapi, &sapi_index); + sig_mg_cia_new_xid(&sndcp_data->mg.cur_xid_block[sapi_index]); + } + +} /* mg_reset_compressors() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_reset_comp_ack ++------------------------------------------------------------------------------ +| Description : all compression entities using +| acknowledged peer-to-peer LLC operation on this SAPI are reset. +| +| Parameters : sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_reset_comp_ack (UBYTE sapi) { + UBYTE nsapi = 0; + TRACE_FUNCTION( "mg_reset_comp_ack" ); + /* + * All nsapis at this sapi that use ack mode reset their compressors. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) { + UBYTE s = 0; + BOOL ack = FALSE; + BOOL used = FALSE; + sndcp_is_nsapi_used(nsapi, &used); + if (!used) { + continue; + } + sndcp_get_nsapi_sapi(nsapi, &s); + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack && s == sapi) { + mg_reset_compressors(nsapi); + } + } /* for all nsapis */ + +} /* mg_reset_comp_ack() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_reset_states_n_rej ++------------------------------------------------------------------------------ +| Description : Resets all states for ntts and p/dcomp to "unassigned". +| Resets the arrays with information on rejcted entities. +| +| Parameters : index of the affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_reset_states_n_rej (UBYTE sapi_index) +{ + + UBYTE ntt = 0; + UBYTE nsapi = 0; + UBYTE dcomp = 0; + UBYTE pcomp = 0; + TRACE_FUNCTION( "mg_reset_states_n_rej" ); + + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + sndcp_data->mg.sapi_dntt_state_ra[sapi_index][ntt] = MG_UNASSIGNED; + sndcp_data->mg.sapi_pntt_state_ra[sapi_index][ntt] = MG_UNASSIGNED; + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + sndcp_data->mg.sapi_dntt_nsapi_set_ra[sapi_index][ntt][nsapi] = FALSE; + sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][ntt][nsapi] = FALSE; + } + sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE; + sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE; + } + for (dcomp = 0; dcomp < MG_MAX_DCOMP; dcomp++) { + sndcp_data->mg.sapi_dcomp_state_ra[sapi_index][dcomp] = MG_UNASSIGNED; + } + for (pcomp = 0; pcomp < MG_MAX_PCOMP; pcomp++) { + sndcp_data->mg.sapi_pcomp_state_ra[sapi_index][pcomp] = MG_UNASSIGNED; + } + /* + * sapi_dcomp_dntt_ra, sapi_pcomp_pntt_ra not initialized. + */ + +} /* mg_reset_states_n_rej() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_xid_nsapis ++------------------------------------------------------------------------------ +| Description : AN LL_XID_IND has delivered a desired set of nsapis for +| a V42.bis or VJ compressor entity. Now this is compared to a possibly +| already existing set of nsapis connected to the given entity. +| Also the rules in GSM 4.65, 6.8.x are checked. +| +| Parameters : a flag telling if we work on V42 or VanJacobson 'nsapis': +| MG_XID_V42_NSAPIS or MG_XID_VJ_NSAPIS. +| affected sapi, +| ++------------------------------------------------------------------------------ +*/ +LOCAL void mg_set_xid_nsapis (UBYTE sapi, UBYTE p_type) +{ + USHORT* cur_nsapis = 0; + USHORT* ind_nsapis = 0; + USHORT* res_nsapis = 0; + BOOL* ind_nsapis_set = NULL; + UBYTE sapi_index = 0; + UBYTE* p_bit = NULL; + UBYTE ntt_state = MG_UNASSIGNED; + U8 nsapi = 0; + U8 s0_m_1_min = 0; + + + TRACE_FUNCTION( "mg_set_xid_nsapis" ); + + sndcp_get_sapi_index(sapi, &sapi_index); + + /* + * V42.bis or VanJacobson? + */ + if (p_type == MG_XID_V42_NSAPIS) { + cur_nsapis = &(sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis); + ind_nsapis = &(sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis); + res_nsapis = &(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis); + ind_nsapis_set = + &(sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis_set); + p_bit = &(sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit); + + *res_nsapis = 0; + /* + * Only those nsapis will be set in the response for which the user + * requested compression. + * Note: te other params are not yet set, must be implemented later. + */ + sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis_set = FALSE; + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((((1 << nsapi) & sndcp_data->mg.user_xid_block[nsapi].v42.nsapis) > + 0) && + (((1 << nsapi) & + sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0)) { + + *res_nsapis |= (1 << nsapi); + sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis_set = TRUE; + + } + } /* for nsapi */ + + } else { + cur_nsapis = &(sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis); + ind_nsapis = &(sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis); + res_nsapis = &(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis); + ind_nsapis_set = + &(sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis_set); + p_bit = &(sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit); + + *res_nsapis = 0; + /* + * Only those nsapis will be set in the response for which the user + * requested compression. + * In the same loop we set the s0_m_1 to the minimum of + * the indicated value and the values requested by the user. + * Also the direction is set to the minimum of all requested + * directions. + */ + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.s0_m_1 > 0) { + s0_m_1_min = sndcp_data->mg.ind_xid_block[sapi_index].vj.s0_m_1; + } else if (sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 > 0) { + s0_m_1_min = sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1; + } else { + s0_m_1_min = SNDCP_VJ_DEFAULT_S0_M_1; + } + #ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.res_xid_block[sapi_index].vj.direction = + NAS_HCOMP_BOTH_DIRECT; +#else + sndcp_data->mg.res_xid_block[sapi_index].vj.direction = + SNSM_COMP_BOTH_DIRECT; +#endif + + sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis_set = FALSE; + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & sndcp_data->mg.user_xid_block[nsapi].vj.nsapis) > + 0 && + (((1 << nsapi) & + sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis) > 0)) { + + *res_nsapis |= (1 << nsapi); + sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis_set = TRUE; + if (sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1 < s0_m_1_min) { + s0_m_1_min = sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1; + } + sndcp_data->mg.res_xid_block[sapi_index].vj.direction &= + sndcp_data->mg.user_xid_block[nsapi].vj.direction; + } + } /* for nsapi */ + sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1 = s0_m_1_min; + if (s0_m_1_min > 0) { + sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1_set = TRUE; + } else { + sndcp_data->mg.res_xid_block[sapi_index].vj.direction = 0; + } + } + + + + /* + * Rules in GSM 4.65, 6.8.1: acknowledged and unacknowlegded contexts may not + * share the same compressor. If that is demanded by the indication, reset + * nsapis parameter to the ones currently used. + */ + if (*ind_nsapis_set && + *ind_nsapis > 0) { + BOOL vio = FALSE; + mg_detect_mode_clash(*ind_nsapis, &vio); + if (!vio) { + /* + * Modes are the same, set cur to res. + */ + *cur_nsapis = *res_nsapis; + } else { + *res_nsapis = *cur_nsapis; + } + } + + /* + * Also from 6.8.3: If an unassigned entity number is included with the + * p bit set to 0, then the Applicable NSAPIs field shall be set to 0. + */ + if (p_type == MG_XID_V42_NSAPIS) { + mg_get_sapi_dntt_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, &ntt_state); + } else { + mg_get_sapi_pntt_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, &ntt_state); + } + if (ntt_state == MG_UNASSIGNED && *p_bit == 0) { + *cur_nsapis = 0; + *res_nsapis = 0; + } + +} /* mg_set_xid_nsapis() */ + + +/*==== PUBLIC FUNCTIONS =====================================================*/ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_check_cnf_xid ++------------------------------------------------------------------------------ +| Description : The confirmation of a requested XID negotiation has been +| received. The answer is now checked. +| A main issue is the comparison with the service variable +| req_xid_block which holds the requested xid block sent to the +| network. +| Detected errors: +| - SNDCP version number not correct +| - incorrect entity number (must be proposed one) +| - incorrect sense of negotiation for each parameter (down mainly, +| NSAPI down bitwise) +| - an entity is included in the cnf that was not requested, does not exist +| Not checked: +| - out of range value of parameters (must be in range if sense ofnegotiation was right. +| - parameters with duplicated instances. +| If one of these errors occurs ret is set to MG_XID_BAD_CONTENT, else +| MG_XID_OK. +| +| Parameters : ret, affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_check_cnf_xid (UBYTE* ret, UBYTE sapi) +{ + UBYTE sapi_index = 0; + BOOL wrong = FALSE; + TRACE_FUNCTION( "mg_check_cnf_xid" ); + sndcp_get_sapi_index(sapi, &sapi_index); + *ret = MG_XID_BAD_CONTENT; + /* + * Check SNDCP version. + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].version_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].version != + SNDCP_XID_VERSION) { + return; + } + } + /* + * If an entity is included that has not been requested / does not exist: + * bad content! + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.is_set && + ! sndcp_data->mg.req_xid_block[sapi_index].v42.is_set && + ! sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set) { + + return; + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.is_set && + ! sndcp_data->mg.req_xid_block[sapi_index].vj.is_set && + ! sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) { + + return; + } + + /* + * Check V42 parameters, if they are set. + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.is_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p_bit == 1) { + return; + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.ntt != + sndcp_data->mg.req_xid_block[sapi_index].v42.ntt) { + return; + } + /* + * Sense of negotiation. If cnf value has been set, but req has not been + * set then cnf value will be compared with cur value. This + * is not applied to "applicable nsapis". + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.nsapis_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set) { + mg_ushort_sense_bitwise + (sndcp_data->mg.cnf_xid_block[sapi_index].v42.nsapis, + sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis, + &wrong); + } + if (wrong) { + return; + } + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set) { + mg_ubyte_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0, + sndcp_data->mg.req_xid_block[sapi_index].v42.p0, + &wrong); + } else { + mg_ubyte_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].v42.p0, + sndcp_data->mg.cur_xid_block[sapi_index].v42.p0, + &wrong); + } + if (wrong) { + return; + } + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1 > + sndcp_data->mg.req_xid_block[sapi_index].v42.p1) { + return; + } + } else { + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p1 > + sndcp_data->mg.cur_xid_block[sapi_index].v42.p1) { + return; + } + } + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2 > + sndcp_data->mg.req_xid_block[sapi_index].v42.p2) { + return; + } + } else { + if (sndcp_data->mg.cnf_xid_block[sapi_index].v42.p2 > + sndcp_data->mg.cur_xid_block[sapi_index].v42.p2) { + return; + } + } + } + } + /* + * Check VJ parameters, if they are set. + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.is_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.p_bit == 1) { + return; + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.ntt != + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt) { + return; + } + /* + * Sense of negotiation. + */ + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.nsapis_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis_set) { + mg_ushort_sense_bitwise(sndcp_data->mg.cnf_xid_block[sapi_index].vj.nsapis, + sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis, + &wrong); + } + if (wrong) { + return; + } + } + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1_set) { + if (sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1_set) { + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1 > + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1) { + return; + } + } else { + if (sndcp_data->mg.cnf_xid_block[sapi_index].vj.s0_m_1 > + sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1) { + return; + } + } + } + } + *ret = MG_XID_OK; + +} /* mg_check_cnf_xid() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_check_ind_xid ++------------------------------------------------------------------------------ +| Description : Service variable ind_xid_block holds the xid block indicated +| by the peer. The ind_xid_block is now checked: (from 4.65 6.8.2). +| Criterium 1: +| If the indicated ntt is already used and pcomp or dcomp values are different, +| ret is set to MG_XID_BAD_CONTENT. +| Criterium 2: +| If the indicated algorithm type is already used and pcomp or dcomp values +| are different, ret is set to MG_XID_BAD_CONTENT. +| +| Note: implementation dependent: if data compression is proposed, it will +| be rejected. +| +| Otherwise ret is set to MG_XID_OK. +| Parameters : ret, affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_check_ind_xid (UBYTE* ret, UBYTE sapi) +{ + UBYTE sapi_index = 0; + UBYTE status = MG_UNASSIGNED; + TRACE_FUNCTION( "mg_check_ind_xid" ); + sndcp_get_sapi_index(sapi, &sapi_index); + *ret = MG_XID_OK; + + /* + * Check criterium 1. + */ + if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set && + sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) { + mg_get_sapi_dntt_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, &status); + if (status == MG_ASSIGNED) { + /* + * Entity already used. DCOMP values differ? + */ + mg_get_sapi_dcomp_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp, &status); + if (status != MG_ASSIGNED) { + /* + * The indicated dcomp is not assigned. Error. + */ + mg_set_sapi_dntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } else { + UBYTE dntt = 0; + mg_get_sapi_dcomp_dntt + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp, &dntt); + if (dntt != sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt) { + /* + * Dcomp values differ, Error. + */ + mg_set_sapi_dntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + } + } + } + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set && + sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit == SNDCP_P_BIT_1) { + mg_get_sapi_pntt_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, &status); + if (status == MG_ASSIGNED) { + /* + * Entity already used. PCOMP values differ? + */ + /* + * PCOMP 1. + */ + mg_get_sapi_pcomp_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &status); + if (status != MG_ASSIGNED) { + /* + * The indicated pcomp is not assigned. Error. + */ + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } else { + UBYTE pntt = 0; + mg_get_sapi_pcomp_pntt + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &pntt); + if (pntt != sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt) { + /* + * Pcomp values differ, Error. + */ + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + } + /* + * PCOMP 2. + */ + mg_get_sapi_pcomp_state + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &status); + if (status != MG_ASSIGNED) { + /* + * The indicated pcomp is not assigned. Error. + */ + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } else { + UBYTE pntt = 0; + mg_get_sapi_pcomp_pntt + (sapi, sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1, &pntt); + if (pntt != sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt) { + /* + * Dcomp values differ, Error. + */ + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + } + } + } + + /* + * Check criterium 2. + * Since in the current implementation there is only SNDCP_XID_VJ and + * SNDCP_XID_V42, and only 1 instance of each, + * it will be sufficient to compare the proposed values for pcomp/dcomp + * with the ones in cur_xid_block. + * An error may only occur if cur and ind are set. + */ + if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set && + sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set && + sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) { + if (sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp != + sndcp_data->mg.cur_xid_block[sapi_index].v42.dcomp) { + mg_set_sapi_dntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + } + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set && + sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set && + sndcp_data->mg.ind_xid_block[sapi_index].v42.p_bit == SNDCP_P_BIT_1) { + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1 != + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1) { + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp2 != + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2) { + mg_set_sapi_pntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + *ret = MG_XID_BAD_CONTENT; + } + } + +#ifndef TI_PS_FF_V42BIS + /* + * Implementation dependent: If data compression is proposed, reject it! + */ + if (sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set) { + mg_set_sapi_dntt_rej(sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + TRUE); + } +#endif /* !TI_PS_FF_V42BIS */ +} /* mg_check_ind_xid() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_clean_xid ++------------------------------------------------------------------------------ +| Description : Cleans up the XID organizing arrays for nsapis and ntts +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_clean_xid (UBYTE sapi) { + UBYTE nsapi = 0; + UBYTE sapi_index = 0; + UBYTE stat = MG_UNASSIGNED; + TRACE_FUNCTION( "mg_clean_xid" ); + sndcp_get_sapi_index(sapi, &sapi_index); + + + /* + * NSAPIs that were assigned to a compressor unit but are not any more. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + BOOL connected = + ((1 << nsapi) & (sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis)) > 0; + mg_set_sapi_dntt_nsapi(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt, + nsapi, + connected); + connected = + ((1 << nsapi) & (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis)) > 0; + mg_set_sapi_pntt_nsapi(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt, + nsapi, + connected); + + + } + + /* + * Formerly assigned ntts that are now unassigned are cleaned. + * Implemented here: the one dntt and the one pntt in cur_xid_block are now + * checked. If they are in state MG_ASSIGNED but the affected 'nsapis' + * element is set to all '0' then the entities enter state MG_UNASSIGNED, + * all nsapis re set to FALSE in the sapi_?ntt_nsapi_ra, all + * affected pcomp/dcomp values are set to MG_UNASSIGNED. + */ + mg_get_sapi_dntt_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt, + &stat); + if (stat == MG_ASSIGNED && + sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis == 0) { + /* + * Reset dntt state. + */ + mg_set_sapi_dntt_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt, + MG_UNASSIGNED); + + /* + * reset nsapi connections. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + mg_set_sapi_dntt_nsapi(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].v42.ntt, + nsapi, + FALSE); + } + /* + * Reset dcomp. + */ + mg_set_sapi_dcomp_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].v42.dcomp, + MG_UNASSIGNED); + } + + + /* + * The same for header compresion. + */ + mg_get_sapi_pntt_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt, + &stat); + if (stat == MG_ASSIGNED && + sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis == 0) { + /* + * Reset pntt state. + */ + mg_set_sapi_pntt_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt, + MG_UNASSIGNED); + /* + * reset nsapi connections. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + mg_set_sapi_pntt_nsapi(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt, + nsapi, + FALSE); + } + /* + * Reset pcomps. + */ + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1, + MG_UNASSIGNED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2, + MG_UNASSIGNED); + } + + + +} /* mg_clean_xid() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_col_no_re ++------------------------------------------------------------------------------ +| Description : The function mg_col_no_re represents the SDL label +| COL_NO_RE: an LL_ESTABLISH_IND has been received, we do +| have a collision situation like given in [GSM 4.65, 6.2.1.4], +| we do not have a re-establishment situation. +| +| Parameters : the received LL_ESTABLISH_IND +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_col_no_re (T_LL_ESTABLISH_IND* ll_establish_ind) +{ + TRACE_FUNCTION( "mg_col_no_re" ); + + /* + * Resume data transfer suspended due to pending establishment; + */ + sig_mg_su_resume(ll_establish_ind->sapi); + sig_mg_sua_resume(ll_establish_ind->sapi); + mg_resume_affected_nus(ll_establish_ind->sapi); + + /* + * Now proceed like without collision. + */ + mg_no_col_no_re(ll_establish_ind); + + +} /* mg_col_no_re() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_col_re ++------------------------------------------------------------------------------ +| Description : The function mg_col_re represents the SDL label +| COL_RE: an LL_ESTABLISH_IND has been received, we do +| have a collision situation like given in [GSM 4.65, 6.2.1.4], +| we do have a re-establishment situation. +| +| Parameters : the received LL_ESTABLISH_IND +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_col_re (T_LL_ESTABLISH_IND* ll_establish_ind) +{ + TRACE_FUNCTION( "mg_col_re" ); + /* + * Resume data transfer suspended due to pending establishment; + */ + sig_mg_su_resume(ll_establish_ind->sapi); + sig_mg_sua_resume(ll_establish_ind->sapi); + mg_resume_affected_nus(ll_establish_ind->sapi); + /* + * Now proceed like without collision. + */ + mg_no_col_re(ll_establish_ind); +} /* mg_col_re() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_decode_xid ++------------------------------------------------------------------------------ +| Description : Implementation dependent. +| The entity number +| Works only for algorithm types 0 +| (V42 for data and VanJacobson for header). +| This procedure reads the given xid block (in form of an sdu) +| and writes the fields to the given xid_block variable, if +| compression fields for algorithms 0 (V42 or VanJacobson) are +| given. +| If the parsed sdu starts a negotiation then the p bit will be +| set to 1 and the "algorithm type" field will be included. If +| the parsed sdu ends a negotiation then the p bit will be set +| to 0 and the "algorithm type" field will not be included. +| In this case it will be checked if the "entity number" field +| corresponds with the entity number set in req_xid_block. +| +| Note: This procedure only re-formats the xid_block. The content +| of the xid_block are not checked. This will be done in a later +| procedure on the basis of the xid_block filled in here. +| The only error possibly detected is returned, if the byte format +| of the given xid block sdu is not correct: MG_XID_BAD_FORMAT. +| Then parameter type 1 list is read. If a data comp field has +| an algorithm of type 0 (V42bis) then its values are written +| to the given xid_block. If the algorithm is not 0 (V42bis) then +| the entity is rejected. +| The same for parameter type 2, here only algorithm type 0 +| (VanJacobson) is written to the xid_block. +| Note: it is assumed here that the parameters come in line 0, 1, 2. +| If that will no be the case, the parsing will have to modified +| slightly. +| If an unknown parameter type (not 0, 1, 2) is detected, an +| MG_XID_BAD_FORMAT is returned. +| +| Parameters : the sdu to be parsed, is negotiation started here?, the +| destination T_XID_BLOCK, a return value that should be MG_XID_OK +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_decode_xid (T_sdu* sdu, + T_XID_BLOCK* xid_block, + UBYTE* ret, + UBYTE sapi) +{ + +#define CHECK_XID_BUFFER_LEN if (index + field_index >= ((sdu->l_buf) >> 3)) return + UBYTE sapi_index = 0; + /* + * Index for the whole sdu. + */ + USHORT index = sdu->o_buf / 8; + /* + * Sub index used in compression fields. + */ + USHORT field_index = 0; + /* + * This is the index where the parameter 2 for header compression begins. + */ + USHORT beginning_of_header_comp = 0; + /* + * Length of complete parameter blocks of type 1 or 2. + */ + USHORT length = 0; + /* + * Was decoding successful? + */ + BOOL ok = FALSE; + + TRACE_FUNCTION( "mg_decode_xid" ); + + /* + * Reset xid_block. + */ + sndcp_reset_xid_block(xid_block); + + sndcp_get_sapi_index(sapi, &sapi_index); + *ret = MG_XID_BAD_FORMAT; + + /* + * If end is reached, return with ok. + */ + if (sdu->l_buf == 0) { + *ret = MG_XID_OK; + return; + } + /* + * If parameter type 0 is included, store it. + */ + CHECK_XID_BUFFER_LEN; + if (sdu->buf[index] == SNDCP_XID_PARAM_TYPE_0) { + index++; + xid_block->version_set = TRUE; + /* + * Length should be SNDCP_XID_0_LEN, but is not checked. + */ + CHECK_XID_BUFFER_LEN; + length = sdu->buf[index]; + + index++; + /* + * Set the version in xid_block. + */ + CHECK_XID_BUFFER_LEN; + xid_block->version = sdu->buf[index]; + index+= length; + } + + /* + * If end is reached, return with ok. + */ + if (index == ((sdu->l_buf) >> 3)) { + *ret = MG_XID_OK; + return; + } + + /* + * If parameter type 1 is included, store it. + */ + if (sdu->buf[index] == SNDCP_XID_PARAM_TYPE_1) { + /* + * Length of all data compression parameters. + */ + index++; + CHECK_XID_BUFFER_LEN; + length = sdu->buf[index]; + /* + * This is the index where the parameter 2 infos for header compression + * begin. + */ + beginning_of_header_comp = index + length + 1; + + /* + * Search data compression parameters for algorithm type 1. + */ + while (length > 0) { + /* + * Index is now on p-bit-entity-octet for one field. + * If the p bit is set to 1 then we read the algorithm + * type and drop the field if it is not SNDCP_XID_V42. + * If the p bit is not set to 1 then we read the + * entity number and drop the field if it is not the entity number + * proposed in req_xid_block. + */ + + /* + * Set field_index to beginning of next data compression field. + */ + field_index++; + + CHECK_XID_BUFFER_LEN; + if ((sdu->buf[index + field_index] & 0x80) > 0) { + /* + * P bit set to 1. Check algorithm type and drop field if + * type is not known. + * Set ntt. + */ + xid_block->v42.ntt = sdu->buf[index + field_index] & 0x1F; + /* + * Set field_index to algorithm type. + */ + field_index ++; + CHECK_XID_BUFFER_LEN; + if ((sdu->buf[index + field_index] & 0xf) != SNDCP_XID_V42) { + /* + * Wrong algorithm type. Add the ntt to list of rejected ones. + */ + mg_set_sapi_dntt_rej(sapi, xid_block->v42.ntt, TRUE); + /* + * Set index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed but entity number has not been found because in + * that case the loop would have been left with break; + */ + xid_block->v42.is_set = FALSE; + break; + } + continue; + } else { + /* + * Correct algorithm type. + */ + if (xid_block->v42.is_set == FALSE) { + /* + * This is the first occurrence. + */ + xid_block->v42.is_set = TRUE; + xid_block->v42.p_bit = 1; + + + mg_decode_v42(sdu, + &index, + &field_index, + xid_block, + &ok, + SNDCP_P_BIT_1); + if (!ok) { + /* + * Decoding was not successful. + */ + return; + } + } else { + /* + * There has been an occurrence of this algorithm. + */ + /* + * Set index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed. + */ + break; + } + + } + /* + * If all data parameters are read, go ahead for header ones. + */ + if (field_index == length) { + break; + } + } + } else { + /* + * P bit set to 0. + * Check entity number and drop field if it is not the proposed one or + * V42 has not been proposed yet. + * field_index is already on p-bit-entity-octet. + */ + CHECK_XID_BUFFER_LEN; + if (((sdu->buf[index + field_index] & 0x1f) != + xid_block->v42.ntt) && xid_block->v42.is_set) { + /* + * Wrong entity number. + */ + /* + * Set field_index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed but entity number has not been found because in + * that case the loop would have been left with break; + */ + xid_block->v42.is_set = FALSE; + break; + } + continue; + } else { + /* + * The entity number of this field equals the entity number in + * ththat is already in the xid block or there is no entity in + * the xid block yet. + */ + xid_block->v42.is_set = TRUE; + xid_block->v42.p_bit = 0; + xid_block->v42.ntt = + (sdu->buf[index + field_index] & 0x1f); + + mg_decode_v42(sdu, + &index, + &field_index, + xid_block, + &ok, + SNDCP_P_BIT_0); + if (!ok) { + /* + * Decoding was not successful. + */ + return; + } + + /* + * If all data parameters are read, go ahead for header ones. + */ + if (field_index == length) { + break; + } + } + } /* p bit set to 0 */ + } /* while */ + field_index = 0; + index = beginning_of_header_comp; + } + + /* + * Now comes the header compression parameter type 2. + * Is it omitted? + */ + if (index == ((sdu->l_buf) >> 3)) { + *ret = MG_XID_OK; + return; + } + + /* + * Parameter type should be SNDCP_XID_PARAM_TYPE_2. + */ + CHECK_XID_BUFFER_LEN; + if (sdu->buf[index] != SNDCP_XID_PARAM_TYPE_2) { + return; + } + /* + * Length of all header compression parameters. + */ + index++; + CHECK_XID_BUFFER_LEN; + length = sdu->buf[index]; + + + /* + * Search header compression parameters for algorithm type 2. + */ + while (length > 0) { + /* + * Index is now on p-bit-entity-octet for one field. + * If the p bit is set to 1 then we read the algorithm + * type and drop the field if it is not SNDCP_XID_VJ. + * If the p bit is not set to 1 then we read the + * entity number and drop the field if it is not the entity number + * proposed in req_xid_block. + */ + /* + * Set field_index to beginning of next header compression field. + */ + field_index++; + CHECK_XID_BUFFER_LEN; + if ((sdu->buf[index + field_index] & 0x80) > 0) { + UBYTE ntt = 0; + /* + * P bit set to 1. Check algorithm type and drop field if + * type is not known. + * Set ntt. + */ + ntt = sdu->buf[index + field_index] & 0x1F; + + /* + * Set index to algorithm type. + */ + field_index ++; + CHECK_XID_BUFFER_LEN; + if (((sdu->buf[index + field_index] & 0xf) != SNDCP_XID_VJ) + || + ((sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) && + (xid_block->vj.is_set == FALSE) && + (ntt != sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt) + ) + ) { + /* + * Wrong algorithm type or + * vj comp is currently used and proposed ntt is not equal to currently + * used one. + * Add ntt to list of rejected ones. + */ + mg_set_sapi_pntt_rej(sapi, ntt, TRUE); + /* + * Set index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed but entity number has not been found because in + * that case the loop would have been left with break; + */ + xid_block->vj.is_set = FALSE; + break; + } + continue; + } + /* + * Correct algorithm type and vj requested. + */ + /* + * If no vj comp is currently used and xid_block.vj is not set yet, take + * the proposed one. + * Also if vj comp is currently used and xid block is not yet set and + * proposed ntt is equal to currently used one. + */ + if (((! sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) && + (xid_block->vj.is_set == FALSE)) + || + ((sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) && + (xid_block->vj.is_set == FALSE) && + (ntt == sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt))) { + + xid_block->vj.is_set = TRUE; + xid_block->vj.p_bit = 1; + xid_block->vj.ntt = ntt; + + mg_decode_vj (sdu, + &index, + &field_index, + xid_block, + &ok, + SNDCP_P_BIT_1); + if (!ok) { + /* + * Decoding was not successful. + */ + return; + } + /* + * If all header parameters are read, go ahead for header ones. + */ + if (field_index == length) { + break; + } + continue; + } + /* + * This is not the first occurrence. Ignore. + */ + /* + * Set index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed. + */ + break; + } + + } else { + /* + * P bit set to 0. + * Check entity number and drop field if it is not the proposed one or + * VJ has not been proposed yet. + * Index is already on p-bit-entity-octet. + */ + CHECK_XID_BUFFER_LEN; + if (((sdu->buf[index + field_index] & 0x1f) != + xid_block->vj.ntt) && xid_block->vj.is_set) { + /* + * Wrong entity number. + * Set index to length octet. + */ + field_index ++; + /* + * Set index to next field. Check field length. + */ + CHECK_XID_BUFFER_LEN; + field_index += sdu->buf[index + field_index]; + if (field_index > length) { + /* + * Field is too long, bad format. + */ + return; + } + if (field_index == length) { + /* + * Field is completed but entity number has not been found because in + * that case the loop would have been left with break; + */ + break; + } + continue; + } else { + /* + * The entity number of this field equals the entity number in + * that is already in the xid_block or there is no entity number + * in the block yet. + */ + xid_block->vj.is_set = TRUE; + xid_block->vj.p_bit = 0; + xid_block->vj.ntt = + (sdu->buf[index + field_index] & 0x1f); + + mg_decode_vj (sdu, + &index, + &field_index, + xid_block, + &ok, + SNDCP_P_BIT_0); + if (!ok) { + /* + * Decoding was not successful. + */ + return; + } + /* + * The one field with same entity number as in req_xid_block has been + * found and loop of data compression field may be left. + * If errors in not used fields are to be detected then we must continue here! + */ + /* + * If all header parameters are read, leave. + */ + if (field_index == length) { + break; + } + } + } + } /* while */ + /* + * It is not checked here whether the sdu is completely read. + */ + *ret = MG_XID_OK; + +} /* mg_decode_xid() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_dti_close ++------------------------------------------------------------------------------ +| Description : Closes DTI connection +| Parameters : nsapi ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_dti_close (UBYTE nsapi) +{ + +#ifdef _SNDCP_DTI_2_ + UBYTE interfac = SNDCP_INTERFACE_UNACK; +#ifndef SNDCP_UPM_INCLUDED + sndcp_get_nsapi_interface(nsapi, &interfac); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + dti_close(sndcp_data->hDTI, /* DTI_HANDLE *hDTI, */ + 0, /* U8 instance, */ + interfac, /* U8 interface, */ + nsapi, + NULL/* U8 channel); */ + ); +#else /*_SNDCP_DTI_2_*/ + UBYTE interfac = SNDCP_INTERFACE_UNACK; + + sndcp_get_nsapi_interface(nsapi, &interfac); + dti_close(sndcp_data->hDTI, /* DTI_HANDLE *hDTI, */ + 0, /* U8 instance, */ + interfac, /* U8 interface, */ + nsapi /* U8 channel); */ + + ); +#endif /*_SNDCP_DTI_2_*/ + + /* + * The following is done in any case since the callback will not be called. + */ + nu_connection_state(nsapi, FALSE); + + /*FIXME ! Added newly. To be verified.*/ +#ifdef SNDCP_UPM_INCLUDED + { + U32 linkid = 0; + PALLOC (sn_dti_cnf, SN_DTI_CNF); + sndcp_get_nsapi_linkid(nsapi, &linkid); + sn_dti_cnf->dti_linkid = linkid; + sn_dti_cnf->dti_conn = NAS_DISCONNECT_DTI; + PSEND(hCommMMI, sn_dti_cnf); + } +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +} /* mg_dti_close() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_dti_open ++------------------------------------------------------------------------------ +| Description : Opens DTI connection +| Parameters : nsapi ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_dti_open (UBYTE nsapi) +{ +#ifdef _SNDCP_DTI_2_ + UBYTE* neighbor = NULL; + ULONG linkid = 0; +#ifndef SNDCP_UPM_INCLUDED + BOOL ack = FALSE; +#endif + U8 direction = DTI_CHANNEL_TO_LOWER_LAYER; + UBYTE interfac = SNDCP_INTERFACE_UNACK; + + sndcp_get_nsapi_linkid(nsapi, &linkid); + sndcp_get_nsapi_neighbor(nsapi, &neighbor); +#ifndef SNDCP_UPM_INCLUDED + sndcp_get_nsapi_ack(nsapi, &ack); +#endif + sndcp_get_nsapi_direction(nsapi, &direction); +#ifndef SNDCP_UPM_INCLUDED + if (ack) { + interfac = SNDCP_INTERFACE_ACK; + sndcp_set_nsapi_interface(nsapi, interfac); + } +#endif + + dti_open(sndcp_data->hDTI, /* DTI_HANDLE hDTI */ + 0, /* U8 instance */ + interfac, /* U8 interface */ + nsapi, /* U8 channel */ + 0, /* U8 queue_size */ + direction, /* U8 direction */ + DTI_QUEUE_WATERMARK, /* U8 link options */ + DTI_VERSION_10, /* U32 version */ + neighbor, /* U8 *neighbor_entity */ + linkid/* U32 link_id */ + ); +#else /*_SNDCP_DTI_2_*/ + UBYTE* neighbor = NULL; + ULONG linkid = 0; + BOOL ack = FALSE; + BOOL direction = HOME; + UBYTE interfac = SNDCP_INTERFACE_UNACK; + + sndcp_get_nsapi_linkid(nsapi, &linkid); + sndcp_get_nsapi_neighbor(nsapi, &neighbor); + sndcp_get_nsapi_ack(nsapi, &ack); + sndcp_get_nsapi_direction(nsapi, &direction); +#ifndef SNDCP_UPM_INCLUDED + if (ack) { + interfac = SNDCP_INTERFACE_ACK; + sndcp_set_nsapi_interface(nsapi, interfac); + } +#endif + + dti_open(sndcp_data->hDTI, /* DTI_HANDLE *hDTI */ + 0, /* U8 instance */ + interfac, /* U8 interface */ + nsapi, /* U8 channel */ + 0, /* U8 queue_size */ + direction, /* BOOL direction */ + FLOW_CNTRL_ENABLED, /* U8 comm_type */ + DTI_VERSION_10, /* U32 version */ + neighbor, /* U8 *neighbor_entity */ + linkid/* U32 link_id */ + ); + +#endif /*_SNDCP_DTI_2_*/ +} /* mg_dti_open() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_init ++------------------------------------------------------------------------------ +| Description : The function mg_init() .... +| +| Parameters : +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_init (void) +{ + + UBYTE sapi_index = 0; + UBYTE nsapi = 0; + TRACE_FUNCTION( "mg_init" ); + INIT_STATE(MG, MG_DEFAULT); + /* + * req_xid_block, cnf_xid_block, cur_xid_block not initialized. + */ + for (sapi_index = 0; sapi_index < SNDCP_NUMBER_OF_SAPIS; sapi_index++) { + + mg_reset_states_n_rej(sapi_index); + /* + * Init renegotiation counter and cur_xid_block with default values. + */ + sndcp_data->mg.renego[sapi_index] = 0; + + sndcp_reset_xid_block(&sndcp_data->mg.req_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.cnf_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.ind_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.res_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.new_xid_block[sapi_index]); + + } + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + sndcp_reset_xid_block(&sndcp_data->mg.user_xid_block[nsapi]); + sndcp_data->mg.user_xid_block[nsapi].vj.s0_m_1 = 0; + sndcp_data->cur_pcomp[nsapi] = 0; + sndcp_data->cur_dcomp[nsapi] = 0; + sndcp_data->cur_seg_pos[nsapi] = 0; + sndcp_data->cur_pdu_ref[nsapi].ref_nsapi = 0; + sndcp_data->cur_pdu_ref[nsapi].ref_npdu_num = 0; + sndcp_data->cur_pdu_ref[nsapi].ref_seg_num = 0; + sndcp_data->big_head[nsapi] = FALSE; + } + + + sndcp_data->mg.mod_expects = MG_MOD_X_NONE; + sndcp_data->mg.waiting_nsapis = 0; + sndcp_data->mg.suspended_nsapis = 0; + +} /* mg_init() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_is_ack ++------------------------------------------------------------------------------ +| Description : This procedure takes the snsm_qos!rely +| information: +| +| 0 SNSM_RELCLASS_SUB Subscribed reliability class +| 1 SNSM_GTP_LLC_RLC_PROT Acknowledged GTP, LLC, and RLC; Protected data +| 2 SNSM_LLC_RLC_PROT Unacknowledged GTP; Acknowledged LLC and RLC, Protected data +| 3 SNSM_RLC_PROT Unacknowledged GTP and LLC; Acknowledged RLC, Protected data +| 4 SNSM_PROT Unacknowledged GTP, LLC, and RLC, Protected data +| 5 SNSM_NO_REL Unacknowledged GTP, LLC, and RLC, Unprotected data +| +| and sets "spec" to TRUE, "b" to TRUE in case of SNSM_GTP_LLC_RLC_PROT or +| SNSM_LLC_RLC_PROT, +| [should be, is not:["spec" to FALSE in case of SNSM_RELCLASS_SUB]] and "spec" +| to TRUE, "b" to FALSE else. +| +| Important note: in case of SNSM_RELCLASS_SUB "spec" will actually be set to +| to TRUE, "b" to FALSE, to be robust in case of downlink protocol error! +| +| Parameters : snsm_qos +| BOOL* spec (FALSE for REL_CLASS_SUB), +| BOOL* b) +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_is_ack (T_snsm_qos snsm_qos, + BOOL* spec, + BOOL* b) +{ + TRACE_FUNCTION( "mg_is_ack" ); + + +#ifdef SNDCP_UPM_INCLUDED + if (snsm_qos.relclass == PS_GTP_LLC_RLC_PROT || + snsm_qos.relclass == PS_LLC_RLC_PROT) { +#else + if (snsm_qos.relclass == SNSM_GTP_LLC_RLC_PROT || + snsm_qos.relclass == SNSM_LLC_RLC_PROT) { +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + *spec = TRUE; + *b = TRUE; + /* } else if (snsm_qos.relclass == SNSM_RELCLASS_SUB) { + *spec = FALSE; + */ + } else { + *spec = TRUE; + *b = FALSE; + } + + +} /* mg_is_ack() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_no_col_no_re ++------------------------------------------------------------------------------ +| Description : The function mg_no_col_no_re represents the SDL label +| NO_COL_NO_RE: an LL_ESTABLISH_IND has been received, we do not +| have a collision situation like given in [GSM 4.65, 6.2.1.4], +| we do not have a re-establishment situation. +| +| Parameters : the received LL_ESTABLISH_IND +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_no_col_no_re (T_LL_ESTABLISH_IND* ll_establish_ind) +{ + UBYTE dec_ret = 0; + UBYTE check_ret = 0; + UBYTE sapi_index = 0; + U8 nsapi = 0; + TRACE_FUNCTION( "mg_no_col_no_re" ); + sndcp_get_sapi_index(ll_establish_ind->sapi, &sapi_index); + + TRACE_EVENT_P3("l3_valid?: %d, N201_I: %d, N201_U: %d", + ll_establish_ind->xid_valid, ll_establish_ind->n201_i, + ll_establish_ind->n201_u); + /* + * Set N201 values in uplink services. + */ + sig_mg_su_n201(ll_establish_ind->sapi, ll_establish_ind->n201_u); + sig_mg_sua_n201(ll_establish_ind->sapi, ll_establish_ind->n201_i); + /* + * If SNDCP XID block is not valid, we are ready. + */ + if (ll_establish_ind->xid_valid == LL_XID_INVALID) { + + PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, 0); + /* + * Set sapi in ll_establish_res. + */ + ll_establish_res->sapi = ll_establish_ind->sapi; + ll_establish_res->xid_valid = ll_establish_ind->xid_valid; + ll_establish_res->sdu.l_buf = 0; + + /* + * Mark the affected sapi as MG_XID_IDLE. + */ + sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST); + + sig_mg_sda_end_est(ll_establish_res->sapi, TRUE); + + sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE); + + PSEND(hCommLLC, ll_establish_res); + + /* + * All nsapis at this sapi that use ack mode, enter recovery state. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) { + UBYTE sapi = 0; + BOOL ack = FALSE; + + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack && (sapi == ll_establish_ind->sapi)) { + sig_mg_cia_delete_npdus(nsapi); + sig_mg_sua_delete_pdus(nsapi, sapi, FALSE); + sig_mg_nu_recover(nsapi); + sig_mg_nd_recover(nsapi); + } + } /* for all nsapis */ + + return; + } + /* + * SNDCP XID block is valid and checked now. + */ + mg_decode_xid(&(ll_establish_ind->sdu), + &(sndcp_data->mg.ind_xid_block[sapi_index]), + &dec_ret, + ll_establish_ind->sapi); + if (dec_ret == MG_XID_OK) { + mg_check_ind_xid(&check_ret, ll_establish_ind->sapi); + if (check_ret == MG_XID_OK) { + /* + * Label MG_IND_OK_EST + */ + USHORT res_sdu_bit_len = 0; + UBYTE ntt = 0; + BOOL v42_rej = FALSE; + BOOL vj_rej = FALSE; + + mg_set_res_cur_xid_block(ll_establish_ind->sapi, &res_sdu_bit_len); + /* + * Add the extra space for ntts with nsapis == 0. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_dntt_rej(ll_establish_ind->sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + v42_rej = TRUE; + } + mg_get_sapi_pntt_rej(ll_establish_ind->sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + vj_rej = TRUE; + } + } + if (! sndcp_data->mg.res_xid_block[sapi_index].v42.is_set && + v42_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + if (! sndcp_data->mg.res_xid_block[sapi_index].vj.is_set && + vj_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + + /* + * SDL Label MG_CNF_OK_ACK + */ + + { + + USHORT sapi_state = MG_IDLE; + + PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, res_sdu_bit_len); + /* + * Set sapi in ll_establish_res. + */ + ll_establish_res->sapi = ll_establish_ind->sapi; + ll_establish_res->xid_valid = ll_establish_ind->xid_valid; + /* + * Write res_xid_block struct to sdu byte buffer. Implementation dep.. + */ + mg_set_res_xid_params(&ll_establish_res->sdu, ll_establish_res->sapi); + + /* + * Mark the affected nsapis and sapi as MG_XID_IDLE. + */ + sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_XID); + sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST); + + sig_mg_sda_end_est(ll_establish_res->sapi, TRUE); + + sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE); + + PSEND(hCommLLC, ll_establish_res); + + /* + * All nsapis at this sapi that use ack mode, enter recovery state. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) { + UBYTE sapi = 0; + BOOL ack = FALSE; + + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack && (sapi == ll_establish_ind->sapi)) { + sig_mg_cia_delete_npdus(nsapi); + sig_mg_sua_delete_pdus(nsapi, sapi, FALSE); + sig_mg_nu_recover(nsapi); + sig_mg_nd_recover(nsapi); + } + } /* for all nsapis */ + + /* + * Reset nsapis or ntts that were assigned, but are not any more. + */ + mg_clean_xid(ll_establish_ind->sapi); + /* + * If there was a collision and xid has not been negotiated + * sufficiently. + */ + mg_resend_xid_if_nec(ll_establish_ind->sapi); + + /* + * If nsapi has been in state xid_pending or est_pending then + * an snsm_activate_res will be sent now.!!! + */ + mg_respond_if_nec(ll_establish_ind->sapi); + sndcp_get_sapi_state(ll_establish_ind->sapi, &sapi_state); + if ((sapi_state & MG_XID) == 0) { + mg_xid_cnf_ok_res(ll_establish_ind->sapi); + } + + + } + + } else { + /* + * not (check_ret == MG_IND_XID_OK) + */ + /* + * Label MG_CHECK_FAIL_EST + */ + USHORT res_sdu_bit_len = 0; + UBYTE ntt = 0; + BOOL v42_rej = FALSE; + BOOL vj_rej = FALSE; + /* + * Add the extra space for ntts with nsapis == 0. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_dntt_rej(ll_establish_ind->sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + v42_rej = TRUE; + } + mg_get_sapi_pntt_rej(ll_establish_ind->sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + vj_rej = TRUE; + } + } + if (v42_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + if (vj_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + /* + * Allocate response and send it. + */ + { + + PALLOC_SDU (ll_establish_res, LL_ESTABLISH_RES, res_sdu_bit_len); + /* + * Reset res_xid_block, ind_xid_block. + */ + sndcp_reset_xid_block(&sndcp_data->mg.res_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.ind_xid_block[sapi_index]); + /* + * Set sapi in ll_establish_res. + */ + ll_establish_res->sapi = ll_establish_ind->sapi; + ll_establish_res->xid_valid = ll_establish_ind->xid_valid; + /* + * Write res_xid_block struct to sdu byte buffer. Implementation dep.. + */ + mg_set_res_xid_params(&ll_establish_res->sdu, ll_establish_ind->sapi); + /* + * Modify the affected sapi state. + */ + sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_XID); + sndcp_unset_sapi_state(ll_establish_ind->sapi, MG_EST); + + sndcp_set_sapi_ack(ll_establish_res->sapi, TRUE); + /* + * Send the XID block to LLC. + */ + PSEND(hCommLLC, ll_establish_res); + /* + * All nsapis at this sapi that use ack mode, enter recovery state. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) { + UBYTE sapi = 0; + BOOL ack = FALSE; + + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_nsapi_ack(nsapi, &ack); + if (ack && (sapi == ll_establish_ind->sapi)) { + sig_mg_cia_delete_npdus(nsapi); + sig_mg_sua_delete_pdus(nsapi, sapi, FALSE); + sig_mg_nu_recover(nsapi); + sig_mg_nd_recover(nsapi); + } + } /* for all nsapis */ + + } + + /* + * Reset nsapis or ntts that were assigned before + * but are not anymore. + */ + sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]); + mg_clean_xid(ll_establish_ind->sapi); + /* + * Allocate status req and send it (label MG_SEND_STATUS_REQ_EST). + */ + { +#ifdef SNDCP_UPM_INCLUDED + PALLOC (snsm_status_req, SN_STATUS_IND); +#else + PALLOC (snsm_status_req, SNSM_STATUS_REQ); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + snsm_status_req->sapi = ll_establish_ind->sapi; +#ifdef SNDCP_UPM_INCLUDED + snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp; + snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID; + PSEND (hCommUPM, snsm_status_req); +#else + snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID; + PSEND (hCommSM, snsm_status_req); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + } + } + } else { /* not if (dec_ret == MG_XID_OK_EST) */ + /* + * Reset nsapis or ntts that were assigned before + * but are not anymore. + */ + sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]); + mg_clean_xid(ll_establish_ind->sapi); + /* + * Decoding of ll_establish_ind failed (label MG_SEND_STATUS_REQ). + * Allocate status req and send it. + */ + + { +#ifdef SNDCP_UPM_INCLUDED + PALLOC (snsm_status_req, SN_STATUS_IND); + snsm_status_req->sapi = ll_establish_ind->sapi; + snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp; + snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID; + PSEND (hCommUPM, snsm_status_req); +#else + PALLOC (snsm_status_req, SNSM_STATUS_REQ); + snsm_status_req->sapi = ll_establish_ind->sapi; + snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID; + PSEND (hCommSM, snsm_status_req); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + } + + } + +} /* mg_no_col_no_re() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_no_col_re ++------------------------------------------------------------------------------ +| Description : The function mg_no_col_no_re represents the SDL label +| NO_COL_RE: an LL_ESTABLISH_IND has been received, we do not +| have a collision situation like given in [GSM 4.65, 6.2.1.4], +| we do have a re-establishment situation. +| +| Parameters : the received LL_ESTABLISH_IND +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_no_col_re (T_LL_ESTABLISH_IND* ll_establish_ind) +{ + + TRACE_FUNCTION( "mg_no_col_re" ); + /* + * Do the same things as without collision. + */ + mg_no_col_no_re (ll_establish_ind); + +} /* mg_no_col_re() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_re_negotiate ++------------------------------------------------------------------------------ +| Description : The answer to the sent LL_XID_REQ has been invalid +| (bad format or content). If service var renego < MG_MAX_RENEGO then +| same LL_XID_REQ is resent, else SNSM_STATUS_REQ is sent. +| This function represents the SDl label MG_RE_NEGOTIATE. +| +| Parameters : the affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_re_negotiate (UBYTE sapi) { + UBYTE sapi_index = 0; + + TRACE_FUNCTION( "mg_re_negotiate" ); + sndcp_get_sapi_index(sapi, &sapi_index); + + /* + * If number of re-negotiations is reached, deactivate all pdp contexts for + * the affected sapi. + */ + if (sndcp_data->mg.renego[sapi_index] < MG_MAX_RENEGO) { + PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN); + /* + * Set sapi in ll_xid_req. + */ + ll_xid_req->sapi = sapi; + + /* + * Fill the XID block. Implementation dependent. + */ + mg_set_xid_params(ll_xid_req->sapi, + &ll_xid_req->sdu, + sndcp_data->mg.req_xid_block[sapi_index]); + /* + * Send the XID block to LLC. + */ + + sndcp_unset_sapi_state(sapi, MG_XID_NEC); + sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID); + PSEND(hCommLLC, ll_xid_req); + /* + * Increment renegotiation counter. + */ + sndcp_data->mg.renego[sapi_index]++; + } else { + +#ifdef SNDCP_UPM_INCLUDED + PALLOC (snsm_status_req, SN_STATUS_IND); +#else + PALLOC (snsm_status_req, SNSM_STATUS_REQ); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Set all ntts and dcomp/pcomp states to "unassigned". + */ + mg_reset_states_n_rej(sapi_index); + /* + * Set prim parameters. + */ +#ifdef SNDCP_UPM_INCLUDED + snsm_status_req->sapi = sapi; + snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp; + snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_INVALID_XID; +#else + snsm_status_req->sapi = sapi; + snsm_status_req->status_cause = SNSM_RELCS_INVALID_XID; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + + sndcp_data->mg.renego[sapi_index] = 0; + /* + * Reset cur_xid_block. + */ + sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]); + /* + * Reset all compression entities for the affected sapi. + */ + mg_clean_xid(sapi); + +#ifdef SNDCP_UPM_INCLUDED + PSEND (hCommUPM, snsm_status_req); +#else + PSEND (hCommSM, snsm_status_req); +#endif + } + + +} /* mg_re_negotiate() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_re_negotiate_ack ++------------------------------------------------------------------------------ +| Description : The answer to the sent LL_ESTABLISH_REQ has been invalid +| (bad format or content). If service var renego < MG_MAX_RENEGO then +| same LL_ESTABLISH_REQ is resent, else SNSM_STATUS_REQ is sent. +| This function represents the SDl label MG_RE_NEGOTIATE_ACK. +| +| Parameters : the affected sapi, cause +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_re_negotiate_ack (UBYTE sapi, U16 cause) { + UBYTE sapi_index = 0; + + TRACE_FUNCTION( "mg_re_negotiate_ack" ); + sndcp_get_sapi_index(sapi, &sapi_index); + + /* + * If number of re-negotiations is reached, deactivate all pdp contexts for + * the affected sapi. + */ + if (sndcp_data->mg.renego[sapi_index] < MG_MAX_RENEGO) { + PALLOC_SDU(ll_establish_req, + LL_ESTABLISH_REQ, + SNDCP_XID_BLOCK_BIT_LEN); + /* + * Set sapi in ll_establish_req. + */ + ll_establish_req->sapi = sapi; + + /* + * Fill the XID block. Implementation dependent. + */ + mg_set_xid_params(ll_establish_req->sapi, + &ll_establish_req->sdu, + sndcp_data->mg.req_xid_block[sapi_index]); + /* + * Send the XID block to LLC, with establish request. + */ + sig_mg_sda_start_est(sapi); + + PSEND(hCommLLC, ll_establish_req); + /* + * Increment renegotiation counter. + */ + sndcp_data->mg.renego[sapi_index]++; + } else { + +#ifdef SNDCP_UPM_INCLUDED + PALLOC (snsm_status_req, SN_STATUS_IND); +#else + PALLOC (snsm_status_req, SNSM_STATUS_REQ); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Service sda may now leave state SDA_ESTABLISH_REQUESTED. + */ + sig_mg_sda_end_est(sapi, FALSE); + /* + * Set all ntts and dcomp/pcomp states to "unassigned". + */ + mg_reset_states_n_rej(sapi_index); + /* + * Set prim parameters. + */ +#ifdef SNDCP_UPM_INCLUDED + snsm_status_req->sapi = sapi; + snsm_status_req->ps_cause.ctrl_value = CAUSE_is_from_sndcp; +#else + snsm_status_req->sapi = sapi; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + + sndcp_data->mg.renego[sapi_index] = 0; + /* + * Reset cur_xid_block. + */ + sndcp_reset_xid_block(&sndcp_data->mg.cur_xid_block[sapi_index]); + sndcp_reset_xid_block(&sndcp_data->mg.req_xid_block[sapi_index]); + /* + * Reset all compression entities for the affected sapi. + */ + mg_clean_xid(sapi); + /* + * The renegotiation is failed. If the cause is NO_PEER_RESPONSE + * or DM_RECEIVED, set it to RELCS_NORMAL to make SM deactivate + * PDP context. Otherwise the cause is forwarded to SM and the SM + * will deactivate PDP context depending on cause. + */ +#ifdef SNDCP_UPM_INCLUDED + if((cause == CAUSE_SN_NO_PEER_RESPONSE) || + (cause == CAUSE_SN_DM_RECEIVED) ){ + snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_NORMAL_RELEASE; +#else /* SNDCP_UPM_INCLUDED */ +#ifdef _SNDCP_DTI_2_ + if((cause == LL_RELCS_NO_PEER_RES) || + (cause == LL_RELCS_DM_RECEIVED) ){ + snsm_status_req->ps_cause.value.sn_cause = LL_RELCS_NORMAL; +#else + if((cause == CAUSE_SN_NO_PEER_RESPONSE) || + (cause == CAUSE_SN_DM_RECEIVED) ){ + snsm_status_req->ps_cause.value.sn_cause = CAUSE_SN_NORMAL_RELEASE; +#endif +#endif /* SNDCP_UPM_INCLUDED */ + sig_mg_su_resume(sapi); + sig_mg_sua_resume(sapi); + mg_resume_affected_nus(sapi); + sndcp_unset_sapi_state (sapi, MG_EST); + } else { +#ifdef SNDCP_UPM_INCLUDED + snsm_status_req->ps_cause.value.sn_cause = cause; +#else + snsm_status_req->status_cause = cause; +#endif + } + +#ifdef SNDCP_UPM_INCLUDED + PSEND (hCommUPM, snsm_status_req); +#else + PSEND (hCommSM, snsm_status_req); +#endif + + } + +} /* mg_re_negotiate_ack() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_resend_xid_if_nec ++------------------------------------------------------------------------------ +| Description : This procedure will be called after reception and computation +| of an LL_XID_IND or LL_ESTABLISH_IND in case of a collision +| or after receiving LL_XID_CNF or LL_ESTABLISH_CNF and does the +| following: +| (GSM 04.65 version 6.5.1 Release 1997), 6.2.1.4: +| If the +| LL-ESTABLISH.request or LL-XID.request contains one or more XID parameters, +| or one or more compression fields +| in an XID parameter, or one or more parameters in a compression field, +| that are not negotiated as part of the collision +| resolution, then negotiation of these XID parameters shall be performed at +| the earliest opportunity after conclusion of +| the collision resolution. +| +| Parameters : Affected sapi, out: was LL_XID_REQ sent? +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_resend_xid_if_nec (UBYTE sapi) { + UBYTE sapi_index = 0; + BOOL resend_necessary = FALSE; + USHORT sapi_state = MG_IDLE; + T_XID_BLOCK* req_xid_block = NULL; + T_XID_BLOCK* cur_xid_block = NULL; + T_XID_BLOCK* new_xid_block = NULL; + + TRACE_FUNCTION( "mg_resend_xid_if_nec" ); + + sndcp_get_sapi_index(sapi, &sapi_index); + req_xid_block = &sndcp_data->mg.req_xid_block[sapi_index]; + cur_xid_block = &sndcp_data->mg.cur_xid_block[sapi_index]; + new_xid_block = &sndcp_data->mg.new_xid_block[sapi_index]; + + /* + * Data compression. + */ + /* + * If a context is deactivated, maybe compressors must be switched off. + */ + if (cur_xid_block->v42.is_set) { + USHORT nsapis = cur_xid_block->v42.nsapis; + UBYTE nsapi = 0; + + /* + * XID renegotiation will only be necessary if one of the nsapis + * that are requested to use the data compression is in state + * MG_DEACT. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & nsapis) > 0) { + USHORT state = MG_IDLE; + sndcp_get_nsapi_state(nsapi, &state); + if ((state & MG_DEACT) > 0) { + UBYTE dntt = cur_xid_block->v42.ntt; + resend_necessary = TRUE; + mg_set_sapi_dntt_rej(sapi, dntt, TRUE); + } + } + } + } + + if (req_xid_block->v42.is_set && ! cur_xid_block->v42.is_set) { + UBYTE sapi_index_local = 0; + BOOL used = FALSE; + /* + * If one instance of v42 is used at a different sapi, + * we may not use another one here. + */ + for (sapi_index_local = 0; + sapi_index_local < SNDCP_NUMBER_OF_SAPIS; + sapi_index_local++) { + + if (sndcp_data->mg.cur_xid_block[sapi_index_local].v42.is_set) { + used = TRUE; + } + } + if (! used) { + USHORT nsapis = req_xid_block->v42.nsapis; + UBYTE nsapi = 0; + + /* + * XID renegotiation will only be necessary if one of the nsapis + * that are requested to use the data compression are not all in state + * MG_DEACT. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & nsapis) > 0) { + USHORT state = MG_IDLE; + sndcp_get_nsapi_state(nsapi, &state); + if ((state & MG_DEACT) == 0) { + resend_necessary = TRUE; + } + } + } + + } + } + /* + * Header compression. + */ + /* + * If a context is deactivated, maybe compressors must be switched off. + */ + if (cur_xid_block->vj.is_set) { + USHORT nsapis = cur_xid_block->vj.nsapis; + UBYTE nsapi = 0; + + /* + * XID renegotiation will only be necessary if one of the nsapis + * that are requested to use the header compression is in state + * MG_DEACT. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & nsapis) > 0) { + USHORT state = MG_IDLE; + sndcp_get_nsapi_state(nsapi, &state); + if ((state & MG_DEACT) > 0) { + UBYTE pntt = cur_xid_block->vj.ntt; + resend_necessary = TRUE; + mg_set_sapi_pntt_rej(sapi, pntt, TRUE); + } + } + } + + } + /* + * If a compressor is requested and not yet negotiated it must be requested + * now. + */ + if (req_xid_block->vj.is_set && !cur_xid_block->vj.is_set) { + USHORT nsapis = req_xid_block->vj.nsapis; + UBYTE nsapi = 0; + + req_xid_block->vj.p_bit = 1; + + /* + * XID renegotiation will only be necessary if the affected nsapis + * is not currently being deactivated. + */ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & nsapis) > 0) { + USHORT state = MG_IDLE; + sndcp_get_nsapi_state(nsapi, &state); + if ((state & MG_DEACT) == 0) { + resend_necessary = TRUE; + } + } + } + + } + + /* + * If in the meantime more compression has been requested, + * or compressors must be deactivated, + * re-negotiate. + */ + if (new_xid_block->v42.is_set) { + if ((! req_xid_block->v42.is_set) || + (req_xid_block->v42.is_set && + (new_xid_block->v42.nsapis != req_xid_block->v42.nsapis))) { + + *req_xid_block = *new_xid_block; + resend_necessary = TRUE; + } + } + + /* + * If in the meantime more compression has been requested, + * or compressors must be deactivated, + * re-negotiate. + */ + if (new_xid_block->vj.is_set) { + if ((! req_xid_block->vj.is_set) || + (req_xid_block->vj.is_set && + (new_xid_block->vj.nsapis != req_xid_block->vj.nsapis))) { + + *req_xid_block = *new_xid_block; + resend_necessary = TRUE; + } + } + + + sndcp_get_sapi_state(sapi, &sapi_state); + /* + * If re-negotiation is necessary but not possible because MG_REL or + * MG_XID, set MG_XID_NEC. + */ + if (resend_necessary + && + ((sapi_state & (MG_REL + MG_XID)) > 0)) + { + sndcp_set_sapi_state(sapi, MG_XID_NEC); + mg_set_cur_xid_block(sapi); + return; + } + + + /* + * If renegotiation of XID is necessary, send LL_XID_REQ. + */ + if (! resend_necessary) { +// mg_set_cur_xid_block(sapi); + return; + } + + + /* + * Now req_xid_block is in good shape. Send it. + */ + { + PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN); + /* + * Set sapi in ll_xid_req. + */ + ll_xid_req->sapi = sapi; + /* + * Write data from snsm_activate_ind to service variable req_xid_block. + */ + mg_set_ntt_comp(sapi); + /* + * Fill the XID block. Implementation dependent. + */ + mg_set_xid_params(ll_xid_req->sapi, + &ll_xid_req->sdu, + sndcp_data->mg.req_xid_block[sapi_index]); + /* + * Mark the affected sapi as MG_XID. + */ + sndcp_set_sapi_state(sapi, MG_XID); + sndcp_unset_sapi_state(sapi, MG_XID_NEC); + + /* + * Uplink data transfer on SAPI is completely suspended. + */ + sig_mg_su_suspend(sapi); + sig_mg_sua_suspend(sapi); + mg_suspend_affected_nus(sapi); + /* + * Send the XID block to LLC. + */ + + sndcp_unset_sapi_state(sapi, MG_XID_NEC); + sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID); + PSEND(hCommLLC, ll_xid_req); + } + +} /* mg_resend_xid_if_nec() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_resume_affected_nus ++------------------------------------------------------------------------------ +| Description : Resumes all nu service instances affected by +| If nsapi is waiting for SNSM_SEQUENCE_IND, fct. returns. +| +| Parameters : sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_resume_affected_nus (UBYTE sapi) { + UBYTE nsapi = 0; + TRACE_FUNCTION( "mg_resume_affected_nus" ); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + UBYTE local_sapi = 0; + sndcp_get_nsapi_sapi(nsapi, &local_sapi); + if (local_sapi == sapi) { + USHORT nsapi_state = 0; + sndcp_get_nsapi_state(nsapi, &nsapi_state); + if ((nsapi_state & MG_SEQ) > 0) { + return; + } + if (((1 << nsapi) & sndcp_data->mg.suspended_nsapis) > 0) { + sig_mg_nu_resume(nsapi); + sndcp_data->mg.suspended_nsapis &= (~ (ULONG)(1 << nsapi)); + } + } + } +} /* mg_resume_affected_nus() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_is_rel_comp_nec ++------------------------------------------------------------------------------ +| Description : This function will be called in course of the deactivation of +| the given nsapi. If the nsapi used a certain compressor, +| but has been the only one to do this, then with the +| compressor entity will also have to +| be deactivated and all affected +| arrays will be modified. +| Parameters : UBYTE nsapi -- the given nsapi +| BOOL* nec, a compressor +| Post : An "mg_set_sapi_[p/d]ntt_rej(sapi, pntt, TRUE);" will be called +| for +| each entity to be released. Later this information may be used +| to build up the right xid negotiation. +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_is_rel_comp_nec (UBYTE nsapi, BOOL* nec) +{ + UBYTE dntt = 0; + UBYTE pntt = 0; + UBYTE sapi = 0; + UBYTE nsp = 0; + + TRACE_FUNCTION( "mg_is_rel_comp_nec" ); + + sndcp_get_nsapi_sapi(nsapi, &sapi); + + + /* + * Which pntt is used? + */ + for (pntt = 0; pntt < MG_MAX_ENTITIES; pntt++) { + UBYTE state = MG_UNASSIGNED; + BOOL used = FALSE; + BOOL another = FALSE; + BOOL rej_known = FALSE; + /* + * Is pntt already known to be deactivated? + */ + mg_get_sapi_pntt_rej(sapi, pntt, &rej_known); + if (rej_known) { + *nec = TRUE; + continue; + } + /* + * Is ntt used? + */ + mg_get_sapi_pntt_state(sapi, pntt, &state); + if (state == MG_UNASSIGNED) { + continue; + } + /* + * Does the given nsapi use it? + */ + mg_get_sapi_pntt_nsapi(sapi, pntt, nsapi, &used); + if (! used) { + continue; + } + /* + * Is the given nsapi the only user? + */ + for (nsp = 0; nsp < SNDCP_NUMBER_OF_NSAPIS; nsp++) { + mg_get_sapi_pntt_nsapi(sapi, pntt, nsp, &used); + if (used && nsapi != nsp) { + another = TRUE; + } + } + if (another) { + continue; + } + mg_set_sapi_pntt_rej(sapi, pntt, TRUE); + *nec = TRUE; + } + + /* + * Which dntt is used? + */ + for (dntt = 0; dntt < MG_MAX_ENTITIES; dntt++) { + UBYTE state = MG_UNASSIGNED; + BOOL used = FALSE; + BOOL another = FALSE; + BOOL rej_known = FALSE; + /* + * Is pntt already known to be deactivated? + */ + mg_get_sapi_dntt_rej(sapi, dntt, &rej_known); + if (rej_known) { + *nec = TRUE; + continue; + } + /* + * Is ntt used? + */ + mg_get_sapi_dntt_state(sapi, dntt, &state); + if (state == MG_UNASSIGNED) { + continue; + } + /* + * Does the given nsapi use it? + */ + mg_get_sapi_dntt_nsapi(sapi, dntt, nsapi, &used); + if (! used) { + continue; + } + /* + * Is the given nsapi the only user? + */ + for (nsp = 0; nsp < SNDCP_NUMBER_OF_NSAPIS; nsp++) { + mg_get_sapi_dntt_nsapi(sapi, dntt, nsp, &used); + if (used && nsapi != nsp) { + another = TRUE; + } + } + if (another) { + continue; + } + + mg_set_sapi_dntt_rej(sapi, dntt, TRUE); + *nec = TRUE; + } + +} /* mg_is_rel_comp_nec() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_rel_nsapi_nec ++------------------------------------------------------------------------------ +| Description : The SAPI connected to this NSAPI shall release acknowledged LLC +| operation mode if the indicated NSAPI is the last one using +| acknowledged mode on this SAPI. If an LL_RELEASE_REQ is sent +| then the given NSAPI (the one in parameter!) shall enter state +| MG_REL and wait for an LL_RELEASE_CNF. If the affected +| NSAPI doesn't use ack mode then the procedure just returns. +| If the affected sapi does not use acknowledged LLC operation +| mode then the procedure just returns. +| If an LL_ESTABLISH_REQ or LL_XID_REQ for the affected sapi is +| pending, no LL_RELEASE_REQ primitive will be sent, but the +| flag MG_REL_NEC_LOC will be set. +| Pre : This procedure is called after receipt of an +| SNSM_DEACTIVATE_IND, so the "local" parameter in an +| LL_RELEASE_REQ will be set to LL_REL_LOCAL. +| The procedure will only be called if the given nsapi is +| currently using acknowledged LLC operation mode, so this +| does not have to be checked. +| Parameters : UBYTE nsapi -- the given nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_rel_nsapi_nec (UBYTE nsapi) +{ + UBYTE sapi = 0; + UBYTE npi = 0; + UBYTE spi = 0; + USHORT sapi_state = MG_IDLE; + /* + * Are there other contexts using acknowledged mode on the same SAPI? + */ + BOOL another_ack = FALSE; + BOOL sack = FALSE; + TRACE_FUNCTION( "mg_rel_nsapi_nec" ); + /* + * Which SAPI is connected to the given NSAPI? + */ + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_sapi_ack(sapi, &sack); + sndcp_get_sapi_state(sapi, &sapi_state); + + if(!sack){ + if ((sapi_state & MG_EST) != 0) { + sndcp_set_sapi_state(sapi, MG_REL_NEC_LOC); + } + return; + } + /* + * If release is pending, no need to send an other release. + */ + if ((sapi_state & MG_REL) > 0) { + return; + } + /* + * Are there other contexts using acknowledged mode on the same SAPI? + */ + for (npi = 0; npi < SNDCP_NUMBER_OF_NSAPIS; npi++) { + BOOL used = FALSE; + sndcp_is_nsapi_used(npi, &used); + if (!used) { + continue; + } + sndcp_get_nsapi_sapi(npi, &spi); + if (spi == sapi && npi != nsapi) { + BOOL is_ack = FALSE; + sndcp_get_nsapi_ack(npi, &is_ack); + if (is_ack) { + another_ack = TRUE; + } + break; + } + } + if (!another_ack) { + + if (((sapi_state & MG_EST) == 0) + && + ((sapi_state & MG_XID) == 0)) + { + /* + * No LL_ESTABLISH_REQ or LL_XID_REQ pending. + * LL_RELEASE_REQ may be sent. + */ + + PALLOC(ll_release_req, LL_RELEASE_REQ); + ll_release_req->sapi = sapi; + /* + * Note: this is always set to TRUE because the preconditions include that + * this procedure has been called after an SNSM_DEACTIVATE_IND. + * If this precondition changes the local flag will have to be a parameter. + * (GSM 4.65, 6.2.2.2). + */ + ll_release_req->local = TRUE; + /* + * Set the "state" for the affected sapi to MG_REL. + */ + sndcp_set_sapi_state(sapi, MG_REL); + sndcp_unset_sapi_state(sapi, MG_EST); + + PSEND(hCommLLC, ll_release_req); + + } else { + /* + * LL_ESTABLISH_REQ or LL_XID_REQ pending. + * LL_RELEASE_REQ may not be sent. + */ + sndcp_set_sapi_state(sapi, MG_REL_NEC_LOC); + + } + } /* if (!another_ack) */ + + +} /* mg_rel_nsapi_nec() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_send_empty_xid_req ++------------------------------------------------------------------------------ +| Description : This procedure sets the pending-states of the affected sapi +| and nsapi to MG_XID_PENDING and sends an LL_XID_REQ with +| the sapi from the given snsm_activate_ind and an empty XID +| block. +| +| Parameters : the SNSM_ACTIVATE_IND +| ++------------------------------------------------------------------------------ +*/ +#ifdef SNDCP_UPM_INCLUDED +GLOBAL void mg_send_empty_xid_req (T_SN_ACTIVATE_REQ* snsm_activate_ind) +#else +GLOBAL void mg_send_empty_xid_req (T_SNSM_ACTIVATE_IND* snsm_activate_ind) +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +{ + TRACE_FUNCTION( "mg_send_empty_xid_req" ); + { + PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN); + /* + * Set sapi in ll_xid_req. + */ + ll_xid_req->sapi = snsm_activate_ind->sapi; + ll_xid_req->sdu.l_buf = 0; + + /* + * Mark sapi as pending. + */ + sndcp_set_sapi_state(snsm_activate_ind->sapi, MG_XID); + /* + * Send the XID block to LLC. + */ + + sndcp_unset_sapi_state(ll_xid_req->sapi, MG_XID_NEC); + sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID); + PSEND(hCommLLC, ll_xid_req); + } +} /* mg_send_xid_req() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_send_snsm_activate_res ++------------------------------------------------------------------------------ +| Description : Allocates prim, sets parameters and sends prim +| +| Parameters : the affected nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_send_snsm_activate_res (UBYTE nsapi) +{ + + TRACE_FUNCTION( "mg_send_snsm_activate_res" ); + { + UBYTE sapi_index = 0; + UBYTE sapi = 0; + +#ifdef SNDCP_UPM_INCLUDED + PALLOC(snsm_activate_res, SN_ACTIVATE_CNF); +#else + PALLOC(snsm_activate_res, SNSM_ACTIVATE_RES); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + + sndcp_get_nsapi_sapi(nsapi, &sapi); + sndcp_get_sapi_index(sapi, &sapi_index); + + snsm_activate_res->nsapi = nsapi; + + /* + * If nsapi uses data compressor, set dcomp parameter + * in snsm_activate_res. + */ + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set && + ((sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis & + (1 << nsapi)) > 0)) { + +#ifdef SNDCP_UPM_INCLUDED + snsm_activate_res->comp_params.dcomp = + sndcp_data->mg.cur_xid_block[sapi_index].v42.p0; +#else + snsm_activate_res->dcomp = + sndcp_data->mg.cur_xid_block[sapi_index].v42.p0; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + } else + { +#ifdef SNDCP_UPM_INCLUDED + snsm_activate_res->comp_params.dcomp = 0; +#else + snsm_activate_res->dcomp = 0; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + } + + /* + * If nsapi uses header compressor, set hcomp parameter + * and msid field in snsm_activate_res. + */ + +#ifdef SNDCP_UPM_INCLUDED + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set && + ((sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis & + (1 << nsapi)) > 0)) { + snsm_activate_res->comp_params.msid = + sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 + 1; + /* + * How is that one negotiated? + * Missing in VJ XID block. + */ + snsm_activate_res->comp_params.hcomp = + sndcp_data->mg.cur_xid_block[sapi_index].vj.direction; + } else { + snsm_activate_res->comp_params.hcomp = 0; + snsm_activate_res->comp_params.msid = 0; + } + + PSEND(hCommUPM, snsm_activate_res); +#else /*#ifdef SNDCP_UPM_INCLUDED*/ + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set && + ((sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis & + (1 << nsapi)) > 0)) { + snsm_activate_res->msid = + sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 + 1; + /* + * How is that one negotiated? + * Missing in VJ XID block. + */ + snsm_activate_res->hcomp = + sndcp_data->mg.cur_xid_block[sapi_index].vj.direction; + } else { + snsm_activate_res->hcomp = 0; + snsm_activate_res->msid = 0; + } + PSEND(hCommSM, snsm_activate_res); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +} + } /* mg_send_snsm_activate_res() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_send_xid_req ++------------------------------------------------------------------------------ +| Description : This procedure sets the pending-states of the affected sapi +| and nsapi to MG_XID_PENDING and sends an LL_XID_REQ with +| parameters set according to the compression informations in +| the given snsm_activate_ind and according to constants that +| determine the capabilities of the data compression entity. +| The part of this procedure that deals with the constant +| compressor capabilities is implementation dependent. +| +| Parameters : the SNSM_ACTIVATE_IND +| ++------------------------------------------------------------------------------ +*/ +#ifdef SNDCP_UPM_INCLUDED +GLOBAL void mg_send_xid_req (T_SN_ACTIVATE_REQ* snsm_activate_ind) +#else +GLOBAL void mg_send_xid_req (T_SNSM_ACTIVATE_IND* snsm_activate_ind) +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +{ + UBYTE sapi_index = 0; + TRACE_FUNCTION( "mg_send_xid_req" ); + sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index); + { + PALLOC_SDU(ll_xid_req, LL_XID_REQ, SNDCP_XID_BLOCK_BIT_LEN); + /* + * Set sapi in ll_xid_req. + */ + ll_xid_req->sapi = snsm_activate_ind->sapi; + /* + * Write data from snsm_activate_ind to service variable req_xid_block. + */ + + mg_set_req_xid_block(snsm_activate_ind); + /* + * Fill the XID block. Implementation dependent. + */ + mg_set_xid_params(ll_xid_req->sapi, + &ll_xid_req->sdu, + sndcp_data->mg.req_xid_block[sapi_index]); + /* + * Mark the affected sapi as xid pending + */ + + sndcp_set_sapi_state(snsm_activate_ind->sapi, MG_XID); + + /* + * Trace xid block. + */ +#ifdef SNDCP_TRACE_ALL + TRACE_EVENT("outcoming xid block:"); + sndcp_trace_sdu(&ll_xid_req->sdu); +#endif + /* + * Send the XID block to LLC. + */ + + sndcp_unset_sapi_state(ll_xid_req->sapi, MG_XID_NEC); + sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID); + PSEND(hCommLLC, ll_xid_req); + } +} /* mg_send_xid_req() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_send_xid_req_del ++------------------------------------------------------------------------------ +| Description : If mg_get_sapi_pntt_rej() or mg_get_sapi_dntt_rej() indicate +| that compressors must be removed, this function will +| send an LL_XID_REQ which does this, or if an XID is pending, +| the information about the rejected compressors will be stored +| to new_xid_block and the MG_XID_NEC will be set. +| +| Parameters : the SNSM_ACTIVATE_IND +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_send_xid_req_del (UBYTE sapi) +{ + UBYTE sapi_index = 0; + UBYTE ntt = 0; + T_XID_BLOCK mt_xid_block; + /* + * Only length of parameter type 0. + */ + USHORT res_sdu_bit_len = 24; + BOOL v42_rej = FALSE; + BOOL vj_rej = FALSE; + + TRACE_FUNCTION( "mg_send_xid_req_del" ); + + sndcp_reset_xid_block(&mt_xid_block); + + sndcp_get_sapi_index(sapi, &sapi_index); + /* + * How long will xid_block be? + */ + /* + * Add the extra space for ntts with nsapis == 0. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_dntt_rej(sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + v42_rej = TRUE; + /* + * Change new_xid_block. + */ + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis = 0; + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = TRUE; + sndcp_data->mg.new_xid_block[sapi_index].v42.is_set = TRUE; + } + + mg_get_sapi_pntt_rej(sapi, ntt, &rej); + if (rej) { + /* + * length of ntt octet and nsapis. + */ + res_sdu_bit_len += 32; + vj_rej = TRUE; + /* + * Change req_xid_block. + */ + sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis = 0; + sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis_set = TRUE; + sndcp_data->mg.new_xid_block[sapi_index].vj.is_set = TRUE; + + } + } + if (v42_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + if (vj_rej) { + /* + * Add length of parameter type and length. + */ + res_sdu_bit_len += 16; + } + + if (v42_rej || vj_rej) { + + USHORT state = MG_IDLE; + + sndcp_get_sapi_state(sapi, &state); + if ((state & MG_XID) == 0) { + + PALLOC_SDU(ll_xid_req, LL_XID_REQ, res_sdu_bit_len); + + sndcp_data->mg.req_xid_block[sapi_index] = + sndcp_data->mg.new_xid_block[sapi_index]; + /* + * Set sapi in ll_xid_req. + */ + ll_xid_req->sapi = sapi; + /* + * Write data from snsm_activate_ind to service variable req_xid_block. + */ + sndcp_reset_xid_block(&mt_xid_block); + sndcp_reset_xid_block(&sndcp_data->mg.new_xid_block[sapi_index]); + /* + * Fill the XID block. Implementation dependent. + */ + mg_set_xid_params(ll_xid_req->sapi, + &ll_xid_req->sdu, + mt_xid_block); + /* + * Mark the affected sapi as MG_DEL_XID_PENDING. + */ + sndcp_set_sapi_state(sapi, MG_XID); + /* + * Send the XID block to LLC. + */ + + sndcp_unset_sapi_state(sapi, MG_XID_NEC); + sndcp_set_sapi_state(ll_xid_req->sapi, MG_XID); + PSEND(hCommLLC, ll_xid_req); + } else { + sndcp_set_sapi_state(sapi, MG_XID_NEC); + } + } +} /* mg_send_xid_req_del() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_cur_xid_block ++------------------------------------------------------------------------------ +| Description : This procedure sets the cur_xid_block service variable +| according to the values given in req_xid_block and cnf_xid_block. +| It also sets the unassigned, selected, assigned states of the affected +| dcomp, pcomp, ntt. +| The p bit in the req_xid_block is unset, if affected. +| See GSM 4.65, 6.8.2. +| +| Parameters : the affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_set_cur_xid_block (UBYTE sapi) { + UBYTE sapi_index = 0; + T_XID_BLOCK* cur_xid_block; + T_XID_BLOCK* req_xid_block; + T_XID_BLOCK* cnf_xid_block; + TRACE_FUNCTION( "mg_set_cur_xid_block" ); + sndcp_get_sapi_index(sapi, &sapi_index); + cur_xid_block = &sndcp_data->mg.cur_xid_block[sapi_index]; + req_xid_block = &sndcp_data->mg.req_xid_block[sapi_index]; + cnf_xid_block = &sndcp_data->mg.cnf_xid_block[sapi_index]; + /* + * SNDCP version has been tested to be SNDCP_XID_VERSION. + */ + cur_xid_block->version = SNDCP_XID_VERSION; + + /* + * V42bis parameters. + */ + if (req_xid_block->v42.is_set) { + cur_xid_block->v42.is_set = TRUE; + cur_xid_block->v42.ntt = req_xid_block->v42.ntt; + mg_set_sapi_dntt_state(sapi, + req_xid_block->v42.ntt, + MG_ASSIGNED); + req_xid_block->v42.p_bit = SNDCP_P_BIT_0; + + /* + * Algorithm type and DCOMP are only set in req. + */ + cur_xid_block->v42.algo_type = req_xid_block->v42.algo_type; + cur_xid_block->v42.dcomp = req_xid_block->v42.dcomp; + mg_set_sapi_dcomp_state(sapi, + req_xid_block->v42.dcomp, + MG_ASSIGNED); + + if (cnf_xid_block->v42.is_set) { + + if (cnf_xid_block->v42.nsapis_set) { + cur_xid_block->v42.nsapis = cnf_xid_block->v42.nsapis; + cur_xid_block->v42.nsapis_set = TRUE; + } else if (req_xid_block->v42.nsapis_set) { + cur_xid_block->v42.nsapis = req_xid_block->v42.nsapis; + cur_xid_block->v42.nsapis_set = TRUE; + } + if (cnf_xid_block->v42.p0_set) { + cur_xid_block->v42.p0 = cnf_xid_block->v42.p0; + cur_xid_block->v42.p0_set = TRUE; + } else if (req_xid_block->v42.p0_set) { + cur_xid_block->v42.p0 = req_xid_block->v42.p0; + cur_xid_block->v42.p0_set = TRUE; + } + if (cnf_xid_block->v42.p1_set) { + cur_xid_block->v42.p1 = cnf_xid_block->v42.p1; + cur_xid_block->v42.p1_set = TRUE; + } else if (req_xid_block->v42.p1_set) { + cur_xid_block->v42.p1 = req_xid_block->v42.p1; + cur_xid_block->v42.p1_set = TRUE; + } + if (cnf_xid_block->v42.p2_set) { + cur_xid_block->v42.p2 = cnf_xid_block->v42.p2; + cur_xid_block->v42.p2_set = TRUE; + } else if (req_xid_block->v42.p2_set) { + cur_xid_block->v42.p2 = req_xid_block->v42.p2; + cur_xid_block->v42.p2_set = TRUE; + } + + } else { + /* + * NOT cnf_xid_block->v42.is_set. + */ + + if (req_xid_block->v42.nsapis_set) { + cur_xid_block->v42.nsapis = req_xid_block->v42.nsapis; + cur_xid_block->v42.nsapis_set = TRUE; + } + if (req_xid_block->v42.p0_set) { + cur_xid_block->v42.p0 = req_xid_block->v42.p0; + cur_xid_block->v42.p0_set = TRUE; + } + if (req_xid_block->v42.p1_set) { + cur_xid_block->v42.p1 = req_xid_block->v42.p1; + cur_xid_block->v42.p1_set = TRUE; + } + if (req_xid_block->v42.p2_set) { + cur_xid_block->v42.p2 = req_xid_block->v42.p2; + cur_xid_block->v42.p2_set = TRUE; + } + + } + } else { + /* + * NOT req_xid_block->v42.is_set. + */ + if (cnf_xid_block->v42.is_set) { + + cur_xid_block->v42.is_set = TRUE; + if (cnf_xid_block->v42.nsapis_set) { + cur_xid_block->v42.nsapis = cnf_xid_block->v42.nsapis; + cur_xid_block->v42.nsapis_set = TRUE; + } + if (cnf_xid_block->v42.p0_set) { + cur_xid_block->v42.p0 = cnf_xid_block->v42.p0; + cur_xid_block->v42.p0_set = TRUE; + } + if (cnf_xid_block->v42.p1_set) { + cur_xid_block->v42.p1 = cnf_xid_block->v42.p1; + cur_xid_block->v42.p1_set = TRUE; + } + if (cnf_xid_block->v42.p2_set) { + cur_xid_block->v42.p2 = cnf_xid_block->v42.p2; + cur_xid_block->v42.p2_set = TRUE; + } + + } else { + /* + * Req and cnf are not set, cur_xid_block keeps its values. + */ + } + } + + + /* + * VJ parameters. + */ + if (req_xid_block->vj.is_set) { + cur_xid_block->vj.is_set = TRUE; + cur_xid_block->vj.ntt = req_xid_block->vj.ntt; + mg_set_sapi_pntt_state(sapi, + req_xid_block->vj.ntt, + MG_ASSIGNED); + req_xid_block->vj.p_bit = SNDCP_P_BIT_0; + /* + * Algorithm type and PCOMPs are only set in req. + * The direction is only set in req. + */ + cur_xid_block->vj.algo_type = req_xid_block->vj.algo_type; + cur_xid_block->vj.pcomp1 = req_xid_block->vj.pcomp1; + mg_set_sapi_pcomp_state(sapi, + req_xid_block->vj.pcomp1, + MG_ASSIGNED); + cur_xid_block->vj.pcomp2 = req_xid_block->vj.pcomp2; + mg_set_sapi_pcomp_state(sapi, + req_xid_block->vj.pcomp2, + MG_ASSIGNED); + cur_xid_block->vj.direction = req_xid_block->vj.direction; + if (cnf_xid_block->vj.is_set) { + if (cnf_xid_block->vj.nsapis_set) { + cur_xid_block->vj.nsapis = cnf_xid_block->vj.nsapis; + cur_xid_block->vj.nsapis_set = TRUE; + } else { + cur_xid_block->vj.nsapis = req_xid_block->vj.nsapis; + cur_xid_block->vj.nsapis_set = TRUE; + } + if (cnf_xid_block->vj.s0_m_1_set) { + cur_xid_block->vj.s0_m_1 = cnf_xid_block->vj.s0_m_1; + cur_xid_block->vj.s0_m_1_set = TRUE; + } else { + cur_xid_block->vj.s0_m_1 = req_xid_block->vj.s0_m_1; + cur_xid_block->vj.s0_m_1_set = TRUE; + } + } else { + if (req_xid_block->vj.nsapis_set) { + cur_xid_block->vj.nsapis = req_xid_block->vj.nsapis; + cur_xid_block->vj.nsapis_set = TRUE; + } + if (req_xid_block->vj.s0_m_1_set) { + cur_xid_block->vj.s0_m_1 = req_xid_block->vj.s0_m_1; + cur_xid_block->vj.s0_m_1_set = TRUE; + } + } + } else { + /* + * NOT req_xid_block->vj.es_set. + */ + if (cnf_xid_block->vj.is_set) { + cur_xid_block->vj.is_set = TRUE; + if (cnf_xid_block->vj.nsapis_set) { + cur_xid_block->vj.nsapis = cnf_xid_block->vj.nsapis; + cur_xid_block->vj.nsapis_set = TRUE; + } + if (cnf_xid_block->vj.s0_m_1_set) { + cur_xid_block->vj.s0_m_1 = cnf_xid_block->vj.s0_m_1; + cur_xid_block->vj.s0_m_1_set = TRUE; + } + } else { + /* + * Req and cnf are not set, cur_xid_block keeps it's values. + */ + } + } + + /* + * If nsapis are 0, deactivate compressor. + */ + if (cur_xid_block->v42.nsapis == 0 || + cur_xid_block->v42.nsapis_set == FALSE) { + + /* + * Find the affected compressor entity. + */ + UBYTE dntt = 0; + mg_get_sapi_dcomp_dntt(sapi, req_xid_block->v42.dcomp, &dntt); + + cur_xid_block->v42.is_set = FALSE; + mg_set_sapi_dcomp_state(sapi, + req_xid_block->v42.dcomp, + MG_UNASSIGNED); + mg_set_sapi_dntt_state(sapi, + dntt, + MG_UNASSIGNED); + /* + * One compressor less, something like sndcp_data->v42_count--; + * should come here! + */ + + } + if (cur_xid_block->vj.nsapis == 0 || + cur_xid_block->vj.nsapis_set == FALSE) { + + /* + * Find the affected compressor entity. + */ + UBYTE pntt = 0; + mg_get_sapi_pcomp_pntt(sapi, req_xid_block->vj.pcomp1, &pntt); + mg_get_sapi_pcomp_pntt(sapi, req_xid_block->vj.pcomp2, &pntt); + cur_xid_block->vj.is_set = FALSE; + mg_set_sapi_pcomp_state(sapi, + req_xid_block->vj.pcomp1, + MG_UNASSIGNED); + mg_set_sapi_pcomp_state(sapi, + req_xid_block->vj.pcomp2, + MG_UNASSIGNED); + mg_set_sapi_pntt_state(sapi, + pntt, + MG_UNASSIGNED); + /* + * One compressor less. + */ + if (sndcp_data->vj_count > 0) { + sndcp_data->vj_count--; + } + } + + + /* + * Send new block to service cia. + */ + sig_mg_cia_new_xid(cur_xid_block); + +} /* mg_set_cur_xid_block() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_new_xid_block ++------------------------------------------------------------------------------ +| Description : This procedure reads data from the given snsm_activate_ind and +| from the already requested xid block and +| writes them to the service variable new_xid_block. +| When the pending establishment or xid negotiation is finished +| this new_xid_block will be newly evaluated. +| +| Parameters : +| the new SNSM_ACTIVATE_IND +| ++------------------------------------------------------------------------------ +*/ +#ifdef SNDCP_UPM_INCLUDED +GLOBAL void mg_set_new_xid_block (T_SN_ACTIVATE_REQ* snsm_activate_ind) +#else +GLOBAL void mg_set_new_xid_block (T_SNSM_ACTIVATE_IND* snsm_activate_ind) +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +{ + UBYTE sapi_index = 0; + TRACE_FUNCTION( "mg_set_new_xid_block" ); + sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index); + /* + * Set the version number. + */ + sndcp_data->mg.new_xid_block[sapi_index].version = SNDCP_XID_VERSION; + /* + * Set the V42.bis parameters, + */ +#ifdef TI_PS_FF_V42BIS + sndcp_data->mg.new_xid_block[sapi_index].v42.is_set = +#ifdef SNDCP_UPM_INCLUDED + (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT); +#else + (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.new_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_1; + sndcp_data->mg.new_xid_block[sapi_index].v42.ntt = SNDCP_NTT_0; + sndcp_data->mg.new_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42; + sndcp_data->mg.new_xid_block[sapi_index].v42.dcomp = SNDCP_DCOMP1; + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis = + 1 << (snsm_activate_ind->nsapi); + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = TRUE; +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.new_xid_block[sapi_index].v42.p0 = snsm_activate_ind->comp_params.dcomp; +#else + sndcp_data->mg.new_xid_block[sapi_index].v42.p0 = snsm_activate_ind->dcomp; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.new_xid_block[sapi_index].v42.p0_set = TRUE; + + /* + * Set p1 and p2 to default values. + */ + sndcp_data->mg.new_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1; + sndcp_data->mg.new_xid_block[sapi_index].v42.p1_set = TRUE; + sndcp_data->mg.new_xid_block[sapi_index].v42.p2 = + SNDCP_V42_DEFAULT_P2; + sndcp_data->mg.new_xid_block[sapi_index].v42.p2_set = TRUE; + + /* + * Set affected entities and dcomp/pcomp values. + */ + mg_set_ntt_comp(snsm_activate_ind->sapi); + +#else /* !TI_PS_FF_V42BIS */ + + + sndcp_data->mg.new_xid_block[sapi_index].v42.is_set = FALSE; + + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis = 0; + + sndcp_data->mg.new_xid_block[sapi_index].v42.nsapis_set = FALSE; + sndcp_data->mg.new_xid_block[sapi_index].v42.p0_set = FALSE; + + /* + * Set p1 and p2 to default values. + */ + sndcp_data->mg.new_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1; + sndcp_data->mg.new_xid_block[sapi_index].v42.p1_set = TRUE; + sndcp_data->mg.new_xid_block[sapi_index].v42.p2 = + SNDCP_V42_DEFAULT_P2; + sndcp_data->mg.new_xid_block[sapi_index].v42.p2_set = TRUE; + +#endif /* TI_PS_FF_V42BIS */ + + /* + * Set the Van Jacobson parameters, + */ + sndcp_data->mg.new_xid_block[sapi_index].vj.is_set = +#ifdef SNDCP_UPM_INCLUDED + (snsm_activate_ind->comp_params.hcomp != NAS_HCOMP_OFF) || +#else + (snsm_activate_ind->hcomp != SNSM_COMP_NEITHER_DIRECT) || +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.new_xid_block[sapi_index].vj.is_set || + sndcp_data->mg.req_xid_block[sapi_index].vj.is_set; + + if (! sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) { + sndcp_data->mg.new_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_1; + } else { + sndcp_data->mg.new_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0; + } + + sndcp_data->mg.new_xid_block[sapi_index].vj.ntt = SNDCP_NTT_0; + sndcp_data->mg.new_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ; + sndcp_data->mg.new_xid_block[sapi_index].vj.pcomp1 = SNDCP_PCOMP1; + sndcp_data->mg.new_xid_block[sapi_index].vj.pcomp2 = SNDCP_PCOMP2; + + sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis |= + (sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis | + 1 << (snsm_activate_ind->nsapi)); + sndcp_data->mg.new_xid_block[sapi_index].vj.nsapis_set = TRUE; + +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1 = + snsm_activate_ind->comp_params.msid - 1; +#else + sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1 = + snsm_activate_ind->msid - 1; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.new_xid_block[sapi_index].vj.s0_m_1_set = TRUE; + /* + * Only used internally, not in XID block. + * Not: it is assumed that the indicated values match the existing ones! + */ +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.new_xid_block[sapi_index].vj.direction = + snsm_activate_ind->comp_params.hcomp; +#else + sndcp_data->mg.new_xid_block[sapi_index].vj.direction = + snsm_activate_ind->hcomp; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + +} /* mg_set_new_xid_block() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_req_xid_block ++------------------------------------------------------------------------------ +| Description : This procedure reads data from the given snsm_activate_ind and +| writes it to the service variable req_xid_block. +| +| Parameters : +| the SNSM_ACTIVATE_IND that caused the negotiation. +| ++------------------------------------------------------------------------------ +*/ +#ifdef SNDCP_UPM_INCLUDED +GLOBAL void mg_set_req_xid_block (T_SN_ACTIVATE_REQ* snsm_activate_ind) +#else +GLOBAL void mg_set_req_xid_block (T_SNSM_ACTIVATE_IND* snsm_activate_ind) +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ +{ + UBYTE sapi_index = 0; + BOOL vio; + TRACE_FUNCTION( "mg_set_req_xid_block" ); + sndcp_get_sapi_index(snsm_activate_ind->sapi, &sapi_index); + /* + * Set the version number. + */ + sndcp_data->mg.req_xid_block[sapi_index].version = SNDCP_XID_VERSION; + /* + * Set the V42.bis parameters, + */ +#ifdef TI_PS_FF_V42BIS + +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.req_xid_block[sapi_index].v42.is_set = + (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT); +#else + sndcp_data->mg.req_xid_block[sapi_index].v42.is_set = + (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.req_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_1; + sndcp_data->mg.req_xid_block[sapi_index].v42.ntt = SNDCP_NTT_0; + sndcp_data->mg.req_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42; + sndcp_data->mg.req_xid_block[sapi_index].v42.dcomp = SNDCP_DCOMP1; + + sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis = + 1 << (snsm_activate_ind->nsapi); + sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set = TRUE; +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.req_xid_block[sapi_index].v42.p0 = snsm_activate_ind->comp_params.dcomp; +#else + sndcp_data->mg.req_xid_block[sapi_index].v42.p0 = snsm_activate_ind->dcomp; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set = TRUE; + + /* + * Set p1 and p2 to default values. + */ + sndcp_data->mg.req_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1; + sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set = TRUE; + sndcp_data->mg.req_xid_block[sapi_index].v42.p2 = + SNDCP_V42_DEFAULT_P2; + sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set = TRUE; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.is_set = + #ifdef SNDCP_UPM_INCLUDED + (snsm_activate_ind->comp_params.dcomp != NAS_DCOMP_NEITHER_DIRECT); + #else + (snsm_activate_ind->dcomp != SNSM_COMP_NEITHER_DIRECT); + #endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p_bit = SNDCP_P_BIT_1; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.ntt = SNDCP_NTT_0; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.algo_type = SNDCP_XID_V42; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.dcomp = SNDCP_DCOMP1; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.nsapis = + 1 << (snsm_activate_ind->nsapi); + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.nsapis_set = TRUE; + #ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0 = snsm_activate_ind->comp_params.dcomp; + #else + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0 = snsm_activate_ind->dcomp; + #endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p0_set = TRUE; + + /* + * Set p1 and p2 to default values. + */ + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p1 = SNDCP_V42_DEFAULT_P1; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p1_set = TRUE; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p2 = + SNDCP_V42_DEFAULT_P2; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].v42.p2_set = TRUE; + + /* + * Set affected entities and dcomp/pcomp values. + */ + mg_set_ntt_comp(snsm_activate_ind->sapi); + + +#else /* !TI_PS_FF_V42BIS */ + + sndcp_data->mg.req_xid_block[sapi_index].v42.is_set = FALSE; + + sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis = 0; + + sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis_set = FALSE; + sndcp_data->mg.req_xid_block[sapi_index].v42.p0_set = FALSE; + + /* + * Set p1 and p2 to default values. + */ + sndcp_data->mg.req_xid_block[sapi_index].v42.p1 = SNDCP_V42_DEFAULT_P1; + sndcp_data->mg.req_xid_block[sapi_index].v42.p1_set = TRUE; + sndcp_data->mg.req_xid_block[sapi_index].v42.p2 = + SNDCP_V42_DEFAULT_P2; + sndcp_data->mg.req_xid_block[sapi_index].v42.p2_set = TRUE; + +#endif /* TI_PS_FF_V42BIS */ + + /* + * Set the Van Jacobson parameters. + * Note: + * If number of state slots is set to 0, do not request VJ in XID request. + */ +#ifdef SNDCP_UPM_INCLUDED + if (snsm_activate_ind->comp_params.msid == 0) { +#else + if (snsm_activate_ind->msid == 0) { +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.req_xid_block[sapi_index].vj.is_set = FALSE; + return; + } + + sndcp_data->mg.req_xid_block[sapi_index].vj.is_set = + #ifdef SNDCP_UPM_INCLUDED + (snsm_activate_ind->comp_params.hcomp != NAS_HCOMP_OFF); + #else + (snsm_activate_ind->hcomp != SNSM_COMP_NEITHER_DIRECT); + #endif /*#ifdef SNDCP_UPM_INCLUDED*/ + if (!sndcp_data->mg.req_xid_block[sapi_index].vj.is_set) { + return; + } + /* + * This function will only be called after snsm_activate_ind. So the + * user_xid_block will be set for the affected nsapi. + */ + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.p_bit = + SNDCP_P_BIT_0; + } else { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.p_bit = + SNDCP_P_BIT_1; + } + + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.ntt = + SNDCP_NTT_0; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.algo_type = + SNDCP_XID_VJ; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.pcomp1 = + SNDCP_PCOMP1; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.pcomp2 = + SNDCP_PCOMP2; + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.nsapis += + 1 << (snsm_activate_ind->nsapi); + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.nsapis_set = TRUE; +#ifdef SNDCP_UPM_INCLUDED + if (snsm_activate_ind->comp_params.msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = + SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1; + } else { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = + snsm_activate_ind->comp_params.msid - 1; + } +#else + if (snsm_activate_ind->msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = + SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1; + } else { + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1 = + snsm_activate_ind->msid - 1; + } +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.s0_m_1_set = TRUE; + /* + * Only used internally, not in XID block. + */ +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.direction = + snsm_activate_ind->comp_params.hcomp; +#else + sndcp_data->mg.user_xid_block[snsm_activate_ind->nsapi].vj.direction = + snsm_activate_ind->hcomp; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + + /* + * Set affected entities and dcomp/pcomp values. + */ + mg_set_ntt_comp(snsm_activate_ind->sapi); + + mg_detect_mode_clash ((USHORT) + (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis + + (1 << (snsm_activate_ind->nsapi))), + &vio); + if (vio) { + return; + } + + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) { + sndcp_data->mg.req_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0; + } else { + sndcp_data->mg.req_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_1; + } + sndcp_data->mg.req_xid_block[sapi_index].vj.ntt = SNDCP_NTT_0; + sndcp_data->mg.req_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ; + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp1 = SNDCP_PCOMP1; + sndcp_data->mg.req_xid_block[sapi_index].vj.pcomp2 = SNDCP_PCOMP2; + + /* + * All the nsapis that currently use the compressor and the new one + * shall be set in the nsapis field of the XID block. + */ + sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis = + (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis | + (1 << (snsm_activate_ind->nsapi))); + + sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis_set = TRUE; +#ifdef SNDCP_UPM_INCLUDED + if (snsm_activate_ind->comp_params.msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = + SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1; + } else { + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = + snsm_activate_ind->comp_params.msid - 1; + } +#else + if (snsm_activate_ind->msid > SNDCP_MAX_NUMBER_OF_VJ_SLOTS) { + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = + SNDCP_MAX_NUMBER_OF_VJ_SLOTS - 1; + } else { + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1 = + snsm_activate_ind->msid - 1; + } +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + sndcp_data->mg.req_xid_block[sapi_index].vj.s0_m_1_set = TRUE; + /* + * Only used internally, not in XID block. + */ +#ifdef SNDCP_UPM_INCLUDED + sndcp_data->mg.req_xid_block[sapi_index].vj.direction = + snsm_activate_ind->comp_params.hcomp; +#else + sndcp_data->mg.req_xid_block[sapi_index].vj.direction = + snsm_activate_ind->hcomp; +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Set affected entities and dcomp/pcomp values. + */ + mg_set_ntt_comp(snsm_activate_ind->sapi); + +} /* mg_set_req_xid_block() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_res_cur_xid_block ++------------------------------------------------------------------------------ +| Description : This procedure sets the service variables res_xid_block and +| cur_xid_block. The needed data comes from the service variable ind_xid_block, +| and from default settings. +| Note: if the indicated compressors do not match with compressors requested +| or currently used then they will be unset by adding them to the list of +| rejected compressors. +| +| +| Parameters : +| the affected sapi, +| the necessary bit length of an sdu that will later store the +| xid block derived from res_xid_block. +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_set_res_cur_xid_block (UBYTE sapi, USHORT* res_sdu_bit_len) +{ + UBYTE sapi_index = 0; + UBYTE nsapi = 0; + /* + * Which compressors are indicated? + */ + BOOL v42_ind, vj_ind; + /* + * Which compressors are possible? + * (The indicated set of nsapis must overlap with the + * currently used one.) + */ + BOOL v42_possible, vj_possible; + /* + * Is compressor going to rejected? In this case the compressor should not + * be requested. + */ + BOOL v42_rejected, vj_rejected; + + TRACE_FUNCTION( "mg_set_res_cur_xid_block" ); + + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_reset_xid_block(&(sndcp_data->mg.res_xid_block[sapi_index])); + + /* + * Set bit length to "only version", 3 bytes. + */ + *res_sdu_bit_len = 24; + /* + * Set the version number. + */ + sndcp_data->mg.res_xid_block[sapi_index].version = SNDCP_XID_VERSION; + + v42_ind = sndcp_data->mg.ind_xid_block[sapi_index].v42.is_set; + v42_possible = FALSE; + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((sndcp_data->mg.user_xid_block[nsapi].v42.nsapis & + sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) { + + U8 local_sapi = 0; + sndcp_get_nsapi_sapi(nsapi, &local_sapi); + if (local_sapi == sapi) { + v42_possible = TRUE; + } + } + } + + + if (v42_ind && ! v42_possible) { + sndcp_data->mg.res_xid_block[sapi_index].v42.is_set = FALSE; + mg_set_sapi_dntt_rej (sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + TRUE); + } + + mg_get_sapi_dntt_rej (sapi, + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt, + &v42_rejected); + + + if (v42_ind && ! v42_rejected) { + /* + * Data compression will be included, increment bit len (+ 10 bytes). + */ + *res_sdu_bit_len += 80; + + /* + * Set the V42.bis parameters, + */ + sndcp_data->mg.res_xid_block[sapi_index].v42.is_set = TRUE; + + sndcp_data->mg.res_xid_block[sapi_index].v42.p_bit = SNDCP_P_BIT_0; + + sndcp_data->mg.res_xid_block[sapi_index].v42.ntt = + sndcp_data->mg.ind_xid_block[sapi_index].v42.ntt; + + + sndcp_data->mg.res_xid_block[sapi_index].v42.algo_type = SNDCP_XID_V42; + + sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp = + sndcp_data->mg.ind_xid_block[sapi_index].v42.dcomp; + + /* + * Set the 'nsapis' parameter in res_xid_block: + * Check rules in 4.65, subclause 6.8.1, compare with cur_xid_block. + */ + mg_set_xid_nsapis(sapi, MG_XID_V42_NSAPIS); + + /* + * It is assumed that the values desired by the user / the + * values possible with the current implementation are written in + * req_xid_block, the responded values are then the minimum of + * req and ind values: + */ + /* + * For the direction parameter p0 take the logical AND: + */ + sndcp_data->mg.res_xid_block[sapi_index].v42.p0 = + (sndcp_data->mg.req_xid_block[sapi_index].v42.p0 & + sndcp_data->mg.ind_xid_block[sapi_index].v42.p0); + sndcp_data->mg.res_xid_block[sapi_index].v42.p0_set = TRUE; + + /* + * For p1 and p2 take minimum. + */ + sndcp_data->mg.res_xid_block[sapi_index].v42.p1 = + (sndcp_data->mg.req_xid_block[sapi_index].v42.p1 < + sndcp_data->mg.ind_xid_block[sapi_index].v42.p1)? + sndcp_data->mg.req_xid_block[sapi_index].v42.p1 : + sndcp_data->mg.ind_xid_block[sapi_index].v42.p1; + sndcp_data->mg.res_xid_block[sapi_index].v42.p1_set = TRUE; + + sndcp_data->mg.res_xid_block[sapi_index].v42.p2 = + (sndcp_data->mg.req_xid_block[sapi_index].v42.p2 < + sndcp_data->mg.ind_xid_block[sapi_index].v42.p2)? + sndcp_data->mg.req_xid_block[sapi_index].v42.p2 : + sndcp_data->mg.ind_xid_block[sapi_index].v42.p2; + sndcp_data->mg.res_xid_block[sapi_index].v42.p2_set = TRUE; + + } /* v42.is_set */ + + + /* + * Header compression, + */ + + + vj_ind = sndcp_data->mg.ind_xid_block[sapi_index].vj.is_set; + vj_possible = FALSE; + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if ((sndcp_data->mg.user_xid_block[nsapi].vj.nsapis & + sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis) > 0) { + + U8 local_sapi = 0; + sndcp_get_nsapi_sapi(nsapi, &local_sapi); + if (local_sapi == sapi) { + vj_possible = TRUE; + } + } + } + + if (vj_ind && ! vj_possible) { + sndcp_data->mg.res_xid_block[sapi_index].vj.is_set = FALSE; + mg_set_sapi_pntt_rej (sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + TRUE); + } + + mg_get_sapi_pntt_rej (sapi, + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt, + &vj_rejected); + + if (vj_ind && ! vj_rejected) { + /* + * Header compression will be included, increment bit len (+ 7 bytes). + */ + *res_sdu_bit_len += 56; + + /* + * Set the VJ parameters, + */ + sndcp_data->mg.res_xid_block[sapi_index].vj.is_set = TRUE; + + sndcp_data->mg.res_xid_block[sapi_index].vj.p_bit = SNDCP_P_BIT_0; + + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt = + sndcp_data->mg.ind_xid_block[sapi_index].vj.ntt; + + sndcp_data->mg.res_xid_block[sapi_index].vj.algo_type = SNDCP_XID_VJ; + + if (sndcp_data->mg.ind_xid_block[sapi_index].vj.p_bit == SNDCP_P_BIT_1) { + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1 = + sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp1; + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2 = + sndcp_data->mg.ind_xid_block[sapi_index].vj.pcomp2; + } else { + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1 = + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp1; + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2 = + sndcp_data->mg.cur_xid_block[sapi_index].vj.pcomp2; + } + + /* + * Set the 'nsapis' parameter in res_xid_block: + * Check rules in 4.65, subclause 6.8.1, compare with cur_xid_block. + * State slots and direction are also set here. + */ + mg_set_xid_nsapis(sapi, MG_XID_VJ_NSAPIS); + + + } /* vj.is_set */ + + + /* + * Set affected entities and dcomp/pcomp values. + */ + if (v42_ind && v42_possible) { + mg_set_sapi_dntt_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].v42.ntt, + MG_ASSIGNED); + + mg_set_sapi_dcomp_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp, + MG_ASSIGNED); + mg_set_sapi_dcomp_dntt(sapi, + sndcp_data->mg.res_xid_block[sapi_index].v42.dcomp, + sndcp_data->mg.res_xid_block[sapi_index].v42.ntt); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) { + mg_set_sapi_dntt_nsapi(sapi, + sndcp_data->mg.res_xid_block[sapi_index].v42.ntt, + nsapi, + TRUE); + } /* if nsapi is selected */ + } /* for loop over all nsapis */ + + } + /* + * If VJ is indicated and possible, switch on compressor. + */ + if (vj_ind && vj_possible) { + mg_set_sapi_pntt_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt, + MG_ASSIGNED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1, + MG_ASSIGNED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2, + MG_ASSIGNED); + mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt); + mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) { + mg_set_sapi_pntt_nsapi(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt, + nsapi, + TRUE); + } /* if nsapi is selected */ + } /* for loop over all nsapis */ + } + + /* + * If VJ has been switched on and is now indicated to be switched off: + * switch off compressor. + */ + if (vj_ind + && + sndcp_data->mg.ind_xid_block[sapi_index].vj.nsapis == 0 + && + sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis > 0) + { + mg_set_sapi_pntt_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt, + MG_UNASSIGNED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1, + MG_UNASSIGNED); + mg_set_sapi_pcomp_state(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2, + MG_UNASSIGNED); +/* mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp1, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt); + mg_set_sapi_pcomp_pntt(sapi, + sndcp_data->mg.res_xid_block[sapi_index].vj.pcomp2, + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt); +*/ + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (((1 << nsapi) & sndcp_data->mg.ind_xid_block[sapi_index].v42.nsapis) > 0) { + mg_set_sapi_pntt_nsapi(sapi, + sndcp_data->mg.cur_xid_block[sapi_index].vj.ntt, + nsapi, + FALSE); + } /* if nsapi is selected */ + } /* for loop over all nsapis */ + } + + + /* + * Add same values for cur_xid_block. + */ + + if (sndcp_data->mg.res_xid_block[sapi_index].v42.is_set) { + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis = + sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis; + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p0_set) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.p0 = + sndcp_data->mg.res_xid_block[sapi_index].v42.p0; + } + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p1_set) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.p1 = + sndcp_data->mg.res_xid_block[sapi_index].v42.p1; + } + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.p2_set) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.p2 = + sndcp_data->mg.res_xid_block[sapi_index].v42.p2; + } + } else { + sndcp_data->mg.cur_xid_block[sapi_index].v42 = + sndcp_data->mg.res_xid_block[sapi_index].v42; + } + } + + if (sndcp_data->mg.res_xid_block[sapi_index].vj.is_set) { + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set) { + sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis = + sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis; + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1_set) { + sndcp_data->mg.cur_xid_block[sapi_index].vj.s0_m_1 = + sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1; + } + } else { + sndcp_data->mg.cur_xid_block[sapi_index].vj = + sndcp_data->mg.res_xid_block[sapi_index].vj; + } + } + + + if (vj_rejected) { + sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis = 0; + } + if (sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis == 0) { + sndcp_data->mg.cur_xid_block[sapi_index].vj.is_set = FALSE; + } + + if (v42_rejected) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis = 0; + } + if (sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis == 0) { + sndcp_data->mg.cur_xid_block[sapi_index].v42.is_set = FALSE; + } + + sig_mg_cia_new_xid(& sndcp_data->mg.cur_xid_block[sapi_index]); + + +} /* mg_set_res_cur_xid_block */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_res_xid_params ++------------------------------------------------------------------------------ +| Description : This procedure fills the XID block. It is implementation +| dependent. In the current version V42bis and VanJacobson +| header compression are applied. +| +| Parameters : +| the sdu that will be filled, +| Post : Reset arrays with reject information to all FALSE. +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_set_res_xid_params (T_sdu* sdu, UBYTE sapi) +{ + /* + * Byte index in destination sdu. + */ + UBYTE index = 3; + UBYTE type_2_header_index = 0; + UBYTE sapi_index = 0; + UBYTE ntt = 0; + BOOL type_1_header_set = FALSE; + BOOL type_2_header_set = FALSE; + TRACE_FUNCTION( "mg_set_res_xid_params" ); + sndcp_get_sapi_index(sapi, &sapi_index); + /* + * Set the values for parameter type 0 (version number). + */ + sdu->buf[0] = SNDCP_XID_PARAM_TYPE_0; + /*lint -e{415} (Warning -- access of out-of-bounds pointer)*/ + sdu->buf[1] = SNDCP_XID_0_LEN; + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + sdu->buf[2] = + sndcp_data->mg.res_xid_block[sapi_index].version; + + sdu->l_buf = 3 * 8; + sdu->o_buf = 0; + /* + * Set the values for data compression, if necessary. + */ + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + if (sndcp_data->mg.res_xid_block[sapi_index].v42.is_set) { + sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1; + sdu->buf[4] = SNDCP_XID_1_LEN_RES; + sdu->buf[5] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p_bit << 7) + + sndcp_data->mg.res_xid_block[sapi_index].v42.ntt; + sdu->buf[6] = SNDCP_XID_V42_LEN_RES; + sdu->buf[7] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis >> 8); + sdu->buf[8] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.nsapis & 0xff); + sdu->buf[9] = sndcp_data->mg.res_xid_block[sapi_index].v42.p0; + sdu->buf[10] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p1 >> 8); + sdu->buf[11] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].v42.p1 & 0xff); + sdu->buf[12] = sndcp_data->mg.res_xid_block[sapi_index].v42.p2; + + index = 13; + sdu->l_buf = 13 * 8; + + type_1_header_set = TRUE; + } + /* + * Add rejected data compression entities. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_dntt_rej(sapi, ntt, &rej); + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + if (rej) { + if (! type_1_header_set) { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_1; + index++; + sdu->buf[index] = 0; + index++; + type_1_header_set = TRUE; + sdu->l_buf += 16; + } + + sdu->buf[index] = ntt; + index++; + /* + * Length of field. + */ + sdu->buf[index] = 2; + index++; + /* + * Set 2 'nsapis' octets to 0. + */ + sdu->buf[index] = 0; + index++; + sdu->buf[index] = 0; + index++; + /* + * Increment sdu length. + */ + sdu->l_buf = sdu->l_buf + 32; + /* + * Increment parameter type 1 length octet. + */ + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + sdu->buf[4] += 4; + } + } + type_2_header_index = index; + + /* + * Set the values for header compression, if requested. + */ + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + if (sndcp_data->mg.res_xid_block[sapi_index].vj.is_set) { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2; + index++; + sdu->buf[index] = SNDCP_XID_2_LEN_RES; + index++; + sdu->buf[index] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.p_bit << 7) + + sndcp_data->mg.res_xid_block[sapi_index].vj.ntt; + index++; + sdu->buf[index] = SNDCP_XID_VJ_LEN_RES; + index++; + sdu->buf[index] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis >> 8); + index++; + sdu->buf[index] = + (UBYTE)(sndcp_data->mg.res_xid_block[sapi_index].vj.nsapis & 0xff); + index++; + sdu->buf[index] = + sndcp_data->mg.res_xid_block[sapi_index].vj.s0_m_1; + index++; + + sdu->l_buf = sdu->l_buf + 7 * 8; + + type_2_header_set = TRUE; + } + /* + * Add rejected header compression entities. + */ + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_pntt_rej(sapi, ntt, &rej); + if (rej) { + if (! type_2_header_set) { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2; + index++; + sdu->buf[index] = 0; + index++; + type_2_header_set = TRUE; + sdu->l_buf += 16; + } + sdu->buf[index] = ntt; + index++; + /* + * Length of field. + */ + sdu->buf[index] = 2; + index++; + /* + * Set 2 'nsapis' octets to 0. + */ + sdu->buf[index] = 0; + index++; + sdu->buf[index] = 0; + index++; + /* + * Increment sdu length. + */ + sdu->l_buf = sdu->l_buf + 32; + /* + * Increment parameter type 2 length octet. + */ + sdu->buf[type_2_header_index + 1] += 4; + } + } + /* + * Set sdu offset to 0. + */ + sdu->o_buf = 0; + /* + * Reset the arrays with rejected params to all FALSE. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE; + sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE; + } + +} /* mg_set_res_xid_params() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_set_xid_params ++------------------------------------------------------------------------------ +| Description : This procedure fills the XID block. It is implementation +| dependent. In the current version V42bis and VanJacobson +| header compression are applied. +| +| Parameters : +| sapi and sdu from the LL_XID_REQ that will be filled and +| xid_block that defines the desired compressors +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_set_xid_params (UBYTE sapi, T_sdu* sdu, T_XID_BLOCK xid_block) +{ + /* + * Byte index in destination sdu. + */ + UBYTE index = 3; + UBYTE sapi_index = 0; + UBYTE ntt = 0; + BOOL type_1_header_set = FALSE; + BOOL type_2_header_set = FALSE; + UBYTE type_2_header_index = 0; + UBYTE type_1_header_index = 3; + USHORT p1 = SNDCP_V42_DEFAULT_P1; + TRACE_FUNCTION( "mg_set_xid_params" ); + sndcp_get_sapi_index(sapi, &sapi_index); + /* + * Set the values for parameter type 0 (version number). + */ + sdu->buf[0] = SNDCP_XID_PARAM_TYPE_0; + /*lint -e{415} (Warning -- access of out-of-bounds pointer)*/ + sdu->buf[1] = SNDCP_XID_0_LEN; + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + sdu->buf[2] = SNDCP_XID_VERSION; + + sdu->l_buf = 24; /* 3 * 8 */ + sdu->o_buf = 0; + /* + * Set the values for data compression, if necessary. + */ + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + if (xid_block.v42.is_set && + #ifdef SNDCP_UPM_INCLUDED + xid_block.v42.p0 != NAS_DCOMP_OFF && + #else + xid_block.v42.p0 != SNSM_COMP_NEITHER_DIRECT && + #endif /*#ifdef SNDCP_UPM_INCLUDED*/ + xid_block.v42.nsapis_set && + xid_block.v42.nsapis > 0) { + + if (xid_block.v42.p_bit > 0) { + sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1; + sdu->buf[4] = SNDCP_XID_1_LEN; + sdu->buf[5] = (UBYTE)(xid_block.v42.p_bit << 7) + xid_block.v42.ntt; + sdu->buf[6] = xid_block.v42.algo_type; + sdu->buf[7] = SNDCP_XID_V42_LEN; + sdu->buf[8] = (UBYTE)(xid_block.v42.dcomp << 4); + sdu->buf[9] = (UBYTE)(xid_block.v42.nsapis >> 8); + sdu->buf[10] = (UBYTE)(xid_block.v42.nsapis & 0xff); + sdu->buf[11] = xid_block.v42.p0; + /* + * P1, P2 + */ + sdu->buf[12] = (p1 & 0xff00) >> 8; + sdu->buf[13] = p1 & 0x00ff; + sdu->buf[14] = SNDCP_V42_DEFAULT_P2; + + index = 15; + sdu->l_buf = 15 * 8; + } else { + sdu->buf[3] = SNDCP_XID_PARAM_TYPE_1; + sdu->buf[4] = SNDCP_XID_1_LEN_RES; + sdu->buf[5] = xid_block.v42.ntt; + sdu->buf[6] = SNDCP_XID_V42_LEN_RES; + sdu->buf[7] = (UBYTE)(xid_block.v42.nsapis >> 8); + sdu->buf[8] = (UBYTE)(xid_block.v42.nsapis & 0xff); + sdu->buf[9] = xid_block.v42.p0; + /* + * P1, P2 + */ + sdu->buf[10] = (p1 & 0xff00) >> 8; + sdu->buf[11] = p1 & 0x00ff; + sdu->buf[12] = SNDCP_V42_DEFAULT_P2; + + index = 13; + sdu->l_buf = 13 * 8; + + } + } + type_2_header_index = index; + /* + * Set the values for header compression, if requested. + */ + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + if (xid_block.vj.is_set && + #ifdef SNDCP_UPM_INCLUDED + xid_block.vj.direction != NAS_HCOMP_OFF && + #else + xid_block.vj.direction != SNSM_COMP_NEITHER_DIRECT && + #endif /*#ifdef SNDCP_UPM_INCLUDED*/ + xid_block.vj.nsapis_set && + xid_block.vj.nsapis > 0) { + + if (xid_block.vj.p_bit > 0) { + + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2; + sdu->buf[index + 1] = SNDCP_XID_2_LEN; + sdu->buf[index + 2] = + (UBYTE)(xid_block.vj.p_bit << 7) + xid_block.vj.ntt; + sdu->buf[index + 3] = SNDCP_XID_VJ; + sdu->buf[index + 4] = SNDCP_XID_VJ_LEN; + sdu->buf[index + 5] = + (UBYTE)(xid_block.vj.pcomp1 << 4) + xid_block.vj.pcomp2; + sdu->buf[index + 6] = + (UBYTE)(xid_block.vj.nsapis >> 8); + sdu->buf[index + 7] = + (UBYTE)(xid_block.vj.nsapis & 0xff); + sdu->buf[index + 8] = xid_block.vj.s0_m_1; + + sdu->l_buf = sdu->l_buf + 9 * 8; + + type_2_header_set = TRUE; + } else { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2; + sdu->buf[index + 1] = SNDCP_XID_2_LEN_RES; + sdu->buf[index + 2] = xid_block.vj.ntt; + + sdu->buf[index + 3] = SNDCP_XID_VJ_LEN_RES; + + sdu->buf[index + 4] = + (UBYTE)(xid_block.vj.nsapis >> 8); + sdu->buf[index + 5] = + (UBYTE)(xid_block.vj.nsapis & 0xff); + sdu->buf[index + 6] = xid_block.vj.s0_m_1; + + sdu->l_buf = sdu->l_buf + 7 * 8; + + type_2_header_set = TRUE; + } + } + /* + * Add rejected data compression entities. + */ + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_dntt_rej(sapi, ntt, &rej); + if (rej) { + if (! type_1_header_set) { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_1; + index++; + sdu->buf[index] = 0; + index++; + type_1_header_set = TRUE; + sdu->l_buf += 16; + } + sdu->buf[index] = ntt; + index++; + /* + * Length of field. + */ + sdu->buf[index] = 2; + index++; + /* + * Set 2 'nsapis' octets to 0. + */ + sdu->buf[index] = 0; + index++; + sdu->buf[index] = 0; + index++; + /* + * Increment sdu length. + */ + sdu->l_buf = sdu->l_buf + 32; + /* + * Increment parameter type 2 length octet. + */ + /*lint -e{415, 416} (Warning -- access/creation of out-of-bounds pointer)*/ + sdu->buf[type_1_header_index + 1] += 4; + } + } /* for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) */ + /* + * Add rejected header compression entities. + */ + /*lint -e{661, 662} (Warning -- Possible access/creation of out-of-bounds pointer)*/ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + BOOL rej = FALSE; + mg_get_sapi_pntt_rej(sapi, ntt, &rej); + if (rej) { + if (! type_2_header_set) { + sdu->buf[index] = SNDCP_XID_PARAM_TYPE_2; + index++; + sdu->buf[index] = 0; + index++; + type_2_header_set = TRUE; + sdu->l_buf += 16; + } + sdu->buf[index] = ntt; + index++; + /* + * Length of field. + */ + sdu->buf[index] = 2; + index++; + /* + * Set 2 'nsapis' octets to 0. + */ + sdu->buf[index] = 0; + index++; + sdu->buf[index] = 0; + index++; + /* + * Increment sdu length. + */ + sdu->l_buf = sdu->l_buf + 32; + /* + * Increment parameter type 2 length octet. + */ + sdu->buf[type_2_header_index + 1] += 4; + } + } /* for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) */ + /* + * Set sdu offset to 0. + */ + sdu->o_buf = 0; + /* + * Reset the arrays with rejected params to all FALSE. + */ + for (ntt = 0; ntt < MG_MAX_ENTITIES; ntt++) { + sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][ntt] = FALSE; + sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][ntt] = FALSE; + } + +} /* mg_set_xid_params() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_del_comp_pdus_ack ++------------------------------------------------------------------------------ +| Description : The function mg_del_comp_pdus_ack() +| GSM 4.65, 5.1.2.7: +| "compressed N-PDUs queuing to be forwarded to the affected +| SAPI are deleted from the SNDCP layer." +| Assumption: It is assumed here that acknowledged and +| unacknowledged npdus are deleted the same. +| +| Parameters : UBYTE sapi: the affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_del_comp_pdus_ack (UBYTE sapi) +{ + UBYTE nsapi = 0; + + TRACE_FUNCTION( "mg_del_comp_pdus_ack" ); + + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + UBYTE sp = 0; + sndcp_get_nsapi_sapi(nsapi, &sp); + if (sp == sapi) { + sig_mg_cia_delete_npdus(nsapi); + sig_mg_su_delete_pdus(nsapi, sapi); + sig_mg_sua_delete_pdus(nsapi, sapi, TRUE); + sig_mg_sd_delete_npdus(nsapi, sapi); + sig_mg_sda_delete_npdus(nsapi, sapi); + } + } +} /* mg_del_comp_pdus_ack() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_delete_npdus ++------------------------------------------------------------------------------ +| Description : The function mg_delete_npdus() sends signals to all affected +| services to delete the buffered npdus. +| +| Parameters : UBYTE nsapi: the affected nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_delete_npdus (UBYTE nsapi) +{ + UBYTE sapi = 0; + TRACE_FUNCTION( "mg_delete_npdus" ); + sndcp_get_nsapi_sapi(nsapi, &sapi); + + sig_mg_cia_delete_npdus(nsapi); + sig_mg_su_delete_pdus(nsapi, sapi); + sig_mg_sua_delete_pdus(nsapi, sapi, TRUE); + sig_mg_sd_delete_npdus(nsapi, sapi); + sig_mg_sda_delete_npdus(nsapi, sapi); + + sig_mg_nu_delete_npdus(nsapi); + +} /* mg_delete_npdus() */ + + +/* ++------------------------------------------------------------------------------ +| Function : mg_suspend_affected_nus ++------------------------------------------------------------------------------ +| Description : Suspends all nu service instances affected by XID negotiation +| Sets service variable 'suspended_nsapis'. +| +| Parameters : sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_suspend_affected_nus (UBYTE sapi) { + UBYTE nsapi = 0; + UBYTE sapi_index = 0; + TRACE_FUNCTION( "mg_resume_affected_nus" ); + sndcp_get_sapi_index(sapi, &sapi_index); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + if (1 << nsapi & sndcp_data->mg.req_xid_block[sapi_index].vj.nsapis || + 1 << nsapi & sndcp_data->mg.cur_xid_block[sapi_index].vj.nsapis || + 1 << nsapi & sndcp_data->mg.req_xid_block[sapi_index].v42.nsapis || + 1 << nsapi & sndcp_data->mg.cur_xid_block[sapi_index].v42.nsapis) { + + sndcp_data->mg.suspended_nsapis |= (1 << nsapi); + sig_mg_nu_suspend(nsapi); + } + } +} /* mg_suspend_affected_nus() */ + + + + + + +/* + * Getters and setters for the organizing arrays. + */ +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_dntt_rej ++------------------------------------------------------------------------------ +| Description : The procedures informs about if a given data +| compression entity on a given SAPI is to be rejected in +| LL_XID_REQ because it cannot be set up. +| +| Parameters : FPAR IN sapi UBYTE, +| IN dntt UBYTE, +| IN/OUT rej BOOL +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_get_sapi_dntt_rej (UBYTE sapi, UBYTE dntt, BOOL* rej) +{ + TRACE_FUNCTION( "mg_get_sapi_dntt_rej" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *rej = sndcp_data->mg.sapi_dntt_rej_ra[sapi_index][dntt]; + } +} /* mg_get_sapi_dntt_rej() */ + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_pntt_rej ++------------------------------------------------------------------------------ +| Description : The procedures informs about if a given header +| compression entity on a given SAPI is to be rejected in +| LL_XID_REQ because it cannot be set up. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN/OUT rej BOOL +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_get_sapi_pntt_rej (UBYTE sapi, UBYTE pntt, BOOL* rej) +{ + TRACE_FUNCTION( "mg_get_sapi_pntt_rej" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *rej = sndcp_data->mg.sapi_pntt_rej_ra[sapi_index][pntt]; + } +} /* mg_get_sapi_pntt_rej() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_pntt_nsapi ++------------------------------------------------------------------------------ +| Description : The procedure informs if a given nsapi uses a given pntt on a +| given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pntt UBYTE, +| IN nsapi UBYTE, +| IN/OUT used BOOL +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_get_sapi_pntt_nsapi (UBYTE sapi, UBYTE pntt, UBYTE nsapi, BOOL* used) +{ + TRACE_FUNCTION( "mg_get_sapi_pntt_nsapi" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *used = sndcp_data->mg.sapi_pntt_nsapi_set_ra[sapi_index][pntt][nsapi]; + } +} /* mg_get_sapi_pntt_nsapi() */ + + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_get_sapi_pcomp_pntt ++------------------------------------------------------------------------------ +| Description : The procedures indicates the pntt assigned to a given pcomp +| for a given sapi. +| +| Parameters : FPAR IN sapi UBYTE, +| IN pcomp UBYTE, +| IN/OUT dntt UBYTE +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_get_sapi_pcomp_pntt (UBYTE sapi, UBYTE pcomp, UBYTE* pntt) +{ + TRACE_FUNCTION( "mg_get_sapi_pcomp_pntt" ); + { + UBYTE sapi_index = 0; + sndcp_get_sapi_index(sapi, &sapi_index); + *pntt = sndcp_data->mg.sapi_pcomp_pntt_ra[sapi_index][pcomp]; + } +} /* mg_get_sapi_pcomp_pntt() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : mg_xid_cnf_ok_res ++------------------------------------------------------------------------------ +| Description : +| After an LL_XID_REQ has been sent there are contexts in state MG_XID. +| These are now reset after reception of the LL_XID_CNF. +| The "applicable nsapis" in req_xid_block.v42 and req_xid_block.vj, each one +| only once. +| SIG_MG_NU_RESET(nsapi, discard_ready) is used. +| In every nu instance: N-PDU number is set to 0 for this instance and an +| SN_UNITREADY_IND is sent. State is set to NU_UNACK_SU_RECEPTIVE +| Then the SNSM_ACTIVATE_RES is sent for each one of these. +| +| Parameters : affected sapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_xid_cnf_ok_res (UBYTE sapi) +{ + UBYTE nsapi = 0; + + TRACE_FUNCTION( "mg_xid_cnf_ok_res" ); + for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi++) { + USHORT nsapi_state = MG_IDLE; + USHORT sapi_state = MG_IDLE; + UBYTE sapi_index = 0; + UBYTE func_sapi = 0; + sndcp_get_nsapi_sapi(nsapi, &func_sapi); + if (func_sapi != sapi) { + continue; + } + sndcp_get_sapi_index(sapi, &sapi_index); + sndcp_get_nsapi_state(nsapi, &nsapi_state); + sndcp_get_sapi_state(func_sapi, &sapi_state); + + + if (((sapi_state & MG_XID_NEC) > 0) + && + ((sapi_state & MG_REL) == 0)) { + mg_resend_xid_if_nec(sapi); + + sndcp_get_sapi_state(func_sapi, &sapi_state); + /* + * If now XID is sent, no further actions for this nsapi. + */ + if ((sapi_state & MG_XID) > 0) { + continue; + } + + } else if ((nsapi_state & MG_ACT) > 0 && + (sapi_state & MG_EST) == 0) { + + BOOL ack = FALSE; + + sndcp_get_nsapi_ack(nsapi, &ack); + /* + * Open DTI connection. + */ +#ifndef SNDCP_UPM_INCLUDED + mg_dti_open(nsapi); +#endif + if (ack) { + sig_mg_nu_reset_ack(nsapi, 0, 0, FALSE); + sig_mg_sda_getdata(sapi, nsapi); + } else { + sig_mg_nu_reset(nsapi, FALSE); + sig_mg_sd_getunitdata(sapi, nsapi); + } + + if ((sapi_state & MG_XID) == 0) { + mg_send_snsm_activate_res(nsapi); + /* + * Set nsapi state to MG_IDLE. + */ + sndcp_unset_nsapi_state(nsapi, MG_ACT); + } + } /* if state is MG_ACT and not MG_EST */ + + if ((nsapi_state & MG_DEACT) > 0) { + + USHORT local_sapi_state = MG_IDLE; + + sndcp_get_sapi_state(sapi, &local_sapi_state); + + if ((local_sapi_state & + (MG_REL_NEC_LOC + MG_REL_NEC_PEER + MG_XID_NEC + MG_XID)) + == 0) + { + /* + * No LL_RELEASE_REQ necessary. Notify sndcp. + */ +#ifdef SNDCP_UPM_INCLUDED + PALLOC(snsm_deactivate_res, SN_DEACTIVATE_CNF); +#else + PALLOC(snsm_deactivate_res, SNSM_DEACTIVATE_RES); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Now the NSAPI is not in use anymore: + */ + sndcp_set_nsapi_used(nsapi, FALSE); + sndcp_set_nsapi_ack(nsapi, FALSE); + + snsm_deactivate_res->nsapi = nsapi; + sndcp_unset_nsapi_state(nsapi, MG_DEACT); +#ifdef SNDCP_UPM_INCLUDED + PSEND(hCommUPM, snsm_deactivate_res); +#else + PSEND(hCommSM, snsm_deactivate_res); +#endif /*#ifdef SNDCP_UPM_INCLUDED*/ + /* + * Resume nsapi. + */ + mg_resume_affected_nus(sapi); + + } else if ((local_sapi_state & (MG_REL_NEC_LOC + MG_REL_NEC_PEER)) > 0) { + /* + * LL_RELEASE_REQ must be sent. + */ + + PALLOC(ll_release_req, LL_RELEASE_REQ); + + sndcp_unset_sapi_state(sapi, MG_REL_NEC_LOC); + ll_release_req->sapi = sapi; + ll_release_req->local = TRUE; + /* + * Set the "state" for the affected and sapi to MG_REL_PENDING. + */ + sndcp_set_sapi_state(sapi, MG_REL); + + PSEND(hCommLLC, ll_release_req); + } else { + + UBYTE local_sapi = 0; + UBYTE local_nsapi = 0; + BOOL local_nec = FALSE; + for (local_nsapi = 0; + local_nsapi < SNDCP_NUMBER_OF_NSAPIS; + local_nsapi++) { + + sndcp_get_nsapi_sapi(local_nsapi, &local_sapi); + if (sapi == local_sapi) { + /* + * is compressor deactivation necessary? + */ + sndcp_get_nsapi_state(local_nsapi, &nsapi_state); + if ((nsapi_state & MG_DEACT) > 0) { + mg_is_rel_comp_nec(local_nsapi, &local_nec); + } + } + } + + /* + * Negotiate possible deactivation of compressors. + */ + if (local_nec) { + mg_send_xid_req_del(sapi); + } + } + + } + + } + +} /* mg_xid_cnf_ok_res */ + + +#ifdef TI_DUAL_MODE +/* ++------------------------------------------------------------------------------ +| Function : mg_get_unsent_unconfirmed_npdus ++------------------------------------------------------------------------------ +| Description : This procedure retrieves any unsent or unconfirmed acknowledged +| NPDU from SNDCP's internal buffers. ANY retrieved NPDU is packed +| the primitive SN_GET_PENDING_PDU_CNF data. +| +| Parameters : nsapi, pointer to the primitive. +| ++------------------------------------------------------------------------------ +*/ +GLOBAL T_SN_GET_PENDING_PDU_CNF* mg_get_unsent_unconfirmed_npdus + (U8 nsapi, + T_SN_GET_PENDING_PDU_CNF* sn_get_pending_pdu_cnf) +{ + + int count = 0; + U8 used_sapi=0, sapi_index=0; + T_NPDU_BUFFER* help = NULL; + + TRACE_FUNCTION( "mg_get_unsent_unconfirmed_npdus" ); + + /* + * set service instance according to nsapi in primitive + */ + sndcp_data->nu = & sndcp_data->nu_base[nsapi]; + + /* + * Find number of unconfirmed NPDUs + */ + help = sndcp_data->nu->first_buffered_npdu; + while(help != NULL) + { + count++; + help = help->next; + } + + sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2 = + (T_SN_desc_list2*)DRP_ALLOC( count * sizeof( T_SN_desc_list2 ), 0 ); + + sn_get_pending_pdu_cnf->ul_pdus[nsapi].nsapi = nsapi; + sn_get_pending_pdu_cnf->ul_pdus[nsapi].dl_sequence_number = + sndcp_data->nu->rec_npdu_number_ack; + sn_get_pending_pdu_cnf->ul_pdus[nsapi].c_desc_list2 = count; + + count = 0; + + /* + * Check if there are buffered any acknowledged type NPDUs. + */ + help = sndcp_data->nu->first_buffered_npdu; + while(help != NULL) + { + + sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2[count].first = + help->sn_data_req->desc_list2.first; + sn_get_pending_pdu_cnf->ul_pdus[nsapi].ptr_desc_list2[count].list_len = + help->sn_data_req->desc_list2.list_len; + count++; + help = help->next; + } + return sn_get_pending_pdu_cnf; +} + +/* ++------------------------------------------------------------------------------ +| Function : mg_clean_ack_npdu_queues_leave_data ++------------------------------------------------------------------------------ +| Description : This procedure deletes SNDCP's internal buffers containing +| unconfirmed acknowledged type NPDU's. +| The data stored in the queues are not deleted. +| +| Parameters : nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_clean_ack_npdu_queues_leave_data(U8 nsapi) +{ + + U8 used_sapi=0, sapi_index=0; + T_NPDU_BUFFER* help = NULL; + T_SN_DATA_REQ* sn_data_req = NULL; + + TRACE_FUNCTION( "mg_clean_ack_npdu_queues_leave_data" ); + + /* + * set service instance according to sapi + */ + sndcp_get_nsapi_sapi(nsapi, &used_sapi); + sndcp_get_sapi_index(used_sapi, &sapi_index); + sndcp_data->sua = & sndcp_data->sua_base[sapi_index]; + + if (sndcp_data->sua->sn_data_q_write != sndcp_data->sua->sn_data_q_read) + { + /* + * remove unhandled sn_data_req from queue. + */ + sn_data_req = sndcp_data->sua->sn_data_q[sndcp_data->sua->sn_data_q_read]; + FREE(sn_data_req); + } + + /* + * set service instance according to nsapi + */ + + sndcp_data->nu = & sndcp_data->nu_base[nsapi]; + + /* + * clean buffer with unconfirmed NPDUs + */ + + while(sndcp_data->nu->first_buffered_npdu != NULL) + { + help = sndcp_data->nu->first_buffered_npdu; + sndcp_data->nu->first_buffered_npdu = help->next; + MFREE(help->sn_data_req); + MFREE(help); + } +} + + +/* ++------------------------------------------------------------------------------ +| Function : mg_clean_unack_npdu_queues_including_data ++------------------------------------------------------------------------------ +| Description : This procedure deletes SNDCP's internal buffers containing +| unacknowledged type NPDU's. +| The data stored in the queues are also deleted. +| +| Parameters : nsapi +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void mg_clean_unack_npdu_queues_including_data(U8 nsapi) +{ + /* + * Delete affected N-PDUS from sn_unitdata_q. + */ + BOOL still = TRUE; + U8 index = sndcp_data->su->sn_unitdata_q_read; + + while (still) + { + if (index == sndcp_data->su->sn_unitdata_q_write) { + break; + } + if (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) { + /* + * The index for the prims to be shifted when 1 entry is deleted. + */ + U8 i = 0; + + if (sndcp_data->su->sn_unitdata_q[index] != NULL) { + PFREE_DESC2(sndcp_data->su->sn_unitdata_q[index]); + sndcp_data->su->sn_unitdata_q[index] = NULL; + } + + for (i = index; + i != sndcp_data->su->sn_unitdata_q_write; + i = (i + 1) % SN_UNITDATA_Q_LEN) + { + sndcp_data->su->sn_unitdata_q[i] = + sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN]; + + sndcp_data->su->sn_unitdata_q[(i + 1) % SN_UNITDATA_Q_LEN]=NULL; + } + sndcp_data->su->sn_unitdata_q_write = + (sndcp_data->su->sn_unitdata_q_write - 1 + + SN_UNITDATA_Q_LEN) % SN_UNITDATA_Q_LEN; + } + else + { + index = (index + 1) % SN_UNITDATA_Q_LEN; + } /* else (sndcp_data->su->sn_unitdata_q[index]->nsapi == nsapi) */ + } +} + +/* ++------------------------------------------------------------------------------ +| Function : sm_make_test_pending_pdu_cnf ++------------------------------------------------------------------------------ +| Description : Initialize SN_TEST_GET_PENDING_PDU_CNF primitive +| Parameters : sn_get_pending_pdu_cnf - primitive +| sn_test_get_pending_pdu_cnf - primitive +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void sm_make_test_pending_pdu_cnf + (T_SN_GET_PENDING_PDU_CNF* sn_get_pending_pdu_cnf, + T_SN_TEST_GET_PENDING_PDU_CNF* sn_test_get_pending_pdu_cnf) +{ + int i,j; + + for (i = 0; i < SN_SIZE_NSAPI; i++) { + sn_test_get_pending_pdu_cnf->c_test_ul_pdus = + sn_get_pending_pdu_cnf->c_ul_pdus; + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].nsapi = + sn_get_pending_pdu_cnf->ul_pdus[i].nsapi; + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_dl_sequence_number = + sn_get_pending_pdu_cnf->ul_pdus[i].dl_sequence_number; + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].c_test_desc_list2 = + sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2; + + if (sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2) { + for(j = 0; j < sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2; j++) { + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].c_test_desc_list2 = + sn_get_pending_pdu_cnf->ul_pdus[i].c_desc_list2; + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_desc_list2[j].c_test_pending_pdu = + (U8)sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].list_len; + memcpy( + sn_test_get_pending_pdu_cnf->test_ul_pdus[i].test_desc_list2[j].test_pending_pdu, + ((T_desc2 *)sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].first)->buffer, + sn_get_pending_pdu_cnf->ul_pdus[i].ptr_desc_list2[j].list_len); + } + } + } +} + +#endif /*#ifdef TI_DUAL_MODE*/