view src/g23m-gprs/sndcp/sndcp_sdas.c @ 382:7bdd370f6f59

doc/Voice-pseudo-modem: minor fixes
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 13 Jan 2018 21:47:32 +0000
parents 219afcfc6250
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GPRS (8441)
|  Modul   :  sndcp_sdas.c
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This modul is part of the entity SNDCP and implements all 
|             functions to handles the incoming process internal signals as  
|             described in the SDL-documentation (SD-statemachine)
+----------------------------------------------------------------------------- 
*/ 


#define ENTITY_SNDCP

/*==== INCLUDES =============================================================*/

#include "typedefs.h"    /* to get Condat data types */
#include "vsi.h"        /* to get a lot of macros */
#include "macdef.h"
#include "gsm.h"        /* to get a lot of macros */
#include "prim.h"       /* to get the definitions of used SAP and directions */

#include "dti.h"
#include "sndcp.h"        /* to get the global entity definitions */
#include "sndcp_f.h"       /* to get the functions to access the global arrays*/

#include "sndcp_sdaf.h"    /* to get the internal functions of this service */
#include "sndcp_nds.h"    /* to get signals to nd service */


/*==== CONST ================================================================*/

/*==== LOCAL VARS ===========================================================*/

/*==== PRIVATE FUNCTIONS ====================================================*/

/*==== PUBLIC FUNCTIONS =====================================================*/

/*
+------------------------------------------------------------------------------
| Function    : sig_cia_sda_cia_decomp_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CIA_SDA_CIA_DECOMP_IND
|
| Parameters  : cia_decomp_ind, p_id
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_cia_sda_cia_decomp_ind (T_CIA_DECOMP_IND* cia_decomp_ind, UBYTE p_id) 
{ 
  UBYTE sapi_index = 0;
  UBYTE sapi = 0;
  UBYTE nsapi= cia_decomp_ind->pdu_ref.ref_nsapi;
  BOOL rec = FALSE;
  T_SN_DATA_IND* sn_data_ind = NULL;

  TRACE_ISIG( "sig_cia_sda_cia_decomp_ind" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_nsapi_sapi(cia_decomp_ind->pdu_ref.ref_nsapi, &sapi);
  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];

  
  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
    case SDA_RECEIVE_FIRST_SEGMENT:
    case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
    case SDA_ESTABLISH_REQUESTED:
      {
       
        MALLOC(sn_data_ind, sizeof(T_SN_DATA_IND));

#ifdef _SNDCP_DTI_2_
        sn_data_ind->desc_list2.first = cia_decomp_ind->desc_list2.first;
        sn_data_ind->desc_list2.list_len = cia_decomp_ind->desc_list2.list_len;
#endif /*_SNDCP_DTI_2_*/

#ifdef SNDCP_TRACE_ALL

        sndcp_data->cia.cia_decomp_ind_number[nsapi] --;
        TRACE_EVENT_P1("number of cia_decomp_ind: % d",
                       sndcp_data->cia.cia_decomp_ind_number[nsapi]);
#endif /* SNDCP_TRACE_ALL */

        sn_data_ind->nsapi = nsapi;
        sn_data_ind->p_id = p_id;
        sda_is_nsapi_rec(nsapi, &rec);
        if (rec) {
          sda_set_nsapi_rec(nsapi, FALSE);
          sig_sda_nd_data_ind(nsapi, 
                              sn_data_ind, 
                              (UBYTE)cia_decomp_ind->pdu_ref.ref_npdu_num);
          sda_get_data_if_nec(sapi);
        } else {
          if (sndcp_data->sda->cur_sn_data_ind[nsapi] NEQ NULL)
          {
#ifndef NTRACE
#ifdef SNDCP_TRACE_ALL
            TRACE_EVENT_P1("Discard cur_sn.. in %s", sndcp_data->sda->state_name);
#endif /* SNDCP_TRACE_ALL */
#endif /* NTRACE */
            sda_delete_cur_sn_data_ind(nsapi);
          }
          sndcp_data->sda->cur_sn_data_ind[nsapi] = sn_data_ind;
          sndcp_data->sda->uncomp_npdu_num = 
                               (UBYTE)cia_decomp_ind->pdu_ref.ref_npdu_num;
          sndcp_set_nsapi_rec_state(nsapi, SDA_WAIT_NSAPI);
          sda_get_data_if_nec ( sapi );
        }
      }
      MFREE(cia_decomp_ind);
      break;
    default:
      TRACE_ERROR( "SIG_CIA_SDA_CIA_DECOMP_IND unexpected" );
      MFREE_PRIM(cia_decomp_ind); 
      break;
  }
} /* sig_cia_sda_cia_decomp_ind() */



