view src/g23m-gprs/upm/upm_sndcp_control.c @ 624:012028896cfb

FFS dev.c, Leonardo target: Fujitsu MB84VF5F5F4J2 #if 0'ed out The FFS code we got from TI/Openmoko had a stanza for "Fujitsu MB84VF5F5F4J2 stacked device", using a fake device ID code that would need to be patched manually into cfgffs.c (suppressing and overriding autodetection) and using an FFS base address in the nCS2 bank, indicating that this FFS config was probably meant for the MCP version of Leonardo which allows for 16 MiB flash with a second bank on nCS2. We previously had this FFS config stanza conditionalized under CONFIG_TARGET_LEONARDO because the base address contained therein is invalid for other targets, but now that we actually have a Leonardo build target in FC Magnetite, I realize that the better approach is to #if 0 out this stanza altogether: it is already non-functional because it uses a fake device ID code, thus it is does not add support for more Leonardo board variants, instead it is just noise.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 22 Dec 2019 21:24:29 +0000
parents 2cf312e56ee7
children
line wrap: on
line source

/*----------------------------------------------------------------------------
|  Project :  3G PS
|  Module  :  UPM
+-----------------------------------------------------------------------------
|             Copyright 2003 Texas Instruments.
|             All rights reserved. 
| 
|             This file is confidential and a trade secret of Texas 
|             Instruments .
|             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. 
+-----------------------------------------------------------------------------
| Purpose:    SNDCP Control state machine implementation in the UPM entity.
|             For design details, see:
|             8010.939 UPM Detailed Specification
+---------------------------------------------------------------------------*/

/*==== DECLARATION CONTROL =================================================*/

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

#include "upm.h"

#include "upm_sndcp_control.h"
#include "upm_sndcp_output_handler.h"
#include "upm_aci_output_handler.h"
#include "upm_sm_output_handler.h"
#include "upm_mm_output_handler.h"

/*==== CONSTS ===============================================================*/

/*==== TYPES ================================================================*/

typedef void (*T_UPM_SNDCP_CONTROL_TRANSITION_FUNC)(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);

typedef struct {
#ifdef DEBUG
  T_UPM_SNDCP_CONTROL_EVENT            event;
#endif /* DEBUG */
  T_UPM_SNDCP_CONTROL_TRANSITION_FUNC  func;
} T_UPM_SNDCP_CONTROL_TRANSITION;

/*==== LOCALS ===============================================================*/

static void state_event_error   (struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void ignored             (struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_passive_activate(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_active_activate(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_passive_activate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_active_activate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_deactivate   (struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_sn_deactivate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_modify_llc_link(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_sn_modify_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_mmpm_sequence_ind(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);
static void handle_status_ind   (struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data);

/***********************************************************************
 * State/Transition Table
 */
static const T_UPM_SNDCP_CONTROL_TRANSITION
transition[UPM_SNDCP_CONTROL_NUMBER_OF_STATES]
          [UPM_LINK_CONTROL_NUMBER_OF_EVENTS] =
{
  { /* S0: UPM SNDCP INACTIVE */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          state_event_error),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        state_event_error),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            state_event_error),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            state_event_error),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        state_event_error),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    handle_passive_activate),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, handle_active_activate),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   state_event_error)
  },
  { /* S1: UPM SNDCP AWAIT ACTIVATE */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          handle_passive_activate_cnf),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        state_event_error),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            state_event_error),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            handle_status_ind),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        state_event_error),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, state_event_error),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   handle_deactivate)
  },
  { /* S2: UPM SNDCP ACTIVATING */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          handle_active_activate_cnf),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        state_event_error),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            state_event_error),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            handle_status_ind),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        state_event_error),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, state_event_error),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   handle_deactivate)
  },
  { /* S3: UPM SNDCP ACTIVE */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          state_event_error),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        state_event_error),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            state_event_error),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            handle_status_ind),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        handle_mmpm_sequence_ind),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, state_event_error),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    handle_modify_llc_link),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   handle_deactivate)
  },
  { /* S4: UPM SNDCP MODIFYING */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          state_event_error),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        state_event_error),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            handle_sn_modify_cnf),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            handle_status_ind),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        handle_mmpm_sequence_ind),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, state_event_error),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   handle_deactivate)
  },
  { /* S5: UPM SNDCP DEACTIVATING */
    M_TRANSITION(UPM_P_SN_ACTIVATE_CNF,          state_event_error),
    M_TRANSITION(UPM_P_SN_DEACTIVATE_CNF,        handle_sn_deactivate_cnf),
    M_TRANSITION(UPM_P_SN_MODIFY_CNF,            ignored),
    M_TRANSITION(UPM_P_SN_STATUS_IND,            handle_status_ind),
    M_TRANSITION(UPM_P_MMPM_SEQUENCE_IND,        state_event_error),
    M_TRANSITION(UPM_I_SNDCP_AWAIT_ESTABLISH,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_ESTABLISH_LLC_LINK, state_event_error),
    M_TRANSITION(UPM_I_SNDCP_MODIFY_LLC_LINK,    state_event_error),
    M_TRANSITION(UPM_I_SNDCP_RELEASE_LLC_LINK,   ignored)
  }
};

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

