FreeCalypso > hg > fc-tourmaline
diff src/g23m-aci/aci/cmh_sms.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 diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-aci/aci/cmh_sms.c Fri Oct 16 06:25:50 2020 +0000 @@ -0,0 +1,3307 @@ +/* ++----------------------------------------------------------------------------- +| 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 module implements the set fuinctions related to the +| protocol stack adapter for GPRS session management ( SM ). ++----------------------------------------------------------------------------- +*/ + +#if defined (GPRS) && defined (DTI) + +#ifndef CMH_SMS_C +#define CMH_SMS_C +#endif + +#include "aci_all.h" + +/*==== INCLUDES ===================================================*/ +#include "dti.h" /* functionality of the dti library */ +#include "aci_cmh.h" +#include "ati_cmd.h" +#include "aci_cmd.h" +#include "aci_io.h" + +#include "dti_conn_mng.h" +#include "dti_cntrl_mng.h" + +#include "gaci.h" +#include "gaci_cmh.h" +#include "psa.h" +#include "psa_sm.h" +#include "psa_gppp.h" +#include "psa_gmm.h" +#include "psa_tcpip.h" + +#include "cmh.h" +#include "cmh_sm.h" +#include "cmh_gppp.h" +#include "cmh_gmm.h" +#include "gaci_srcc.h" +#include "aci_mem.h" + +#include "cl_inline.h" +#include "phb.h" +#include "wap_aci.h" + +/*==== CONSTANTS ==================================================*/ + +/*==== EXPORT =====================================================*/ + +/*==== VARIABLES ==================================================*/ +EXTERN T_PDP_CONTEXT_INTERNAL *p_pdp_context_list; + + +/*==== FUNCTIONS ==================================================*/ +LOCAL void string_to_dns(CHAR* dns, ULONG *dns_long); +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGQREQ | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGQREQ= AT + command which sets the requested QOS. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGQREQ( T_ACI_CMD_SRC srcId, U8 cid ,T_PS_qos *qos) +{ + T_ACI_RETURN retCd; /* holds return code */ + T_PDP_CONTEXT_STATE context_state; /* state of context */ + T_PS_qos_r99 temp_qos; /* Temp. var to hold R99 input parameters for conversion */ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + TRACE_FUNCTION ("sAT_PlusCGQREQ()"); + +/* Need work to fit into R99 QoS SMNEW 05032001 + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( ((cid < PDP_CONTEXT_CID_MIN) OR (cid > PDP_CONTEXT_CID_MAX)) AND (cid NEQ PDP_CONTEXT_CID_OMITTED) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + + if( qos ) + { + if( (qos->qos_r97.preced > 3) AND + (qos->qos_r97.preced NEQ PDP_CONTEXT_QOS_OMITTED) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if( (qos->qos_r97.delay > 4) AND + (qos->qos_r97.delay NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.relclass > 5) AND + (qos->qos_r97.relclass NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.peak > 9) AND + (qos->qos_r97.peak NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.mean > 18) AND + (qos->qos_r97.mean NEQ 31) AND + (qos->qos_r97.mean NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + if (cid EQ PDP_CONTEXT_CID_OMITTED ) + /* + * cid omitted: A special form of the set command that is not defined in the Spec. + * This set the default value of QoS. + */ + { + cmhSM_change_def_QOS( qos, PS_is_R97 ); + + retCd = AT_CMPL; + } + else + { + context_state = pdp_context_get_state_for_cid( cid ); + + if ( !qos OR ( qos->qos_r97.preced EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.delay EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.relclass EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.peak EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.mean EQ PDP_CONTEXT_QOS_OMITTED ) ) + + { /* QoS omitted -> undefine the requested QOS */ + if ( context_state EQ PDP_CONTEXT_STATE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + cmhSM_Set_default_QOS( cid ); + + retCd = AT_CMPL; + } + else + { /* define the requested QOS */ + if ( context_state EQ PDP_CONTEXT_STATE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + if( p_pdp_context_node->ctrl_qos EQ PS_is_R99 ) + { + /* Convert existing R99 parameters to R97 parameters */ + memcpy( &temp_qos, &p_pdp_context_node->qos.qos_r99, sizeof(T_PS_qos_r99) ); + if( !cl_qos_convert_r99_to_r97( &temp_qos, &p_pdp_context_node->qos.qos_r97) ) + return( AT_FAIL ); + } + + p_pdp_context_node->ctrl_qos = PS_is_R97; + + if( qos->qos_r97.preced NEQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->qos.qos_r97.preced = qos->qos_r97.preced; + if( qos->qos_r97.delay NEQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->qos.qos_r97.delay = qos->qos_r97.delay; + if( qos->qos_r97.relclass NEQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->qos.qos_r97.relclass = qos->qos_r97.relclass; + if( qos->qos_r97.peak NEQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->qos.qos_r97.peak = qos->qos_r97.peak; + if( qos->qos_r97.mean NEQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->qos.qos_r97.mean = qos->qos_r97.mean; + + retCd = AT_CMPL; + } + else + { + retCd = AT_FAIL; + } + + } + + } + + return retCd; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGQMIN | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGQMIN= AT + command which sets the minimum acceptable QOS. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGQMIN( T_ACI_CMD_SRC srcId, U8 cid ,T_PS_min_qos *qos) +{ + T_ACI_RETURN retCd; /* holds return code */ + T_PDP_CONTEXT_STATE context_state; /* state of context */ + T_PS_qos_r99 temp_qos; /* Temp. var to hold R99 input parameters for conversion */ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + TRACE_FUNCTION ("sAT_PlusCGQMIN()"); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( ((cid < PDP_CONTEXT_CID_MIN) OR (cid > PDP_CONTEXT_CID_MAX)) AND (cid NEQ PDP_CONTEXT_CID_OMITTED) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + + if ( qos ) + { + if( (qos->qos_r97.preced > 3) AND + (qos->qos_r97.preced NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if( (qos->qos_r97.delay > 4) AND + (qos->qos_r97.delay NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.relclass > 5) AND + (qos->qos_r97.relclass NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.peak > 9) AND + (qos->qos_r97.peak NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + if( (qos->qos_r97.mean > 18) AND + (qos->qos_r97.mean NEQ 31) AND + (qos->qos_r97.mean NEQ PDP_CONTEXT_QOS_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + +/* +*------------------------------------------------------------------- +* process parameter +*------------------------------------------------------------------- +*/ + if( cid EQ PDP_CONTEXT_CID_OMITTED ) + /* + * cid omitted: A special form of the set command that is not defined in the Spec. + * This set the default value of QoS. + */ + { + cmhSM_change_def_QOS_min( qos, (T_PS_ctrl_min_qos)PS_is_R97 ); + + retCd = (T_ACI_RETURN)AT_CMPL; + } + else + { + context_state = pdp_context_get_state_for_cid( cid ); + + if ( !qos OR ( qos->qos_r97.preced EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.delay EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.relclass EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.peak EQ PDP_CONTEXT_QOS_OMITTED AND + qos->qos_r97.mean EQ PDP_CONTEXT_QOS_OMITTED ) ) + { /* QoS omitted -> undefine the requested QOS */ + + if ( context_state EQ PDP_CONTEXT_STATE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + cmhSM_Set_default_QOS_min( cid ); + + retCd = AT_CMPL; + } + else + { /* define the requested QOS */ + + if ( context_state EQ PDP_CONTEXT_STATE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + + if( p_pdp_context_node ) + { + + if( p_pdp_context_node->ctrl_min_qos EQ (T_PS_ctrl_min_qos)PS_is_R99 ) + { + /* Convert existing R99 parameters to R97 parameters */ + memcpy( &temp_qos, &p_pdp_context_node->min_qos.qos_r99, sizeof(T_PS_qos_r99) ); + if( !cl_qos_convert_r99_to_r97( &temp_qos, &p_pdp_context_node->min_qos.qos_r97) ) + return( AT_FAIL ); + } + + p_pdp_context_node->ctrl_min_qos = (T_PS_ctrl_min_qos)PS_is_R97; + + /* Set input values for context or keep the previous/converted values if omitted */ + if( qos->qos_r97.preced EQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->min_qos.qos_r97.preced = PS_PRECED_SUB; + else + p_pdp_context_node->min_qos.qos_r97.preced = qos->qos_r97.preced; + + if( qos->qos_r97.delay EQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->min_qos.qos_r97.delay = PS_DELAY_SUB; + else + p_pdp_context_node->min_qos.qos_r97.delay = qos->qos_r97.delay; + + if( qos->qos_r97.relclass EQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->min_qos.qos_r97.relclass = PS_RELCLASS_SUB; + else + p_pdp_context_node->min_qos.qos_r97.relclass = qos->qos_r97.relclass; + + if( qos->qos_r97.peak EQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->min_qos.qos_r97.peak = PS_PEAK_SUB; + else + p_pdp_context_node->min_qos.qos_r97.peak = qos->qos_r97.peak; + + if( qos->qos_r97.mean EQ PDP_CONTEXT_QOS_OMITTED ) + p_pdp_context_node->min_qos.qos_r97.mean = PS_MEAN_SUB; + else + p_pdp_context_node->min_qos.qos_r97.mean = qos->qos_r97.mean; + + retCd = AT_CMPL; + } + else + { + retCd = AT_FAIL; + } + + } + + } + + return retCd; +} + +#ifdef REL99 +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : devellopment ROUTINE : sAT_PlusCGEQREQ | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGEQREQ= AT + command which sets the 3G requested QOS parameters. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGEQREQ( T_ACI_CMD_SRC srcId, U8 cid, T_PS_qos *qos ) +{ + T_ACI_RETURN retCd; /* holds return code */ + T_PDP_CONTEXT_STATE c_state; /* state of context */ + BOOL outOfRange; /* TRUE if one or more parameters are out of range */ + U16 tempComp; /* Used for range check of SDU error ratio and bit error ratio */ + T_PS_qos_r97 temp_qos; /* Temp. var to hold R97 input parameters for conversion */ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + TRACE_FUNCTION( "sAT_PlusCGEQREQ()" ); + + outOfRange = FALSE; + + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * Parameter range check. + *------------------------------------------------------------------- + */ + if ( ((cid < PDP_CONTEXT_CID_MIN) OR (cid > PDP_CONTEXT_CID_MAX)) AND (cid NEQ PDP_CONTEXT_CID_OMITTED) ) + { + outOfRange = TRUE; + } + + if ( qos AND (outOfRange EQ FALSE) ) + { + if( (qos->qos_r99.tc > 4 ) AND + (qos->qos_r99.tc NEQ QOS_R99_TC_OMITTED) ) /* 4 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.max_rate_ul > 2048 ) AND + (qos->qos_r99.max_rate_ul NEQ QOS_R99_MAX_BR_UL_OMITTED) ) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.max_rate_dl > 2048 ) AND + (qos->qos_r99.max_rate_dl NEQ QOS_R99_MAX_BR_DL_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.guar_br_ul > 2048 ) AND + (qos->qos_r99.guar_br_ul NEQ QOS_R99_GUAR_BR_UL_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.guar_br_dl > 2048 ) AND + (qos->qos_r99.guar_br_dl NEQ QOS_R99_GUAR_BR_DL_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.order > 2 ) AND + (qos->qos_r99.order NEQ QOS_R99_ORDER_OMITTED )) /* 2 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.xfer_delay > 65534 ) AND + (qos->qos_r99.xfer_delay NEQ QOS_R99_XFER_DELAY_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.del_err_sdu > 3 ) AND + (qos->qos_r99.del_err_sdu NEQ QOS_R99_DEL_ERR_SDU_OMITTED )) /* 3 = subscribed value */ + outOfRange = TRUE; + + if( (qos->qos_r99.handling_pri > 3 ) AND + (qos->qos_r99.handling_pri NEQ QOS_R99_HANDLING_PRIO_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + + if( cid NEQ PDP_CONTEXT_CID_OMITTED ) + { + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + if( !strcmp( p_pdp_context_node->attributes.pdp_type, "PPP") ) + { + if( (qos->qos_r99.max_sdu > 1502 ) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value, 1502 for PPP */ + outOfRange = TRUE; + } + else + { + if( (qos->qos_r99.max_sdu > 1500 ) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + } + } + else + { + TRACE_ERROR( "ERROR: PDP context not found, in function sAT_PlusCGEQREQ" ); + outOfRange = TRUE; + } + } + else + { + /* It is decided that the max_sdu for the default qos is 1500 and NOT 1502 since 1500 is valid for both ppp and ip */ + if( (qos->qos_r99.max_sdu > 1500 ) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value, 1502 for PPP */ + outOfRange = TRUE; + } + + /* to simplify the parameter range check the to bytes are joined in to a U16. */ + + tempComp = (U16) qos->qos_r99.sdu_err_ratio.ratio_mant; + tempComp = tempComp << 8; + tempComp = tempComp | qos->qos_r99.sdu_err_ratio.ratio_exp; + + if( tempComp NEQ 0 AND + tempComp NEQ ((QOS_R99_RATIO_MANT_OMITTED<<8) + QOS_R99_RATIO_EXP_OMITTED) ) /* Check parameter range if "sdu_err_ratio" NEQ subscribed value or omitted. */ + { + switch( qos->qos_r99.tc ) + { + case PS_TC_CONV: /* Conversational class */ + if( tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 ) /* 0x0102 = 1 * 10^-2 */ + outOfRange = TRUE; + break; + + case PS_TC_STREAM: /* Streaming class */ + if( tempComp NEQ 0x0101 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 ) + outOfRange = TRUE; + break; + + case PS_TC_INTER: /* Interactive class */ + case PS_TC_BG: /* Background class */ + if( tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_SUB: /* Subscribed value */ + case QOS_R99_TC_OMITTED: + if( tempComp NEQ 0x0101 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + default: + outOfRange = TRUE; + break; + } + } + + tempComp = (U16) qos->qos_r99.ber.ratio_mant; + tempComp = tempComp << 8; + tempComp = tempComp | qos->qos_r99.ber.ratio_exp; + + if( tempComp NEQ 0 AND + tempComp NEQ ((QOS_R99_RATIO_MANT_OMITTED<<8) + QOS_R99_RATIO_EXP_OMITTED) ) /* Check parameter range if "ber" NEQ subscribed value or omitted. */ + { + switch( qos->qos_r99.tc ) + { + case PS_TC_CONV: /* Conversational class */ + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_STREAM: /* Streaming class */ + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_INTER: /* Interactive class */ + case PS_TC_BG: /* Background class */ + if( tempComp NEQ 0x0403 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0608 ) + outOfRange = TRUE; + break; + + case PS_TC_SUB: /* Subscribed value */ + case QOS_R99_TC_OMITTED: + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0403 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + default: + outOfRange = TRUE; + break; + } + } + } + + if( outOfRange EQ TRUE ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + if(cid EQ PDP_CONTEXT_CID_OMITTED ) + /* + * cid omitted: A special form of the set command that is not defined in the Spec. + * This set the default value of QoS. + */ + { + cmhSM_change_def_QOS( qos, PS_is_R99 ); + + retCd = AT_CMPL; + } + else + { +/* + * Check that a context is defined before changing the QoS. + */ + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( ! p_pdp_context_node ) + { + return AT_FAIL; + } + + c_state = get_state_over_cid( cid ); + switch (c_state) + { + case PDP_CONTEXT_STATE_INVALID: + /* Wrong context state (not defined): Reject command */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + default: ; + /* Context is defined: Continue */ + } + + if( !qos OR ( qos->qos_r99.tc EQ QOS_R99_TC_OMITTED AND + qos->qos_r99.order EQ QOS_R99_ORDER_OMITTED AND + qos->qos_r99.del_err_sdu EQ QOS_R99_DEL_ERR_SDU_OMITTED AND + qos->qos_r99.max_sdu EQ QOS_R99_MAX_SDU_OMITTED AND + qos->qos_r99.max_rate_ul EQ QOS_R99_MAX_BR_UL_OMITTED AND + qos->qos_r99.max_rate_dl EQ QOS_R99_MAX_BR_DL_OMITTED AND + qos->qos_r99.xfer_delay EQ QOS_R99_XFER_DELAY_OMITTED AND + qos->qos_r99.handling_pri EQ QOS_R99_HANDLING_PRIO_OMITTED AND + qos->qos_r99.guar_br_ul EQ QOS_R99_GUAR_BR_UL_OMITTED AND + qos->qos_r99.guar_br_dl EQ QOS_R99_GUAR_BR_DL_OMITTED AND + qos->qos_r99.ber.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED AND + qos->qos_r99.ber.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED AND + qos->qos_r99.sdu_err_ratio.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED AND + qos->qos_r99.sdu_err_ratio.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) ) + + { +/* + * QoS omitted -> undefine the requested QOS + */ + cmhSM_Set_default_QOS( cid ); + + /* If the default parameters is in R97 format, it must be converted to R99 */ + if( p_pdp_context_node->ctrl_qos EQ PS_is_R97) + { + memcpy( &temp_qos, &p_pdp_context_node->qos.qos_r97, sizeof(T_PS_qos_r97) ); + cl_qos_convert_r97_to_r99( &temp_qos, &p_pdp_context_node->qos.qos_r99 ); + p_pdp_context_node->ctrl_qos = PS_is_R99; + } + + retCd = AT_CMPL; + } + else + { +/* + * Define the requested QOS + */ + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + + if( p_pdp_context_node->ctrl_qos EQ PS_is_R97 ) + { + /* Convert existing R97 parameters to R99 parameters */ + p_pdp_context_node->ctrl_qos = PS_is_R99; + memcpy( &temp_qos, &p_pdp_context_node->qos.qos_r97, sizeof(T_PS_qos_r97) ); + if( !cl_qos_convert_r97_to_r99( &temp_qos, &p_pdp_context_node->qos.qos_r99) ) + return( AT_FAIL ); + } + else + p_pdp_context_node->ctrl_qos = PS_is_R99; //FDU - 13082003 + + + /* Set the new values for context or keep the old values if omitted */ + if( qos->qos_r99.tc NEQ QOS_R99_TC_OMITTED ) + p_pdp_context_node->qos.qos_r99.tc = qos->qos_r99.tc; + + if( qos->qos_r99.order NEQ QOS_R99_ORDER_OMITTED ) + p_pdp_context_node->qos.qos_r99.order = qos->qos_r99.order; + + if( qos->qos_r99.del_err_sdu NEQ QOS_R99_DEL_ERR_SDU_OMITTED ) + p_pdp_context_node->qos.qos_r99.del_err_sdu = qos->qos_r99.del_err_sdu; + + if( qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED ) + p_pdp_context_node->qos.qos_r99.max_sdu = qos->qos_r99.max_sdu; + + if( qos->qos_r99.max_rate_ul NEQ QOS_R99_MAX_BR_UL_OMITTED ) + p_pdp_context_node->qos.qos_r99.max_rate_ul = qos->qos_r99.max_rate_ul; + + if( qos->qos_r99.max_rate_dl NEQ QOS_R99_MAX_BR_DL_OMITTED ) + p_pdp_context_node->qos.qos_r99.max_rate_dl = qos->qos_r99.max_rate_dl; + + if( qos->qos_r99.xfer_delay NEQ QOS_R99_XFER_DELAY_OMITTED ) + p_pdp_context_node->qos.qos_r99.xfer_delay = qos->qos_r99.xfer_delay; + + if( qos->qos_r99.handling_pri NEQ QOS_R99_HANDLING_PRIO_OMITTED ) + p_pdp_context_node->qos.qos_r99.handling_pri = qos->qos_r99.handling_pri; + + if( qos->qos_r99.guar_br_ul NEQ QOS_R99_GUAR_BR_UL_OMITTED ) + p_pdp_context_node->qos.qos_r99.guar_br_ul = qos->qos_r99.guar_br_ul; + + if( qos->qos_r99.guar_br_dl NEQ QOS_R99_GUAR_BR_DL_OMITTED ) + p_pdp_context_node->qos.qos_r99.guar_br_dl = qos->qos_r99.guar_br_dl; + + if( qos->qos_r99.ber.ratio_mant NEQ QOS_R99_RATIO_MANT_OMITTED ) + p_pdp_context_node->qos.qos_r99.ber.ratio_mant = qos->qos_r99.ber.ratio_mant; + + if( qos->qos_r99.ber.ratio_exp NEQ QOS_R99_RATIO_EXP_OMITTED ) + p_pdp_context_node->qos.qos_r99.ber.ratio_exp = qos->qos_r99.ber.ratio_exp; + + if( qos->qos_r99.sdu_err_ratio.ratio_mant NEQ QOS_R99_RATIO_MANT_OMITTED ) + p_pdp_context_node->qos.qos_r99.sdu_err_ratio.ratio_mant = qos->qos_r99.sdu_err_ratio.ratio_mant; + + if( qos->qos_r99.sdu_err_ratio.ratio_exp NEQ QOS_R99_RATIO_EXP_OMITTED ) + p_pdp_context_node->qos.qos_r99.sdu_err_ratio.ratio_exp = qos->qos_r99.sdu_err_ratio.ratio_exp; + } + else + { + return( AT_FAIL ); + } + } + + retCd = AT_CMPL; + + } + + return retCd; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : devellopment ROUTINE : sAT_PlusCGEQMIN | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGEQMIN= AT + command which sets the 3G requested QOS min. parameters. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGEQMIN( T_ACI_CMD_SRC srcId, U8 cid, T_PS_qos *qos ) +{ + T_ACI_RETURN retCd; /* holds return code */ + T_PDP_CONTEXT_STATE c_state; /* state of context */ + BOOL outOfRange; /* TRUE if one or more parameters are out of range */ + U16 tempComp; /* Used for range check of SDU error ratio and bit error ratio */ + T_PS_qos_r97 temp_qos; /* Temp. var to hold R97 input parameters for conversion */ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + TRACE_FUNCTION( "sAT_PlusCGEQMIN()" ); + + outOfRange = FALSE; + + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( ((cid < PDP_CONTEXT_CID_MIN) OR (cid > PDP_CONTEXT_CID_MAX)) AND (cid NEQ PDP_CONTEXT_CID_OMITTED) ) + { + outOfRange = TRUE; + } + if ( qos EQ NULL) + { + return( AT_FAIL ); + } + if ( qos AND (outOfRange EQ FALSE) ) + { + if( (qos->qos_r99.tc > 3) AND + (qos->qos_r99.tc NEQ QOS_R99_TC_OMITTED )) + outOfRange = TRUE; + + if( (qos->qos_r99.max_rate_ul < 1 OR + qos->qos_r99.max_rate_ul > 2048) AND + qos->qos_r99.max_rate_ul NEQ QOS_R99_MAX_BR_UL_OMITTED ) + outOfRange = TRUE; + + if( (qos->qos_r99.max_rate_dl < 1 OR + qos->qos_r99.max_rate_dl > 2048) AND + qos->qos_r99.max_rate_dl NEQ QOS_R99_MAX_BR_DL_OMITTED ) + outOfRange = TRUE; + + if( (qos->qos_r99.guar_br_ul < 1 OR + qos->qos_r99.guar_br_ul > 2048) AND + qos->qos_r99.guar_br_ul NEQ QOS_R99_GUAR_BR_UL_OMITTED ) + outOfRange = TRUE; + + if( (qos->qos_r99.guar_br_dl < 1 OR + qos->qos_r99.guar_br_dl > 2048) AND + qos->qos_r99.guar_br_dl NEQ QOS_R99_GUAR_BR_DL_OMITTED ) + outOfRange = TRUE; + + if( (qos->qos_r99.order > 1) AND + (qos->qos_r99.order NEQ QOS_R99_ORDER_OMITTED )) + outOfRange = TRUE; + + if( (qos->qos_r99.xfer_delay > 65534) AND + (qos->qos_r99.xfer_delay NEQ QOS_R99_XFER_DELAY_OMITTED )) + outOfRange = TRUE; + + if( (qos->qos_r99.del_err_sdu > 2) AND + (qos->qos_r99.del_err_sdu NEQ QOS_R99_DEL_ERR_SDU_OMITTED )) + outOfRange = TRUE; + + if( (qos->qos_r99.handling_pri < 1 OR + qos->qos_r99.handling_pri > 3) AND + qos->qos_r99.handling_pri NEQ QOS_R99_HANDLING_PRIO_OMITTED ) + outOfRange = TRUE; + + if( cid NEQ PDP_CONTEXT_CID_OMITTED ) + { + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + if( !strcmp( p_pdp_context_node->attributes.pdp_type, "PPP") ) + { + if( (qos->qos_r99.max_sdu > 1502) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value, 1502 for PPP */ + outOfRange = TRUE; + } + else + { + if( (qos->qos_r99.max_sdu > 1500) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + } + } + else + { + TRACE_ERROR( "ERROR: PDP context not found, in function sAT_PlusCGEQMIN" ); + outOfRange = TRUE; + } + } + else + { + if( (qos->qos_r99.max_sdu > 1500) AND + (qos->qos_r99.max_sdu NEQ QOS_R99_MAX_SDU_OMITTED )) /* 0 = subscribed value */ + outOfRange = TRUE; + } + + /* to simplify the parameter range check the to bytes are joined in to a U16. */ + + tempComp = (U16) qos->qos_r99.sdu_err_ratio.ratio_mant; + tempComp = tempComp << 8; + tempComp = tempComp | qos->qos_r99.sdu_err_ratio.ratio_exp; + + if( tempComp NEQ 0 AND + tempComp NEQ ((QOS_R99_RATIO_MANT_OMITTED<<8) + QOS_R99_RATIO_EXP_OMITTED) ) /* Check parameter range if "sdu_err_ratio" NEQ subscribed value or omitted. */ + { + switch( qos->qos_r99.tc ) + { + case PS_TC_CONV: /* Conversational class */ + if( tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 ) /* 0x0102 = 1 * 10^-2 */ + outOfRange = TRUE; + break; + + case PS_TC_STREAM: /* Streaming class */ + if( tempComp NEQ 0x0101 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 ) + outOfRange = TRUE; + break; + + case PS_TC_INTER: /* interactive class */ + if( tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_BG: /* Background class */ + if( tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_SUB: /* Subscribed value */ + case QOS_R99_TC_OMITTED: + if( tempComp NEQ 0x0101 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0703 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + default: + outOfRange = TRUE; + break; + } + } + + tempComp = (U16) qos->qos_r99.ber.ratio_mant; + tempComp = tempComp << 8; + tempComp = tempComp | qos->qos_r99.ber.ratio_exp; + + if( tempComp NEQ 0 AND + tempComp NEQ ((QOS_R99_RATIO_MANT_OMITTED<<8) + QOS_R99_RATIO_EXP_OMITTED) ) /* Check parameter range if "ber" NEQ subscribed value or omitted. */ + { + switch( qos->qos_r99.tc ) + { + case PS_TC_CONV: /* Conversational class */ + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_STREAM: /* Streaming class */ + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + case PS_TC_INTER: /* Interactive class */ + if( tempComp NEQ 0x0403 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0608 ) + outOfRange = TRUE; + break; + + case PS_TC_BG: /* Background class */ + if( tempComp NEQ 0x0403 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0608 ) + outOfRange = TRUE; + break; + + case PS_TC_SUB: /* Subscribed value */ + case QOS_R99_TC_OMITTED: + if( tempComp NEQ 0x0502 AND + tempComp NEQ 0x0102 AND + tempComp NEQ 0x0503 AND + tempComp NEQ 0x0403 AND + tempComp NEQ 0x0103 AND + tempComp NEQ 0x0104 AND + tempComp NEQ 0x0105 AND + tempComp NEQ 0x0106 ) + outOfRange = TRUE; + break; + + default: + outOfRange = TRUE; + break; + } + } + + } + + if( outOfRange EQ TRUE ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + if(cid EQ PDP_CONTEXT_CID_OMITTED ) + /* + * cid omitted: A special form of the set command that is not defined in the Spec. + * This set the default value of QoS. + */ + { + /* Replace omitted values with subscribed values to avoid check in SM (subscribed=accept parameter from network unconditionally) */ + if( qos->qos_r99.tc EQ QOS_R99_TC_OMITTED ) qos->qos_r99.tc = PS_TC_SUB; + if( qos->qos_r99.order EQ QOS_R99_ORDER_OMITTED ) qos->qos_r99.order = PS_ORDER_SUB; + if( qos->qos_r99.del_err_sdu EQ QOS_R99_DEL_ERR_SDU_OMITTED ) qos->qos_r99.del_err_sdu = PS_DEL_ERR_SUB; + if( qos->qos_r99.max_sdu EQ QOS_R99_MAX_SDU_OMITTED ) qos->qos_r99.max_sdu = PS_MAX_SDU_SUB; + if( qos->qos_r99.max_rate_ul EQ QOS_R99_MAX_BR_UL_OMITTED ) qos->qos_r99.max_rate_ul = PS_MAX_BR_UL_SUB; + if( qos->qos_r99.max_rate_dl EQ QOS_R99_MAX_BR_DL_OMITTED ) qos->qos_r99.max_rate_dl = PS_MAX_BR_DL_SUB; + if( qos->qos_r99.xfer_delay EQ QOS_R99_XFER_DELAY_OMITTED ) qos->qos_r99.xfer_delay = PS_XFER_DELAY_SUB; + if( qos->qos_r99.handling_pri EQ QOS_R99_HANDLING_PRIO_OMITTED ) qos->qos_r99.handling_pri = PS_HANDLING_PRI_SUB; + if( qos->qos_r99.guar_br_ul EQ QOS_R99_GUAR_BR_UL_OMITTED ) qos->qos_r99.guar_br_ul = PS_GUAR_BR_UL_SUB; + if( qos->qos_r99.guar_br_dl EQ QOS_R99_GUAR_BR_DL_OMITTED ) qos->qos_r99.guar_br_dl = PS_GUAR_BR_DL_SUB; + if( qos->qos_r99.ber.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED ) qos->qos_r99.ber.ratio_mant = 0; /* '0' is the subscribed value */ + if( qos->qos_r99.ber.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) qos->qos_r99.ber.ratio_exp = 0; /* '0' is the subscribed value */ + if( qos->qos_r99.sdu_err_ratio.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED ) qos->qos_r99.sdu_err_ratio.ratio_mant = 0; /* '0' is the subscribed value */ + if( qos->qos_r99.sdu_err_ratio.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) qos->qos_r99.sdu_err_ratio.ratio_exp = 0; /* '0' is the subscribed value */ + cmhSM_change_def_QOS_min( (T_PS_min_qos *)qos, (T_PS_ctrl_min_qos)PS_is_R99 ); + + retCd = AT_CMPL; + } + else + { +/* + * Check that a context is defined before changing the QoS. + */ + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( !p_pdp_context_node ) + { + return AT_FAIL; + } + + c_state = get_state_over_cid( cid ); + switch (c_state) + { + case PDP_CONTEXT_STATE_INVALID: + /* Wrong context state (not defined): Reject command */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + default: ; + /* Context is defined: Continue */ + } + + if( !qos OR ( qos->qos_r99.tc EQ QOS_R99_TC_OMITTED AND + qos->qos_r99.order EQ QOS_R99_ORDER_OMITTED AND + qos->qos_r99.del_err_sdu EQ QOS_R99_DEL_ERR_SDU_OMITTED AND + qos->qos_r99.max_sdu EQ QOS_R99_MAX_SDU_OMITTED AND + qos->qos_r99.max_rate_ul EQ QOS_R99_MAX_BR_UL_OMITTED AND + qos->qos_r99.max_rate_dl EQ QOS_R99_MAX_BR_DL_OMITTED AND + qos->qos_r99.xfer_delay EQ QOS_R99_XFER_DELAY_OMITTED AND + qos->qos_r99.handling_pri EQ QOS_R99_HANDLING_PRIO_OMITTED AND + qos->qos_r99.guar_br_ul EQ QOS_R99_GUAR_BR_UL_OMITTED AND + qos->qos_r99.guar_br_dl EQ QOS_R99_GUAR_BR_DL_OMITTED AND + qos->qos_r99.ber.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED AND + qos->qos_r99.ber.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED AND + qos->qos_r99.sdu_err_ratio.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED AND + qos->qos_r99.sdu_err_ratio.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) ) + + { +/* + * QoS omitted -> undefine the requested QOS + */ + cmhSM_Set_default_QOS_min( cid ); + + /* If the default parameters is in R97 format, is must be converted to R99 */ + if( p_pdp_context_node->ctrl_min_qos EQ (T_PS_ctrl_min_qos)PS_is_R97) + { + memcpy( &temp_qos, &p_pdp_context_node->min_qos.qos_r97, sizeof(T_PS_qos_r97) ); + cl_qos_convert_r97_to_r99( &temp_qos, &p_pdp_context_node->min_qos.qos_r99 ); + p_pdp_context_node->ctrl_min_qos = (T_PS_ctrl_min_qos)PS_is_R99; + } + + retCd = AT_CMPL; + } + else + { +/* + * Define the requested QOS + */ + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + /* Conversion of old R97 to R99 is not necessary because +CGEQMIN always specifies all parameters (omitting=not checking). */ + p_pdp_context_node->ctrl_min_qos = (T_PS_ctrl_min_qos)PS_is_R99; + + /* Copy the checked parameters directly to pdp_context */ + memcpy( &p_pdp_context_node->min_qos.qos_r99, qos, sizeof(T_PS_qos_r99) ); + + /* Replace omitted values with subscribed values to avoid check in SM (subscribed=accept parameter from network unconditionally) */ + if( qos->qos_r99.tc EQ QOS_R99_TC_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.tc = PS_TC_SUB; + + if( qos->qos_r99.order EQ QOS_R99_ORDER_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.order = PS_ORDER_SUB; + + if( qos->qos_r99.del_err_sdu EQ QOS_R99_DEL_ERR_SDU_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.del_err_sdu = PS_DEL_ERR_SUB; + + if( qos->qos_r99.max_sdu EQ QOS_R99_MAX_SDU_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.max_sdu = PS_MAX_SDU_SUB; + + if( qos->qos_r99.max_rate_ul EQ QOS_R99_MAX_BR_UL_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.max_rate_ul = PS_MAX_BR_UL_SUB; + + if( qos->qos_r99.max_rate_dl EQ QOS_R99_MAX_BR_DL_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.max_rate_dl = PS_MAX_BR_DL_SUB; + + if( qos->qos_r99.xfer_delay EQ QOS_R99_XFER_DELAY_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.xfer_delay = PS_XFER_DELAY_SUB; + + if( qos->qos_r99.handling_pri EQ QOS_R99_HANDLING_PRIO_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.handling_pri = PS_HANDLING_PRI_SUB; + + if( qos->qos_r99.guar_br_ul EQ QOS_R99_GUAR_BR_UL_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.guar_br_ul = PS_GUAR_BR_UL_SUB; + + if( qos->qos_r99.guar_br_dl EQ QOS_R99_GUAR_BR_DL_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.guar_br_dl = PS_GUAR_BR_DL_SUB; + + if( qos->qos_r99.ber.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.ber.ratio_mant = 0; /* '0' is the subscribed value */ + + if( qos->qos_r99.ber.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.ber.ratio_exp = 0; /* '0' is the subscribed value */ + + if( qos->qos_r99.sdu_err_ratio.ratio_mant EQ QOS_R99_RATIO_MANT_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.sdu_err_ratio.ratio_mant = 0; /* '0' is the subscribed value */ + + if( qos->qos_r99.sdu_err_ratio.ratio_exp EQ QOS_R99_RATIO_EXP_OMITTED ) + p_pdp_context_node->min_qos.qos_r99.sdu_err_ratio.ratio_exp = 0; /* '0' is the subscribed value */ + } + else + { + return( AT_FAIL ); + } + + retCd = AT_CMPL; + } + + } + + return retCd; +} +#endif /* REL99 */ + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGDCONT | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGDCONT= AT + command which sets the current setting for each context. + + GACI Context Definition GSM - 7.60 10.2.1 + + Special case +CGDCONT=<n> undefines context n + is handled as separate function call + + otherwise: + ++CGDCONT=[<cid> [,<PDP_TYPE> [,<APN> [,<PDP_addr> [,<h_comp> [,<d_comp>]]]]]] + + Issue of what happens if user changes data of an active context. + + Take simple approach, do not renegotiate current context. + Undefinition is more complex, reject attempt if context is active? + + Current pdp address is left alone and only reset when context is + explicitly undefined. + See GSM 7.60 10.2.7. + +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGDCONT( T_ACI_CMD_SRC srcId, U8 cid, T_PDP_CONTEXT *pdp_context_input ) +{ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + T_PDP_CONTEXT_STATE pdp_context_state; + + enum + { + PDP_CONTEXT_UNDEFINE = 0, + PDP_CONTEXT_DEFINE = 1, + PDP_CONTEXT_DEFINE_DEFAULT = 2 + } pdp_context_action = PDP_CONTEXT_DEFINE; + + TRACE_FUNCTION ("sAT_PlusCGDCONT()"); + + + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if( (cid < PDP_CONTEXT_CID_MIN OR + cid > PDP_CONTEXT_CID_MAX) AND (cid NEQ PDP_CONTEXT_CID_OMITTED )) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + +/* right now data compression is not supported, add PDP_CONTEXT_D_COMP_ON condition + * if enabled in the future + */ + if( pdp_context_input->d_comp NEQ PDP_CONTEXT_D_COMP_OMITTED AND + pdp_context_input->d_comp >= PDP_CONTEXT_D_COMP_INVALID) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if( pdp_context_input->h_comp NEQ PDP_CONTEXT_H_COMP_OMITTED AND + pdp_context_input->h_comp >= PDP_CONTEXT_H_COMP_INVALID) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if( ! pdp_context_type_omitted( pdp_context_input->pdp_type ) ) + { + if( ! pdp_context_type_valid( pdp_context_input->pdp_type ) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + + if( ! pdp_context_apn_omitted( pdp_context_input->pdp_apn ) ) + { + if( ! pdp_context_apn_valid( pdp_context_input->pdp_apn ) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + + if( ! pdp_context_addr_omitted( &pdp_context_input->pdp_addr ) ) + { + if( ! pdp_context_addr_valid( &pdp_context_input->pdp_addr ) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + +/* + *------------------------------------------------------------------- + * A special form of set command + *------------------------------------------------------------------- + */ + if( cid NEQ PDP_CONTEXT_CID_OMITTED AND + pdp_context_type_omitted( pdp_context_input->pdp_type ) AND + pdp_context_apn_omitted( pdp_context_input->pdp_apn ) AND + pdp_context_addr_omitted( &pdp_context_input->pdp_addr ) AND + pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED AND + pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED ) + { + pdp_context_action = PDP_CONTEXT_UNDEFINE; + } /* end if ... the special form of the set command */ + else if( (cid EQ PDP_CONTEXT_CID_OMITTED) AND( + !pdp_context_type_omitted( pdp_context_input->pdp_type ) OR + !pdp_context_apn_omitted( pdp_context_input->pdp_apn ) OR + !pdp_context_addr_omitted( &pdp_context_input->pdp_addr ) OR + !((T_PDP_CONTEXT_D_COMP)pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED) OR + !((T_PDP_CONTEXT_H_COMP)pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED) )) + { + pdp_context_action = PDP_CONTEXT_DEFINE_DEFAULT; + } + else + { + + /* + *------------------------------------------------------------------- + * default parameter + *------------------------------------------------------------------- + */ + if( pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED ) + pdp_context_input->d_comp = PDP_CONTEXT_D_COMP_OFF; + + if( pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED ) + pdp_context_input->h_comp = PDP_CONTEXT_H_COMP_OFF; + + if ( pdp_context_type_omitted( pdp_context_input->pdp_type ) ) + strcpy(pdp_context_input->pdp_type, "IP"); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + + switch ( pdp_context_action ) + { + case PDP_CONTEXT_UNDEFINE: + { + pdp_context_state = pdp_context_get_state_for_cid( cid ); + + if( pdp_context_state EQ PDP_CONTEXT_STATE_DEFINED ) + { + if( !pdp_context_cid_used_by_other( cid ) ) + { + pdp_context_remove_node( cid ); + } + else + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + else + { + ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow ); + return( AT_FAIL ); + } + break; + } + case PDP_CONTEXT_DEFINE: + { + p_pdp_context_node = pdp_context_create_node( cid ); + if( p_pdp_context_node ) + { + set_state_over_cid( cid, PDP_CONTEXT_STATE_DEFINED ); + } + else + { + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + + if( p_pdp_context_node) + { + switch(p_pdp_context_node->internal_data.state) + { + /* every time allowed */ + case PDP_CONTEXT_STATE_INVALID: + case PDP_CONTEXT_STATE_DEFINED: + p_pdp_context_node->internal_data.state = PDP_CONTEXT_STATE_DEFINED; + break; + /* allowed during context deactivation, but + WITHOUT state change */ + case PDP_CONTEXT_STATE_ABORT_ESTABLISH: + case PDP_CONTEXT_STATE_DEACTIVATE_NORMAL: + case PDP_CONTEXT_STATE_BREAKDOWN_LINK_NORMAL: + case PDP_CONTEXT_STATE_REACTIVATION_1: + case PDP_CONTEXT_STATE_REACTIVATION_2: + break; + /* Not allowed during context activation or + for activated context */ + case PDP_CONTEXT_STATE_ATTACHING: + case PDP_CONTEXT_STATE_ESTABLISH_1: + case PDP_CONTEXT_STATE_ESTABLISH_2: + case PDP_CONTEXT_STATE_ESTABLISH_3: + case PDP_CONTEXT_STATE_ACTIVATING: + case PDP_CONTEXT_STATE_ACTIVATED: + case PDP_CONTEXT_STATE_DATA_LINK: + default: + ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow ); + return( AT_FAIL ); + } + } + } + + cmhSM_Set_default_QOS( cid ); + cmhSM_Set_default_QOS_min( cid ); + + sAT_PlusCGDCONT_exec( cid, pdp_context_input ); + + if ( p_pdp_context_node NEQ NULL ) + { + set_state_over_cid( cid, p_pdp_context_node->internal_data.state ); + } + + break; + } + case PDP_CONTEXT_DEFINE_DEFAULT: + { + memcpy(&pdp_context_default.attributes, pdp_context_input, sizeof(T_PDP_CONTEXT)); + } + } + + return AT_CMPL; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : - ROUTINE : sAT_PlusCGDCONT_exec | ++--------------------------------------------------------------------+ +*/ +GLOBAL void sAT_PlusCGDCONT_exec( U8 cid, T_PDP_CONTEXT *p_pdp_context_input) +{ + + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; +/*lint -e662 (Warning:Possible creation of out-of-bounds pointe)*/ + + TRACE_FUNCTION("sAT_PlusCGDCONT_exec"); + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + p_pdp_context_node->type = PDP_CONTEXT_TYPE_PRIMARY; + + //if context type is omitted, use the one from the default context + if(pdp_context_type_omitted( p_pdp_context_input->pdp_type )) + { + memcpy( &(p_pdp_context_node->attributes.pdp_type), + &(pdp_context_default.attributes.pdp_type), + sizeof(T_PDP_CONTEXT_PDP_TYPE) ); + } + else + { + memcpy( &(p_pdp_context_node->attributes.pdp_type), + &(p_pdp_context_input->pdp_type), + sizeof(T_PDP_CONTEXT_PDP_TYPE) ); + } + + //if pdp apn is omitted, use the one from the default context + if (pdp_context_apn_omitted( p_pdp_context_input->pdp_apn )) + { + memcpy( &(p_pdp_context_node->attributes.pdp_apn), + &(pdp_context_default.attributes.pdp_apn), + sizeof(T_PDP_CONTEXT_APN) ); + } + else + { + memcpy( &(p_pdp_context_node->attributes.pdp_apn), + &(p_pdp_context_input->pdp_apn), + sizeof(T_PDP_CONTEXT_APN) ); + } + + //if context address is omitted, use the one from the default context + if (pdp_context_addr_omitted( &p_pdp_context_input->pdp_addr ) ) + { + memcpy( &(p_pdp_context_node->attributes.pdp_addr), + &(pdp_context_default.attributes.pdp_addr), + sizeof(T_NAS_ip) ); + } + else + { + memcpy( &(p_pdp_context_node->attributes.pdp_addr), + &(p_pdp_context_input->pdp_addr), + sizeof(T_NAS_ip) ); + } + + //copy default pco setting to context + memcpy(&(p_pdp_context_node->internal_data.network_pco), &(pdp_context_default.internal_data.network_pco), sizeof(T_PDP_CONTEXT_PCO)); + memcpy(&(p_pdp_context_node->internal_data.user_pco), &(pdp_context_default.internal_data.user_pco), sizeof(T_PDP_CONTEXT_PCO)); + + if(p_pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED) + p_pdp_context_node->attributes.d_comp = pdp_context_default.attributes.d_comp; + else + p_pdp_context_node->attributes.d_comp = p_pdp_context_input->d_comp; + + if (p_pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED) + p_pdp_context_node->attributes.h_comp = pdp_context_default.attributes.h_comp; + else + p_pdp_context_node->attributes.h_comp = p_pdp_context_input->h_comp; + } +} + +#ifdef REL99 +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : - ROUTINE : sAT_PlusCGDSCONT | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGDSCONT= + AT command which sets the current setting for each secondary + PDP context. + + Special case: +CGDSCONT=<cid> undefines a secondary PDP context + + +CGDSCONT=<cid> [,<p_cid> [,<h_comp> [,<d_comp>]]] +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGDSCONT( T_ACI_CMD_SRC srcId, U8 cid, T_PDP_CONTEXT *p_pdp_context_input ) +{ + + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + enum + { + PDP_CONTEXT_UNDEFINE = 0, + PDP_CONTEXT_DEFINE = 1 + + } pdp_context_action = PDP_CONTEXT_DEFINE; + + TRACE_FUNCTION ("sAT_PlusCGDSCONT()"); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( ((cid < PDP_CONTEXT_CID_MIN) OR (cid > PDP_CONTEXT_CID_MAX)) AND (cid NEQ PDP_CONTEXT_CID_OMITTED) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + + if( p_pdp_context_input->p_cid NEQ PDP_CONTEXT_CID_OMITTED ) + { + if( p_pdp_context_input->p_cid >= PDP_CONTEXT_CID_MIN AND + p_pdp_context_input->p_cid <= PDP_CONTEXT_CID_MAX ) + { + p_pdp_context_node = pdp_context_find_node_from_cid( p_pdp_context_input->p_cid ); + if( p_pdp_context_node ) + { + if( p_pdp_context_node->type NEQ PDP_CONTEXT_TYPE_PRIMARY ) + { + /* The PDP context found is not a primary PDP context */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + } + else + { + /* The primary PDP context has not been created */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + } + } + +/* right now data compression is not supported, add PDP_CONTEXT_D_COMP_ON condition + * if enabled in the future + */ + if( p_pdp_context_input->d_comp NEQ PDP_CONTEXT_D_COMP_OMITTED AND + p_pdp_context_input->d_comp >= PDP_CONTEXT_D_COMP_INVALID) + { + /* d_comp out of range */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if( p_pdp_context_input->h_comp NEQ PDP_CONTEXT_H_COMP_OMITTED AND + p_pdp_context_input->h_comp >= PDP_CONTEXT_H_COMP_INVALID ) + { + /* h_copm out of range */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } +/* + p_pdp_context_node = pdp_context_find_node_from_cid( p_pdp_context_input->p_cid ); + if( !p_pdp_context_node ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } +*/ +/* + *------------------------------------------------------------------- + * A special form of set command, that causes the context to become + * undefined. + *------------------------------------------------------------------- + */ + + if( cid NEQ PDP_CONTEXT_CID_OMITTED AND + p_pdp_context_input->p_cid EQ PDP_CONTEXT_CID_OMITTED AND + p_pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED AND + p_pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED ) + { + pdp_context_action = PDP_CONTEXT_UNDEFINE; + } /* end if ... the special form of the set command */ + +/* + *------------------------------------------------------------------- + * default parameter + *------------------------------------------------------------------- + */ + if( pdp_context_action EQ PDP_CONTEXT_DEFINE ) + { + if( p_pdp_context_input->d_comp EQ PDP_CONTEXT_D_COMP_OMITTED ) + { + p_pdp_context_input->d_comp = PDP_CONTEXT_D_COMP_OFF; + } + + if( p_pdp_context_input->h_comp EQ PDP_CONTEXT_H_COMP_OMITTED ) + { + p_pdp_context_input->h_comp = PDP_CONTEXT_H_COMP_OFF; + } + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + + switch ( pdp_context_action ) + { + case PDP_CONTEXT_UNDEFINE: + { + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + + if( !p_pdp_context_node->p_tft_pf ) + { + if( !pdp_context_remove_node( cid ) ) + { + TRACE_ERROR( "ERROR: Failed to remove secondary PDP context" ); + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + } + else + { + TRACE_ERROR( "ERROR: TFT Packet Filter not removed" ); + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + return( AT_CMPL ); + } + + case PDP_CONTEXT_DEFINE: + { + if( sAT_PlusCGDSCONT_exec( cid, p_pdp_context_input ) ) + { + set_state_over_cid( cid, PDP_CONTEXT_STATE_DEFINED ); + cmhSM_Set_default_QOS( cid ); + cmhSM_Set_default_QOS_min( cid ); + return( AT_CMPL ); + } + else + return( AT_FAIL ); + } + } + + return( AT_FAIL ); +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : - ROUTINE : sAT_PlusCGDSCONT_exec | ++--------------------------------------------------------------------+ + If the function fails to create the secondary PDP context + FALSE is returned otherwise TRUE. + +*/ +GLOBAL BOOL sAT_PlusCGDSCONT_exec( U8 cid, T_PDP_CONTEXT *p_pdp_context_input) +{ + + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node_primary = NULL; + + TRACE_FUNCTION("sAT_PlusCGDSCONT_exec"); + + p_pdp_context_node = pdp_context_create_node( cid ); + p_pdp_context_node_primary = pdp_context_find_node_from_cid( p_pdp_context_input->p_cid ); + + if( p_pdp_context_node AND p_pdp_context_node_primary ) + { + p_pdp_context_node->type = PDP_CONTEXT_TYPE_SECONDARY; + p_pdp_context_node->attributes.p_cid = p_pdp_context_input->p_cid; + + memcpy( &(p_pdp_context_node->attributes.pdp_type), + &(p_pdp_context_node_primary->attributes.pdp_type), + sizeof(T_PDP_CONTEXT_PDP_TYPE) ); + + memcpy( &(p_pdp_context_node->attributes.pdp_apn), + &(p_pdp_context_node_primary->attributes.pdp_apn), + sizeof(T_PDP_CONTEXT_APN) ); + + memcpy( &(p_pdp_context_node->attributes.pdp_addr), + &(p_pdp_context_node_primary->attributes.pdp_addr), + sizeof(T_NAS_ip) ); + + p_pdp_context_node->attributes.d_comp = p_pdp_context_input->d_comp; + p_pdp_context_node->attributes.h_comp = p_pdp_context_input->h_comp; + } + else + { + return FALSE; + } + + return TRUE; + +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : - ROUTINE : sAT_PlusCGTFT | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGTFT= AT command + which defines a PF for a TFT. + + +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGTFT( T_ACI_CMD_SRC srcId, U8 cid, T_NAS_tft_pf *p_tft_pf_input ) +{ + + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + T_TFT_INTERNAL *p_tft_pf = NULL; + + U8 pdp_context_cids[PDP_CONTEXT_CID_MAX]; /* containds cids of contexts associated to the same PDP address */ + int i = 0; + + TRACE_FUNCTION("sAT_PlusCGTFT()"); + + memset( pdp_context_cids, 0, sizeof( pdp_context_cids ) ); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + { + return( AT_BUSY ); + } + + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( !p_pdp_context_node ) + { + TRACE_EVENT("ERROR: PDP context not defined"); + return( AT_FAIL ); + } + + if( p_tft_pf_input->tft_pf_id < TFT_PF_ID_MIN OR p_tft_pf_input->tft_pf_id > TFT_PF_ID_MAX ) + { + TRACE_EVENT("ERROR: PF identifier out of range"); + return( AT_FAIL ); + } + + /* Check the evaluation precedence index. */ + /* The precedence index must be unike within the same PDP address. */ + + /* Is is a secondary PDP context */ + switch( p_pdp_context_node->type ) + { + case PDP_CONTEXT_TYPE_PRIMARY: + pdp_context_cids[i++] = p_pdp_context_node->cid; + break; + + case PDP_CONTEXT_TYPE_SECONDARY: + pdp_context_cids[i++] = p_pdp_context_node->attributes.p_cid; + p_pdp_context_node = pdp_context_find_node_from_cid( p_pdp_context_node->attributes.p_cid ); + break; + + default: + TRACE_EVENT("ERROR: PDP context type error"); + return( AT_FAIL ); + } + + + /* Search throug all defined PDP contexts. */ + /* Since the primary PDP context must be defined before defining a */ + /* secondary PDP context, the search is performed form the primary context */ + while( p_pdp_context_node ) + { + if( p_pdp_context_node->attributes.p_cid EQ pdp_context_cids[0] ) + { + pdp_context_cids[i] = p_pdp_context_node->cid; + if( p_pdp_context_node->p_next ) + i++; + } + p_pdp_context_node = p_pdp_context_node->p_next; + } + + i--; + while( i >= (PDP_CONTEXT_CID_MIN - 1) AND i < PDP_CONTEXT_CID_MAX ) + { + p_pdp_context_node = pdp_context_find_node_from_cid( pdp_context_cids[i] ); + + p_tft_pf = p_pdp_context_node->p_tft_pf; + + while( p_tft_pf ) + { + if( p_tft_pf->pf_attributes.tft_pf_precedence NEQ p_tft_pf_input->tft_pf_precedence ) + { + p_tft_pf = p_tft_pf->p_next; + } + else + { + TRACE_EVENT("ERROR: Precedence index in use"); + return( AT_FAIL ); + } + } + + i--; + } + + + /* + * Check for omitted parameters. If all, except cid and tft_pf_id, are omitted the TFT PF must be removed. + */ + if( cid AND + p_tft_pf_input->tft_pf_id AND + ! p_tft_pf_input->tft_pf_precedence AND + ! p_tft_pf_input->tft_pf_valid_bits ) + { + if( ! pdp_context_del_tft_pf( cid, p_tft_pf_input->tft_pf_id ) ) + { + return AT_FAIL; + } + } + else + { + + /* Check if the TFT PF is already created */ + p_tft_pf = pdp_context_find_tft_pf( cid, p_tft_pf_input->tft_pf_id ); + if( p_tft_pf ) + { + /* The TFT PF is already created, overwrite existing attrributes */ + + memset( &p_tft_pf->pf_attributes, 0, sizeof(T_NAS_tft_pf) ); + memcpy( &p_tft_pf->pf_attributes, p_tft_pf_input, sizeof( T_NAS_tft_pf ) ); + + if( get_state_over_cid(cid) EQ PDP_CONTEXT_STATE_ACTIVATED OR + get_state_over_cid(cid) EQ PDP_CONTEXT_STATE_DATA_LINK ) + { + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + p_pdp_context_node->tft_changed = TRUE; + } + } + + } + else + { + p_tft_pf = pdp_context_add_tft_pf( cid, p_tft_pf_input->tft_pf_id ); + if( p_tft_pf ) + { + memcpy( &p_tft_pf->pf_attributes, p_tft_pf_input, sizeof( T_NAS_tft_pf ) ); + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( p_pdp_context_node ) + { + p_pdp_context_node->tft_changed = TRUE; + } + + } + else + { + return( AT_FAIL ); + } + } + } + + return AT_CMPL; + +} +#endif /* REL99 */ +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGACT | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGACT= AT + command which causes the cids specified in the cids list to + be activated or deactivated according to state. + + An empty list will cause all defined contexts to be + activated or deactivated. If taken literally, this means that + if more contexts are defined than supported, each will be + activated, resulting in 'no resource' errors for the late ones + as the GACI SEM will reject requests for more activations + than it can cope with. + + Note that the context is/are activated, but no CONNECT is sent + to the TE. This is the difference between ACT and DATA commands. + + SMREG activate req does not need l2p to be sent, but in this case + the PDP config options are undefined (see below). + + How does a DATA call bind these 'orphan' connections to a TE given + that a cid definition is a 'template' due to its ambiguity. + + Practically, the activate form of this command has little meaning in the + case of PPP and loopback protocols (only ones supported at present). + + Simplest option at the moment is not to support the activate form until + a protocol type is supported can make real use of it. The deactivate form + is of use in switching off a Loopback connection. + + If activation before protocol establishment is supported, a NULL protocol service + will have to be provided which supplies a default (empty?) PCO list to SMREG for + activation and stores the network PCO response until a CGDATA is issued, must then + convert the protocol into that requested by the CGDATA command. + For future implementation + + + Other issues for multiple context activation : + + - need to add a para onto GACI activate to tell it whether + to do a CONNECT or an OK callback on activation. + +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGACT( T_ACI_CMD_SRC srcId, T_CGACT_STATE state, SHORT *cids ) +{ + T_PDP_CONTEXT_STATE pdp_context_state; + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + U8 i = 0; + U8 j = 0; + + + char * number= "*99#"; + T_ACI_RETURN ret_val; + TRACE_FUNCTION ("sAT_PlusCGACT()"); + +/* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if(!cmh_IsVldCmdSrc (srcId)) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( (state < CGACT_STATE_OMITTED) OR (state >= CGACT_STATE_INVALID) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + + i = 0; + while ((i<PDP_CONTEXT_CID_MAX) AND (cids[i] NEQ PDP_CONTEXT_CID_INVALID)) + { + if ( (cids[i] < PDP_CONTEXT_CID_MIN OR cids[i] > PDP_CONTEXT_CID_MAX) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + i++; + } + +/* + *------------------------------------------------------------------- + * default parameter + *------------------------------------------------------------------- + */ + if ( state EQ CGACT_STATE_OMITTED ) + { /* state is not optional */ + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + +/* + *------------------------------------------------------------------- + * enable +CGACT to deactivate a context during activation + *------------------------------------------------------------------- + */ + if( CGACT_STATE_DEACTIVATED EQ state ) + { + ret_val = cmhSM_deactivateContexts(srcId, cids); + switch(ret_val) + { + case AT_EXCT: + smEntStat.curCmd = AT_CMD_CGACT; + smEntStat.entOwn = srcId; + smShrdPrm.owner = (UBYTE) srcId; + return AT_EXCT; + default: + return ret_val; + } + } + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + + if( gpppEntStat.curCmd EQ AT_CMD_CGDATA ) + return( AT_BUSY ); + + /* FDN check */ + if (pb_get_fdn_mode () EQ FDN_ENABLE AND state EQ CGACT_STATE_ACTIVATED) + { + if (pb_check_fdn (FDN, (UBYTE*)number) NEQ 1) + { + TRACE_EVENT("sAT_PlusCGACT: Entry not found in FDN, GPRS not allowed."); + ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow); + return (AT_FAIL); + } + TRACE_EVENT("sAT_PlusCGACT: Entry found in FDN, GPRS allowed."); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + + cid_pointer = 0; + + if( *cids EQ PDP_CONTEXT_CID_INVALID ) /* all defined or activated contexts (dependent by state) */ + { + p_pdp_context_node = p_pdp_context_list; + while( p_pdp_context_node ) + { + if( p_pdp_context_node->internal_data.state EQ PDP_CONTEXT_STATE_DEFINED ) + { + work_cids[j] = p_pdp_context_node->cid; + j++; + } + p_pdp_context_node = p_pdp_context_node->p_next; + } + work_cids[j] = PDP_CONTEXT_CID_INVALID; + + if( work_cids[0] EQ PDP_CONTEXT_CID_INVALID ) + { + return AT_CMPL; + } + } + else /* all declarated contexts */ + { + /* copy cid list */ + for( i = 0; cids[i] NEQ PDP_CONTEXT_CID_INVALID; i++ ) + { + if( (cids[i] < PDP_CONTEXT_CID_MIN OR cids[i] > PDP_CONTEXT_CID_MAX) OR i >= PDP_CONTEXT_CID_MAX ) + { + TRACE_EVENT("not a valid cid!!!"); + work_cids[0] = PDP_CONTEXT_CID_INVALID; + return AT_FAIL; + } + else + { + work_cids[i] = (U8)cids[i]; + } + } + work_cids[i] = PDP_CONTEXT_CID_INVALID; + + for(j = 0; work_cids[j] NEQ PDP_CONTEXT_CID_INVALID; j++) + { + pdp_context_state = get_state_over_cid( work_cids[j] ); + if( pdp_context_state EQ PDP_CONTEXT_STATE_INVALID ) + { /* Context not defined, define it. */ + if( sAT_PlusCGDCONT( srcId, work_cids[j], &pdp_context_default.attributes ) EQ AT_FAIL ) + { + return AT_FAIL; + } + } + else + { + if ( pdp_context_state NEQ PDP_CONTEXT_STATE_DEFINED ) + { + cid_pointer = 0; + work_cids[0] = PDP_CONTEXT_CID_INVALID; + return ( AT_FAIL ); + } + } + } + } + TRACE_EVENT("activating context!"); + + smEntStat.curCmd = AT_CMD_CGACT; + smEntStat.entOwn = srcId; + smShrdPrm.owner = (UBYTE) srcId; + + smShrdPrm.direc = CGEREP_EVENT_ME_ACT; + + set_conn_param_on_all_working_cids( (UBYTE)srcId, DTI_ENTITY_INVALID ); + + /* + *------------------------------------------------------------------- + * Check the PS attach state and attach if necessary. + *------------------------------------------------------------------- + */ + switch (cmhGMM_attach_if_necessary( srcId, AT_CMD_CGACT )) + { + case AT_EXCT: + { + /* Performing the attach procedure */ + set_state_working_cid( PDP_CONTEXT_STATE_ATTACHING ); + break; + } + case AT_CMPL: + { + /* Already attached -> activate the context */ + cmhSM_activate_context(); + break; + } + default: + { + smEntStat.curCmd = AT_CMD_NONE; + return AT_FAIL; + } + } + + return AT_EXCT; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGDATA | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGDATA= AT + command which establish the communication. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGDATA( T_ACI_CMD_SRC srcId, char *L2P, U8 *p_cid_array ) +{ + U8 i = 0; + U8 j = 0; + U8 k = 0; + + U8 contexts_to_activate[PDP_CONTEXT_CID_MAX]; // old work_cid + T_DTI_ENTITY_ID connectToEntity = DTI_ENTITY_INVALID; + T_PDP_CONTEXT_INTERNAL *p_pdp_context_prim_node = NULL; /* Primary PDP context node */ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_sec_node = NULL; /* Secondary PDP context node */ + T_PDP_CONTEXT_STATE pdp_context_state_prim; + + TRACE_FUNCTION ("sAT_PlusCGDATA()"); + + memset( &contexts_to_activate, PDP_CONTEXT_CID_INVALID, sizeof( contexts_to_activate ) ); + +/* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if(!cmh_IsVldCmdSrc (srcId)) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + + if( gpppEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + + if (pb_get_fdn_mode () EQ FDN_ENABLE) + { + + + + if (pb_check_fdn (0, (const UBYTE *)"*99#") NEQ PHB_OK) + { + TRACE_EVENT("sAT_PlusCGDATA: Entry not found in FDN, GPRS not allowed."); + ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow); + return (AT_FAIL); + } + TRACE_EVENT("sAT_PlusCGDATA: Entry found in FDN, GPRS allowed."); + } + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( L2P[0] EQ 0 ) + strcpy (L2P, "PPP"); /* default value */ + + if ( (!strcmp(L2P, "PPP")) OR (!strcmp(L2P, "IP")) ) + { +#if defined(FF_PKTIO) OR defined(FF_TCP_IP) + if ( TRUE NEQ srcc_reserve_sources( SRCC_PKTIO_SNDCP_LINK, 1 ) ) + return ( AT_FAIL ); +#endif +/* if ( FALSE EQ srcc_reserve_sources( SRCC_PPPS_SNDCP_LINK, 1 ) ) + return ( AT_FAIL );*/ + connectToEntity = DTI_ENTITY_PPPS; + } +#if defined(FF_PKTIO) OR defined(FF_TCP_IP) OR defined(FF_PSI) + else if( !strcmp(L2P, "M-PKT") OR !strcmp(L2P, "M-IP")) + { + if ( FALSE EQ srcc_reserve_sources( SRCC_PKTIO_SNDCP_LINK, 1 ) ) + return ( AT_FAIL ); + } +#endif /* FF_PKTIO OR FF_TCP_IP OR FF_PSI */ + else + { + return ( AT_FAIL ); + } + +/* + *----------------------------------------------------------------- + * cid parameter range check + *----------------------------------------------------------------- + */ + i=0; + while ((i<PDP_CONTEXT_CID_MAX) AND (p_cid_array[i] NEQ PDP_CONTEXT_CID_INVALID)) + { + if (p_cid_array[i] > PDP_CONTEXT_CID_INVALID) + return (AT_FAIL); + i++; + } + + /* + *----------------------------------------------------------------- + * Validate the cid array, primary PDP before secondary contexts + *----------------------------------------------------------------- + */ + + while( p_cid_array[i] NEQ PDP_CONTEXT_CID_INVALID ) + { + p_pdp_context_sec_node = pdp_context_find_node_from_cid( p_cid_array[i] ); + if( p_pdp_context_sec_node ) + { + if( p_pdp_context_sec_node->type EQ PDP_CONTEXT_TYPE_SECONDARY ) + { + pdp_context_state_prim = pdp_context_get_state_for_cid( p_pdp_context_sec_node->attributes.p_cid ); + if( pdp_context_state_prim NEQ PDP_CONTEXT_STATE_ACTIVATED AND + pdp_context_state_prim NEQ PDP_CONTEXT_STATE_DATA_LINK ) + { + k = 0; + while( k <= j ) + { + if( p_pdp_context_sec_node->attributes.p_cid EQ contexts_to_activate[k] ) + { + contexts_to_activate[j] = p_cid_array[i]; + j++; + break; + } + else + { + k++; + } + } + if( k > j ) + { + /* since k > j the primary context was not privious entered */ + return( AT_FAIL ); + } + } + p_pdp_context_prim_node = pdp_context_find_node_from_cid( p_pdp_context_sec_node->attributes.p_cid ); + if( p_pdp_context_prim_node ) + { + if( !p_pdp_context_sec_node->p_tft_pf AND !p_pdp_context_prim_node->p_tft_pf ) + { + return( AT_FAIL ); + } + } + else + { + return( AT_FAIL ); + } + } + else + { + contexts_to_activate[j] = p_cid_array[i]; + j++; + } + } + + i++; + + } + + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + + memset (work_cids, PDP_CONTEXT_CID_INVALID, PDP_CONTEXT_CID_MAX); + cid_pointer=0; + + i = 0; + while( i < PDP_CONTEXT_CID_MAX AND p_cid_array[i] NEQ PDP_CONTEXT_CID_INVALID ) + { + switch( pdp_context_get_state_for_cid( p_cid_array[i] ) ) + { + case PDP_CONTEXT_STATE_INVALID: + /* define pdp context and */ + /* add pdp context cid to the work_cids array */ + + if( sAT_PlusCGDCONT( srcId, p_cid_array[i], &pdp_context_default.attributes ) EQ AT_FAIL ) + { + return AT_FAIL; + } + else + { + work_cids[i] = p_cid_array[i]; + } + + break; + + case PDP_CONTEXT_STATE_DEFINED: + case PDP_CONTEXT_STATE_ACTIVATED: + /* add pdp context cid to the activation list */ + + work_cids[i] = p_cid_array[i]; + break; + + default: + TRACE_FUNCTION("sAT_PlusCGDATA: Invalid state for cid"); + break; + } + + i++; + } + +/* + *------------------------------------------------------------------- + * check if any cids to activate in work_cids. + *------------------------------------------------------------------- + */ + if (work_cids[0] EQ PDP_CONTEXT_CID_INVALID) + return AT_FAIL; + + +/* + *------------------------------------------------------------------- + * check number of context + *------------------------------------------------------------------- + */ +#if defined(FF_PKTIO) OR defined(FF_TCP_IP) + if ( TRUE NEQ srcc_reserve_sources( SRCC_PKTIO_SNDCP_LINK, j ) ) // j is not used !!! + return ( AT_FAIL ); +#endif +/* process function + *------------------------------------------------------------------- + */ + + /* APN validation */ + +/* + *------------------------------------------------------------------- + * Store the command and entity parameters. + *------------------------------------------------------------------- + */ + set_conn_param_on_working_cid( (UBYTE)srcId, connectToEntity ); + if (connectToEntity EQ DTI_ENTITY_PPPS) + { + gpppEntStat.curCmd = AT_CMD_CGDATA; + gpppEntStat.entOwn = srcId; + gpppShrdPrm.owner = (UBYTE) srcId; + } + else + { + smEntStat.curCmd = AT_CMD_CGDATA; + smEntStat.entOwn = srcId; + smShrdPrm.owner = (UBYTE) srcId; + } + + smShrdPrm.direc = CGEREP_EVENT_ME_ACT; + +/* + *------------------------------------------------------------------- + * Check the PS attach state and attach if necessary. + *------------------------------------------------------------------- + */ + switch (cmhGMM_attach_if_necessary( srcId, AT_CMD_CGDATA )) + { + case AT_EXCT: + { + /* Performing the attach procedure */ + set_state_working_cid( PDP_CONTEXT_STATE_ATTACHING ); + break; + } + case AT_CMPL: + { + cmhSM_data_link_context(); + break; + } + default: + { + smEntStat.curCmd = AT_CMD_NONE; + gpppEntStat.curCmd = AT_CMD_NONE; + return AT_FAIL; + } + } + return AT_EXCT; + +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGPADDR | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGPADDR= AT + command which give the PDP address back. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGPADDR ( T_ACI_CMD_SRC srcId, SHORT *cids, T_NAS_ip *pdp_adress ) +{ + U8 index = 0; + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + TRACE_FUNCTION ("sAT_PlusCGPADDR()"); + + p_pdp_context_node = p_pdp_context_list; + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + if( *cids EQ PDP_CONTEXT_CID_OMITTED ) + { + /* + * the PDP addresse for all defined contexts are returned + */ + + while( p_pdp_context_node ) + { + cids[index] = cmhSM_get_pdp_addr_for_CGPADDR( p_pdp_context_node->cid, &pdp_adress[index] ); + + p_pdp_context_node = p_pdp_context_node->p_next; + index++; + } + + cids[index] = PDP_CONTEXT_CID_INVALID; + + } + else + { + /* + * the PDP addresse for all specified contexts are returned + */ + + while( cids[index] NEQ PDP_CONTEXT_CID_INVALID ) + { + p_pdp_context_node = pdp_context_find_node_from_cid( (U8)cids[index] ); + if( p_pdp_context_node ) + { + cids[index] = cmhSM_get_pdp_addr_for_CGPADDR( p_pdp_context_node->cid, &pdp_adress[index] ); + } + else + { + return (AT_FAIL); + } + index++; + } + } + + return AT_CMPL; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGAUTO | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGAUTO= AT + command which set the mode of automatic response to + network request for PDP context activation. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGAUTO ( T_ACI_CMD_SRC srcId, T_CGAUTO_N n ) +{ + TRACE_FUNCTION ("sAT_PlusCGAUTO()"); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if ( (n < CGAUTO_N_OMITTED) OR (n >= CGAUTO_N_INVALID) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return AT_FAIL; + } + +/* + *------------------------------------------------------------------- + * default parameter + *------------------------------------------------------------------- + */ + if ( n EQ CGAUTO_N_OMITTED ) + n = CGAUTO_N_MCM_GPRS_CSC; + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + automatic_response_mode = (SHORT) n; + + /* the MT shall attempt to perform a GPRS attach if it is not already attached */ + if ( n EQ 1 ) + { + return sAT_PlusCGATT ( srcId, CGATT_STATE_ATTACHED ); + } + return AT_CMPL; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finnished ROUTINE : sAT_PlusCGANS | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the +CGANS= AT + command to respond manual to a network request for + PDP context activation. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGANS ( T_ACI_CMD_SRC srcId, USHORT response, char *l2p, U8 cid ) +{ + char L2P[MAX_L2P_LENGTH]; + T_PDP_CONTEXT pdp_context; + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + U8 i = 0; + U8 cid_to_activate = PDP_CONTEXT_CID_INVALID; + + TRACE_FUNCTION ("sAT_PlusCGANS()"); + + memcpy( &pdp_context, &pdp_context_default, sizeof( pdp_context ) ); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if(!cmh_IsVldCmdSrc (srcId)) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * check parameter + *------------------------------------------------------------------- + */ + if (response >= CGANS_RESPONSE_INVALID) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * check call table + *------------------------------------------------------------------- + */ + if( gprs_ct_index EQ current_gprs_ct_index ) + return ( AT_FAIL ); + +/* + *------------------------------------------------------------------- + * stop ringing + *------------------------------------------------------------------- + */ + for( i = 0; i < CMD_SRC_MAX; i++ ) + { + R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)i )( 0 ); + } +#ifdef FF_ATI + io_setRngInd ( IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */ +#endif + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + switch( response ) + { + case CGANS_RESPONSE_REJECT: + psaSM_PDP_No_activate(gprs_call_table[current_gprs_ct_index].sm_ind.ti, CAUSE_NWSM_ACTIVATE_REJECTED_UNSPECIFIED); + + cmhSM_next_call_table_entry(); + + return AT_CMPL; + + case CGANS_RESPONSE_ACCEPT: + /* + *------------------------------------------------------------------- + * check number of context + *------------------------------------------------------------------- + */ +#if defined(FF_PKTIO) OR defined(FF_TCP_IP) + if( srcc_reserve_sources( SRCC_PKTIO_SNDCP_LINK, 1 ) EQ FALSE ) + return ( AT_FAIL ); +#endif + /* + *------------------------------------------------------------------- + * check the last two command arguments + *------------------------------------------------------------------- + */ + if( !gprs_call_table[current_gprs_ct_index].L2P[0] ) + { + if ( l2p NEQ NULL ) + { + if( !(*l2p) ) + strcpy(L2P, "PPP"); + else + { + strncpy(L2P, l2p, MAX_L2P_LENGTH - 1); + L2P[MAX_L2P_LENGTH - 1] = 0; + } + } + else + strcpy(L2P, "PPP"); + + if ( strcmp(L2P, "PPP") ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + cid_to_activate = cid; + } + else + { + cid_to_activate = (U8) gprs_call_table[current_gprs_ct_index].cid; + } + + /* find first free position in work_cids array */ + i = 0; + while( i < PDP_CONTEXT_CID_MAX AND work_cids[i] NEQ PDP_CONTEXT_CID_INVALID ) + { + i++; + } + + if( i >= PDP_CONTEXT_CID_MAX ) + { + return AT_FAIL; + } + + cid_pointer = i; + + switch( cid_to_activate ) + { + case PDP_CONTEXT_CID_OMITTED: + p_pdp_context_node = pdp_context_find_matching_node( + (T_SMREG_VAL_pdp_type) gprs_call_table[current_gprs_ct_index].sm_ind.pdp_type, + gprs_call_table[current_gprs_ct_index].sm_ind.ctrl_ip_address, + &gprs_call_table[current_gprs_ct_index].sm_ind.ip_address ); + + if( p_pdp_context_node AND p_pdp_context_node->type EQ PDP_CONTEXT_TYPE_PRIMARY ) + { + cid_to_activate = p_pdp_context_node->cid; + work_cids[cid_pointer] = cid_to_activate; + } + else + { + // No defined context found, with matching parameters. + + cid_to_activate = pdp_context_get_free_cid(); + + // Define PDP context with default parameters. + + if( sAT_PlusCGDCONT( srcId, cid_to_activate, &pdp_context_default.attributes ) EQ AT_FAIL ) + { + return AT_FAIL; + } + else + { + work_cids[cid_pointer] = cid_to_activate; + } + + } + + break; + + case PDP_CONTEXT_CID_INVALID: + break; + + default: + switch( pdp_context_get_state_for_cid( cid_to_activate ) ) + { + case PDP_CONTEXT_STATE_INVALID: + /* define pdp context and */ + /* add pdp context cid to the work_cids array */ + + if( sAT_PlusCGDCONT( srcId, cid_to_activate, &pdp_context_default.attributes ) EQ AT_FAIL ) + { + return AT_FAIL; + } + else + { + work_cids[cid_pointer] = cid_to_activate; + } + break; + + case PDP_CONTEXT_STATE_DEFINED: + /* add pdp context cid to the activation list */ + + work_cids[cid_pointer] = cid_to_activate; + break; + } + } + + /* + *------------------------------------------------------------------- + * set the actually context data + *------------------------------------------------------------------- + */ +/* + ctx.qos.preced = gprs_call_table[current_gprs_ct_index].sm_ind.smreg_qos.preced; + ctx.qos.delay = gprs_call_table[current_gprs_ct_index].sm_ind.smreg_qos.delay; + ctx.qos.relclass = gprs_call_table[current_gprs_ct_index].sm_ind.smreg_qos.relclass; + ctx.qos.peak = gprs_call_table[current_gprs_ct_index].sm_ind.smreg_qos.peak; + ctx.qos.mean = gprs_call_table[current_gprs_ct_index].sm_ind.smreg_qos.mean; +*/ + strncpy(pdp_context.pdp_apn, (const char *) gprs_call_table[current_gprs_ct_index].sm_ind.apn.apn_buf, + gprs_call_table[current_gprs_ct_index].sm_ind.apn.c_apn_buf); + + /* IP v4 address */ + pdp_context.pdp_addr.ctrl_ip_address = gprs_call_table[current_gprs_ct_index].sm_ind.ctrl_ip_address; + switch( gprs_call_table[current_gprs_ct_index].sm_ind.ctrl_ip_address) + { + case NAS_is_ipv4: /* IPv4 address */ + memcpy( &pdp_context.pdp_addr.ip_address.ipv4_addr.a4, &gprs_call_table[current_gprs_ct_index].sm_ind.ip_address.ipv4_addr.a4, NAS_SIZE_IPv4_ADDR ); +/* + sprintf( ctx.pdp_addr, "%hd.%hd.%hd.%hd", + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[0], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[1], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[2], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[3]); +*/ + break; + case NAS_is_ipv6: /* IPv6 address */ + memcpy( &pdp_context.pdp_addr.ip_address.ipv6_addr.a6, &gprs_call_table[current_gprs_ct_index].sm_ind.ip_address.ipv6_addr.a6, NAS_SIZE_IPv6_ADDR ); +/* + sprintf( ctx.pdp_addr, "%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd.%hd", + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 0], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 1], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 2], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 3], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 4], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 5], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 6], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 7], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 8], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[ 9], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[10], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[11], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[12], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[13], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[14], + gprs_call_table[current_gprs_ct_index].sm_ind.pdp_address.pdp_buf[15]); +*/ + break; + default: + return( AT_FAIL ); + } + + switch( (T_SMREG_VAL_pdp_type) gprs_call_table[current_gprs_ct_index].sm_ind.pdp_type ) + { + case SMREG_PDP_PPP: + strcpy( pdp_context.pdp_type, "PPP" ); + break; + case SMREG_PDP_IPV4: + strcpy( pdp_context.pdp_type, "IP" ); + break; + case SMREG_PDP_IPV6: + strcpy( pdp_context.pdp_type, "IPV6" ); + break; + default: + return( AT_FAIL ); + } + + /* + *------------------------------------------------------------------- + * set some parameter of the call table + *------------------------------------------------------------------- + */ + if ( !gprs_call_table[current_gprs_ct_index].L2P[0]) + { + /*lint -e{645} */ /* L2P is initialized within the same if-construct some lines above */ + strcpy (gprs_call_table[current_gprs_ct_index].L2P, L2P); + gprs_call_table[current_gprs_ct_index].cid = cid_to_activate; + } + + sAT_PlusCGDCONT_exec( cid_to_activate, &pdp_context ); + + p_pdp_context_node = pdp_context_find_node_from_cid( cid_to_activate ); + if( p_pdp_context_node ) + { + p_pdp_context_node->internal_data.smreg_ti = gprs_call_table[current_gprs_ct_index].sm_ind.ti; + } + else + { + TRACE_ERROR( "ERROR: PDP context not found, in function sAT_PlusCGANS" ); + } + + /* + *------------------------------------------------------------------- + * process function + *------------------------------------------------------------------- + */ + gpppEntStat.curCmd = AT_CMD_CGDATA; + gpppEntStat.entOwn = srcId; + gpppShrdPrm.owner = (UBYTE) srcId; + + smShrdPrm.direc = CGEREP_EVENT_NW_ACT; + + set_conn_param_on_working_cid( (UBYTE)srcId, DTI_ENTITY_PPPS ); + + cmhSM_data_link_context(); + return AT_EXCT; + } + + return AT_FAIL; +} + +GLOBAL T_ACI_RETURN sAT_PlusCGEREP ( T_ACI_CMD_SRC srcId, T_CGEREP_MODE mode, T_CGEREP_BFR bfr ) +{ + + TRACE_FUNCTION ("sAT_PlusCGEREP()"); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check first command argument + *------------------------------------------------------------------- + */ + if ( mode < CGEREP_MODE_OMITTED OR mode >= CGEREP_MODE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + if ( bfr < CGEREP_BFR_OMITTED OR bfr >= CGEREP_BFR_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + + /* only the last source which used CGEREP will receive those indications */ + sm_cgerep_srcId = srcId; + + if ( mode NEQ CGEREP_MODE_OMITTED ) + sm_cgerep_mode = mode; + + if ( bfr NEQ CGEREP_BFR_OMITTED ) + sm_cgerep_bfr = bfr; + + switch ( mode ) + { + case CGEREP_MODE_BUFFER: + case CGEREP_MODE_DICARD_RESERVED: + cmhSM_cgerep_buffer ( ); + break; + case CGEREP_MODE_BUFFER_RESERVED: + break; + case CGEREP_MODE_INVALID: + case CGEREP_MODE_OMITTED: + default: + break; + } + + return AT_CMPL; +} + +#ifdef DTI +GLOBAL T_ACI_RETURN sAT_PlusCGSMS ( T_ACI_CMD_SRC srcId, T_CGSMS_SERVICE service ) +{ + T_ACI_RETURN retCd = AT_CMPL; /* holds return code */ + + TRACE_FUNCTION ("sAT_PlusCGSMS()"); + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check first command argument + *------------------------------------------------------------------- + */ + if ( service < CGSMS_SERVICE_OMITTED OR service >= CGSMS_SERVICE_INVALID ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * process parameter + *------------------------------------------------------------------- + */ + if ( service EQ CGSMS_SERVICE_OMITTED ) + service = sm_cgsms_service; + + if ( service NEQ sm_cgsms_service ) + { + smEntStat.curCmd = AT_CMD_CGSMS; + smEntStat.entOwn = srcId; + smShrdPrm.owner = (UBYTE) srcId; + + cmhSM_set_sms_service ( service ); + + retCd = AT_EXCT; + } + + return retCd; +} +#endif +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finished ROUTINE : string_to_dns | ++--------------------------------------------------------------------+ + +PURPOSE : +*/ +LOCAL void string_to_dns(CHAR* dns, ULONG *dns_long) +{ + UBYTE dns_len = 4; + CHAR dns_adrtest[3]; + UBYTE dns_adr [4]; + UBYTE i = 0; + + memset(&dns_adrtest,0,dns_len-1); + memset(&dns_adr,0,dns_len); + + if(strlen(dns) NEQ 0) + { + for(i=0;i<dns_len;i++) + { + strncpy(dns_adrtest,dns,dns_len-1); + dns_adr[i] = (UBYTE)atoi(dns_adrtest); + dns = dns+dns_len; + } + for(i=0;i<dns_len;i++) + { + *dns_long= *dns_long + dns_adr[i]; + if (i<(dns_len-1)) + *dns_long = *dns_long<<8; + } + } +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finished ROUTINE : sAT_PercentCGPCO_HEX | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the ?CGPCO= AT + command to set protocol configuration options for the + PDP context activation. +*/ + +GLOBAL T_ACI_RETURN sAT_PercentCGPCO_HEX ( T_ACI_CMD_SRC srcId, UBYTE cid, UBYTE *pco_array, UBYTE pco_len) +{ + T_ACI_RETURN ret; + + TRACE_FUNCTION("sAT_PercentCGPCO_HEX"); + /* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if ( !cmh_IsVldCmdSrc (srcId) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + ret = cmhSM_CGPCO_HEX (cid, pco_array, pco_len); + return ret; +} + + +/* ++--------------------------------------------------------------------+ +| PROJECT : GSM-PS (8441) MODULE : CMH_SMS | +| STATE : finished ROUTINE : sAT_PercentCGPCO | ++--------------------------------------------------------------------+ + +PURPOSE : This is the functional counterpart to the ?CGPCO= AT + command to set protocol configuration options for the + PDP context activation. +*/ + +GLOBAL T_ACI_RETURN sAT_PercentCGPCO( T_ACI_CMD_SRC srcId, + U8 cid, USHORT protocol, + CHAR *user, CHAR *pwd, CHAR *dns1, CHAR *dns2 ) +{ + U8 pco_len = ACI_PCO_MAX_LEN; + UBYTE *pco_array; + T_ACI_RETURN ret; + + + /* + * Due to introduction of dynamic data structures the functionality of the command is changed. + * NOTE: User PCO is only applied to already defined PDP contexts. + */ + ULONG dns_adr1 = 0x00000000; + ULONG dns_adr2 = 0x00000000; + + + TRACE_FUNCTION("sAT_PercentCGPCO"); + /* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if ( !cmh_IsVldCmdSrc (srcId) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + ACI_MALLOC (pco_array, ACI_PCO_MAX_LEN); + + string_to_dns( dns1, &dns_adr1 ); + string_to_dns( dns2, &dns_adr2 ); + + ret = (T_ACI_RETURN) utl_create_pco( pco_array, (USHORT*)&pco_len, + ACI_PCO_CONTENTMASK_AUTH | + ACI_PCO_CONTENTMASK_DNS1 | + ACI_PCO_CONTENTMASK_DNS2, + ACI_PCO_CONFIG_PROT_PPP, + protocol, (UBYTE*)user, (UBYTE*)pwd, dns_adr1, dns_adr2); + if (ret < 0) + { + TRACE_EVENT_P1 ("sAT_PercentCGPCO(): invalid protocol=%d", protocol); + + ACI_MFREE (pco_array); + return (AT_FAIL); + } + ret = cmhSM_CGPCO_HEX (cid, pco_array, pco_len); + ACI_MFREE (pco_array); + return ret; +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : GPRS MODULE : CMH_SMS | +| STATE : finished ROUTINE : qAT_PercentCGPCO | ++--------------------------------------------------------------------+ + + PURPOSE : %CGPCO command + * analyze network PCO a cid +*/ + +GLOBAL T_ACI_RETURN qAT_PercentCGPCO ( T_ACI_CMD_SRC srcId, ULONG * gateway, + ULONG * dns1,ULONG * dns2, USHORT cid) +{ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + + + TRACE_FUNCTION("qAT_PercentCGPCO()"); + + p_pdp_context_node = pdp_context_find_node_from_cid( (U8)cid); + if( !p_pdp_context_node) + { + return (AT_FAIL); + } + + switch(p_pdp_context_node->internal_data.state) + { + case PDP_CONTEXT_STATE_ACTIVATED: + case PDP_CONTEXT_STATE_ESTABLISH_3: + case PDP_CONTEXT_STATE_DATA_LINK: + utl_analyze_pco(p_pdp_context_node->internal_data.network_pco.pco, p_pdp_context_node->internal_data.network_pco.len, dns1, dns2, gateway); + break; + default: + break; + } + return (AT_CMPL); +} + +#ifdef REL99 +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : finished ROUTINE : sAT_PlusCGEQNEG | ++--------------------------------------------------------------------+ + + PURPOSE : This is the functional counterpart to the +CGEQNEG= AT + command and returns current settings for the specified + PDP context. The function might be called multiple times + if more cids are specified. + The QoS returned is always in Release 99 format (3GPP). + RETURNS: - AT_CMPL : Completed. + - AT_FAIL : Command not valid for srcId. + UPDATES: - qos: Quality of service for cid. Not updated if cid is undefined. + - qos_valid: Indicates whether qos is updated not. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGEQNEG ( T_ACI_CMD_SRC srcId, U8 cid, BOOL *qos_valid, T_PS_qos *qos) +{ + T_PDP_CONTEXT_INTERNAL *p_pdp_context_node = NULL; + TRACE_FUNCTION ("sAT_PlusCGEQNEG()"); + +/* + *------------------------------------------------------------------- + * check command source - should be Serial link ? + *------------------------------------------------------------------- + */ + if ( !cmh_IsVldCmdSrc (srcId) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + + p_pdp_context_node = pdp_context_find_node_from_cid( cid ); + if( ! p_pdp_context_node ) + { + *qos_valid = FALSE; + return AT_CMPL; + } + +/* + *------------------------------------------------------------------- + * fill in parameters + *------------------------------------------------------------------- + */ + switch ( get_state_over_cid(cid) ) + { + case PDP_CONTEXT_STATE_ACTIVATED: + case PDP_CONTEXT_STATE_DATA_LINK: + { + if( p_pdp_context_node->ctrl_neg_qos EQ PS_is_R99 ) + { + memcpy( qos, &p_pdp_context_node->neg_qos, sizeof(T_PS_qos) ); + } + else + { + /* The QoS is in Release 97 format and must be converted first. */ + if( !cl_qos_convert_r97_to_r99( &p_pdp_context_node->neg_qos.qos_r97, &(qos->qos_r99)) ) + { + /* Failed to convert to Release 99. Never end here !!!! */ + return( AT_FAIL ); + } + } + *qos_valid = TRUE; + break; + } + default : + *qos_valid = FALSE; + } + + return( AT_CMPL ); +} + +/* ++--------------------------------------------------------------------+ +| PROJECT : UMTS MODULE : CMH_SMS | +| STATE : finished ROUTINE : sAT_PlusCGCMOD | ++--------------------------------------------------------------------+ + + PURPOSE : This is the functional counterpart to the +CGCMOD= AT + command. + RETURNS: - AT_EXCT : Executing. + - AT_FAIL : One of the cids is not valid or not active. +*/ +GLOBAL T_ACI_RETURN sAT_PlusCGCMOD ( T_ACI_CMD_SRC srcId, U8 *cid) +{ + + + TRACE_FUNCTION ("sAT_PlusCGCMOD()"); + +/* + *------------------------------------------------------------------- + * check command source + *------------------------------------------------------------------- + */ + if ( !cmh_IsVldCmdSrc (srcId) ) + { + ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); + return( AT_FAIL ); + } + +/* + *------------------------------------------------------------------- + * check entity status + *------------------------------------------------------------------- + */ + if( smEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + + if( gpppEntStat.curCmd NEQ AT_CMD_NONE ) + return( AT_BUSY ); + +/* + *------------------------------------------------------------------- + * check all context and fill work_cids list + *------------------------------------------------------------------- + */ + if (!cmhSM_make_active_cid_list ( srcId, cid )) + return( AT_FAIL ); + +/* + *------------------------------------------------------------------- + * fill in parameters command parameters and send the modify request + *------------------------------------------------------------------- + */ + switch( get_state_over_cid(work_cids[cid_pointer]) ) + { + case PDP_CONTEXT_STATE_ACTIVATED: + set_state_over_cid(work_cids[cid_pointer], PDP_CONTEXT_STATE_ACTIVATED_MODIFYING); + break; + + case PDP_CONTEXT_STATE_DATA_LINK: + set_state_over_cid(work_cids[cid_pointer], PDP_CONTEXT_STATE_DATA_LINK_MODIFYING); + break; + + default: + return( AT_FAIL ); /* Obsolete: State already checked in cmhSM_make_active_cid_list */ + } + + /* Send the modify request */ + psaSM_PDP_Modify(); + smEntStat.curCmd = AT_CMD_CGCMOD; + smEntStat.entOwn = srcId; + smShrdPrm.owner = (UBYTE) srcId; + return( AT_EXCT ); +} + +#endif /* REL99 */ + +#endif /* GPRS */ +/*==== EOF ========================================================*/