/*
+------------------------------------------------------------------------------
| Function    : sig_mg_sda_delete_npdus
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_MG_SD_DELETE_NPDUS
|
| Parameters  : affected NSAPI, SAPI
| Pre         : If the affected SAPI no longer uses acknowledged LLC operation
|               mode, no LL_GETDATA_REQ shall be sent. So sndcp_sapi_state_ra
|               must already be set to MG_REL_PENDING before this functon is 
|               called (if that sub state is desired).
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_mg_sda_delete_npdus (UBYTE nsapi,
                                    UBYTE sapi) 
{ 
  UBYTE sapi_index = 0;

  TRACE_ISIG( "sig_mg_sda_delete_npdus" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];
  
  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
    case SDA_ESTABLISH_REQUESTED:
    case SDA_RECEIVE_FIRST_SEGMENT:
    case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
      if (sndcp_data->sda->cur_sn_data_ind[nsapi] != NULL) {
        sda_delete_cur_sn_data_ind(nsapi);
        sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
      } else {
        sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
      }
      break;
    case SDA_WAIT_NSAPI:
      if (sndcp_data->sda->cur_sn_data_ind[nsapi] != NULL) {
        USHORT sapi_state = MG_IDLE;

        sda_delete_cur_sn_data_ind(nsapi);
        /*
         * Does it make sense to request another acknowlegded segment or is
         * the whole SAPI now using only unacknowledged mode?
         */
        sndcp_get_sapi_state(sapi, &sapi_state);
        if ((sapi_state & MG_REL) == 0) {
          sda_get_data_if_nec(sapi);
        }
        sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
      } 
      break;
    default:
      TRACE_ERROR( "SIG_MG_SDA_DELETE_NPDUS unexpected" );
      break;
  }
} /* sig_mg_sda_delete_npdus() */


/*
+------------------------------------------------------------------------------
| Function    : sig_mg_sda_end_est
+------------------------------------------------------------------------------
| Description : Handles the signal PD_SD_END_EST
|
| Parameters  : affected sapi, success
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_mg_sda_end_est (UBYTE sapi, BOOL success)
{ 
  UBYTE sapi_index = 0;
  UBYTE nsapi = 0;

  TRACE_FUNCTION( "sig_pda_sda_est_cnf" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];

  /*
   * Send LL_GETDATA_REQ. 
   */
  if (success){
    sndcp_data->sda->llc_may_send = FALSE;
    sda_get_data_if_nec(sapi);
  }
  /*
   * All nsapis at this sapi that use ack mode, enter 
   * SDA_ESTABLISH_REQUESTED state.
   */
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
    UBYTE local_sapi = 0;
    BOOL used = FALSE;

    sndcp_is_nsapi_used(nsapi, &used);
    if (!used) {
      continue;
    }
    sndcp_get_nsapi_sapi(nsapi, &local_sapi);
    if (local_sapi == sapi) {
      switch( sndcp_get_nsapi_rec_state(nsapi) )
      {
        case SDA_ESTABLISH_REQUESTED:
        case SDA_RECEIVE_FIRST_SEGMENT:
        case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
        case SDA_WAIT_NSAPI:
        case SDA_ACK_DISCARD:
          sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
          break;
        default:
          TRACE_EVENT( "SIG_MG_SDA_END_EST unexpected for this NSAPI" );
          break;
      }
    }
  } /* for all nsapis */


} /* sig_mg_sda_end_est() */


/*
+------------------------------------------------------------------------------
| Function    : sig_mg_sda_getdata
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_MG_SD_GETDATA
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_mg_sda_getdata (UBYTE sapi, UBYTE nsapi) 
{ 
  UBYTE sapi_index = 0;

  TRACE_ISIG( "sig_mg_sda_getdata" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];
  
  switch( GET_STATE(SDA) )
  {
    case SDA_DEFAULT:
      sda_get_data_if_nec(sapi);
      sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
      break;
    default:
      TRACE_ERROR( "SIG_MG_SDA_GETDATA unexpected" );
      break;
  }
} /* sig_mg_sda_getdata() */