/*
+------------------------------------------------------------------------------
| Function    : state_event_error
+------------------------------------------------------------------------------
| Description : General function used to report state event errors.
|
| Parameters  : ptr_context_data - Not used
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void state_event_error(/*@unused@*/ struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_ERROR("UPM SNDCP Control: STATE EVENT ERROR!");
}

/*
+------------------------------------------------------------------------------
| Function    : ignored
+------------------------------------------------------------------------------
| Description : General function used for transitions that shall be ignored
|
| Parameters  : ptr_context_data - Not used
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void ignored (/*@unused@*/ struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("UPM SNDCP Control: Event ignored.");
}

/*
+------------------------------------------------------------------------------
| Function    : handle_passive_activate
+------------------------------------------------------------------------------
| Description : Handle UPM_I_SNDCP_AWAIT_ESTABLISH in S0
|
| Parameters  : ptr_context_data - Context data
|               data             - Pointer to compression parameters
+------------------------------------------------------------------------------
*/
static void handle_passive_activate(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_passive_activate");

  /* Send SN_ACTIVATE_REQ with establish flag == FALSE */
  send_sn_activate_req(ptr_context_data, (T_NAS_comp_params *)data, FALSE);

  /* Go to state UPM SNDCP AWAIT ACTIVATE */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_AWAIT_ACTIVATE;

#ifndef UPM_WITHOUT_USER_PLANE
  /* Suspend Uplink Data */
  upm_uplink_data_control(ptr_context_data, UPM_I_UPLINK_DATA_SUSPEND,
                          (void *)UPM_LINK);
#endif /* UPM_WITHOUT_USER_PLANE */
}

/*
+------------------------------------------------------------------------------
| Function    : handle_active_activate
+------------------------------------------------------------------------------
| Description : Handle UPM_I_SNDCP_ESTABLISH_LLC_LINK in S0
|
| Parameters  : ptr_context_data - Context data
|               data             - Pointer to compression parameters
+------------------------------------------------------------------------------
*/
static void handle_active_activate(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_active_activate");

  /* Send SN_ACTIVATE_REQ with establish flag == TRUE */
  send_sn_activate_req(ptr_context_data, (T_NAS_comp_params *)data, TRUE);

  /* Go to state UPM SNDCP ACTIVATING */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_ACTIVATING;
}

/*
+------------------------------------------------------------------------------
| Function    : handle_passive_activate_cnf
+------------------------------------------------------------------------------
| Description : Handle UPM_P_SN_ACTIVATE_CNF in S1
|
| Parameters  : ptr_context_data - Context data
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void handle_passive_activate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_passive_activate_cnf");

  /* Go to state UPM SNDCP ACTIVE */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_ACTIVE;

#ifndef UPM_WITHOUT_USER_PLANE
  /* Resume Uplink Data */
  upm_uplink_data_control(ptr_context_data, UPM_I_UPLINK_DATA_RESUME,
                          (void *)UPM_LINK);
