view src/g23m-gprs/sm/sm_dispatch_message.c @ 478:5e39123540e6

hybrid fw: Openmoko-mimicking AT@BAND command implemented
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 14 Jun 2018 06:04:54 +0000
parents 219afcfc6250
children
line wrap: on
line source

/*----------------------------------------------------------------------------
|  Project :  3G PS
|  Module  :  SM
+-----------------------------------------------------------------------------
|             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:    This module implements the process dispatcher for incoming
|             air interface messages in the Session Management (SM) entity.
|             For design details, see:
|             8010.908 SM Detailed Specification
+---------------------------------------------------------------------------*/

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

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

#include "sm.h"
#include "ccdapi.h"

#include "sm_network_control.h"
#include "sm_aci_output_handler.h"
#include "sm_mm_output_handler.h"

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

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

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

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

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

/*
+------------------------------------------------------------------------------
| Function    : sm_disp_mmpm_unitdata_ind
+------------------------------------------------------------------------------
| Description : Dispatch MMPM_UNITDATA_IND
|
| Parameters  : prim        - received primitive
+------------------------------------------------------------------------------
*/
void sm_disp_mmpm_unitdata_ind(T_MMPM_UNITDATA_IND *prim)
{
  U8                        ti, ti_flag, msg_type, *msg, ccdResult;
  U16                       offset;
  struct T_SM_CONTEXT_DATA *context;
  T_CAUSE_ps_cause          cause;

  (void)TRACE_FUNCTION("sm_disp_mmpm_unitdata_ind");

  offset     = (U16)(prim->sdu.o_buf + 7) >> 3; /* Offset in octets/bytes in message buffer */
  msg        = &prim->sdu.buf[offset];

  /* Read L3 header: First TI/PD octet */
  ti_flag    = (msg[0] & SM_TI_FLAG) == (U8)0 ? (U8)SM_TI_FLAG : (U8)0;
  ti         = (msg[0] >> 4) & SM_TI_NON_EXT_MASK;

  /* Check for extended TI: If TI == 7, read next octet for real TI */
  if (ti == (U8)SM_TI_EXTEND_VALUE) {
    ti       = msg[1]; /* Read real TI from next octet in message */

    if ((ti & (U8)SM_TI_FLAG) == (U8)0) {
      /* Messages with TI EXT bit = 0 shall be ignored: [3G 24.008, 8.3.2] */
      (void)TRACE_ERROR("Warning: TI EXT bit = 0 in message - message ignored!");
      return;
    } else {
      ti    &= SM_TI_MASK;
    }
    offset   = (U16)16; /* # bits to advance message pointer to reach message type */
    msg_type = msg[2]; /* Get message type octet after TI */
    (void)TRACE_EVENT_P1("  Extended TI found: 0x%02x", ti);
  } else {
    offset   = (U16)8;  /* # bits to advance message pointer to reach message type */
    (void)TRACE_EVENT_P1("  Non-extended TI found: 0x%02x", ti);
    msg_type = msg[1]; /* Get message type octet after TI */
  }
  /* Set highest bit iff the direction flag bit was set above */
  ti |= ti_flag;
  /* Advance message pointer past TI/PD octet(s) */
  prim->sdu.l_buf -= offset;
  prim->sdu.o_buf += offset;

  /* Check for message too short: [3G 24.008, 8.2] */
  if (prim->sdu.l_buf < (U16)8) {
    (void)TRACE_ERROR("Warning! Message too short - discarded...");
    return;
  }

  /* Find context with TI = ti, if already active/being activated */
  context = sm_get_context_data_from_ti(ti);

  switch (msg_type) {
  case ACTIVATE_PDP_CONTEXT_ACCEPT:
  case ACTIVATE_PDP_CONTEXT_REJECT:
  case ACTIVATE_SECONDARY_PDP_CONTEXT_ACCEPT:
  case ACTIVATE_SECONDARY_PDP_CONTEXT_REJECT:
  case D_MODIFY_PDP_CONTEXT_REQUEST:
  case D_MODIFY_PDP_CONTEXT_ACCEPT:
  case MODIFY_PDP_CONTEXT_REJECT:
  case DEACTIVATE_PDP_CONTEXT_REQUEST:
  case DEACTIVATE_PDP_CONTEXT_ACCEPT:
    if (context == NULL) {
      /* Message received on TI not relating to an active context, or context
       * being activated/deactivated: [3G 24.008, 8.3.2 b)]*/
      (void)TRACE_ERROR("Message received on TI not relating to an active context, or context being activated/deactivated");
      cause.ctrl_value       = CAUSE_is_from_nwsm;
      cause.value.nwsm_cause = (U16)CAUSE_NWSM_INVALID_TI;
      send_msg_sm_status(ti, &cause);
      return;
    }
    break;
  case REQUEST_PDP_CONTEXT_ACTIVATION:
    if (ti_flag == (U8)0) {
      /* Ignore REQUEST PDP CONTEXT ACTIVATION msg with TI flag = 1 [3G 24.008, 8.3.2 c)] */
      /* Note: flag bit is inverted above! */
      (void)TRACE_EVENT("REQUEST PDP CONTEXT ACTIVATION msg with TI flag = 1 ignored...");
      return;
    }
    if (context == NULL) {
      /* If no context exists for the TI, create one. */
      context = sm_insert_mt_context_data(ti);
    }
    break;
  case SM_STATUS:
    if (context == NULL) {
      /* Silently ignore message */
      return;
    }
    break;
  case ACTIVATE_PDP_CONTEXT_REQUEST:             /* FALL-THROUGH */
  case ACTIVATE_SECONDARY_PDP_CONTEXT_REQUEST:   /* FALL-THROUGH */
  case REQUEST_PDP_CONTEXT_ACTIVATION_REJECT:    /* FALL-THROUGH */
  case U_MODIFY_PDP_CONTEXT_REQUEST:             /* FALL-THROUGH */
  case U_MODIFY_PDP_CONTEXT_ACCEPT:              /* FALL-THROUGH */
  default:
    /* Message type not defined for the PD in the given direction: [3G 24.008, 8.4] */
    (void)TRACE_ERROR("Message type not defined for the PD in the given direction");
    cause.ctrl_value       = CAUSE_is_from_nwsm;
    cause.value.nwsm_cause = (U16)CAUSE_NWSM_MSG_TYPE_NOT_IMPLEMENTED;
    send_msg_sm_status(ti, &cause);
    return;
  } /* switch */

  TRACE_ASSERT(context != NULL);

  /* Decode message */
  ccdResult = ccd_decodeMsg((U8)CCDENT_SM,
			    (U8)DOWNLINK,
			    (T_MSGBUF *)&prim->sdu,
			    (UBYTE *) _decodedMsg,
			    (U8)NOT_PRESENT_8BIT);

  if (ccdResult != (U8)ccdOK) {
    /* Error Handling */
    U16    parlist[6];
    U8     first_err;
    U8     ccd_err;

    /* clear parlist */
    memset (parlist, 0, sizeof (parlist));
    first_err = ccd_getFirstError((U8)CCDENT_SM, parlist);

    ccd_err = first_err;
    /* Loop over errors in parlist.  Fix inherited from TI Berlin. */
    do
    {
    /* Error Handling */
    switch (ccd_err) {
      case ERR_COMPREH_REQUIRED:    /* Comprehension required */
      case ERR_MAND_ELEM_MISS: {    /* Mandatory elements missing */
        (void)TRACE_ERROR("CCD ERROR: Mandatory elements missing");
	if (msg_type == (U8)DEACTIVATE_PDP_CONTEXT_REQUEST) {
	  /* [3G 24.008, 8.5.5]: If msg_type is DEACTIVATE PDP CONTEXT REQUEST,
	   * respond with DEACTIVATE PDP CONTEXT ACCEPT and release context. */
	  send_msg_deactivate_pdp_context_accept(context);
	} else if (msg_type == (U8)REQUEST_PDP_CONTEXT_ACTIVATION) {
	  /* [3G 24.008, 8.5.5]: If msg_type is REQUEST PDP CONTEXT ACTIVATION,
	   * respond with SM STATUS, cause #96 "invalid mandatory information". */
	  cause.ctrl_value       = CAUSE_is_from_nwsm;
	  cause.value.nwsm_cause = (U16)CAUSE_NWSM_INVALID_MANDATORY_ELEMENT;
	  send_msg_sm_status(ti, &cause);
          return;
        } else {
 	  cause.ctrl_value       = CAUSE_is_from_nwsm;
	  cause.value.nwsm_cause = (U16)CAUSE_NWSM_INVALID_MANDATORY_ELEMENT;
	  send_msg_sm_status(ti, &cause);
          return;
	}
        /*@switchbreak@*/
	break;
      }
    } /* switch */
    ccd_err = ccd_getNextError ((U8)CCDENT_SM, parlist);
    } while (ccd_err != (U8)ERR_NO_MORE_ERROR);
  } /* if (ccdResult...) */

  switch (msg_type) {
  case ACTIVATE_PDP_CONTEXT_ACCEPT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_ACTIVATE_PDP_CONTEXT_ACCEPT, _decodedMsg);
    break;
  case ACTIVATE_PDP_CONTEXT_REJECT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_ACTIVATE_PDP_CONTEXT_REJECT, _decodedMsg);
    break;
  case ACTIVATE_SECONDARY_PDP_CONTEXT_ACCEPT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_ACTIVATE_SECONDARY_PDP_CONTEXT_ACCEPT, _decodedMsg);
    break;
  case ACTIVATE_SECONDARY_PDP_CONTEXT_REJECT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_ACTIVATE_SECONDARY_PDP_CONTEXT_REJECT, _decodedMsg);
    break;
  case REQUEST_PDP_CONTEXT_ACTIVATION:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_REQUEST_PDP_CONTEXT_ACTIVATION, _decodedMsg);
    break;
  case D_MODIFY_PDP_CONTEXT_REQUEST:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_MODIFY_PDP_CONTEXT_REQUEST, _decodedMsg);
    break;
  case D_MODIFY_PDP_CONTEXT_ACCEPT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_MODIFY_PDP_CONTEXT_ACCEPT, _decodedMsg);
    break;
  case MODIFY_PDP_CONTEXT_REJECT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_MODIFY_PDP_CONTEXT_REJECT, _decodedMsg);
    break;
  case DEACTIVATE_PDP_CONTEXT_REQUEST:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_DEACTIVATE_PDP_CONTEXT_REQUEST, _decodedMsg);
    break;
  case DEACTIVATE_PDP_CONTEXT_ACCEPT:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_DEACTIVATE_PDP_CONTEXT_ACCEPT, _decodedMsg);
    break;
  case SM_STATUS:
    /* Forward to Network Control */
    sm_network_control(context, SM_M_SM_STATUS, _decodedMsg);
    break;
  } /* switch */

  /* Deallocate context if it was marked for deactivation by the above operation */
  /*lint -e613 (Possible use of null pointer 'context' in left argument to operator '->') */
  if (sm_is_context_pending_deallocation(context)) {
    sm_free_context_data_by_nsapi(context->nsapi);
  }
}

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