FreeCalypso > hg > fc-tourmaline
view src/g23m-gprs/llc/llc_rxp.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
line wrap: on
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 | functions to handles the incoming primitives as described in | the SDL-documentation (RX-statemachine) +----------------------------------------------------------------------------- */ #ifndef LLC_RXP_C #define LLC_RXP_C #endif #define ENTITY_LLC /*==== INCLUDES =============================================================*/ #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "macdef.h" #include "gprs.h" #include "gsm.h" /* to get a lot of macros */ #include "cnf_llc.h" /* to get cnf-definitions */ #include "mon_llc.h" /* to get mon-definitions */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include "llc.h" /* to get the global entity definitions */ #include "llc_rxf.h" /* to get local RX functions */ #include "llc_us.h" /* to get signal interface to U */ #include "llc_uirxs.h" /* to get signal interface to UIRX */ #include "llc_irxs.h" /* to get signal interface to IRX */ #ifdef _SIMULATION_ #include <string.h> /* to get memcpy() */ #endif /*==== CONST ================================================================*/ /*==== LOCAL VARS ===========================================================*/ /*==== PRIVATE FUNCTIONS ====================================================*/ #ifdef _SIMULATION_ LOCAL void rx_copy_test_primitive_data (T_GRLC_UNITDATA_IND_TEST *grlc_unitdata_ind_test, T_GRLC_UNITDATA_IND *grlc_unitdata_ind); #endif #ifndef CF_FAST_EXEC GLOBAL void rx_grlc_xdata_ind (T_GRLC_UNITDATA_IND *grlc_unitdata_ind); #endif /* CF_FAST_EXEC */ /*==== PUBLIC FUNCTIONS =====================================================*/ /* +------------------------------------------------------------------------------ | Function : rx_grlc_data_ind +------------------------------------------------------------------------------ | Description : Handles the primitive GRLC_DATA_IND | | Parameters : *grlc_data_ind - Ptr to primitive payload | +------------------------------------------------------------------------------ */ #ifndef CF_FAST_EXEC GLOBAL void rx_grlc_data_ind ( T_GRLC_DATA_IND *grlc_data_ind ) { TRACE_FUNCTION( "grlc_data_ind" ); switch( GET_STATE( RX ) ) { case RX_TLLI_ASSIGNED: { /* * Both primitives are treated the same way and contain the same * information. */ PPASS (grlc_data_ind, grlc_unitdata_ind, GRLC_UNITDATA_IND); /* * Primitive is handled in rx_grlc_xdata_ind(). */ rx_grlc_xdata_ind (grlc_unitdata_ind); break; } default: PFREE_DESC (grlc_data_ind); TRACE_ERROR( "GRLC_DATA_IND unexpected" ); break; } } /* rx_grlc_data_ind() */ #endif /* CF_FAST_EXEC */ /* +------------------------------------------------------------------------------ | Function : rx_grlc_unitdata_ind +------------------------------------------------------------------------------ | Description : Handles the primitive GRLC_UNITDATA_IND | | Parameters : *grlc_unitdata_ind - Ptr to primitive payload | +------------------------------------------------------------------------------ */ #ifndef CF_FAST_EXEC GLOBAL void rx_grlc_unitdata_ind ( T_GRLC_UNITDATA_IND *grlc_unitdata_ind ) { TRACE_FUNCTION( "grlc_unitdata_ind" ); switch( GET_STATE( RX ) ) { case RX_TLLI_ASSIGNED: /* * Primitive is handled in rx_grlc_xdata_ind(). */ rx_grlc_xdata_ind (grlc_unitdata_ind); break; default: PFREE_DESC (grlc_unitdata_ind); TRACE_ERROR( "GRLC_UNITDATA_IND unexpected" ); break; } } /* rx_grlc_unitdata_ind() */ #endif /* CF_FAST_EXEC */ /* +------------------------------------------------------------------------------ | Function : rx_cci_decipher_cnf +------------------------------------------------------------------------------ | Description : Handles the primitive CCI_DECIPHER_CNF. | Note: The type LL_UNITDATA_IND is used instead to avoid PPASS . | | Parameters : *ll_unitdata_ind - Ptr to primitive payload | +------------------------------------------------------------------------------ */ /*#if defined(CF_FAST_EXEC) || defined(_SIMULATION_) || \ defined(LL_2to1) */ GLOBAL void rx_cci_decipher_cnf ( T_LL_UNITDATA_IND *ll_unitdata_ind) { UBYTE cipher; T_PDU_TYPE frame_type; T_COMMAND command; T_BIT cr_bit; T_BIT pf_bit; T_FRAME_NUM nr; T_FRAME_NUM ns; BOOL frame_ok; UBYTE frame_rej; USHORT frame_rej_ctrl_length; USHORT ctrl_len; TRACE_FUNCTION( "rx_cci_decipher_cnf" ); cipher = ll_unitdata_ind->cipher; switch( GET_STATE( RX ) ) { case RX_TLLI_ASSIGNED: /* variable sapi is "misused" for fcs_check value */ if (ll_unitdata_ind->sapi EQ CCI_FCS_PASSED) { { /* * Label INTERPRET */ rx_interpret_frame (&ll_unitdata_ind->sdu, &ll_unitdata_ind->sapi, &frame_type, &command, &cr_bit, &pf_bit, &nr, &ns, &frame_ok, &frame_rej, &frame_rej_ctrl_length, cipher); SWITCH_LLC (ll_unitdata_ind->sapi); /* * In case of I-frames check, if the information field exceeds N201-I */ if (frame_type == I_FRAME) { ctrl_len = I_CTRL_MIN_OCTETS; /* * Add sizeof SACK-Bitmap, if necessarry (add K+1) */ if (command == I_SACK) { ctrl_len += (ll_unitdata_ind->sdu.buf[(ll_unitdata_ind->sdu.o_buf/8)+4] & 0x1F) + 1; } if (BYTELEN(ll_unitdata_ind->sdu.l_buf) > *(llc_data->n201_i) + ctrl_len) { frame_ok = FALSE; frame_rej = FRMR_W2; TRACE_0_INFO("Received frame violates N201-I: send FRMR"); } } /* * frame_ok includes: correct frame length, PD bit == 0, SAPI valid, * FCS correct, known PDU type. */ if (frame_ok EQ TRUE) { rx_strip_llc_header (&ll_unitdata_ind->sdu, frame_type, command); /* * Label S_DATA */ switch (frame_type) { case U_FRAME: /* * Label U_FRAME */ /* * Service u_frames receives the SDU within the allocated UNITDATA * primitive. */ sig_rx_u_data_ind (ll_unitdata_ind, command, cr_bit, pf_bit); break; case UI_FRAME: /* * Label UI_FRAME */ sig_rx_uirx_data_ind (ll_unitdata_ind, nr); break; case S_FRAME: /* * No break. S frames and I frames are treated the same way. */ case I_FRAME: /* * Label I_FRAME */ sig_rx_irx_data_ind (ll_unitdata_ind, command, frame_type, cr_bit, pf_bit, ns, nr); break; default: PFREE (ll_unitdata_ind); TRACE_ERROR ("unknown frame type"); break; } } else /* frame_ok EQ FALSE */ { /* * Check if frame rejection condition occurred, and if U has to be * informed. */ if (frame_rej EQ FRAME_NOT_REJ) { TRACE_0_INFO("Frame ignored due to decode problem"); PFREE (ll_unitdata_ind); } else /* W1 bit and/or W3 bit set */ { /* * Inform U of the frame rejection condition. */ TRACE_0_INFO("Frame rejected due to decode problem"); sig_rx_u_frmr_ind (ll_unitdata_ind, frame_type, frame_rej_ctrl_length, cr_bit, frame_rej); } } } /* end of validity range of ll_unitdata_ind */ } else /* fcs_check EQ CCI_FCS_FAILED */ { #ifdef TRACE_EVE UBYTE sapi; rx_interpret_frame (&ll_unitdata_ind->sdu, &sapi, &frame_type, &command, &cr_bit, &pf_bit, &nr, &ns, &frame_ok, &frame_rej, &frame_rej_ctrl_length, cipher); #endif TRACE_0_INFO("Frame discarded due to FCS"); PFREE (ll_unitdata_ind); } break; default: PFREE(ll_unitdata_ind); TRACE_ERROR( "CCI_DECIPHER_CNF unexpected" ); break; } } /* rx_cci_decipher_cnf() */ /*#endif */ /* CF_FAST_EXEC || _SIMULATION_ */ /* +------------------------------------------------------------------------------ | Function : rx_grlc_data_ind_test +------------------------------------------------------------------------------ | Description : Handles the primitive GRLC_DATA_IND_TEST | NOTE: This is only necessary in simulation environment. | | Parameters : *grlc_data_ind_test - Ptr to primitive payload | +------------------------------------------------------------------------------ */ #ifdef _SIMULATION_ GLOBAL void rx_grlc_data_ind_test ( T_GRLC_DATA_IND_TEST *grlc_data_ind_test ) { TRACE_FUNCTION( "grlc_data_ind_test" ); switch( GET_STATE( RX ) ) { case RX_TLLI_ASSIGNED: { /* * Allocate a "normal" GRLC_UNITDATA_IND primitive and copy the data * of the test primitive GRLC_DATA_IND_TEST (sdu) to * GRLC_UNITDATA_IND (desc_list). */ PALLOC_DESC (grlc_unitdata_ind, GRLC_UNITDATA_IND); grlc_unitdata_ind->tlli = grlc_data_ind_test->tlli; rx_copy_test_primitive_data ((T_GRLC_UNITDATA_IND_TEST *)grlc_data_ind_test, grlc_unitdata_ind); /* * Free the received test primitive. */ PFREE (grlc_data_ind_test); /* * Primitive is handled in rx_grlc_xdata_ind(). */ rx_grlc_xdata_ind (grlc_unitdata_ind); break; } default: PFREE (grlc_data_ind_test); TRACE_ERROR( "GRLC_DATA_IND_TEST unexpected" ); break; } } /* rx_grlc_data_ind_test() */ #endif /* _SIMULATION_ */ /* +------------------------------------------------------------------------------ | Function : rx_grlc_unitdata_ind_test +------------------------------------------------------------------------------ | Description : Handles the primitive GRLC_UNITDATA_IND_TEST | NOTE: This is only necessary in simulation environment. | | Parameters : *grlc_unitdata_ind_test - Ptr to primitive payload | +------------------------------------------------------------------------------ */ #ifdef _SIMULATION_ GLOBAL void rx_grlc_unitdata_ind_test ( T_GRLC_UNITDATA_IND_TEST *grlc_unitdata_ind_test ) { TRACE_FUNCTION( "grlc_unitdata_ind_test" ); switch( GET_STATE( RX ) ) { case RX_TLLI_ASSIGNED: { /* * Allocate a "normal" GRLC_UNITDATA_IND primitive and copy the data * of the test primitive GRLC_UNITDATA_IND_TEST (sdu) to * GRLC_UNITDATA_IND (desc_list). */ PALLOC_DESC (grlc_unitdata_ind, GRLC_UNITDATA_IND); grlc_unitdata_ind->tlli = grlc_unitdata_ind_test->tlli; rx_copy_test_primitive_data (grlc_unitdata_ind_test, grlc_unitdata_ind); /* * Free the received test primitive. */ PFREE (grlc_unitdata_ind_test); /* * Primitive is handled in rx_grlc_xdata_ind(). */ rx_grlc_xdata_ind (grlc_unitdata_ind); break; } default: PFREE (grlc_unitdata_ind_test); TRACE_ERROR( "GRLC_UNITDATA_IND_TEST unexpected" ); break; } } /* rx_grlc_unitdata_ind_test() */ #endif /* _SIMULATION_ */ /* +------------------------------------------------------------------------------ | Function : rx_copy_test_primitive_data +------------------------------------------------------------------------------ | Description : Copies the data of a TEST primitive (sdu) to a normal | primitive (desc_list). | ATTENTION: All other parameters of the primitives are left | untouched and are not copied by this function! | | Parameters : *grlc_unitdata_ind_test - source primitive | *grlc_unitdata_ind - destination primitive | +------------------------------------------------------------------------------ */ #ifdef _SIMULATION_ LOCAL void rx_copy_test_primitive_data (T_GRLC_UNITDATA_IND_TEST *grlc_unitdata_ind_test, T_GRLC_UNITDATA_IND *grlc_unitdata_ind) { #define FRAG_LEN 80 /* value + 6 must fit in an pool with lots of entries */ T_sdu *sdu; T_desc *desc; T_desc *last_desc = NULL; int sdu_index; int length; sdu = &grlc_unitdata_ind_test->sdu; /* * Begin at the first relevant octet. */ sdu_index = sdu->o_buf/8; /* * Initialise descriptor list length. */ grlc_unitdata_ind->desc_list.list_len = 0; /* * Copy complete SDU to descriptor list using descriptors of max. 10 bytes. */ while (sdu_index < sdu->l_buf/8) { /* * Calculate length of descriptor data (= length of remaining sdu buffer * with a maximum of FRAG_LEN) */ length = (sdu_index+FRAG_LEN < sdu->l_buf/8) ? FRAG_LEN : (sdu->l_buf/8 - sdu_index); /* * Allocate the necessary size for the data descriptor. The size is * calculated as follows: * - take the size of a descriptor structure * - subtract one because of the array buffer[1] to get the size of * descriptor control information * - add number of octets of descriptor data */ MALLOC (desc, (USHORT)(sizeof(T_desc) - 1 + length)); /* * Fill descriptor control information. */ desc->next = (ULONG)NULL; desc->len = length; /* * Add length of descriptor data to list length. */ grlc_unitdata_ind->desc_list.list_len += length; /* * Copy user data from SDU to descriptor. */ memcpy (desc->buffer, &sdu->buf[sdu_index], length); sdu_index += length; if (last_desc) { /* * Add this descriptor (not the first) to the descriptor list. */ last_desc->next = (ULONG)desc; } else { /* * Insert first descriptor in descriptor list. */ grlc_unitdata_ind->desc_list.first = (ULONG)desc; } /* * Store this descriptor for later use. */ last_desc = desc; } return; } /* rx_copy_test_primitive_data */ #endif /* _SIMULATION_ */ /* +------------------------------------------------------------------------------ | Function : rx_grlc_xdata_ind +------------------------------------------------------------------------------ | Description : Handles the primitives GRLC_DATA_IND / GRLC_UNITDATA_IND. | | Parameters : *grlc_unitdata_ind - Ptr to primitive payload | +------------------------------------------------------------------------------ */ #ifndef CF_FAST_EXEC GLOBAL void rx_grlc_xdata_ind ( T_GRLC_UNITDATA_IND *grlc_unitdata_ind ) { T_PDU_TYPE frame_type; UBYTE protected_mode; UBYTE sapi; T_FRAME_NUM ns; BOOL ciphering; USHORT header_size; BOOL frame_ok; TRACE_FUNCTION( "grlc_xdata_ind" ); /* * Unassigning old TLLI * * GMM has to be informed, that new TLLI has been received. So GMM can unassign old TLLI * and old PTMSI in GRLC * Old tlli will be unassigned here. Normally GMM has to sent LLGMM_ASSIGN_REQ with * new_tlli != all 1's and old_tlli == all 1,s. See 04.64 cp. 6.1 <R.LLC.TLLI_ASS.A.002> */ #ifdef LL_2to1 if ( PS_TLLI_INVALID != llc_data->tlli_old #else if ( LLGMM_TLLI_INVALID != llc_data->tlli_old #endif && grlc_unitdata_ind->tlli != llc_data->tlli_old ) { PALLOC ( llgmm_tlli_ind, LLGMM_TLLI_IND ); llgmm_tlli_ind->new_tlli = grlc_unitdata_ind->tlli; #ifdef LL_2to1 llc_data->tlli_old = PS_TLLI_INVALID; #else llc_data->tlli_old = LLGMM_TLLI_INVALID; #endif PSEND ( hCommGMM, llgmm_tlli_ind); } rx_analyse_ctrl_field (grlc_unitdata_ind, &frame_type, &protected_mode, &sapi, &ns, &ciphering, &header_size, &frame_ok); if (frame_ok EQ TRUE) { /* * Check, if the sapi of the frame is supported. If ok, switch context * and handle the frame. */ switch (sapi) { case LL_SAPI_1: case LL_SAPI_3: case LL_SAPI_5: case LL_SAPI_7: case LL_SAPI_9: case LL_SAPI_11: SWITCH_LLC (sapi); rx_send_decipher_req (grlc_unitdata_ind, frame_type, protected_mode, ns, header_size, ciphering); /* * Free only the primitive (desc_list copied in rx_send_decipher_req) */ PFREE (grlc_unitdata_ind); /* Do not use PFREE_DESC here !*/ break; default: /* * Ignore frame. * Free prim and desc_list, because they are not used further */ PFREE_DESC (grlc_unitdata_ind); TRACE_0_INFO("Frame received for reserved SAPI"); break; } } else /* frame_ok NEQ TRUE */ { /* * Free GRLC_UNITDATA_IND along with complete descriptor list. */ PFREE_DESC (grlc_unitdata_ind); TRACE_EVENT("Frame ignored!"); } return; } /* rx_grlc_xdata_ind() */ #endif /* CF_FAST_EXEC */