#endif /* UPM_WITHOUT_USER_PLANE */

  /* Report link establishment to Link Control */
  upm_link_control(ptr_context_data, UPM_I_SNDCP_LLC_LINK_ESTABLISHED, NULL);
}

/*
+------------------------------------------------------------------------------
| Function    : handle_active_activate_cnf
+------------------------------------------------------------------------------
| Description : Handle UPM_P_SN_ACTIVATE_CNF in S2
|
| Parameters  : ptr_context_data - Context data
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void handle_active_activate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_active_activate_cnf");

  /* Go to state UPM SNDCP ACTIVE */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_ACTIVE;

  /* Report link establishment to Link Control */ 
  upm_link_control(ptr_context_data, UPM_I_SNDCP_LLC_LINK_ESTABLISHED, 
    ((T_SN_ACTIVATE_CNF*)data)); /*To pass comp params*/
}

/*
+------------------------------------------------------------------------------
| Function    : handle_deactivate
+------------------------------------------------------------------------------
| Description : Handle UPM_I_SNDCP_RELEASE_LLC_LINK in S1, S2, S3, or S4.
|
| Parameters  : ptr_context_data - Context data
|               data             - Local flag (rel_ind)
+------------------------------------------------------------------------------
*/
static void handle_deactivate(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void *data)
{
  U32  rel_ind = (U32)data;
  (void)TRACE_FUNCTION("handle_deactivate");

  /* SN_DEACTIVATE_REQ no longer sent in dispatcher function, so send here. */
  send_sn_deactivate_req( ptr_context_data->nsapi, (U8)rel_ind);

  /* Go to state UPM SNDCP DEACTIVATING */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_DEACTIVATING;
}

/*
+------------------------------------------------------------------------------
| Function    : handle_sn_deactivate_cnf
+------------------------------------------------------------------------------
| Description : Handle UPM_P_SN_DEACTIVATE_CNF in S5
|
| Parameters  : ptr_context_data - Context data
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void handle_sn_deactivate_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_sn_deactivate_cnf");

  /* Go to state UPM SNDCP INACTIVE */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_INACTIVE;

  /* Report LLC link release to Link Control */
  upm_link_control(ptr_context_data, UPM_I_SNDCP_LLC_LINK_RELEASED, NULL);
}

/*
+------------------------------------------------------------------------------
| Function    : handle_modify_llc_link
+------------------------------------------------------------------------------
| Description : Handle UPM_I_SNDCP_MODIFY_LLC_LINK
|
| Parameters  : ptr_context_data - Context data
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void handle_modify_llc_link(struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_modify_llc_link");

  /* At this point, relevant flags in Context Data have been set by Link Control */

  /* Send SN_MODIFY_REQ */
  send_sn_modify_req(ptr_context_data);

  /* Go to state UPM SNDCP MODIFYING */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_MODIFYING;
}

/*
+------------------------------------------------------------------------------
| Function    : handle_sn_modify_cnf
+------------------------------------------------------------------------------
| Description : Handle UPM_P_SN_MODIFY_CNF in S4
|
| Parameters  : ptr_context_data - Context data
|               data             - Not used
+------------------------------------------------------------------------------
*/
static void handle_sn_modify_cnf(struct T_CONTEXT_DATA *ptr_context_data, /*@unused@*/ /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_sn_modify_cnf");

  /* Go to state UPM SNDCP ACTIVE */
  ptr_context_data->sndcp_control_state = UPM_SNDCP_ACTIVE;

  /* Report LLC link modification completion to Link Control */
  upm_link_control(ptr_context_data, UPM_I_SNDCP_LLC_LINK_MODIFIED, NULL);
}