/*
+------------------------------------------------------------------------------
| Function    : sig_cia_sda_getdata
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_CIA_SDA_GETDATA
|
| Parameters  : sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_cia_sda_getdata (UBYTE sapi, UBYTE nsapi)
{

  TRACE_ISIG( "sig_cia_sda_getdata" );

  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
    case SDA_RECEIVE_FIRST_SEGMENT:
    case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
    case SDA_WAIT_NSAPI:
      sda_get_data_if_nec(sapi);
      break;
    default:
      TRACE_ERROR( "SIG_CIA_SDA_GETDATA unexpected" );
      break;
  }
} /* sig_cia_sda_getdata() */


/*
+------------------------------------------------------------------------------
| Function    : sig_nd_sda_getdata_req
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_ND_SDA_GETDATA_REQ
|
| Parameters  : affected sapi, affected nsapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_nd_sda_getdata_req (UBYTE sapi,
                                    UBYTE nsapi) 
{ 
  UBYTE sapi_index = 0;

  TRACE_ISIG( "sig_nd_sda_getdata_req" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_sapi_index(sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];
  
  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
    case SDA_RECEIVE_FIRST_SEGMENT:
    case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
      sda_set_nsapi_rec(nsapi, TRUE);
      break;
    case SDA_WAIT_NSAPI:
      if (sndcp_data->sda->cur_sn_data_ind[nsapi] != NULL) {
        /*
         * Send the just reassembled N-PDU (must be present because of state!).
         */
        sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
        sig_sda_nd_data_ind(nsapi, 
                            sndcp_data->sda->cur_sn_data_ind[nsapi], 
                            sndcp_data->sda->uncomp_npdu_num);
        sndcp_data->sda->cur_sn_data_ind[nsapi] = NULL;
        sda_get_data_if_nec(sapi);
      } else {
        /*
         * Set the receptive for the given nsapi.
         */
        sda_set_nsapi_rec(nsapi, TRUE);
      }
      break;
    default:
      TRACE_ERROR( "SIG_ND_SDA_GETDATA_REQ unexpected" );
      break;
  }
} /* sig_nd_sda_getdata_req() */

/*
+------------------------------------------------------------------------------
| Function    : sig_mg_sda_start_est
+------------------------------------------------------------------------------
| Description : Handles the signal PD_SD_START_EST
|
| Parameters  : affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_mg_sda_start_est (UBYTE sapi)
{ 
  UBYTE nsapi = 0;

  TRACE_FUNCTION( "sig_pda_sda_start_est" );
  
  /*
   * All nsapis at this sapi that use ack mode, enter 
   * SDA_ESTABLISH_REQUESTED state.
   */
  for (nsapi = 0; nsapi < SNDCP_NUMBER_OF_NSAPIS; nsapi ++) {
    UBYTE sapi_help = 0;
    BOOL used = FALSE;

    sndcp_is_nsapi_used(nsapi, &used);
    if (!used) {
      continue;
    }
    sndcp_get_nsapi_sapi(nsapi, &sapi_help);
    if (sapi_help == sapi) {
      switch( sndcp_get_nsapi_rec_state(nsapi) )
      {
        case SDA_ESTABLISH_REQUESTED:
        case SDA_RECEIVE_FIRST_SEGMENT:
        case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
        case SDA_WAIT_NSAPI:
          sndcp_set_nsapi_rec_state(nsapi, SDA_ESTABLISH_REQUESTED);
          break;
        default:
          TRACE_EVENT( "SIG_MG_SDA_START_EST unexpected for this NSAPI" );
          break;
      }
    }
  } /* for all nsapis */

} /* sig_mg_sda_start_est() */


