line source
+ − /*
+ − +-----------------------------------------------------------------------------
+ − | Project :
+ − | Modul :
+ − +-----------------------------------------------------------------------------
+ − | Copyright 2002 Texas Instruments Berlin, AG
+ − | All rights reserved.
+ − |
+ − | This file is confidential and a trade secret of Texas
+ − | Instruments Berlin, AG
+ − | The receipt of or possession of this file does not convey
+ − | any rights to reproduce or disclose its contents or to
+ − | manufacture, use, or sell anything it may describe, in
+ − | whole, or in part, without the specific written consent of
+ − | Texas Instruments Berlin, AG.
+ − +-----------------------------------------------------------------------------
+ − | Purpose : This modul is part of the entity LLC and implements all
+ − | procedures and functions as described in the
+ − | SDL-documentation (U-statemachine)
+ − +-----------------------------------------------------------------------------
+ − */
+ −
+ −
+ − #ifndef LLC_UF_C
+ − #define LLC_UF_C
+ − #endif
+ −
+ − #define ENTITY_LLC
+ −
+ − /*==== INCLUDES =============================================================*/
+ −
+ − #include <string.h> /* to get memcpy() */
+ −
+ − #include "typedefs.h" /* to get Condat data types */
+ − #include "vsi.h" /* to get a lot of macros */
+ − #include "macdef.h"
+ − #include "gprs.h"
+ − #include "gsm.h" /* to get a lot of macros */
+ − #include "cnf_llc.h" /* to get cnf-definitions */
+ − #include "mon_llc.h" /* to get mon-definitions */
+ − #include "prim.h" /* to get the definitions of used SAP and directions */
+ − #include "llc.h" /* to get the global entity definitions */
+ −
+ − #include "llc_f.h" /* to get global functions, e.g. llc_init_parameters */
+ − #include "llc_uf.h" /* to get local XID definitions */
+ − #include "llc_t200s.h" /* to get signal interface to T200 */
+ − #include "llc_txs.h" /* to get signal interface to TX */
+ −
+ − /*==== CONST ================================================================*/
+ −
+ − /*==== LOCAL VARS ===========================================================*/
+ −
+ − /*==== PRIVATE FUNCTIONS ====================================================*/
+ −
+ − /*==== PUBLIC FUNCTIONS =====================================================*/
+ −
+ −
+ − /*
+ − * CHECK_INSTANCE:
+ − * v(ariable) - variable name of parameter
+ − */
+ − #define CHECK_INSTANCE(v) \
+ − if (llc_data->decoded_xid.##v##.valid) \
+ − { \
+ − /* \
+ − * More than one instance of the same XID parameter type is included. \
+ − */ \
+ − if (cr_bit EQ SGSN_COMMAND) \
+ − { \
+ − /* \
+ − * XID command: Ignore all instances except the first. \
+ − * <R.LLC.XIDNEG_R.A.014> \
+ − */ \
+ − continue; \
+ − } \
+ − else /* SGSN_RESPONSE */ \
+ − { \
+ − /* \
+ − * XID response: The XID information field is regarded as invalid. \
+ − * <R.LLC.XID_INVA.A.012> \
+ − */ \
+ − TRACE_0_INFO ("More than one instance of an XID-IE in RSP"); \
+ − return FALSE; \
+ − } \
+ − }
+ −
+ −
+ − /*
+ − * CHECK_LENGTH_VALUE:
+ − * l(ength) - default length of parameter
+ − * c(ondition) - out-of-range value condition
+ − * v(ariable) - variable name of parameter
+ − * d(default) - default value of parameter
+ − */
+ − #define CHECK_LENGTH_VALUE(l,c,v,d) \
+ − if ((length NEQ l) OR (c)) \
+ − { \
+ − /* \
+ − * Unsupported length or out-of-range values. \
+ − */ \
+ − if (cr_bit EQ SGSN_COMMAND) \
+ − { \
+ − /* \
+ − * XID command: Set the value for this type according to our \
+ − * preferences. \
+ − * <R.LLC.XIDNEG_R.A.003> \
+ − */ \
+ − llc_data->decoded_xid.##v##.valid = TRUE; \
+ − llc_data->decoded_xid.##v##.value = d; \
+ − break; \
+ − } \
+ − else /* SGSN_RESPONSE */ \
+ − { \
+ − /* \
+ − * XID response: The XID information field is regarded as invalid. \
+ − * <R.LLC.XID_INVA.A.007>, <R.LLC.XID_INVA.A.009> \
+ − */ \
+ − TRACE_0_INFO ("Unsupported length or out-of-range values in RSP"); \
+ − return FALSE; \
+ − } \
+ − }
+ −
+ −
+ − /*
+ − * CHECK_SENSE_OF_NEGOTIATION:
+ − * d(ata) - received data value to check
+ − * v(ariable) - variable name of parameter
+ − * s(ense) - sense of negotiation (XID_SENSE_UP / XID_SENSE_DOWN)
+ − */
+ − #define CHECK_SENSE_OF_NEGOTIATION(d,v,s) \
+ − { \
+ − /* \
+ − * XID response must not contain an XID parameter with a value that \
+ − * violates the sense of negotiation. \
+ − * <R.LLC.XID_INVA.A.008> \
+ − */ \
+ − if (cr_bit EQ SGSN_RESPONSE) \
+ − { \
+ − /* \
+ − * First compare the value with the requested value, if there is any \
+ − */ \
+ − if ( (llc_data->u->requested_xid.##v##.valid) AND \
+ − (llc_data->u->requested_xid.##v##.value s d) ) \
+ − { \
+ − TRACE_0_INFO ("Sense of negotiation error"); \
+ − return FALSE; \
+ − } \
+ − else if( !(llc_data->u->requested_xid.##v##.valid) AND \
+ − (*(llc_data->##v) s d) ) \
+ − { \
+ − /* \
+ − * If the value was not requested but included in response, compare \
+ − * it with the current value \
+ − */ \
+ − TRACE_0_INFO ("Value not requested, but sense of negotiation error"); \
+ − return FALSE; \
+ − } \
+ − } \
+ − }
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_init
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure initialises all necessary variables of u_frames
+ − | for all SAPIs.
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_init (void)
+ − {
+ − TRACE_FUNCTION( "u_init" );
+ −
+ − /*
+ − * Initialise every incarnation of U with state TLLI_UNASSIGNED.
+ − */
+ − SWITCH_SERVICE (llc, u, 0);
+ − INIT_STATE (U_0, U_TLLI_UNASSIGNED);
+ −
+ − SWITCH_SERVICE (llc, u, 1);
+ − INIT_STATE (U_1, U_TLLI_UNASSIGNED);
+ −
+ − SWITCH_SERVICE (llc, u, 2);
+ − INIT_STATE (U_2, U_TLLI_UNASSIGNED);
+ −
+ − SWITCH_SERVICE (llc, u, 3);
+ − INIT_STATE (U_3, U_TLLI_UNASSIGNED);
+ −
+ − SWITCH_SERVICE (llc, u, 4);
+ − INIT_STATE (U_4, U_TLLI_UNASSIGNED);
+ −
+ − SWITCH_SERVICE (llc, u, 5);
+ − INIT_STATE (U_5, U_TLLI_UNASSIGNED);
+ −
+ − return;
+ − } /* u_init() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_init_sapi
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure initialises all necessary variables of u_frames
+ − | for the given SAPI after a TLLI assignment of LLC was occurred.
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_init_sapi (void)
+ − {
+ − TRACE_FUNCTION( "u_init_sapi" );
+ −
+ − /*
+ − * Initial, no XID command is currently being sent.
+ − */
+ − llc_data->u->xid_pending = FALSE;
+ −
+ − llc_data->u->xid_tag = 0L;
+ − llc_data->u->xid_tag_negotiate = 0L;
+ − llc_data->u->xid_tag_sent = 0L;
+ −
+ − llc_data->u->release_requested = FALSE;
+ − llc_data->u->ll_xid_resp_pending = FALSE;
+ −
+ − return;
+ − } /* u_init_sapi() */
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_build_u_frame
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure fills the given sdu with a correct LLC frame,
+ − | containing the address field and the control field (U format).
+ − | The information field is not filled in by this procedure.
+ − | The checksum field (FCS) is also not filled in by this
+ − | procedure, it is filled in by the send_pdu service before
+ − | sending.
+ − |
+ − | Parameters : sdu - a valid pointer to an SDU, containing enough octets for
+ − | the requested command/response
+ − | cr_bit - C/R bit for the frame
+ − | sapi - a valid SAPI for unacknowledged operation
+ − | pf_bit - P/F bit for the U frame
+ − | command - a valid command/response for the U frame
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_build_u_frame
+ − (
+ − #ifdef LL_DESC
+ − T_desc_list3 *desc_list3,
+ − #else
+ − T_sdu *sdu,
+ − #endif
+ − T_BIT cr_bit,
+ − UBYTE sapi,
+ − T_BIT pf_bit,
+ − T_COMMAND command
+ − )
+ − {
+ − #ifdef LL_DESC
+ − T_desc3 *desc3;
+ − UBYTE *desc_buf;
+ − #endif
+ −
+ − TRACE_FUNCTION( "u_build_u_frame" );
+ −
+ − #ifdef LL_DESC
+ − /*
+ − * Let every frame begin at the beginning.
+ − */
+ − desc3 = (T_desc3*)desc_list3->first;
+ − desc3->offset = 0;
+ − desc_buf = (UBYTE*)desc3->buffer;
+ −
+ − /*
+ − * Fill in address and control fields.
+ − * NOTE: The values of the commands are chosen to correspond with the
+ − * defined values of the Mx bits in the control field. Therefore the given
+ − * command can be used to build the header, regardless of its actual value.
+ − */
+ − desc_buf[0] = ((UBYTE)cr_bit << 6) | sapi;
+ − desc_buf[1] = 0xE0 | ((UBYTE)pf_bit << 4) | (UBYTE)command;
+ −
+ −
+ − /*
+ − * Determine the length of the frame, depending on the command/
+ − * response.
+ − */
+ − switch (command)
+ − {
+ − #ifdef REL99
+ − case U_NULL:
+ − /*
+ − * The NULL command contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − desc3->len = U_NULL_SIZE_BITS/8;
+ − break;
+ − #endif /* REL99 */
+ − case U_DM:
+ − /*
+ − * The DM response contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − desc3->len = U_DM_SIZE_BITS/8;
+ − break;
+ − case U_DISC:
+ − /*
+ − * The DISC response contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − desc3->len = U_DISC_SIZE_BITS/8;
+ − break;
+ − case U_UA:
+ − /*
+ − * The UA response may contain an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − desc3->len = 2;
+ − break;
+ − case U_SABM:
+ − /*
+ − * The SABM command may contain an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − desc3->len = 2;
+ − break;
+ − case U_FRMR:
+ − /*
+ − * The FRMR response contains an information field of fixed size.
+ − * u_insert_frmr_information() relies on a sane value in l_buf,
+ − * therefore set only the size of the header (address + control field).
+ − */
+ − desc3->len = 2;
+ − break;
+ − case U_XID:
+ − /*
+ − * The XID command/response contains an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − desc3->len = 2;
+ − break;
+ − default:
+ − desc3->len = 0;
+ − TRACE_ERROR ("Undefined Command specified");
+ − break;
+ − }
+ −
+ − desc_list3->list_len = desc3->len;
+ −
+ − return;
+ −
+ − #else
+ − /*
+ − * Let every frame begin at the beginning.
+ − */
+ − sdu->o_buf = 0;
+ −
+ − /*
+ − * Fill in address and control fields.
+ − * NOTE: The values of the commands are chosen to correspond with the
+ − * defined values of the Mx bits in the control field. Therefore the given
+ − * command can be used to build the header, regardless of its actual value.
+ − */
+ − sdu->buf[0] = ((UBYTE)cr_bit << 6) | sapi;
+ − sdu->buf[1] = 0xE0 | ((UBYTE)pf_bit << 4) | (UBYTE)command;
+ −
+ −
+ − /*
+ − * Determine the length of the frame, depending on the command/
+ − * response.
+ − */
+ − switch (command)
+ − {
+ − #ifdef REL99
+ − case U_NULL:
+ − /*
+ − * The NULL command contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − sdu->l_buf = U_NULL_SIZE_BITS;
+ − break;
+ − #endif /* REL99 */
+ −
+ − case U_DM:
+ − /*
+ − * The DM response contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − sdu->l_buf = U_DM_SIZE_BITS;
+ − break;
+ − case U_DISC:
+ − /*
+ − * The DISC response contains no information field. The size
+ − * of the frame is fixed. (FCS ist not yet considered in l_buf, will
+ − * be included when FCS is appended to the frame.)
+ − */
+ − sdu->l_buf = U_DISC_SIZE_BITS;
+ − break;
+ − case U_UA:
+ − /*
+ − * The UA response may contain an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − sdu->l_buf = 2*8;
+ − break;
+ − case U_SABM:
+ − /*
+ − * The SABM command may contain an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − sdu->l_buf = 2*8;
+ − break;
+ − case U_FRMR:
+ − /*
+ − * The FRMR response contains an information field of fixed size.
+ − * u_insert_frmr_information() relies on a sane value in l_buf,
+ − * therefore set only the size of the header (address + control field).
+ − */
+ − sdu->l_buf = 2*8;
+ − break;
+ − case U_XID:
+ − /*
+ − * The XID command/response contains an information field. Set only the
+ − * size of the header (address + control fields).
+ − */
+ − sdu->l_buf = 2*8;
+ − break;
+ − default:
+ − sdu->l_buf = 0;
+ − TRACE_ERROR ("Undefined Command specified");
+ − break;
+ − }
+ −
+ − return;
+ − #endif /* LL_DESC */
+ − } /* u_build_u_frame() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_check_xid
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure checks the XID information field that is given
+ − | in SDU. If it is invalid, rc_xid_valid is set to FALSE,
+ − | otherwise to TRUE. All XID parameters are decoded and stored
+ − | in llc_decoded_xid (global variable) if they are valid. The
+ − | parameters cr_bit and command are necessary to distinguish
+ − | between the different commands and responses. Each parameter
+ − | is checked for multiple instances, correct sense of
+ − | negotiation, and valid field length and value.
+ − |
+ − | Parameters : sdu - a valid pointer to an SDU
+ − | cr_bit - C/R bit of the frame
+ − | command - command/response of the U frame
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL BOOL u_check_xid (T_sdu *sdu,
+ − T_BIT cr_bit,
+ − T_COMMAND command)
+ − {
+ − UBYTE *par;
+ − BOOL xl;
+ − UBYTE type;
+ − UBYTE length = 0;
+ − UBYTE *data;
+ − ULONG value;
+ −
+ −
+ − TRACE_FUNCTION( "u_check_xid" );
+ −
+ − /*
+ − * Initialise each valid flag to FALSE.
+ − */
+ − llc_data->decoded_xid.version.valid = FALSE;
+ − llc_data->decoded_xid.iov_ui.valid = FALSE;
+ − llc_data->decoded_xid.iov_i.valid = FALSE;
+ − llc_data->decoded_xid.t200.valid = FALSE;
+ − llc_data->decoded_xid.n200.valid = FALSE;
+ − llc_data->decoded_xid.n201_u.valid = FALSE;
+ − llc_data->decoded_xid.n201_i.valid = FALSE;
+ − llc_data->decoded_xid.md.valid = FALSE;
+ − llc_data->decoded_xid.mu.valid = FALSE;
+ − llc_data->decoded_xid.kd.valid = FALSE;
+ − llc_data->decoded_xid.ku.valid = FALSE;
+ − llc_data->decoded_xid.reset.valid = FALSE;
+ −
+ − llc_data->decoded_l3_xid.valid = FALSE;
+ −
+ − /*
+ − * Initialise par with the first XID parameter.
+ − * Process each XID parameter until the end of the list is reached:
+ − * - Check if end of list is reached (max. SDU length).
+ − * ...process XID parameter (set xl and length)...
+ − * - Increment par to point to the next XID parameter (is incremented by
+ − * (data) length plus header length).
+ − */
+ − #ifdef TRACE_EVE
+ − {
+ − int i;
+ − int l = sdu->l_buf/8;
+ − int o = sdu->o_buf/8;
+ −
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "XID sdu dump len:%d bytes", l);
+ −
+ − for (i=0; i<l; i+=10)
+ − {
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x",
+ − sdu->buf[o+i+0], sdu->buf[o+i+1],
+ − sdu->buf[o+i+2], sdu->buf[o+i+3], sdu->buf[o+i+4],
+ −
+ − sdu->buf[o+i+5], sdu->buf[o+i+6],
+ − sdu->buf[o+i+7], sdu->buf[o+i+8], sdu->buf[o+i+9]);
+ − }
+ − }
+ − #endif
+ −
+ − for (par = &(sdu->buf[sdu->o_buf/8]);
+ − par < (&(sdu->buf[sdu->o_buf/8]) + sdu->l_buf/8);
+ − par += length + (xl ? 2 : 1))
+ − {
+ − /*
+ − * Store XL bit in boolean xl.
+ − */
+ − xl = (*par & 0x80) > 0;
+ −
+ − /*
+ − * Store (data) length, and set data to point to the beginning
+ − * of the XID parameter data.
+ − */
+ − if (xl)
+ − {
+ − /*
+ − * XL == 1: length is given in 8 bits.
+ − */
+ − length = (*par & 0x03) << 6;
+ − length += (*(par+1) & 0xFC) >> 2;
+ −
+ − data = par + 2;
+ − }
+ − else
+ − {
+ − /*
+ − * XL == 0: length is given in 2 bits.
+ − */
+ − length = *par & 0x03;
+ −
+ − data = par + 1;
+ − }
+ −
+ −
+ − if (data + length > &(sdu->buf[sdu->o_buf/8]) + sdu->l_buf/8)
+ − {
+ − /*
+ − * The XID parameter field violates the LLC frame format (exceeds given
+ − * SDU size).
+ − * <R.LLC.XID_INVA.A.001>
+ − */
+ − return FALSE;
+ − }
+ −
+ −
+ − /*
+ − * Store type field.
+ − */
+ − type = (*par & 0x7C) >> 2;
+ −
+ −
+ − /*
+ − * Check type and store parameter data, if any.
+ − */
+ − switch (type)
+ − {
+ − case XID_VERSION:
+ − CHECK_INSTANCE (version);
+ −
+ − /*
+ − * XID response must not contain an XID parameter with a value that
+ − * violates the sense of negotiation.
+ − * <R.LLC.XID_INVA.A.008>
+ − */
+ − if (cr_bit EQ SGSN_RESPONSE)
+ − {
+ − /*
+ − * First compare the value with the requested value, if there is any
+ − */
+ − if ( (llc_data->u->requested_xid.version.valid) AND
+ − (llc_data->u->requested_xid.version.value XID_SENSE_DOWN (*data & 0x0F)) )
+ − {
+ − return FALSE;
+ − }
+ − else if( !(llc_data->u->requested_xid.version.valid) AND
+ − llc_data->version XID_SENSE_DOWN (*data & 0x0F) )
+ − {
+ − /*
+ − * If the value was not requested but included in response, compare
+ − * it with the current value
+ − */
+ − return FALSE;
+ − }
+ − }
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_VERSION_LEN,
+ − ((*data & 0x0F) > XID_VERSION_MAX),
+ − version, llc_data->version);
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set version as valid and store value.
+ − */
+ − llc_data->decoded_xid.version.valid = TRUE;
+ − llc_data->decoded_xid.version.value = *data & 0x0F;
+ − TRACE_1_INFO("XID Version:%d", llc_data->decoded_xid.version.value);
+ − break;
+ − case XID_IOV_UI:
+ − CHECK_INSTANCE (iov_ui);
+ −
+ − value = ((ULONG)*data) << 24;
+ − value += ((ULONG)*(data+1)) << 16;
+ − value += ((ULONG)*(data+2)) << 8;
+ − value += *(data+3);
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_IOV_UI_LEN,
+ − (value > XID_IOV_UI_MAX),
+ − iov_ui, llc_data->iov_ui);
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set iov_ui as valid and store value.
+ − */
+ − llc_data->decoded_xid.iov_ui.valid = TRUE;
+ − llc_data->decoded_xid.iov_ui.value = value;
+ − TRACE_1_INFO("XID IOV-UI:0x%.8X", value);
+ − break;
+ − case XID_IOV_I:
+ − if (command EQ U_XID)
+ − {
+ − /*
+ − * IOV-I must not be contained in an XID command/response.
+ − * <R.LLC.XID_INVA.A.010>, <R.LLC.XID_PAR.A.003>
+ − */
+ − TRACE_0_INFO("IOV-I must not be contained in an XID command/response");
+ − return FALSE;
+ − }
+ −
+ − CHECK_INSTANCE (iov_i);
+ −
+ − value = ((ULONG)*data) << 24;
+ − value += ((ULONG)*(data+1)) << 16;
+ − value += ((ULONG)*(data+2)) << 8;
+ − value += *(data+3);
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_IOV_I_LEN,
+ − (value > XID_IOV_I_MAX),
+ − iov_i, *(llc_data->iov_i));
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set iov_i as valid and store value.
+ − */
+ − llc_data->decoded_xid.iov_i.valid = TRUE;
+ − llc_data->decoded_xid.iov_i.value = value;
+ − TRACE_1_INFO("XID IOV-I:0x%.8X", value);
+ − break;
+ − case XID_T200:
+ − CHECK_INSTANCE (t200);
+ −
+ − value = ((ULONG)*data) << 8;
+ − value += *(data+1);
+ − value &= 0x00000FFFL;
+ −
+ − /*
+ − * XID response must not contain an XID parameter with a value that
+ − * violates the sense of negotiation.
+ − * <R.LLC.XID_INVA.A.008>
+ − */
+ − if (cr_bit EQ SGSN_RESPONSE)
+ − {
+ − /*
+ − * First compare the value with the requested value, if there is any
+ − */
+ − if ( (llc_data->u->requested_xid.t200.valid) AND
+ − (llc_data->u->requested_xid.t200.value XID_SENSE_UP value) )
+ − {
+ − TRACE_1_INFO("Value of T200:%d illegal", value);
+ − return FALSE;
+ − }
+ − else if( !(llc_data->u->requested_xid.t200.valid) AND
+ − (USHORT)INT2XID(llc_data->t200->length) XID_SENSE_UP value )
+ − {
+ − /*
+ − * If the value was not requested but included in response, compare
+ − * it with the current value
+ − */
+ − TRACE_1_INFO("Requested value of T200:%d illegal", value);
+ − return FALSE;
+ − }
+ − }
+ −
+ − CHECK_LENGTH_VALUE (XID_T200_LEN,
+ − ((value < XID_T200_MIN) OR (value > XID_T200_MAX)),
+ − t200, (USHORT)INT2XID(llc_data->t200->length));
+ −
+ − /*
+ − * Set t200 as valid and store value.
+ − */
+ − llc_data->decoded_xid.t200.valid = TRUE;
+ − llc_data->decoded_xid.t200.value = (USHORT)value;
+ − TRACE_1_INFO("XID T200:%d", llc_data->decoded_xid.t200.value);
+ − break;
+ − case XID_N200:
+ − CHECK_INSTANCE (n200);
+ −
+ − CHECK_SENSE_OF_NEGOTIATION ((*data & 0x0F), n200, XID_SENSE_UP);
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_N200_LEN,
+ − (((*data & 0x0F) < XID_N200_MIN) OR ((*data & 0x0F) > XID_N200_MAX)),
+ − n200, *(llc_data->n200));
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set n200 as valid and store value.
+ − */
+ − llc_data->decoded_xid.n200.valid = TRUE;
+ − llc_data->decoded_xid.n200.value = *data & 0x0F;
+ − TRACE_1_INFO("XID N200:%d", llc_data->decoded_xid.n200.value);
+ − break;
+ − case XID_N201_U:
+ − CHECK_INSTANCE (n201_u);
+ −
+ − value = ((ULONG)*data) << 8;
+ − value += *(data+1);
+ − value &= 0x000007FFL;
+ −
+ − CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, n201_u, XID_SENSE_DOWN);
+ −
+ − CHECK_LENGTH_VALUE (XID_N201_U_LEN,
+ − (((USHORT)value < XID_N201_U_MIN) OR (value > XID_N201_U_MAX)),
+ − n201_u, *(llc_data->n201_u));
+ −
+ − /*
+ − * Set n201_u as valid and store value.
+ − */
+ − llc_data->decoded_xid.n201_u.valid = TRUE;
+ − llc_data->decoded_xid.n201_u.value = (USHORT)value;
+ − TRACE_1_INFO("XID N201-U:%d", llc_data->decoded_xid.n201_u.value);
+ − break;
+ − case XID_N201_I:
+ − CHECK_INSTANCE (n201_i);
+ −
+ − value = ((ULONG)*data) << 8;
+ − value += *(data+1);
+ − value &= 0x000007FFL;
+ −
+ − CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, n201_i, XID_SENSE_DOWN);
+ −
+ − CHECK_LENGTH_VALUE (XID_N201_I_LEN,
+ − ((value < XID_N201_I_MIN) OR (value > XID_N201_I_MAX)),
+ − n201_i, *(llc_data->n201_i));
+ −
+ − /*
+ − * Set n201_i as valid and store value.
+ − */
+ − llc_data->decoded_xid.n201_i.valid = TRUE;
+ − llc_data->decoded_xid.n201_i.value = (USHORT)value;
+ − TRACE_1_INFO("XID N201-I:%d", llc_data->decoded_xid.n201_i.value);
+ − break;
+ − case XID_MD:
+ − CHECK_INSTANCE (md);
+ −
+ − value = ((ULONG)*data) << 8;
+ − value += *(data+1);
+ − value &= 0x00007FFFL;
+ −
+ − CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, md, XID_SENSE_DOWN);
+ −
+ − CHECK_LENGTH_VALUE (XID_MD_LEN,
+ − ((value != XID_MD_OFF) AND ((value < XID_MD_MIN) OR (value > XID_MD_MAX))),
+ − md, *(llc_data->md));
+ −
+ − /*
+ − * Set md as valid and store value.
+ − */
+ − llc_data->decoded_xid.md.valid = TRUE;
+ − llc_data->decoded_xid.md.value = (USHORT)value;
+ − TRACE_1_INFO("XID MD:%d", llc_data->decoded_xid.md.value);
+ − break;
+ − case XID_MU:
+ − CHECK_INSTANCE (mu);
+ −
+ − value = ((ULONG)*data) << 8;
+ − value += *(data+1);
+ − value &= 0x00007FFFL;
+ −
+ − CHECK_SENSE_OF_NEGOTIATION ((USHORT)value, mu, XID_SENSE_DOWN);
+ −
+ − CHECK_LENGTH_VALUE (XID_MU_LEN,
+ − ((value != XID_MU_OFF) AND ((value < XID_MU_MIN) OR (value > XID_MU_MAX))),
+ − mu, *(llc_data->mu));
+ −
+ − /*
+ − * Set mu as valid and store value.
+ − */
+ − llc_data->decoded_xid.mu.valid = TRUE;
+ − llc_data->decoded_xid.mu.value = (USHORT)value;
+ − TRACE_1_INFO("XID MU:%d", llc_data->decoded_xid.mu.value);
+ − break;
+ − case XID_KD:
+ − CHECK_INSTANCE (kd);
+ −
+ − CHECK_SENSE_OF_NEGOTIATION (*data, kd, XID_SENSE_DOWN);
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_KD_LEN,
+ − ((*data < XID_KD_MIN) OR (*data > XID_KD_MAX)),
+ − kd, *(llc_data->kd));
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set kd as valid and store value.
+ − */
+ − llc_data->decoded_xid.kd.valid = TRUE;
+ − llc_data->decoded_xid.kd.value = *data;
+ − TRACE_1_INFO("XID KD:%d", llc_data->decoded_xid.kd.value);
+ − break;
+ − case XID_KU:
+ − CHECK_INSTANCE (ku);
+ −
+ − CHECK_SENSE_OF_NEGOTIATION (*data, ku, XID_SENSE_DOWN);
+ − /*lint -e685 Relational operator always evaluates to false*/
+ − CHECK_LENGTH_VALUE (XID_KU_LEN,
+ − ((*data < XID_KU_MIN) OR (*data > XID_KU_MAX)),
+ − ku, *(llc_data->ku));
+ − /*lint +e685 Relational operator always evaluates to false*/
+ − /*
+ − * Set ku as valid and store value.
+ − */
+ − llc_data->decoded_xid.ku.valid = TRUE;
+ − llc_data->decoded_xid.ku.value = *data;
+ − TRACE_1_INFO("XID KU:%d", llc_data->decoded_xid.ku.value);
+ − break;
+ − case XID_LAYER_3:
+ − if (llc_data->decoded_l3_xid.valid)
+ − {
+ − /*
+ − * More than one instance of the same XID parameter type is included.
+ − */
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − /*
+ − * XID command: Ignore all instances except the first.
+ − * <R.LLC.XIDNEG_R.A.014>
+ − */
+ − continue;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * XID response: The XID information field is regarded as invalid.
+ − * <R.LLC.XID_INVA.A.012>
+ − */
+ − TRACE_0_INFO("More than one L3 parameters are included in XID response.");
+ − return FALSE;
+ − }
+ − }
+ −
+ − if ((llc_data->current_sapi NEQ LL_SAPI_3) AND
+ − (llc_data->current_sapi NEQ LL_SAPI_5) AND
+ − (llc_data->current_sapi NEQ LL_SAPI_9) AND
+ − (llc_data->current_sapi NEQ LL_SAPI_11))
+ − {
+ − /*
+ − * Layer-3 parameters on a SAPI different from 3, 5, 9, and 11.
+ − * <R.LLC.XID_INVA.A.011>
+ − */
+ − TRACE_0_INFO("L3 parameters on a SAPI different from 3, 5, 9, and 11.");
+ − return FALSE;
+ − }
+ −
+ − /*
+ − * Set layer_3 as valid and store Layer-3 XID parameters.
+ − */
+ − llc_data->decoded_l3_xid.valid = TRUE;
+ − llc_data->decoded_l3_xid.length = length;
+ − memcpy (llc_data->decoded_l3_xid.value, data, length);
+ − TRACE_1_INFO("XID L3:%d bytes", length);
+ − break;
+ − case XID_RESET:
+ − if (par NEQ &(sdu->buf[sdu->o_buf/8]))
+ − {
+ − /*
+ − * Reset must be the first parameter in the XID information field.
+ − * <R.LLC.XID_INVA.A.004>
+ − */
+ − TRACE_0_INFO("Reset must be the first XID parameter.");
+ − return FALSE;
+ − }
+ −
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (command EQ U_SABM)
+ − {
+ − /*
+ − * SABM command: Reset is not allowed.
+ − * <R.LLC.XID_INVA.A.003>
+ − */
+ − TRACE_0_INFO("Reset is not allowed in SABM command");
+ − return FALSE;
+ − }
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * UA/XID response: Reset is not allowed.
+ − * <R.LLC.XID_INVA.A.005>
+ − */
+ − TRACE_0_INFO("Reset is not allowed in UA/XID response");
+ − return FALSE;
+ − }
+ −
+ − /*
+ − * Set reset as valid.
+ − */
+ − llc_data->decoded_xid.reset.valid = TRUE;
+ − TRACE_0_INFO("XID Reset");
+ − break;
+ − default:
+ − /*
+ − * Unrecognised type field.
+ − */
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − /*
+ − * XID command: Skip XID parameter.
+ − * <R.LLC.XIDNEG_R.A.002>
+ − */
+ − continue;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * XID response: The XID information field is regarded as invalid.
+ − * <R.LLC.XID_INVA.A.006>
+ − */
+ − TRACE_0_INFO("Unrecognised type field in XID response.");
+ − return FALSE;
+ − }
+ − }
+ − }
+ −
+ − /*
+ − * All XID parameters have been processed, XID information field seems
+ − * to be correct.
+ − */
+ − return TRUE;
+ − } /* u_check_xid() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_eval_xid
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure evaluates the decoded XID information field in
+ − | llc_decoded_xid (global variable). If Reset is present, the
+ − | state of every incarnation in ABM is set to ADM (including
+ − | the current incarnation!), all LLC layer parameters are set
+ − | to their default values, the OCs for unack. transfer are set
+ − | to 0, and the parameter reset_received is set to TRUE. If a
+ − | command has been received (cr_bit is set to SGSN_COMMAND),
+ − | all XID parameters are evaluated and stored as global values,
+ − | if acceptable. Each XID parameter is tagged in llc_xid_tag
+ − | for the next response. Otherwise (a response has been
+ − | received), store the received parameters as global values
+ − | and reset their valid flags in llc_requested_xid. In each
+ − | case, if N201-I or N201-U have been changed, or if Layer-3
+ − | XID parameters have been received, set xid_ind to TRUE,
+ − | otherwise to FALSE. Additionally remove any received parameter
+ − | in llc_xid_negotiate, because it has been explicitly
+ − | negotiated by the peer.
+ − |
+ − | Parameters : cr_bit - SGSN_COMMAND/_RESPONSE has been received
+ − | reset_received - TRUE indicates received Reset parameter,
+ − | else FALSE
+ − | xid_ind - TRUE indicates changed N201-U and/or N201-I,
+ − | so that LL_XID_IND must be sent to layer 3
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_eval_xid (T_BIT cr_bit,
+ − BOOL *reset_received,
+ − BOOL *xid_ind)
+ − {
+ − UBYTE incarnation;
+ −
+ −
+ − TRACE_FUNCTION ("u_eval_xid");
+ −
+ − /*
+ − * Preset both indicators with default values.
+ − */
+ − *reset_received = FALSE;
+ − *xid_ind = FALSE;
+ −
+ − /*
+ − * Preset global XID indicator for next response.
+ − */
+ − llc_data->u->xid_tag = 0L;
+ −
+ −
+ − /**************************************************************************
+ − * Reset:
+ − * Has to be processed first in order to take effect!
+ − */
+ − if (llc_data->decoded_xid.reset.valid)
+ − {
+ − /*
+ − * Initialise all LLC layer parameters for all SAPIs.
+ − */
+ − llc_init_parameters();
+ − llc_init_requested_xid();
+ −
+ − /*
+ − * Reset all incarnations of service U that are in state 'ABM' to 'ADM'.
+ − */
+ − for (incarnation = 0; incarnation < U_NUM_INC; incarnation++)
+ − {
+ − llc_data->u_base[incarnation].state = U_ADM;
+ − }
+ −
+ − /*
+ − * LLC has to be reset. Send SIG_U_LLME_RESET_IND.
+ − */
+ − *reset_received = TRUE;
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * Version:
+ − * Shall not be negotiated while in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.001>
+ − */
+ − if ((llc_data->decoded_xid.version.valid) AND (GET_STATE(U) NEQ U_ABM))
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_VERSION,
+ − llc_data->decoded_xid.version.value))
+ − {
+ − llc_data->version = llc_data->decoded_xid.version.value;
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_VERSION;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − llc_data->version = llc_data->decoded_xid.version.value;
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_VERSION);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * IOV-UI:
+ − * Shall only be negotiated in state 'ADM'. <R.LLC.XID_PAR.A.002>
+ − */
+ − if ((llc_data->decoded_xid.iov_ui.valid) AND (GET_STATE(U) NEQ U_ABM) )
+ − {
+ − /*
+ − * Do not tag iov_ui for the XID response, because it shall only be
+ − * transmitted in downlink direction.
+ − * <R.LLC.XID_PAR.A.004>
+ − */
+ −
+ − /*
+ − * Copy value to global variable (no sense of negotiation).
+ − */
+ − llc_data->iov_ui = llc_data->decoded_xid.iov_ui.value;
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * IOV-I:
+ − * Shall only be negotiated with SABM and UA frames. This is already
+ − * checked in u_check_xid().
+ − * <R.LLC.XID_PAR.A.003>, <R.LLC.XID_INVA.A.010>
+ − */
+ − if (llc_data->decoded_xid.iov_i.valid)
+ − {
+ − /*
+ − * Do not tag iov_i for the XID response, because it shall only be
+ − * transmitted in downlink direction.
+ − * <R.LLC.XID_PAR.A.004>
+ − */
+ −
+ − /*
+ − * Copy value to global variable (no sense of negotiation).
+ − */
+ − *(llc_data->iov_i) = llc_data->decoded_xid.iov_i.value;
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * T200 (and T201):
+ − * Can be negotiated in state 'ADM' and 'ABM'. New values shall only apply
+ − * to timers set after the negotiation has been completed (which is
+ − * accomplished automatically).
+ − * <R.LLC.XID_PAR.A.006>, <R.LLC.XID_PAR.A.007>
+ − */
+ − if (llc_data->decoded_xid.t200.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_T200,
+ − llc_data->decoded_xid.t200.value))
+ − {
+ − llc_data->t200->length = XID2INT (llc_data->decoded_xid.t200.value);
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a lower!
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.t200.valid AND
+ − llc_data->u->requested_xid.t200.value <= llc_data->decoded_xid.t200.value)
+ − {
+ − llc_data->u->requested_xid.t200.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_T200;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − llc_data->t200->length = XID2INT (llc_data->decoded_xid.t200.value);
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_T200);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * N200:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->decoded_xid.n200.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N200,
+ − llc_data->decoded_xid.n200.value))
+ − {
+ − *(llc_data->n200) = llc_data->decoded_xid.n200.value;
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a lower!
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.n200.valid AND
+ − llc_data->u->requested_xid.n200.value <= llc_data->decoded_xid.n200.value)
+ − {
+ − llc_data->u->requested_xid.n200.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_N200;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − *(llc_data->n200) = llc_data->decoded_xid.n200.value;
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N200);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * N201-U:
+ − * Can be negotiated in state 'ADM' and 'ABM'. If N201-U is negotiated to a
+ − * lower value than previously used, then any queued or new U and UI frames
+ − * that violate the new value of N201-U should be discarded and not
+ − * transmitted.
+ − * <R.LLC.XID_PAR.A.006>, <R.LLC.XID_PAR.A.010>
+ − */
+ − if (llc_data->decoded_xid.n201_u.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U,
+ − llc_data->decoded_xid.n201_u.value))
+ − {
+ − if (llc_data->decoded_xid.n201_u.value NEQ *(llc_data->n201_u))
+ − {
+ − *(llc_data->n201_u) = llc_data->decoded_xid.n201_u.value;
+ −
+ − /*
+ − * LL_XID_IND has to be sent to layer 3.
+ − */
+ − *xid_ind = TRUE;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.n201_u.valid AND
+ − llc_data->u->requested_xid.n201_u.value >= llc_data->decoded_xid.n201_u.value)
+ − {
+ − llc_data->u->requested_xid.n201_u.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_N201_U;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − if (llc_data->decoded_xid.n201_u.value NEQ *(llc_data->n201_u))
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − *(llc_data->n201_u) = llc_data->decoded_xid.n201_u.value;
+ −
+ − /*
+ − * LL_XID_IND has to be sent to layer 3.
+ − */
+ − *xid_ind = TRUE;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N201_U);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * N201-I:
+ − * N201-I can be negotiated to any value in state 'ADM'. It can only be
+ − * negotiated to the same or higher value as previously used in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009>
+ − */
+ − if (llc_data->decoded_xid.n201_i.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I,
+ − llc_data->decoded_xid.n201_i.value))
+ − {
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.n201_i.value > *(llc_data->n201_i)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.n201_i.value NEQ *(llc_data->n201_i)))
+ − {
+ − *(llc_data->n201_i) = llc_data->decoded_xid.n201_i.value;
+ −
+ − /*
+ − * LL_XID_IND has to be sent to layer 3.
+ − */
+ − *xid_ind = TRUE;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ −
+ − if (llc_data->u->requested_xid.n201_i.valid AND
+ − llc_data->u->requested_xid.n201_i.value >= llc_data->decoded_xid.n201_i.value)
+ − {
+ − llc_data->u->requested_xid.n201_i.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_N201_I;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.n201_i.value > *(llc_data->n201_i)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.n201_i.value NEQ *(llc_data->n201_i)))
+ − {
+ − *(llc_data->n201_i) = llc_data->decoded_xid.n201_i.value;
+ −
+ − /*
+ − * LL_XID_IND has to be sent to layer 3.
+ − */
+ − *xid_ind = TRUE;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_N201_I);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * mD:
+ − * mD can be negotiated to any value in state 'ADM'. It can only be
+ − * negotiated to the same or higher value as previously used in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009>
+ − */
+ − if (llc_data->decoded_xid.md.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_MD,
+ − llc_data->decoded_xid.md.value))
+ − {
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.md.value > *(llc_data->md)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.md.value NEQ *(llc_data->md)))
+ − {
+ − *(llc_data->md) = llc_data->decoded_xid.md.value;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.md.valid AND
+ − llc_data->u->requested_xid.md.value >= llc_data->decoded_xid.md.value)
+ − {
+ − llc_data->u->requested_xid.md.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_MD;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.md.value > *(llc_data->md)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.md.value NEQ *(llc_data->md)))
+ − {
+ − *(llc_data->md) = llc_data->decoded_xid.md.value;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_MD);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * mU:
+ − * mU can be negotiated to any value in state 'ADM'. It can only be
+ − * negotiated to the same or higher value as previously used in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009>
+ − */
+ − if (llc_data->decoded_xid.mu.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_MU,
+ − llc_data->decoded_xid.mu.value))
+ − {
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.mu.value > *(llc_data->mu)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.mu.value NEQ *(llc_data->mu)))
+ − {
+ − *(llc_data->mu) = llc_data->decoded_xid.mu.value;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.mu.valid AND
+ − llc_data->u->requested_xid.mu.value >= llc_data->decoded_xid.mu.value)
+ − {
+ − llc_data->u->requested_xid.mu.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_MU;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.mu.value > *(llc_data->mu)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.mu.value NEQ *(llc_data->mu)))
+ − {
+ − *(llc_data->mu) = llc_data->decoded_xid.mu.value;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_MU);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * kD:
+ − * kD can be negotiated to any value in state 'ADM'. It can only be
+ − * negotiated to the same or higher value as previously used in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009>
+ − */
+ − if (llc_data->decoded_xid.kd.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_KD,
+ − llc_data->decoded_xid.kd.value))
+ − {
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.kd.value > *(llc_data->kd)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.kd.value NEQ *(llc_data->kd)))
+ − {
+ − *(llc_data->kd) = llc_data->decoded_xid.kd.value;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.kd.valid AND
+ − llc_data->u->requested_xid.kd.value >= llc_data->decoded_xid.kd.value)
+ − {
+ − llc_data->u->requested_xid.kd.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_KD;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.kd.value > *(llc_data->kd)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.kd.value NEQ *(llc_data->kd)))
+ − {
+ − *(llc_data->kd) = llc_data->decoded_xid.kd.value;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_KD);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * kU:
+ − * kU can be negotiated to any value in state 'ADM'. It can only be
+ − * negotiated to the same or higher value as previously used in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.008>, <R.LLC.XID_PAR.A.009>
+ − */
+ − if (llc_data->decoded_xid.ku.valid)
+ − {
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − if (llc_xid_value_acceptable (llc_data->current_sapi, XID_KU,
+ − llc_data->decoded_xid.ku.value))
+ − {
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.ku.value > *(llc_data->ku)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.ku.value NEQ *(llc_data->ku)))
+ − {
+ − *(llc_data->ku) = llc_data->decoded_xid.ku.value;
+ − }
+ − }
+ − else /* value is not acceptable */
+ − {
+ − /*
+ − * Sense of negotiation down: offer lower value; sense of
+ − * negotiation up: offer higher value.
+ − * This happens automatically by just responding with our current
+ − * global value.
+ − */
+ − }
+ −
+ − /*
+ − * In case we also want to negotiate this value, but to a higher
+ − * value, delete this parameter from the requested XID structure
+ − */
+ − if (llc_data->u->requested_xid.ku.valid AND
+ − llc_data->u->requested_xid.ku.value >= llc_data->decoded_xid.ku.value)
+ − {
+ − llc_data->u->requested_xid.ku.valid = FALSE;
+ − }
+ −
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_KU;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Sense of negotiation-correctness of response has already been checked
+ − * in u_check_xid().
+ − */
+ − if (((GET_STATE (U) EQ U_ABM) AND
+ − (llc_data->decoded_xid.ku.value > *(llc_data->ku)))
+ − OR /* state 'ADM' */
+ − (llc_data->decoded_xid.ku.value NEQ *(llc_data->ku)))
+ − {
+ − *(llc_data->ku) = llc_data->decoded_xid.ku.value;
+ − }
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_KU);
+ − }
+ −
+ −
+ − /**************************************************************************
+ − * Layer 3 stuff
+ − */
+ − if (llc_data->decoded_l3_xid.valid)
+ − {
+ − /*
+ − * LL_XID_IND has to be sent to layer 3.
+ − */
+ − *xid_ind = TRUE;
+ −
+ − if (cr_bit EQ SGSN_COMMAND)
+ − {
+ − /*
+ − * Tag parameter for next response.
+ − */
+ − llc_data->u->xid_tag |= 0x00000001L << XID_LAYER_3;
+ − }
+ − else /* SGSN_RESPONSE */
+ − {
+ − /*
+ − * Reset valid flag of parameter in requested_xid because it has been
+ − * included in the response.
+ − */
+ − llc_data->requested_l3_xid->valid = FALSE;
+ − }
+ −
+ − /*
+ − * Remove tag in xid_tag_negotiate, because this parameter has been
+ − * explicitly negotiated by the peer.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − llc_data->u->xid_tag_negotiate &= ~(0x00000001L << XID_LAYER_3);
+ − }
+ −
+ − return; /* u_eval_xid */
+ − }
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_insert_xid
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure inserts (i.e. appends) the XID parameters that
+ − | are tagged in llc_xid_tag. This variable is normally set in
+ − | u_eval_xid(). The parameter cr_bit indicates if the XID
+ − | information field is written in a command or a response frame.
+ − | The values of the parameters are taken from llc_requested_xid
+ − | if marked as valid (normally the cause when a command frame is
+ − | to be sent), otherwise from global variables (the normal cause
+ − | for a response frame). If a response frame is to be sent, and
+ − | the parameter is tagged in llc_xid_tag, but has not been
+ − | received in the command frame (as indicated by
+ − | llc_decoded_xid), the parameter is tagged in llc_xid_negotiate.
+ − | Each parameter is tagged in llc_xid_tag_sent for collision
+ − | checks and the like
+ − |
+ − | Parameters : sdu - a valid pointer to an SDU, containing enough octets
+ − | for the tagged number of XID parameters
+ − | cr_bit - MS_COMMAND/_RESPONSE is to be sent
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_insert_xid
+ − (
+ − #ifdef LL_DESC
+ − T_desc_list3 *desc_list3,
+ − #else
+ − T_sdu *sdu,
+ − #endif
+ − T_BIT cr_bit
+ − )
+ − {
+ − UBYTE *data;
+ − ULONG value;
+ − #ifdef LL_DESC
+ − UBYTE *desc_buf;
+ − T_desc3 *desc3;
+ − #endif
+ − TRACE_FUNCTION( "u_insert_xid" );
+ −
+ − /*
+ − * Set data to point to the first free data octet in sdu. data has to
+ − * be incremented with each octet that is written in sdu to ensure that
+ − * it always points to the first free data octet.
+ − */
+ − #ifdef LL_DESC
+ − desc3 = (T_desc3*) desc_list3->first;
+ − desc_buf = (UBYTE*)desc3->buffer;
+ − data = &desc_buf[(desc3->offset)+(desc3->len)];
+ − #else
+ − data = &sdu->buf[(sdu->o_buf/8)+(sdu->l_buf/8)];
+ − #endif
+ − /*
+ − * Preset global XID sent indicator for next response.
+ − */
+ − llc_data->u->xid_tag_sent = 0L;
+ −
+ −
+ − /*************************************************************************
+ − * Version:
+ − * Shall not be negotiated while in state 'ABM'.
+ − * <R.LLC.XID_PAR.A.001>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_VERSION) AND
+ − (GET_STATE (U) NEQ U_ABM))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.version.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.version.valid)
+ − {
+ − llc_data->version = llc_data->u->requested_xid.version.value;
+ − }
+ −
+ − value = llc_data->version;
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.version.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_VERSION;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_VERSION << 2) | (UBYTE)XID_VERSION_LEN;
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_VERSION_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_VERSION_LEN + 1) * 8;
+ − #endif
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_VERSION;
+ − }
+ −
+ − /*************************************************************************
+ − * T200:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_T200))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.t200.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.t200.valid)
+ − {
+ − llc_data->t200->length = XID2INT(llc_data->u->requested_xid.t200.value);
+ − }
+ −
+ − value = INT2XID(llc_data->t200->length);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.t200.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_T200;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_T200 << 2) | (UBYTE)XID_T200_LEN;
+ − *data++ = (UBYTE)(value >> 8);
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_T200_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_T200_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_T200;
+ − }
+ −
+ − /*************************************************************************
+ − * N200:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_N200))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.n200.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.n200.valid)
+ − {
+ − *(llc_data->n200) = llc_data->u->requested_xid.n200.value;
+ − }
+ −
+ − value = *(llc_data->n200);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.n200.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N200;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_N200 << 2) | (UBYTE)XID_N200_LEN;
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_N200_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_N200_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_N200;
+ − }
+ −
+ − /*************************************************************************
+ − * N201-U:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_N201_U))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.n201_u.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.n201_u.valid)
+ − {
+ − *(llc_data->n201_u) = llc_data->u->requested_xid.n201_u.value;
+ − }
+ −
+ − value = *(llc_data->n201_u);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.n201_u.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N201_U;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_N201_U << 2) | (UBYTE)XID_N201_U_LEN;
+ − *data++ = (UBYTE)(value >> 8);
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_N201_U_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_N201_U_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_N201_U;
+ − }
+ −
+ − /*************************************************************************
+ − * N201-I:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_N201_I))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.n201_i.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.n201_i.valid)
+ − {
+ − *(llc_data->n201_i) = llc_data->u->requested_xid.n201_i.value;
+ − }
+ −
+ − value = *(llc_data->n201_i);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.n201_i.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_N201_I;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_N201_I << 2) | (UBYTE)XID_N201_I_LEN;
+ − *data++ = (UBYTE)(value >> 8);
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_N201_I_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_N201_I_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_N201_I;
+ − }
+ −
+ − /*************************************************************************
+ − * md:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_MD))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.md.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.md.valid)
+ − {
+ − *(llc_data->md) = llc_data->u->requested_xid.md.value;
+ − }
+ −
+ − value = *(llc_data->md);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.md.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_MD;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_MD << 2) | (UBYTE)XID_MD_LEN;
+ − *data++ = (UBYTE)(value >> 8);
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_MD_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_MD_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_MD;
+ − }
+ −
+ − /*************************************************************************
+ − * mu:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_MU))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.mu.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.mu.valid)
+ − {
+ − *(llc_data->mu) = llc_data->u->requested_xid.mu.value;
+ − }
+ −
+ − value = *(llc_data->mu);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.mu.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_MU;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_MU << 2) | (UBYTE)XID_MU_LEN;
+ − *data++ = (UBYTE)(value >> 8);
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_MU_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_MU_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_MU;
+ − }
+ −
+ − /*************************************************************************
+ − * kd:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_KD))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.kd.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.kd.valid)
+ − {
+ − *(llc_data->kd) = llc_data->u->requested_xid.kd.value;
+ − }
+ −
+ − value = *(llc_data->kd);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.kd.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_KD;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_KD << 2) | (UBYTE)XID_KD_LEN;
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_KD_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_KD_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_KD;
+ − }
+ −
+ − /*************************************************************************
+ − * ku:
+ − * Can be negotiated in state 'ADM' and 'ABM'.
+ − * <R.LLC.XID_PAR.A.006>
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_KU))
+ − {
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − value = llc_data->u->requested_xid.ku.value;
+ − }
+ − else
+ − {
+ − if (llc_data->u->requested_xid.ku.valid)
+ − {
+ − *(llc_data->ku) = llc_data->u->requested_xid.ku.value;
+ − }
+ −
+ − value = *(llc_data->ku);
+ −
+ − /*
+ − * Tag a parameter for further negotiation that was not included in
+ − * the XID command in every XID response until the parameter has been
+ − * explicitly negotiated, either by responding to an XID command that
+ − * included the parameter, or by explicitly including the parameter
+ − * the next time an XID command is transmitted.
+ − * <R.LLC.XIDNEG_R.A.015>
+ − */
+ − if (!llc_data->decoded_xid.ku.valid)
+ − {
+ − llc_data->u->xid_tag_negotiate |= 0x00000001L << XID_KU;
+ − }
+ − }
+ −
+ − /*
+ − * Append determined value to SDU data, increment SDU data pointer to
+ − * point to the first free data octet again.
+ − */
+ − *data++ = (UBYTE)0x00 | ((UBYTE)XID_KU << 2) | (UBYTE)XID_KU_LEN;
+ − *data++ = (UBYTE)value;
+ −
+ − #ifdef LL_DESC
+ − desc3->len += (XID_KU_LEN + 1);
+ − #else
+ − sdu->l_buf += (XID_KU_LEN + 1) * 8;
+ − #endif
+ −
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_KU;
+ − }
+ −
+ − /*************************************************************************
+ − * Insert Layer 3 (sense of negotiation: both)
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3))
+ − {
+ − if (llc_data->requested_l3_xid->valid)
+ − {
+ − /*
+ − * Write two bytes header
+ − */
+ − *data++ = (UBYTE)0x80 /* = set length to 8 bit */ | ((UBYTE)XID_LAYER_3 << 2)
+ − | ((UBYTE)((llc_data->requested_l3_xid->length >> 6) & 0x03));
+ − *data++ = (UBYTE)(llc_data->requested_l3_xid->length << 2);
+ −
+ − /*
+ − * Copy data
+ − */
+ − memcpy (data, llc_data->requested_l3_xid->value,
+ − llc_data->requested_l3_xid->length);
+ −
+ − /*
+ − * Increase DESC/SDU size
+ − */
+ − #ifdef LL_DESC
+ − desc3->len += (llc_data->requested_l3_xid->length + 2);
+ − #else
+ − sdu->l_buf += (llc_data->requested_l3_xid->length + 2) * 8;
+ − #endif
+ − /*
+ − * Tag parameter for collision checks and the like.
+ − */
+ − llc_data->u->xid_tag_sent |= 0x00000001L << XID_LAYER_3;
+ − }
+ − }
+ −
+ − #ifdef LL_DESC
+ − desc_list3->list_len = desc3->len;
+ − #endif /* LL_DESC */
+ −
+ − #ifdef TRACE_EVE
+ − #ifdef LL_DESC
+ − {
+ − int i;
+ − int l = desc3->len;
+ − int o = desc3->offset;
+ −
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "ul XID sdu dump len:%d bytes", l);
+ −
+ − for (i=0; i<l; i+=10)
+ − {
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x",
+ − desc_buf[o+i+0], desc_buf[o+i+1],
+ − desc_buf[o+i+2], desc_buf[o+i+3], desc_buf[o+i+4],
+ −
+ − desc_buf[o+i+5], desc_buf[o+i+6],
+ − desc_buf[o+i+7], desc_buf[o+i+8], desc_buf[o+i+9]);
+ − }
+ − }
+ −
+ − #else
+ − {
+ − int i;
+ − int l = sdu->l_buf/8;
+ − int o = sdu->o_buf/8;
+ −
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "ul XID sdu dump len:%d bytes", l);
+ −
+ − for (i=0; i<l; i+=10)
+ − {
+ − vsi_o_ttrace(VSI_CALLER TC_EVENT, "%.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x",
+ − sdu->buf[o+i+0], sdu->buf[o+i+1],
+ − sdu->buf[o+i+2], sdu->buf[o+i+3], sdu->buf[o+i+4],
+ −
+ − sdu->buf[o+i+5], sdu->buf[o+i+6],
+ − sdu->buf[o+i+7], sdu->buf[o+i+8], sdu->buf[o+i+9]);
+ − }
+ − }
+ −
+ − #endif /* LL_DESC */
+ − #endif /* TRACE_EVE */
+ − /*
+ − * If we have build an response including all XID parameters,
+ − * we can clean all the xid_tags and layer 3 parameters.
+ − */
+ − if (cr_bit EQ MS_RESPONSE)
+ − {
+ − llc_data->u->xid_tag = 0;
+ − llc_data->requested_l3_xid->valid = FALSE;
+ − }
+ −
+ − return;
+ − } /* u_insert_xid() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_insert_frmr_information
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure inserts (i.e. appends) an FRMR information
+ − | field into the given sdu. frame is the rejected frame of which
+ − | the control field is included (ctrl_length is truncated to a
+ − | maximum of six octets; if it is not known, length is
+ − | determinated from pdu_type), v_s and v_r are the current
+ − | send and receive state numbers of ITX/IRX, cr_bit indicates
+ − | if the frame was a command or response (SGSN_COMMAND/RESPONSE),
+ − | and reason indicates the reason of the frame rejection
+ − | condition (the lower nibble of reason is equivalent to W4-W1).
+ − |
+ − | Parameters : sdu - a valid pointer to an SDU, containing enough
+ − | octets for the FRMR information field
+ − | (U_FRMR_INFO_SIZE)
+ − | frame - frame that caused the frame rejection condition
+ − | pdu_type - frame type
+ − | ctrl_length - control field length, if known
+ − | v_s - current V(S)
+ − | v_r - current V(R)
+ − | cr_bit - setting of C/R bit in frame
+ − | reason - reason of the frame rejection condition (lower
+ − | nibble conforms to W4-W1 in FRMR response)
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_insert_frmr_information
+ − (
+ − #ifndef LL_DESC
+ − T_sdu *sdu,
+ − #else
+ − T_desc_list3 *desc_list3,
+ − #endif
+ − T_LL_UNITDATA_IND *frame,
+ − T_PDU_TYPE pdu_type,
+ − USHORT ctrl_length,
+ − T_FRAME_NUM v_s,
+ − T_FRAME_NUM v_r,
+ − T_BIT cr_bit,
+ − UBYTE reason
+ − )
+ − {
+ −
+ − #ifndef LL_DESC
+ − UBYTE *sdu_data;
+ − #else
+ − UBYTE *help, *desc_data;
+ − T_desc3 *desc3;
+ − #endif
+ − UBYTE *ctrl;
+ − USHORT octet;
+ −
+ −
+ − TRACE_FUNCTION( "u_insert_frmr_information" );
+ −
+ − #ifndef LL_DESC
+ − /*
+ − * Set sdu_data to point to the first free data octet in sdu. sdu_data
+ − * has to be incremented with each octet that is written in sdu to ensure
+ − * that it always points to the first free data octet.
+ − */
+ − sdu_data = &sdu->buf[(sdu->o_buf/8)+(sdu->l_buf/8)];
+ −
+ − /*
+ − * Adjust length of SDU to include fixed sized FRMR information field.
+ − */
+ − sdu->l_buf += U_FRMR_INFO_SIZE * 8;
+ −
+ − /*
+ − * Set ctrl to point to the first octet of the faulty frame control field.
+ − */
+ − ctrl = &frame->sdu.buf[(frame->sdu.o_buf/8)+1];
+ −
+ − /*
+ − * If ctrl_length is unknown, the frame type is known, therefore the length
+ − * of the control field can be easily determined.
+ − */
+ − if (ctrl_length EQ FRMR_CTRL_LENGTH_UNKNOWN)
+ − {
+ − if (pdu_type EQ I_FRAME)
+ − {
+ − ctrl_length = I_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ S_FRAME)
+ − {
+ − ctrl_length = S_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ UI_FRAME)
+ − {
+ − ctrl_length = UI_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ U_FRAME)
+ − {
+ − ctrl_length = U_CTRL_OCTETS;
+ − }
+ − else
+ − {
+ − /*
+ − * Undefined control field type, set control field length to SDU length
+ − * minus address field, limited to six octets.
+ − */
+ − TRACE_ERROR ("undefined control field type");
+ − ctrl_length = (sdu->l_buf/8 - 1) < 6 ? (sdu->l_buf/8 - 1) : 6;
+ − }
+ − }
+ − else /* ctrl_length is already known */
+ − {
+ − /*
+ − * Limit control field length to six octets, according to 04.64.
+ − */
+ − ctrl_length = ctrl_length < 6 ? ctrl_length : 6;
+ − }
+ −
+ −
+ − /*
+ − * Copy the first six octets of faulty control field. If the control field
+ − * is smaller that six octets, the unused octets are set to 0.
+ − */
+ − for (octet = 0; octet < 6; octet++)
+ − {
+ − if (octet < ctrl_length)
+ − {
+ − sdu_data[octet] = ctrl[octet];
+ − }
+ − else
+ − {
+ − sdu_data[octet] = 0x00;
+ − }
+ − }
+ −
+ −
+ − /*
+ − * Insert remaining four octets of FRMR information field:
+ − * +---+---+---+---+---+---+---+---+
+ − * | X | X | X | X | V(S) |
+ − * +---+---+---+---+---+---+---+---+
+ − * | V(S) | X | V(R) |
+ − * +---+---+---+---+---+---+---+---+
+ − * | V(R) |C/R|
+ − * +---+---+---+---+---+---+---+---+
+ − * | X | X | X | X | W4| W3| W2| W1|
+ − * +---+---+---+---+---+---+---+---+
+ − */
+ − sdu_data[octet++] = (UBYTE)(v_s >> 5) & 0x0F;
+ − sdu_data[octet++] = (UBYTE)(v_s << 3) | ((UBYTE)(v_r >> 7) & 0x0003);
+ − sdu_data[octet++] = (UBYTE)(v_r << 1) | (cr_bit EQ SGSN_COMMAND ?
+ − 0x00 : 0x01);
+ − sdu_data[octet++] = reason & 0x0F;
+ −
+ − return;
+ − #else
+ − /*
+ − * Set sdu_data to point to the first free data octet in sdu. sdu_data
+ − * has to be incremented with each octet that is written in sdu to ensure
+ − * that it always points to the first free data octet.
+ − */
+ − desc3 = (T_desc3*)desc_list3->first;
+ −
+ − help = (U8*)desc3->buffer;
+ − desc_data = &help[desc3->offset + desc3->len];
+ −
+ − /*
+ − * Adjust length of SDU to include fixed sized FRMR information field.
+ − */
+ − desc3->len += U_FRMR_INFO_SIZE;
+ − desc_list3->list_len += U_FRMR_INFO_SIZE;
+ −
+ − /*
+ − * Set ctrl to point to the first octet of the faulty frame control field.
+ − */
+ − ctrl = &frame->sdu.buf[(frame->sdu.o_buf/8)+1];
+ −
+ − /*
+ − * If ctrl_length is unknown, the frame type is known, therefore the length
+ − * of the control field can be easily determined.
+ − */
+ − if (ctrl_length EQ FRMR_CTRL_LENGTH_UNKNOWN)
+ − {
+ − if (pdu_type EQ I_FRAME)
+ − {
+ − ctrl_length = I_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ S_FRAME)
+ − {
+ − ctrl_length = S_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ UI_FRAME)
+ − {
+ − ctrl_length = UI_CTRL_OCTETS;
+ − }
+ − else if (pdu_type EQ U_FRAME)
+ − {
+ − ctrl_length = U_CTRL_OCTETS;
+ − }
+ − else
+ − {
+ − /*
+ − * Undefined control field type, set control field length to SDU length
+ − * minus address field, limited to six octets.
+ − */
+ − TRACE_ERROR ("undefined control field type");
+ − ctrl_length = desc3->len - 1 < 6 ? (desc3->len - 1) : 6;
+ − }
+ − }
+ − else /* ctrl_length is already known */
+ − {
+ − /*
+ − * Limit control field length to six octets, according to 04.64.
+ − */
+ − ctrl_length = ctrl_length < 6 ? ctrl_length : 6;
+ − }
+ −
+ −
+ − /*
+ − * Copy the first six octets of faulty control field. If the control field
+ − * is smaller that six octets, the unused octets are set to 0.
+ − */
+ − for (octet = 0; octet < 6; octet++)
+ − {
+ − if (octet < ctrl_length)
+ − {
+ − desc_data[octet] = ctrl[octet];
+ − }
+ − else
+ − {
+ − desc_data[octet] = 0x00;
+ − }
+ − }
+ −
+ −
+ − /*
+ − * Insert remaining four octets of FRMR information field:
+ − * +---+---+---+---+---+---+---+---+
+ − * | X | X | X | X | V(S) |
+ − * +---+---+---+---+---+---+---+---+
+ − * | V(S) | X | V(R) |
+ − * +---+---+---+---+---+---+---+---+
+ − * | V(R) |C/R|
+ − * +---+---+---+---+---+---+---+---+
+ − * | X | X | X | X | W4| W3| W2| W1|
+ − * +---+---+---+---+---+---+---+---+
+ − */
+ − desc_data[octet++] = (UBYTE)(v_s >> 5) & 0x0F;
+ − desc_data[octet++] = (UBYTE)(v_s << 3) | ((UBYTE)(v_r >> 7) & 0x0003);
+ − desc_data[octet++] = (UBYTE)(v_r << 1) | (cr_bit EQ SGSN_COMMAND ?
+ − 0x00 : 0x01);
+ − desc_data[octet++] = reason & 0x0F;
+ −
+ − return;
+ − #endif
+ − } /* u_insert_frmr_information() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_sabm
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing
+ − | an SABM command, and sends this primitive to TX. _Before_ it is
+ − | sent to TX, T200 has to be started, because otherwise the
+ − | primitive may not be valid anymore.
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_sabm (void)
+ − {
+ − USHORT sdu_byte_len = 0;
+ − #ifdef LL_DESC
+ − T_desc3 *desc3;
+ − #endif
+ −
+ − TRACE_FUNCTION( "u_send_sabm" );
+ −
+ − u_tag_xid_parameters(0, TRUE);
+ −
+ − /*
+ − * Calculate bit length of tagged XID parameters. First, add
+ − * the size of each tagged parameter. The size of layer-3
+ − * parameters is variable, so add the given length in octets.
+ − */
+ − ADD_IF_TAGGED (sdu_byte_len, XID_VERSION);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_T200);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_N200);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_N201_U);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_N201_I);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_MD);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_MU);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_KD);
+ − ADD_IF_TAGGED (sdu_byte_len, XID_KU);
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3))
+ − {
+ − sdu_byte_len += llc_data->requested_l3_xid->length + 2;
+ − }
+ −
+ − /*
+ − * Add SDU header and FCS field to the XID response size to get
+ − * the overall SDU size.
+ − */
+ − sdu_byte_len += U_HDR_SIZE + FCS_SIZE;
+ −
+ − #ifdef LL_DESC
+ − {
+ − PALLOC(ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc((USHORT)sdu_byte_len, 0); /* One desc3 descriptor and buffer allocated */
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. For retransmission prim
+ − * data is copied in T200.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ −
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ − #endif /* REL99 */
+ − /*
+ − * Set parameter of descriptor list3
+ − */
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ −
+ − u_build_u_frame (&ll_unitdesc_req->desc_list3, MS_COMMAND,
+ − llc_data->current_sapi, 1, U_SABM);
+ −
+ − u_insert_xid (&ll_unitdesc_req->desc_list3, MS_COMMAND);
+ −
+ − /*
+ − * T200 has to be started _before_ the primitive is sent to TX, because
+ − * the primitive is copied by t200_start() and it may not be valid
+ − * anymore after sending to TX.
+ − */
+ − sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − #else
+ − {
+ − PALLOC_SDU (ll_unitdata_req, LL_UNITDATA_REQ, (USHORT)(sdu_byte_len*8));
+ −
+ − ll_unitdata_req->sapi = llc_data->current_sapi;
+ − ll_unitdata_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. For retransmission prim
+ − * data is copied in T200.
+ − */
+ − ll_unitdata_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdata_req->ll_qos.peak = LL_PEAK_SUB;
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdata_req->radio_prio = LL_RADIO_PRIO_1;
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdata_req->pkt_flow_id = LL_PFI_SIGNALING;
+ − #endif /* REL99 */
+ −
+ − u_build_u_frame (&ll_unitdata_req->sdu, MS_COMMAND,
+ − llc_data->current_sapi, 1, U_SABM);
+ −
+ − u_insert_xid (&ll_unitdata_req->sdu, MS_COMMAND);
+ −
+ − /*
+ − * T200 has to be started _before_ the primitive is sent to TX, because
+ − * the primitive is copied by t200_start() and it may not be valid
+ − * anymore after sending to TX.
+ − */
+ − sig_u_t200_start_req (ll_unitdata_req, GRLC_DTACS_DEF);
+ −
+ − sig_u_tx_data_req (ll_unitdata_req, GRLC_DTACS_DEF);
+ − }
+ − #endif
+ − return;
+ − } /* u_send_sabm() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_disc
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing
+ − | an DISC command, and sends this primitive to TX. _Before_ it is
+ − | sent to TX, T200 has to be started, because otherwise the
+ − | primitive may not be valid anymore.
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_disc (void)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ − TRACE_FUNCTION( "u_send_disc" );
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ,
+ − U_HDR_SIZE_BITS + FCS_SIZE_BITS);
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc((U_HDR_SIZE_BITS + FCS_SIZE_BITS)/8, 0);
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ − #endif
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. For retransmission prim
+ − * data is copied in T200.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ −
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ −
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ −
+ − #endif /* REL99 */
+ −
+ −
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_COMMAND,
+ − llc_data->current_sapi, 1, U_DISC
+ − );
+ −
+ − /*
+ − * T200 has to be started _before_ the primitive is sent to TX, because
+ − * the primitive is copied by t200_start() and it may not be valid
+ − * anymore after sending to TX.
+ − */
+ − sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − return;
+ − } /* u_send_disc() */
+ −
+ − #ifdef REL99
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : sig_tx_u_send_null
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing
+ − | an NULL command, and sends this primitive to TX.
+ − |
+ − | Parameters : cause - frame cause indicates grr about cell notification
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void sig_tx_u_send_null (UBYTE cause)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ − TRACE_FUNCTION( "sig_tx_u_send_null" );
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ,
+ − U_HDR_SIZE_BITS + FCS_SIZE_BITS);
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ − desc3 = llc_palloc_desc((U_HDR_SIZE_BITS + FCS_SIZE_BITS)/8, 0);
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ − #endif
+ − /*
+ − * Set TLLI for current transaction.
+ − */
+ − llc_data->u->current_tlli = llc_data->tlli_new;
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. For retransmission prim
+ − * data is copied in T200.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos.peak = GRLC_PEAK_SUB;
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = GRLC_RADIO_PRIO_1;
+ −
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_COMMAND,
+ − llc_data->current_sapi, 0, U_NULL
+ − );
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, cause);
+ − }
+ − return;
+ − } /* sig_tx_u_send_null() */
+ −
+ − #endif /* REL99 */
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ua
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing
+ − | an UA response with the given pf_bit setting, and sends this
+ − | primitive to TX. The parameter include_xid indicates if an
+ − | XID information field (according to llc_xid_tag) shall be
+ − | included (=TRUE) or not.
+ − |
+ − | Parameters : pf_bit - setting of the P/F bit in the received command
+ − | include_xid - include XID information field in frame, or not
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ua (T_BIT pf_bit,
+ − BOOL include_xid)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ − USHORT byte_len = 0;
+ −
+ −
+ − TRACE_FUNCTION( "u_send_ua" );
+ −
+ − if (include_xid EQ TRUE)
+ − {
+ −
+ − u_tag_xid_parameters(1, TRUE);
+ −
+ − /*
+ − * Calculate bit length of tagged XID parameters. First, add
+ − * the size of each tagged parameter. The size of layer-3
+ − * parameters is variable, so add the given length in octets.
+ − */
+ − ADD_IF_TAGGED (byte_len, XID_VERSION);
+ − ADD_IF_TAGGED (byte_len, XID_T200);
+ − ADD_IF_TAGGED (byte_len, XID_N200);
+ − ADD_IF_TAGGED (byte_len, XID_N201_U);
+ − ADD_IF_TAGGED (byte_len, XID_N201_I);
+ − ADD_IF_TAGGED (byte_len, XID_MD);
+ − ADD_IF_TAGGED (byte_len, XID_MU);
+ − ADD_IF_TAGGED (byte_len, XID_KD);
+ − ADD_IF_TAGGED (byte_len, XID_KU);
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3))
+ − {
+ − byte_len += llc_data->requested_l3_xid->length + 2;
+ − }
+ − }
+ −
+ − /*
+ − * Add data header and FCS field to the XID response size to get
+ − * the overall data size.
+ − */
+ − byte_len += U_HDR_SIZE + FCS_SIZE;
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, (USHORT)(byte_len*8));
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc((USHORT)(byte_len), 0);
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ −
+ − #endif
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. There is no retransmission.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ −
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ − #endif /* REL99 */
+ −
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_RESPONSE, llc_data->current_sapi, pf_bit, U_UA
+ − );
+ −
+ − if (include_xid EQ TRUE)
+ − {
+ − u_insert_xid
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_RESPONSE
+ − );
+ − }
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − llc_init_requested_xid_sapi(llc_data->current_sapi);
+ − return;
+ − } /* u_send_ua() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_dm
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | all required parameters, builds an U frame header containing a
+ − | DM response with the given pf_bit setting, and sends this
+ − | primitive to TX.
+ − |
+ − | Parameters : pf_bit - setting of the P/F bit in the received command
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_dm (T_BIT pf_bit)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ −
+ − TRACE_FUNCTION( "u_send_dm" );
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ,
+ − U_DM_SIZE_BITS + FCS_SIZE_BITS);
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc((U_DM_SIZE_BITS + FCS_SIZE_BITS)/8, 0);
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ − #endif
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. There is no retransmission.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ −
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ −
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ −
+ − #endif /* REL99 */
+ −
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_RESPONSE,
+ − llc_data->current_sapi, pf_bit, U_DM
+ − );
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − return;
+ − } /* u_send_dm() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_frmr
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing
+ − | an FRMR response, fills in the FRMR information field based on
+ − | the given frame, vs, vr, the cr_bit setting of frame
+ − | (SGSN_COMMAND/REPONSE), and the reason of the frame rejection
+ − | condition (lower nibble conforms to W4-W1 in FRMR response).
+ − | This primitive is then sent to TX.
+ − |
+ − | Parameters : frame - frame that caused the frame rejection condition
+ − | pdu_type - frame type
+ − | ctrl_length - control field length, if known
+ − | vs - current V(S)
+ − | vr - current V(R)
+ − | cr_bit - setting of C/R bit in frame
+ − | reason - reason of the frame rejection condition (lower
+ − | nibble conforms to W4-W1 in FRMR response)
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_frmr (T_LL_UNITDATA_IND *frame,
+ − T_PDU_TYPE pdu_type,
+ − USHORT ctrl_length,
+ − T_FRAME_NUM vs,
+ − T_FRAME_NUM vr,
+ − T_BIT cr_bit,
+ − UBYTE reason)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ −
+ − TRACE_FUNCTION( "u_send_frmr" );
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ,
+ − U_FRMR_SIZE_BITS + FCS_SIZE_BITS);
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc((U_FRMR_SIZE_BITS + FCS_SIZE_BITS)/8, 0);
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ − #endif
+ −
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->u->current_tlli;
+ − /*
+ − * No attach to primitive necessary. There is no retransmission.
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ −
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ −
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ −
+ − #endif /* REL99 */
+ −
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − MS_RESPONSE,
+ − llc_data->current_sapi, 1, U_FRMR
+ − );
+ −
+ − u_insert_frmr_information
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − frame, pdu_type,
+ − ctrl_length, vs, vr, cr_bit, reason
+ − );
+ −
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − return;
+ − } /* u_send_frmr() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_llgmm_status_ind
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LLGMM_STATUS_IND primitive, fills
+ − | in the error_cause parameter, and sends this primitive to GMM.
+ − |
+ − | Parameters : error_cause - LLGMM error cause
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − #ifdef CC_CONCEPT
+ − GLOBAL void u_send_llgmm_status_ind (USHORT error_cause)
+ − #else
+ − GLOBAL void u_send_llgmm_status_ind (UBYTE error_cause)
+ − #endif
+ − {
+ − TRACE_FUNCTION( "u_send_llgmm_status_ind" );
+ −
+ − {
+ − PALLOC (llgmm_status_ind, LLGMM_STATUS_IND); /* T_LLGMM_STATUS_IND */
+ −
+ − #ifdef LL_2to1
+ − llgmm_status_ind->ps_cause.ctrl_value = CAUSE_is_from_llc;
+ − llgmm_status_ind->ps_cause.value.llc_cause = error_cause;
+ − #else
+ − llgmm_status_ind->error_cause = error_cause;
+ − #endif
+ −
+ − PSEND (hCommGMM, llgmm_status_ind);
+ − }
+ −
+ − return;
+ − } /* u_send_llgmm_status_ind() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_release_cnf
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_RELEASE_CNF primitive, fills in
+ − | tlli and sapi parameters, and sends this primitive to SNDCP.
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ll_release_cnf (void)
+ − {
+ − TRACE_FUNCTION( "u_send_ll_release_cnf" );
+ −
+ − {
+ − PALLOC (ll_release_cnf, LL_RELEASE_CNF);
+ −
+ − ll_release_cnf->sapi = llc_data->current_sapi;
+ − TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi );
+ − PSEND (hCommSNDCP, ll_release_cnf);
+ − }
+ −
+ − llc_data->u->release_requested = FALSE;
+ −
+ − return;
+ − } /* u_send_ll_release_cnf() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_status_ind
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_STATUS_IND primitive, fills in
+ − | tlli, sapi and cause parameters and sends this proimitive to L3
+ − |
+ − | Parameters : cause - LL error cause
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − #ifdef CC_CONCEPT
+ − GLOBAL void u_send_ll_status_ind (USHORT cause)
+ − #else
+ − GLOBAL void u_send_ll_status_ind (UBYTE cause)
+ − #endif
+ − {
+ − TRACE_FUNCTION( "u_send_ll_status_ind" );
+ −
+ − {
+ − PALLOC (ll_status_ind, LL_STATUS_IND);
+ −
+ − ll_status_ind->sapi = llc_data->current_sapi;
+ − #ifdef LL_2to1
+ − ll_status_ind->ps_cause.ctrl_value = CAUSE_is_from_llc;
+ − ll_status_ind->ps_cause.value.llc_cause = cause;
+ − #else
+ − ll_status_ind->error_cause = cause;
+ − #endif
+ −
+ − TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi );
+ − PSEND (hCommSNDCP, ll_status_ind);
+ − }
+ −
+ − return;
+ − } /* u_send_ll_status_ind() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_xid_cnf
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_XID_CNF primitive, fills in
+ − | tlli, sapi and L3 parameter (if being negotiated), and sends
+ − | this primitive to SNDCP
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ll_xid_cnf (void)
+ − {
+ − TRACE_FUNCTION( "u_send_ll_xid_cnf" );
+ −
+ − if (llc_data->decoded_l3_xid.valid EQ TRUE)
+ − {
+ − PALLOC_SDU (ll_xid_cnf, LL_XID_CNF, (USHORT)(llc_data->decoded_l3_xid.length * 8));
+ −
+ − ll_xid_cnf->sdu.l_buf = llc_data->decoded_l3_xid.length * 8;
+ − ll_xid_cnf->sdu.o_buf = 0;
+ −
+ − memcpy (ll_xid_cnf->sdu.buf,
+ − llc_data->decoded_l3_xid.value,
+ − llc_data->decoded_l3_xid.length);
+ −
+ − ll_xid_cnf->sapi = llc_data->current_sapi;
+ −
+ − ll_xid_cnf->n201_u = *(llc_data->n201_u);
+ − ll_xid_cnf->n201_i = *(llc_data->n201_i);
+ −
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, llc_data->decoded_l3_xid.length );
+ − PSEND (hCommSNDCP, ll_xid_cnf);
+ − }
+ − else
+ − {
+ − PALLOC_SDU (ll_xid_cnf, LL_XID_CNF, 0);
+ −
+ − ll_xid_cnf->sdu.l_buf = 0;
+ − ll_xid_cnf->sdu.o_buf = 0;
+ −
+ − ll_xid_cnf->sapi = llc_data->current_sapi;
+ −
+ − ll_xid_cnf->n201_u = *(llc_data->n201_u);
+ − ll_xid_cnf->n201_i = *(llc_data->n201_i);
+ −
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, 0 );
+ − PSEND (hCommSNDCP, ll_xid_cnf);
+ − }
+ −
+ − return;
+ − } /* u_send_ll_xid_cnf() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_establish_ind
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_ESTABLISH_IND primitive, fills
+ − | in all necessary parameters using global LLC values (or in case
+ − | of L-3 XID parameters, using the parameters of received XID
+ − | cmd/res), and sends this primitive to SNDCP
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ll_establish_ind (void)
+ − {
+ − USHORT len;
+ −
+ − TRACE_FUNCTION( "u_send_ll_establish_ind" );
+ −
+ − if (llc_data->decoded_l3_xid.valid EQ TRUE)
+ − {
+ − len = (llc_data->decoded_l3_xid.length * 8);
+ − }
+ − else
+ − {
+ − len = 0;
+ − }
+ −
+ − {
+ − PALLOC_SDU (ll_establish_ind, LL_ESTABLISH_IND, len);
+ −
+ − if (llc_data->decoded_l3_xid.valid EQ TRUE)
+ − {
+ − ll_establish_ind->xid_valid = LL_XID_VALID;
+ −
+ − ll_establish_ind->sdu.o_buf = 0;
+ − ll_establish_ind->sdu.l_buf = llc_data->decoded_l3_xid.length * 8;
+ −
+ − memcpy (ll_establish_ind->sdu.buf,
+ − llc_data->decoded_l3_xid.value,
+ − llc_data->decoded_l3_xid.length);
+ − }
+ − else
+ − {
+ − ll_establish_ind->xid_valid = LL_XID_INVALID;
+ − }
+ −
+ − ll_establish_ind->sapi = llc_data->current_sapi;
+ −
+ − /*
+ − * evaluate N201_U
+ − */
+ − if (llc_data->u->requested_xid.n201_u.valid AND
+ − llc_data->decoded_xid.n201_u.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U,
+ − llc_data->decoded_xid.n201_u.value))
+ − {
+ − ll_establish_ind->n201_u = llc_data->u->requested_xid.n201_u.value;
+ − }
+ − else if (llc_data->u->requested_xid.n201_u.valid AND
+ − !llc_data->decoded_xid.n201_u.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U,
+ − *(llc_data->n201_u)))
+ − {
+ − ll_establish_ind->n201_u = llc_data->u->requested_xid.n201_u.value;
+ − }
+ − else
+ − {
+ − ll_establish_ind->n201_u = *(llc_data->n201_u);
+ − }
+ −
+ − /*
+ − * evaluate N201_I
+ − */
+ − if (llc_data->u->requested_xid.n201_i.valid AND
+ − llc_data->decoded_xid.n201_i.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I,
+ − llc_data->decoded_xid.n201_i.value))
+ − {
+ − ll_establish_ind->n201_i = llc_data->u->requested_xid.n201_i.value;
+ − }
+ − else if (llc_data->u->requested_xid.n201_i.valid AND
+ − !llc_data->decoded_xid.n201_i.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I,
+ − *(llc_data->n201_i)))
+ − {
+ − ll_establish_ind->n201_i = llc_data->u->requested_xid.n201_i.value;
+ − }
+ − else
+ − {
+ − ll_establish_ind->n201_i = *(llc_data->n201_i);
+ − }
+ −
+ −
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_establish_ind->sapi, len/8);
+ − PSEND (hCommSNDCP, ll_establish_ind);
+ −
+ − return;
+ − }
+ − } /* u_send_ll_establish_ind() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_establish_cnf
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_ESTABLISH_CNF primitive, fills
+ − | in all necessary parameters using global LLC values (or in case
+ − | of L-3 XID parameters, using the parameters of received XID
+ − | cmd/res), and sends this primitive to SNDCP
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ll_establish_cnf (void)
+ − {
+ − TRACE_FUNCTION( "u_send_ll_establish_cnf" );
+ −
+ − if (llc_data->decoded_l3_xid.valid EQ TRUE)
+ − {
+ − PALLOC_SDU (ll_establish_cnf, LL_ESTABLISH_CNF,
+ − (USHORT)(llc_data->decoded_l3_xid.length * 8));
+ −
+ − ll_establish_cnf->xid_valid = LL_XID_VALID;
+ −
+ − ll_establish_cnf->sdu.o_buf = 0;
+ − ll_establish_cnf->sdu.l_buf = llc_data->decoded_l3_xid.length * 8;
+ −
+ − memcpy (ll_establish_cnf->sdu.buf,
+ − llc_data->decoded_l3_xid.value,
+ − llc_data->decoded_l3_xid.length);
+ −
+ − ll_establish_cnf->sapi = llc_data->current_sapi;
+ −
+ − ll_establish_cnf->n201_u = *(llc_data->n201_u);
+ − ll_establish_cnf->n201_i = *(llc_data->n201_i);
+ −
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, llc_data->decoded_l3_xid.length );
+ − PSEND (hCommSNDCP, ll_establish_cnf);
+ − }
+ − else
+ − {
+ − PALLOC_SDU (ll_establish_cnf, LL_ESTABLISH_CNF, 0);
+ −
+ − ll_establish_cnf->xid_valid = LL_XID_INVALID;
+ −
+ − ll_establish_cnf->sapi = llc_data->current_sapi;
+ −
+ − ll_establish_cnf->n201_u = *(llc_data->n201_u);
+ − ll_establish_cnf->n201_i = *(llc_data->n201_i);
+ −
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", llc_data->current_sapi, 0 );
+ − PSEND (hCommSNDCP, ll_establish_cnf);
+ − }
+ −
+ − return;
+ − } /* u_send_ll_establish_cnf() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_release_ind
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_RELEASE_IND primitive, fills
+ − | in tlli, sapi and cause parameters, and sends this primitive
+ − | to SNDCP
+ − |
+ − | Parameters : cause - LL error cause
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − #ifdef CC_CONCEPT
+ − GLOBAL void u_send_ll_release_ind (USHORT cause)
+ − #else
+ − GLOBAL void u_send_ll_release_ind (UBYTE cause)
+ − #endif
+ − {
+ − TRACE_FUNCTION( "u_send_ll_release_ind" );
+ −
+ − {
+ − PALLOC (ll_release_ind, LL_RELEASE_IND);
+ −
+ − ll_release_ind->sapi = llc_data->current_sapi;
+ − #ifdef LL_2to1
+ − ll_release_ind->ps_cause.ctrl_value = CAUSE_is_from_llc;
+ − ll_release_ind->ps_cause.value.llc_cause = cause;
+ − #else
+ − ll_release_ind->cause = cause;
+ − #endif
+ −
+ − TRACE_1_OUT_PARA("s:%d", llc_data->current_sapi );
+ − PSEND (hCommSNDCP, ll_release_ind);
+ − }
+ −
+ − llc_data->u->release_requested = FALSE;
+ −
+ − return;
+ − } /* u_send_ll_release_ind() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_ll_xid_ind
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates an LL_XID_IND primitive, fills
+ − | in all necessary parameters using global LLC values (or in case
+ − | of L-3 XID parameters, using the parameters of received XID
+ − | cmd/res), and sends this primitive to SNDCP
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_ll_xid_ind (void)
+ − {
+ − TRACE_FUNCTION( "u_send_ll_xid_ind" );
+ −
+ −
+ −
+ − if (llc_data->decoded_l3_xid.valid EQ TRUE)
+ − {
+ − PALLOC_SDU (ll_xid_ind, LL_XID_IND, (USHORT)(llc_data->decoded_l3_xid.length * 8));
+ −
+ − llc_data->u->ll_xid_resp_pending = TRUE;
+ − ll_xid_ind->xid_valid = LL_XID_VALID;
+ −
+ − ll_xid_ind->sdu.o_buf = 0;
+ − ll_xid_ind->sdu.l_buf = llc_data->decoded_l3_xid.length * 8;
+ −
+ − memcpy (ll_xid_ind->sdu.buf,
+ − llc_data->decoded_l3_xid.value,
+ − llc_data->decoded_l3_xid.length);
+ −
+ − ll_xid_ind->sapi = llc_data->current_sapi;
+ −
+ − if (llc_data->u->requested_xid.n201_u.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_U,
+ − llc_data->decoded_xid.n201_u.value))
+ − {
+ − ll_xid_ind->n201_u = llc_data->u->requested_xid.n201_u.value;
+ − }
+ − else
+ − {
+ − ll_xid_ind->n201_u = *(llc_data->n201_u);
+ − }
+ −
+ − switch (ll_xid_ind->sapi)
+ − {
+ − case LL_SAPI_3:
+ − case LL_SAPI_5:
+ − case LL_SAPI_9:
+ − case LL_SAPI_11:
+ − if (llc_data->u->requested_xid.n201_i.valid AND
+ − !llc_xid_value_acceptable (llc_data->current_sapi, XID_N201_I,
+ − llc_data->decoded_xid.n201_i.value))
+ − {
+ − ll_xid_ind->n201_i = llc_data->u->requested_xid.n201_i.value;
+ − }
+ − else
+ − {
+ − ll_xid_ind->n201_i = *(llc_data->n201_i);
+ − }
+ − break;
+ −
+ − default:
+ − ll_xid_ind->n201_i = 0;
+ − break;
+ − }
+ −
+ − /*
+ − * Send primitive LL_XID_IND to either GMM, SNDCP, or GSMS,
+ − * depending on SAPI.
+ − */
+ − switch (ll_xid_ind->sapi)
+ − {
+ − case LL_SAPI_1:
+ − TRACE_PRIM_TO("GMM");
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length);
+ − PSEND (hCommGMM, ll_xid_ind);
+ − break;
+ − case LL_SAPI_3:
+ − case LL_SAPI_5:
+ − case LL_SAPI_9:
+ − case LL_SAPI_11:
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length);
+ − PSEND (hCommSNDCP, ll_xid_ind);
+ − break;
+ − case LL_SAPI_7:
+ − #ifdef LL_2to1
+ − TRACE_PRIM_TO("MM");
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length);
+ − PSEND (hCommMM, ll_xid_ind);
+ − #else
+ − TRACE_PRIM_TO("GSMS");
+ − TRACE_2_OUT_PARA("s:%d xid-len:%d", ll_xid_ind->sapi, llc_data->decoded_l3_xid.length);
+ − PSEND (hCommGSMS, ll_xid_ind);
+ − #endif
+ − break;
+ − default:
+ − PFREE (ll_xid_ind);
+ − TRACE_ERROR ("Invalid global SAPI value");
+ − break;
+ − }
+ − }
+ − else
+ − {
+ − PALLOC_SDU (ll_xid_ind, LL_XID_IND, 0);
+ −
+ − llc_data->u->ll_xid_resp_pending = FALSE;
+ −
+ − ll_xid_ind->xid_valid = LL_XID_INVALID;
+ −
+ − ll_xid_ind->sapi = llc_data->current_sapi;
+ −
+ − ll_xid_ind->n201_u = *(llc_data->n201_u);
+ −
+ − switch (ll_xid_ind->sapi)
+ − {
+ − case LL_SAPI_3:
+ − case LL_SAPI_5:
+ − case LL_SAPI_9:
+ − case LL_SAPI_11:
+ − ll_xid_ind->n201_i = *(llc_data->n201_i);
+ − break;
+ −
+ − default:
+ − ll_xid_ind->n201_i = 0;
+ − break;
+ − }
+ −
+ − /*
+ − * Send primitive LL_XID_IND to either GMM, SNDCP, or GSMS,
+ − * depending on SAPI.
+ − */
+ − switch (ll_xid_ind->sapi)
+ − {
+ − case LL_SAPI_1:
+ − TRACE_PRIM_TO("GMM");
+ − TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi);
+ − PSEND (hCommGMM, ll_xid_ind);
+ − break;
+ − case LL_SAPI_3:
+ − case LL_SAPI_5:
+ − case LL_SAPI_9:
+ − case LL_SAPI_11:
+ − TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi);
+ − PSEND (hCommSNDCP, ll_xid_ind);
+ − break;
+ − case LL_SAPI_7:
+ − #ifdef LL_2to1
+ − TRACE_PRIM_TO("MM");
+ − TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi);
+ − PSEND (hCommMM, ll_xid_ind);
+ − #else
+ − TRACE_PRIM_TO("GSMS");
+ − TRACE_1_OUT_PARA("s:%d no l3-xid", ll_xid_ind->sapi);
+ − PSEND (hCommGSMS, ll_xid_ind);
+ − #endif
+ − break;
+ − default:
+ − PFREE (ll_xid_ind);
+ − TRACE_ERROR ("invalid global SAPI value");
+ − break;
+ − }
+ − }
+ −
+ − return;
+ − } /* u_send_ll_xid_ind() */
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_tag_xid_parameters
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure tags requested parameters
+ − |
+ − |
+ − | Parameters :
+ − | - send_ack_para- used to include/ignore the ack para in XID-FRAME
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_tag_xid_parameters (T_BIT cr_bit, BOOL send_ack_para)
+ − {
+ − TRACE_FUNCTION( "u_tag_xid_parameters" );
+ −
+ − if (cr_bit EQ MS_RESPONSE)
+ − {
+ − /*
+ − * Do some special handling in case we want to set mD or mU to zero
+ − * (= disable buffered bytes counting) and the peer does not.
+ − */
+ − if (llc_data->decoded_xid.mu.valid)
+ − {
+ − u_handle_mX_zero_rsp ( llc_data->decoded_xid.mu.value,
+ − llc_data->n201_i,
+ − *(llc_data->mu), XID_MU_MAX,
+ − llc_data->ku, XID_KU_MIN, XID_KU );
+ − }
+ −
+ − if (llc_data->decoded_xid.md.valid)
+ − {
+ − u_handle_mX_zero_rsp ( llc_data->decoded_xid.md.value,
+ − llc_data->n201_i,
+ − *(llc_data->md), XID_MD_MAX,
+ − llc_data->kd, XID_KD_MIN, XID_KD );
+ − }
+ − }
+ −
+ − /*
+ − * Tag all possible requested XID parameter
+ − */
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − /*
+ − * In case we are sending a command, we can include all
+ − * parameters, as long they are valid.
+ − */
+ − TAG_IF_REQUESTED (u->requested_xid.version. , XID_VERSION);
+ − TAG_IF_REQUESTED (u->requested_xid.t200. , XID_T200);
+ − TAG_IF_REQUESTED (u->requested_xid.n200. , XID_N200);
+ − TAG_IF_REQUESTED (u->requested_xid.n201_u. , XID_N201_U);
+ − TAG_IF_REQUESTED (requested_l3_xid-> , XID_LAYER_3);
+ − if(send_ack_para)
+ − {
+ − TRACE_EVENT("COMMAND: ACK MODE PARAMETERS INCLUDED");
+ − TAG_IF_REQUESTED (u->requested_xid.n201_i. , XID_N201_I);
+ − TAG_IF_REQUESTED (u->requested_xid.md. , XID_MD);
+ − TAG_IF_REQUESTED (u->requested_xid.mu. , XID_MU);
+ − TAG_IF_REQUESTED (u->requested_xid.kd. , XID_KD);
+ − TAG_IF_REQUESTED (u->requested_xid.ku. , XID_KU);
+ − }
+ − else
+ − {
+ − llc_data->u->requested_xid.n201_i.valid = FALSE;
+ − llc_data->u->requested_xid.md.valid = FALSE;
+ − llc_data->u->requested_xid.mu.valid = FALSE;
+ − llc_data->u->requested_xid.kd.valid = FALSE;
+ − llc_data->u->requested_xid.ku.valid = FALSE;
+ − }
+ −
+ − }
+ − else
+ − {
+ − /*
+ − * In case we are sending a response, we can include all valid
+ − * parameters which are in line with the sense of negotiation.
+ − */
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_UP, n200, XID_N200);
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, n201_u, XID_N201_U);
+ −
+ − if(send_ack_para)
+ − {
+ − TRACE_EVENT("RESPONSE: ACK MODE PARAMETERS INCLUDED");
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, n201_i, XID_N201_I);
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, md, XID_MD);
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, mu, XID_MU);
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, kd, XID_KD);
+ − TAG_IF_REQUESTED_RSP (XID_SENSE_DOWN, ku, XID_KU);
+ − }
+ −
+ − if (llc_data->u->requested_xid.t200.valid)
+ − {
+ − if (llc_data->decoded_xid.t200.valid)
+ − {
+ − /* simple add parameter. Sense of negotiation is already checked */
+ − llc_data->u->xid_tag |= (0x00000001L << XID_T200);
+ − }
+ − else
+ − {
+ − /* Sense of negotiation compared with current values */
+ − if (llc_data->u->requested_xid.t200.value XID_SENSE_UP INT2XID(llc_data->t200->length))
+ − {
+ − llc_data->u->xid_tag |= (0x00000001L << XID_T200);
+ − }
+ − }
+ − }
+ − /*
+ − * L3 parameter cannot be included in response, if not included in
+ − * request
+ − */
+ −
+ − /*
+ − * If an XID parameter which was not included in the SGSN command,
+ − * but included in the MS Response, must be included in every Response
+ − * until the parameter is explicitly negotiated by the SGSN
+ − */
+ −
+ − if(llc_data->u->xid_tag_negotiate)
+ − {
+ − llc_data->u->xid_tag |= llc_data->u->xid_tag_negotiate;
+ − }
+ − }
+ − } /* u_tag_xid_parameters() */
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_send_xid
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure allocates a LL_UNITDATA_REQ primitive, fills in
+ − | the required parameters, builds an U frame header containing an
+ − | XID command/response (depending on the cr_bit setting), inserts
+ − | all XID parmameters that are to be negotiated, and sends this
+ − | primitive to TX. If a command frame is being sent (see cr_bit),
+ − | T200 has to be started _before_ the primitive is sent to TX,
+ − | because otherwise the primitive may not be valid anymore.
+ − |
+ − | NOTE: T200 must not be running, when an XID command is to be
+ − | sent. This must be ensured by the caller of u_send_xid().
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_send_xid (T_BIT cr_bit)
+ − {
+ − #ifdef LL_DESC
+ − T_desc3* desc3;
+ − #endif
+ − USHORT byte_len = 0;
+ −
+ − TRACE_FUNCTION( "u_send_xid" );
+ −
+ − /*
+ − * Calculate bit length of tagged XID parameters. First, add
+ − * the size of each tagged parameter. The size of layer-3
+ − * parameters is variable, so add the given length in octets.
+ − */
+ − ADD_IF_TAGGED (byte_len, XID_VERSION);
+ − ADD_IF_TAGGED (byte_len, XID_T200);
+ − ADD_IF_TAGGED (byte_len, XID_N200);
+ − ADD_IF_TAGGED (byte_len, XID_N201_U);
+ − /*Acknowledge Mode Parameters will be ignored in XID FRAME:
+ − ADD_IF_TAGGED (byte_len, XID_N201_I);
+ − ADD_IF_TAGGED (byte_len, XID_MD);
+ − ADD_IF_TAGGED (byte_len, XID_MU);
+ − ADD_IF_TAGGED (byte_len, XID_KD);
+ − ADD_IF_TAGGED (byte_len, XID_KU);
+ − */
+ − if (llc_data->u->xid_tag & (0x00000001L << XID_LAYER_3))
+ − {
+ − byte_len += llc_data->requested_l3_xid->length + 2;
+ − }
+ −
+ − /*
+ − * Add data header and FCS field to the XID response size to get
+ − * the overall data size.
+ − */
+ − byte_len += U_HDR_SIZE + FCS_SIZE;
+ −
+ − {
+ − #ifndef LL_DESC
+ − PALLOC_SDU (ll_unitdesc_req, LL_UNITDATA_REQ, (USHORT)(byte_len*8));
+ − #else
+ − PALLOC (ll_unitdesc_req, LL_UNITDESC_REQ);
+ −
+ − desc3 = llc_palloc_desc(byte_len, 0);
+ −
+ − ll_unitdesc_req->desc_list3.first = (ULONG)desc3;
+ − ll_unitdesc_req->desc_list3.list_len = desc3->len;
+ − #endif
+ − ll_unitdesc_req->sapi = llc_data->current_sapi;
+ − ll_unitdesc_req->tlli = llc_data->tlli_new;
+ − /*
+ − * LLC does not know the QoS profile.
+ − */
+ − ll_unitdesc_req->ll_qos = llc_data->cur_qos;
+ − TRACE_EVENT_P1("peak throughput = %d",llc_data->cur_qos.peak);
+ −
+ − /*
+ − * LLC signalling frames are always sent with highest priority.
+ − */
+ − ll_unitdesc_req->radio_prio = llc_data->cur_radio_prio;
+ − TRACE_EVENT_P1("radio priority = %d",llc_data->cur_radio_prio);
+ −
+ − #ifdef REL99
+ − /*
+ − * From 24.008 & 23.060 it is interpreted that for all signalling data, a
+ − * predefined PFI LL_PFI_SIGNALING shall be used.
+ − */
+ − ll_unitdesc_req->pkt_flow_id = llc_data->cur_pfi;
+ − TRACE_EVENT_P1("packet flow id = %d",llc_data->cur_pfi);
+ −
+ − #endif /* REL99 */
+ − /*
+ − * No attach to primitive necessary. For retransmission prim
+ − * data is copied in T200 (if requested).
+ − */
+ − ll_unitdesc_req->attached_counter = CCI_NO_ATTACHE;
+ −
+ − /*
+ − * Label U_SEND_XID_CONT
+ − */
+ −
+ − /*
+ − * pf_bit must always be 1 when XID cmd/res are being sent
+ − */
+ − u_build_u_frame
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − cr_bit, llc_data->current_sapi, 1, U_XID
+ − );
+ −
+ − u_insert_xid
+ − (
+ − #ifndef LL_DESC
+ − &ll_unitdesc_req->sdu,
+ − #else
+ − &ll_unitdesc_req->desc_list3,
+ − #endif
+ − cr_bit
+ − );
+ −
+ − if (cr_bit EQ MS_COMMAND)
+ − {
+ − /*
+ − * remember that an XID command is currently being sent
+ − */
+ − llc_data->u->xid_pending = TRUE;
+ −
+ − /*
+ − * T200 has to be started !before! the primitive is sent to TX.
+ − */
+ − sig_u_t200_start_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − /*
+ − * U frames are always sent with default cause
+ − */
+ − sig_u_tx_data_req (ll_unitdesc_req, GRLC_DTACS_DEF);
+ − }
+ −
+ − if (cr_bit EQ MS_RESPONSE)
+ − {
+ − llc_init_requested_xid_sapi(llc_data->current_sapi);
+ − }
+ −
+ − return;
+ − } /* u_send_xid() */
+ −
+ −
+ −
+ − /*
+ − +------------------------------------------------------------------------------
+ − | Function : u_handle_optimization
+ − +------------------------------------------------------------------------------
+ − | Description : This procedure adds the values of the requested XID parameter
+ − | to the decoded XID structure, if they are not included (as an
+ − | optimization issue).
+ − |
+ − | Parameters :
+ − |
+ − +------------------------------------------------------------------------------
+ − */
+ − GLOBAL void u_handle_optimization (void)
+ − {
+ −
+ − TRACE_FUNCTION ("u_handle_optimization");
+ −
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_VERSION) AND
+ − llc_data->decoded_xid.version.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.version.valid = TRUE;
+ − llc_data->decoded_xid.version.value = llc_data->u->requested_xid.version.valid
+ − ? llc_data->u->requested_xid.version.value
+ − : llc_data->version;
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_T200) AND
+ − llc_data->decoded_xid.t200.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.t200.valid = TRUE;
+ − llc_data->decoded_xid.t200.value = llc_data->u->requested_xid.t200.valid
+ − ? llc_data->u->requested_xid.t200.value
+ − : ((USHORT)INT2XID (llc_data->t200->length));
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N200) AND
+ − llc_data->decoded_xid.n200.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.n200.valid = TRUE;
+ − llc_data->decoded_xid.n200.value = llc_data->u->requested_xid.n200.valid
+ − ? llc_data->u->requested_xid.n200.value
+ − : *(llc_data->n200);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N201_U) AND
+ − llc_data->decoded_xid.n201_u.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.n201_u.valid = TRUE;
+ − llc_data->decoded_xid.n201_u.value = llc_data->u->requested_xid.n201_u.valid
+ − ? llc_data->u->requested_xid.n201_u.value
+ − : *(llc_data->n201_u);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_N201_I) AND
+ − llc_data->decoded_xid.n201_i.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.n201_i.valid = TRUE;
+ − llc_data->decoded_xid.n201_i.value = llc_data->u->requested_xid.n201_i.valid
+ − ? llc_data->u->requested_xid.n201_i.value
+ − : *(llc_data->n201_i);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_MD) AND
+ − llc_data->decoded_xid.md.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.md.valid = TRUE;
+ − llc_data->decoded_xid.md.value = llc_data->u->requested_xid.md.valid
+ − ? llc_data->u->requested_xid.md.value
+ − : *(llc_data->md);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_MU) AND
+ − llc_data->decoded_xid.mu.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.mu.valid = TRUE;
+ − llc_data->decoded_xid.mu.value = llc_data->u->requested_xid.mu.valid
+ − ? llc_data->u->requested_xid.mu.value
+ − : *(llc_data->mu);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_KD) AND
+ − llc_data->decoded_xid.kd.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.kd.valid = TRUE;
+ − llc_data->decoded_xid.kd.value = llc_data->u->requested_xid.kd.valid
+ − ? llc_data->u->requested_xid.kd.value
+ − : *(llc_data->kd);
+ − }
+ −
+ − if (llc_data->u->xid_tag_sent & (0x00000001L << XID_KU) AND
+ − llc_data->decoded_xid.ku.valid == FALSE )
+ − {
+ − llc_data->decoded_xid.ku.valid = TRUE;
+ − llc_data->decoded_xid.ku.value = llc_data->u->requested_xid.ku.valid
+ − ? llc_data->u->requested_xid.ku.value
+ − : *(llc_data->ku);
+ − }
+ −
+ −
+ − /*
+ − * Layer 3 XID must be included in resonse, if it was included in request
+ − */
+ −
+ − } /* u_handle_optimization() */
+ −
+ −