/*
+------------------------------------------------------------------------------
| Function    : handle_mmpm_sequence_ind
+------------------------------------------------------------------------------
| Description : Handle UPM_P_MMPM_SEQUENCE_IND
|
| Parameters  : ptr_context_data - Context data
|               data             - sequence number
+------------------------------------------------------------------------------
*/
static void handle_mmpm_sequence_ind(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void* data)
{
  U32  seq_no = (U32)data;
  (void)TRACE_FUNCTION("handle_mmpm_sequence_ind");

  /* Set sequence number for this NSAPI */
  upm_set_sequence_number(ptr_context_data, (U8)seq_no);

#ifndef UPM_WITHOUT_USER_PLANE
  /* Uplink Data Control should discard data older than the sequence number
   * given in data for this NSAPI. */
  upm_uplink_data_control(ptr_context_data, UPM_I_UPLINK_DATA_DISCARD,
                          data);
#endif /* UPM_WITHOUT_USER_PLANE */
}

/*
+------------------------------------------------------------------------------
| Function    : handle_status_ind
+------------------------------------------------------------------------------
| Description : Handle UPM_P_SN_STATUS_IND
|
| Parameters  : ptr_context_data - Context data
|               data             - SN_STATUS_IND primitive
+------------------------------------------------------------------------------
*/
static void handle_status_ind(struct T_CONTEXT_DATA *ptr_context_data, /*@null@*/ void* data)
{
  (void)TRACE_FUNCTION("handle_status_ind");

  TRACE_ASSERT( data != NULL );

  /* If cause is any other than NO_PEER_RESPONSE, SNDCP Control should
   * deactivate SNDCP. */
  /*lint -e613 (Possible use of null pointer 'unknown-name' in left argument to operator '->') */
  if ( (((T_SN_STATUS_IND *)data)->ps_cause.ctrl_value != CAUSE_is_from_llc ||
        ((T_SN_STATUS_IND *)data)->ps_cause.value.llc_cause 
                                 !=(U16)CAUSE_LLC_NO_PEER_RES ) &&
       (((T_SN_STATUS_IND *)data)->ps_cause.ctrl_value != CAUSE_is_from_sndcp ||
        ((T_SN_STATUS_IND *)data)->ps_cause.value.sn_cause 
                                 != (U16)CAUSE_SN_NO_PEER_RESPONSE )  )
  {
    /* Go to state UPM SNDCP INACTIVE */
    ptr_context_data->sndcp_control_state = UPM_SNDCP_INACTIVE;

   /*lint +e613 (Possible use of null pointer 'unknown-name' in left argument to operator '->') */
    /* Report link release to Link Control */
    upm_link_control(ptr_context_data, UPM_I_SNDCP_LLC_LINK_RELEASED, data);
  }
}

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

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_dispatch_mmpm_sequence_ind
+------------------------------------------------------------------------------
| Description : Helper function for Dispatcher. Dispatches MMPM_SEQUENCE_IND
|
| Parameters  : ptr_prim_data    - Pointer to primitive
+------------------------------------------------------------------------------
*/
void upm_sndcp_dispatch_mmpm_sequence_ind(T_MMPM_SEQUENCE_IND *ptr_prim_data)
{
  int               entries;
  T_MMPM_npdu_list *entry;

  (void)TRACE_FUNCTION("upm_sndcp_dispatch_mmpm_sequence_ind");

  entries = (int)ptr_prim_data->c_npdu_list;
  entry   = ptr_prim_data->npdu_list;

  /* Loop over NSAPIs in primitive, and store sequence numbers. */
  while (entries > 0) {
    struct T_CONTEXT_DATA *context;

    context = upm_get_context_data_from_nsapi(entry->nsapi);
    if (context != NULL) {
      upm_sndcp_control(context, UPM_P_MMPM_SEQUENCE_IND,
                        (void *)entry->receive_n_pdu_number_val);
    } else {
      (void)TRACE_ERROR("Received sequence numbers for non-existent context!");
    }

    entries--;
  }

  send_sn_sequence_req(ptr_prim_data);
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_dispatch_sn_status_ind
+------------------------------------------------------------------------------
| Description : Helper function for Dispatcher. Dispatches SN_STATUS_IND
|
| Parameters  : ptr_prim_data    - Pointer to primitive
+------------------------------------------------------------------------------
*/
void upm_sndcp_dispatch_sn_status_ind(T_SN_STATUS_IND *prim)
{
  int                     nsapi;
  struct T_CONTEXT_DATA  *context;

  (void)TRACE_FUNCTION("upm_sndcp_dispatch_sn_status_ind");

  /* If cause is any other than NO_PEER_RESPONSE, SNDCP Control should
   * deactivate SNDCP and inform Session Management. */
  if ( (prim->ps_cause.ctrl_value != CAUSE_is_from_llc ||
        prim->ps_cause.value.llc_cause != (U16)CAUSE_LLC_NO_PEER_RES ) &&
       (prim->ps_cause.ctrl_value != CAUSE_is_from_sndcp ||
        prim->ps_cause.value.sn_cause != (U16)CAUSE_SN_NO_PEER_RESPONSE ) 
     ) {
    /* Alert state machine */
    for (nsapi = (int)NAS_NSAPI_5; nsapi < NAS_SIZE_NSAPI; nsapi++) {
      if ( (prim->nsapi_set & upm_nsapi2nsapi_set(nsapi)) != 0 ) {
        context = upm_get_context_data_from_nsapi(nsapi);
	if (context != NULL) {
	  upm_sndcp_control(context, UPM_P_SN_STATUS_IND, prim);

          /* Release context data if applicable (link and DTI both down) */
          upm_check_for_released_context_and_release(context);
	}
      }
    }

    /* Inform Session Management -- Once for all NSAPIs affected */
    send_sm_status_req(prim->nsapi_set, (T_PS_sapi)prim->sapi,
                       prim->ps_cause.ctrl_value, prim->ps_cause.value.sn_cause);
  }
  /* No action if cause is NO_PEER_RESPONSE */
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_dispatch_sn_sequence_cnf
+------------------------------------------------------------------------------
| Description : Helper function for Dispatcher. Dispatches SN_SEQUENCE_CNF
|
| Parameters  : ptr_prim_data    - Pointer to primitive
+------------------------------------------------------------------------------
*/
void upm_sndcp_dispatch_sn_sequence_cnf(T_SN_SEQUENCE_CNF *prim)
{
  (void)TRACE_FUNCTION("upm_sndcp_dispatch_sn_sequence_cnf");

  /* No action needed but forwarding sequence numbers to MM */
  send_mmpm_sequence_res(prim);
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_dispatch_sn_count_cnf
+------------------------------------------------------------------------------
| Description : Helper function for Dispatcher. Dispatches SN_COUNT_CNF
|
| Parameters  : prim             - Pointer to primitive
+------------------------------------------------------------------------------
*/
void upm_sndcp_dispatch_sn_count_cnf(T_SN_COUNT_CNF *prim)
{
  (void)TRACE_FUNCTION("upm_sndcp_dispatch_sn_count_cnf");

  /* No action needed but forwarding as UPM_COUNT_CNF */
  send_upm_count_cnf(prim->nsapi, prim->octets_uplink, prim->octets_downlink,
                     prim->packets_uplink, prim->packets_downlink);
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_dispatch_upm_count_req
+------------------------------------------------------------------------------
| Description : Helper function for Dispatcher. Dispatches UPM_COUNT_REQ
|
| Parameters  : prim             - Pointer to primitive
+------------------------------------------------------------------------------
*/
void upm_sndcp_dispatch_upm_count_req(T_UPM_COUNT_REQ *prim)
{
  (void)TRACE_FUNCTION("upm_sndcp_dispatch_upm_count_req");

  /* No action needed but forwarding as SN_COUNT_REQ */
  send_sn_count_req(prim->nsapi, prim->reset);
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_control_init
+------------------------------------------------------------------------------
| Description : SNDCP Control state machine initialization function
|
| Parameters  : ptr_context_data - Pointer to context data
+------------------------------------------------------------------------------
*/
void upm_sndcp_control_init(struct T_CONTEXT_DATA *ptr_context_data)
{
  (void)TRACE_FUNCTION("upm_sndcp_control_init");

  TRACE_ASSERT(ptr_context_data != NULL);
  /*lint -e613 (Possible use of null pointer 'ptr_context_data' in left argument to operator '->') */
  ptr_context_data->sndcp_control_state   = UPM_SNDCP_INACTIVE;
  ptr_context_data->gprs_data.pkt_flow_id = (U8)PS_PKT_FLOW_ID_NOT_PRES; 
  /*lint +e613 (Possible use of null pointer 'ptr_context_data' in left argument to operator '->') */ 	
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_control_exit
+------------------------------------------------------------------------------
| Description : SNDCP Control state machine exit function
|
| Parameters  : ptr_context_data - Pointer to context data
+------------------------------------------------------------------------------
*/
void upm_sndcp_control_exit(struct T_CONTEXT_DATA *ptr_context_data)
{
  (void)TRACE_FUNCTION("upm_sndcp_control_exit");

  TRACE_ASSERT(ptr_context_data != NULL);
/*lint -e613 (Possible use of null pointer 'ptr_context_data' in left argument to operator '->') */
  ptr_context_data->sndcp_control_state   = UPM_SNDCP_INACTIVE;
  ptr_context_data->gprs_data.pkt_flow_id = (U8)PS_PKT_FLOW_ID_NOT_PRES;
  /*lint +e613 (Possible use of null pointer 'ptr_context_data' in left argument to operator '->') */
}

/*
+------------------------------------------------------------------------------
| Function    : upm_sndcp_control
+------------------------------------------------------------------------------
| Description : SNDCP Control state machine
|
| Parameters  : ptr_context_data - Pointer to context data
|               event            - Internal event (see upm_sndcp_control.h)
|               data             - Event dependent parameter
+------------------------------------------------------------------------------
*/
void upm_sndcp_control (struct T_CONTEXT_DATA *ptr_context_data,
                        T_UPM_SNDCP_CONTROL_EVENT event,
                        /*@null@*/ void* data)
{
#ifdef DEBUG
  T_UPM_SNDCP_CONTROL_STATE old_state;
  /*@observer@*/
  static const char *state_name[UPM_SNDCP_CONTROL_NUMBER_OF_STATES] = {
    "S0_UPM_SNDCP_INACTIVE",
    "S1_UPM_SNDCP_AWAIT_ACTIVATE",
    "S2_UPM_SNDCP_ACTIVATING",
    "S3_UPM_SNDCP_ACTIVE",
    "S4_UPM_SNDCP_MODIFYING",
    "S5_UPM_SNDCP_DEACTIVATING"
  };
  /*@observer@*/
  static const char *event_name[UPM_LINK_CONTROL_NUMBER_OF_EVENTS] = {
    "UPM_P_SN_ACTIVATE_CNF",
    "UPM_P_SN_DEACTIVATE_CNF",
    "UPM_P_SN_MODIFY_CNF",
    "UPM_P_SN_STATUS_IND",
    "UPM_P_MMPM_SEQUENCE_IND",
    "UPM_I_SNDCP_AWAIT_ESTABLISH",
    "UPM_I_SNDCP_ESTABLISH_LLC_LINK",
    "UPM_I_SNDCP_MODIFY_LLC_LINK",
    "UPM_I_SNDCP_RELEASE_LLC_LINK"
  };

  TRACE_ASSERT(ptr_context_data != NULL);
  TRACE_ASSERT(event < UPM_SNDCP_CONTROL_NUMBER_OF_EVENTS);

  old_state = ptr_context_data->sndcp_control_state;

  if (transition[(U16)old_state][(U16)event].event != event) {
    (void)TRACE_ERROR("Event table error in upm_sndcp_control!");
  }
#endif /* DEBUG */

  transition[(U16)ptr_context_data->sndcp_control_state][(U16)event].func(ptr_context_data, data);

#ifdef DEBUG
  (void)TRACE_EVENT_P4("SNDCP #%d: %s => %s to %s",
                       ptr_context_data->nsapi,
                       event_name[(U16)event],
                       state_name[(U16)old_state],
                       state_name[(U16)ptr_context_data->sndcp_control_state]);
#endif /* DEBUG */
}

/*==== END OF FILE ==========================================================*/