/*
+------------------------------------------------------------------------------
| Function    : sig_pd_sda_data_ind
+------------------------------------------------------------------------------
| Description : Handles the signal PD_SD_DATA_IND
|
| Parameters  : *ll_data_ind - Ptr to primitive payload
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_pda_sda_data_ind ( T_LL_DATA_IND *ll_data_ind )
{ 
  UBYTE sapi_index = 0;
  BOOL valid = FALSE;
  UBYTE nsapi = 0;
  UBYTE sapi = 0;

  TRACE_FUNCTION( "sig_pda_sda_data_ind" );

   /*
    * set service instance according to sapi in primitive
    */
  sndcp_get_sapi_index(ll_data_ind->sapi, &sapi_index);
  sndcp_data->sda = & sndcp_data->sda_base[sapi_index];
  sda_get_nsapi(ll_data_ind, &nsapi);
  
  /*
   * LLC has now "used up" it's pending LL_GETDATA_REQ and will have 
   * to wait for the next one.
   */
  sndcp_data->sda->llc_may_send = FALSE;
  sapi = ll_data_ind->sapi;

  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
    case SDA_ESTABLISH_REQUESTED:
      /* 
       * Just discard the segment. Next segment will be requested after 
       * confirmation of establishment.
       */
      PFREE(ll_data_ind);
      ll_data_ind = NULL;
      break;

    case SDA_RECEIVE_FIRST_SEGMENT:
      /* 
       * Invalid segments are discarded without error notification
       */
      sda_is_seg_valid(ll_data_ind, &valid);
      if (!valid) {
        PFREE(ll_data_ind);
        sda_get_data_if_nec(sapi);
        return;
      }
      if (sda_f_bit(ll_data_ind)) {
        if (sda_m_bit(ll_data_ind)) {
          sda_ac_f_f1_m1(ll_data_ind);
        } else {
          sda_ac_f_f1_m0(ll_data_ind);
        }
      } else {
        sda_ac_f_f0(ll_data_ind);
      }
      
      break;

    case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
      /* 
       * Invalid segments are discarded without error notification
       */
      sda_is_seg_valid(ll_data_ind, &valid);
      if (!valid) {
        PFREE(ll_data_ind);
        sda_get_data_if_nec(sapi);
        return;
      }
      if (sda_f_bit(ll_data_ind)) {
        if (sda_m_bit(ll_data_ind)) {
          sda_ac_s_f1_m1(ll_data_ind);
        } else {
          sda_ac_s_f1_m0(ll_data_ind);
        }
      } else {
        if (sda_m_bit(ll_data_ind)) {
          sda_ac_s_f0_m1(ll_data_ind);
        } else {
          sda_ac_s_f0_m0(ll_data_ind);
        }
      }
      
      break;

    case SDA_WAIT_NSAPI:
      if (ll_data_ind != NULL)
      {
        PFREE(ll_data_ind);
      }
      sda_get_data_if_nec(sapi); 
      break;

    case SDA_ACK_DISCARD:
      /*
       * In this state we will discard every downlink segment till we receive.
       * the last segment.
       * Once we receive the last segment, we will move to the state
       * SDA_RECEIVE_FIRST_SEGMENT.
       */
      TRACE_EVENT( "SDA_ACK_DISCARD state,Discard Segments ..." );
      sndcp_data->cur_segment_number[nsapi] ++;
      if (!sda_m_bit(ll_data_ind))
      {
        TRACE_EVENT( "Received the last Segment in SDA_ACK_DISCARD state " );
        sndcp_data->cur_segment_number[nsapi] = 0;
        sndcp_set_nsapi_rec_state(nsapi, SDA_RECEIVE_FIRST_SEGMENT);
      }
      PFREE(ll_data_ind);
      sda_get_data_if_nec(sapi);
      break;

    default:
      TRACE_ERROR( "SIG_PDA_SDA_DATA_IND unexpected" );
      /*
       * The primitive LL_DATA_IND is unexpected or the
       * NSAPI value is wrong. Discard the prim and send a FC prim.
       */
      if (ll_data_ind != NULL)
      {
        PFREE(ll_data_ind);
      }
      sda_get_data_if_nec(sapi);
      break;
  }
  
} /* sig_pda_sda_data_ind() */


/*
+------------------------------------------------------------------------------
| Function    : sig_mg_sda_reset_ind
+------------------------------------------------------------------------------
| Description : Handles the internal signal SIG_MG_SDA_RESET_IND
|
| Parameters  : affected sapi
|
+------------------------------------------------------------------------------
*/
GLOBAL void sig_mg_sda_reset_ind (UBYTE nsapi) 
{ 

  TRACE_ISIG( "sig_mg_sda_reset_ind" );

  switch( sndcp_get_nsapi_rec_state(nsapi) )
  {
      case SDA_ESTABLISH_REQUESTED:
      case SDA_RECEIVE_FIRST_SEGMENT:
      case SDA_RECEIVE_SUBSEQUENT_SEGMENT:
      case SDA_WAIT_NSAPI:
      case SDA_ACK_DISCARD:
        /*
         * Similar to sd.
         */
        sndcp_data->cur_dcomp[nsapi] = 0;
        sndcp_data->cur_pcomp[nsapi] = 0;
      break;
    default:
      TRACE_ERROR( "SIG_MG_SDA_RESET_IND unexpected" );
      break;
  }
} /* sig_mg_sda_reset_ind() */