FreeCalypso > hg > fc-tourmaline
view src/g23m-gprs/gmm/gmm_pei.c @ 303:f76436d19a7a default tip
!GPRS config: fix long-standing AT+COPS chance hanging bug
There has been a long-standing bug in FreeCalypso going back years:
sometimes in the AT command bring-up sequence of an ACI-only MS,
the AT+COPS command would produce only a power scan followed by
cessation of protocol stack activity (only L1 ADC traces), instead
of the expected network search sequence. This behaviour was seen
in different FC firmware versions going back to Citrine, and seemed
to follow some law of chance, not reliably repeatable.
This bug has been tracked down and found to be specific to !GPRS
configuration, stemming from our TCS2/TCS3 hybrid and reconstruction
of !GPRS support that was bitrotten in TCS3.2/LoCosto version.
ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3
version and had to be pulled from TCS2 - but as it turns out,
there is a new field in the MMR_REG_REQ primitive that needs to be
set correctly, and that psa_mms.c module is the place where this
initialization needed to be added.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 08 Jun 2023 08:23:37 +0000 |
parents | fa8dc04885d8 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GPRS (8441) | Modul : gmm_pei.c +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module implements the process body interface | for the entity GPRS Mobility Management (GMM) | | Exported functions: | | pei_create - Create the Protocol Stack Entity | pei_init - Initialize Protocol Stack Entity | pei_primitive - Process Primitive | pei_timeout - Process Timeout | pei_exit - Close resources and terminate | pei_run - Process Primitive | pei_config - Dynamic Configuration | pei_monitor - Monitoring of physical Parameters +----------------------------------------------------------------------------- */ #define GMM_PEI_C #define ENTITY_GMM /*==== INCLUDES =============================================================*/ #include <stddef.h> /* to get definition of offsetof(), for MAK_FUNC_S */ #include <stdlib.h> /* to get atoi for tokenizer in pei_init */ #include "typedefs.h" /* to get Condat data types */ #include "vsi.h" /* to get a lot of macros */ #include "macdef.h" #include "gprs.h" #include "gsm.h" /* to get a lot of macros */ #include "cnf_gmm.h" /* to get cnf-definitions */ #include "mon_gmm.h" /* to get mon-definitions */ #include "prim.h" /* to get the definitions of used SAP and directions */ #include "pei.h" /* to get PEI interface */ #include "gmm.h" /* to get the global entity definitions */ #include "gmm_f.h" /* to get the debug print function */ #include "gmm_kernp.h" /* to get primitive interface to KERN */ #include "gmm_txp.h" /* to get primitive interface to TX */ #include "gmm_rxp.h" /* to get primitive interface to RX */ #include "gmm_rdyp.h" /* to get primitive interface to RDY */ #include "gmm_syncp.h" /* to get primitive interface to SYNC */ #include "gmm_kernf.h" /* to get functions from KERN */ #include "gmm_txf.h" /* to get functions from TX */ #include "gmm_rxf.h" /* to get functions from RX */ #include "gmm_rdyf.h" /* to get functions from RDY */ #include "gmm_syncf.h" /* to get functions from SYNC */ #include "ccdapi.h" /* to get ccd stuff */ #include "tok.h" /* to get tokenizer */ #include <string.h> /* to get memcpy */ #include "gmm_em.h" /*to get definitions of the Engineering Mode*/ /*==== DEFINITIONS ==========================================================*/ /*==== TYPES ================================================================*/ /*==== GLOBAL VARS ==========================================================*/ /*==== LOCAL VARS ===========================================================*/ static BOOL first_access = TRUE; static T_MONITOR gmm_mon; /* * Jumptables to primitive handler functions. One table per SAP. * * Use MAK_FUNC_0 for primitives which contains no SDU. * Use MAK_FUNC_S for primitives which contains a SDU. */ /******************************************************* * SAVE prim *******************************************************/ #define PEI_SIGNAL_NOT_SAVED FALSE #define PEI_SIGNAL_SAVED TRUE #define PEI_END_SAVETAB 0xFF #define GMM_MAX_SIGNALS_SAVED 5 /* value adjusted to GMM requirements */ typedef struct SAVE_QUEUE { void* prim; T_VOID_FUNC func; struct SAVE_QUEUE* next; } T_SAVE_QUEUE; void gmm_pei_delete_queue( T_SAVE_QUEUE** queue ); typedef struct { USHORT state; USHORT signal[GMM_MAX_SIGNALS_SAVED]; } T_SAVE_TAB; /*==== LOCAL PROTOTYPES =====================================================*/ LOCAL void gmm_pei_handle_prim( T_VOID_FUNC func, void* prim ); LOCAL BOOL gmm_pei_handle_save( void* prim, T_SAVE_QUEUE** queue, const T_SAVE_TAB* table, T_VOID_FUNC func); LOCAL void gmm_pei_handle_queue( T_SAVE_QUEUE** queue, const T_SAVE_TAB* table); /*==== VAR LOCAL ============================================================*/ LOCAL T_SAVE_QUEUE* save_queue; /* SAVE queue hangers */ LOCAL const T_SAVE_TAB save_tab[] = { { KERN_GMM_REG_INITIATED, {MMGMM_LUP_NEEDED_IND, GMMREG_NET_REQ, GMMREG_PLMN_RES, 0, 0 } }, { KERN_GMM_RAU_INITIATED, {MMGMM_LUP_NEEDED_IND, GMMREG_DETACH_REQ, GMMREG_NET_REQ, GMMREG_PLMN_RES, 0 } }, {KERN_GMM_RAU_WAIT_FOR_NPDU_LIST , {GMMRR_CELL_IND, 0, 0, 0, 0 } }, { KERN_GMM_DEREG_SUSPENDING, {GMMREG_NET_REQ, GMMREG_PLMN_RES, GMMRR_CS_PAGE_IND, MMGMM_CM_ESTABLISH_IND, MMGMM_CM_EMERGENCY_IND } }, { KERN_GMM_REG_SUSPENDING, {GMMREG_NET_REQ, GMMREG_PLMN_RES, GMMRR_CS_PAGE_IND, MMGMM_CM_ESTABLISH_IND, MMGMM_CM_EMERGENCY_IND } }, { KERN_GMM_REG_RESUMING, {GMMREG_DETACH_REQ, GMMRR_CS_PAGE_IND, MMGMM_CM_ESTABLISH_IND, MMGMM_CM_EMERGENCY_IND, GMMREG_ATTACH_REQ } }, { KERN_GMM_DEREG_RESUMING, {GMMREG_DETACH_REQ, GMMRR_CS_PAGE_IND, MMGMM_CM_ESTABLISH_IND, MMGMM_CM_EMERGENCY_IND, GMMREG_ATTACH_REQ} }, { PEI_END_SAVETAB, { 0, 0, 0, 0, 0 } } }; /******************************************************* * End SAVE prim *******************************************************/ /* * Function is needed for grr_table[]. This declaration can be removed * as soon as this function is no more called (i.e. all primitives are * handled). */ LOCAL void primitive_not_supported (void *data); static const T_FUNC gmmreg_table[] = { MAK_FUNC_0(kern_gmmreg_attach_req, GMMREG_ATTACH_REQ), MAK_FUNC_0(kern_gmmreg_detach_req, GMMREG_DETACH_REQ), MAK_FUNC_0(kern_gmmreg_net_req, GMMREG_NET_REQ), MAK_FUNC_0(kern_gmmreg_plmn_res, GMMREG_PLMN_RES), MAK_FUNC_0(kern_gmmreg_plmn_mode_req, GMMREG_PLMN_MODE_REQ), MAK_FUNC_0(kern_gmmreg_config_req, GMMREG_CONFIG_REQ), }; #ifdef FF_EM_MODE static const T_FUNC em_ul_table[] = { MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x00 */ /*EM_SC_GPRS_INFO_REQ cannot be sent directly from ACI to GRR, because no SAP is defined. So it have to be passed via GMM.*/ MAK_FUNC_0(em_gmm_sc_gprs_info_req, EM_SC_GPRS_INFO_REQ ), /* 0x01 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x02 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x03 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x04 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x05 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x06 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x07 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x08 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x09 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0A */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0B */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0C */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0D */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0E */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0F */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x10 */ MAK_FUNC_0(em_gmm_pco_trace_req , EM_PCO_TRACE_REQ ), /* 0x11*/ /*PCO output*/ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x12 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x13 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x14 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x15 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x16 */ MAK_FUNC_0(em_gmm_info_req, EM_GMM_INFO_REQ ), /* 0x17 */ /*EM_GRLC_INFO_REQ cannot be sent directly from ACI to GRLC, so it is passed via GMM*/ MAK_FUNC_0(em_gmm_grlc_info_req, EM_GRLC_INFO_REQ ), /* 0x18 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x19 */ MAK_FUNC_0(em_gmm_grr_event_req, EM_GRR_EVENT_REQ ), /* 0x1A */ MAK_FUNC_0(em_gmm_event_req, EM_GMM_EVENT_REQ ), /* 0x1B */ MAK_FUNC_0(em_gmm_grlc_event_req, EM_GRLC_EVENT_REQ ), /* 0x1C */ MAK_FUNC_0(em_gmm_throughput_info_req, EM_THROUGHPUT_INFO_REQ ) /* 0x1D */ }; static const T_FUNC em_dl_table[] = { MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x00 */ /*EM_SC_GPRS_INFO_CNF cannot be sent directly from GRR to ACI, so it is passed via GMM*/ MAK_FUNC_0(em_gmm_sc_gprs_info_cnf, EM_SC_GPRS_INFO_CNF ), /* 0x01 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x02 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x03 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x04 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x05 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x06 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x07 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x08 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x09 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0A */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0B */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0C */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0D */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0E */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x0F */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x10 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x11 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x12 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x13 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x14 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x15 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x16 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x17 */ /*EM_GRLC_INFO_CNF cannot be sent directly from ACI to GRLC, so it is passed via GMM*/ MAK_FUNC_0(em_gmm_grlc_info_cnf, EM_GRLC_INFO_CNF ), /* 0x18 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x19 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x1A */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x1B */ MAK_FUNC_N(primitive_not_supported, 0 ), /* 0x1C */ MAK_FUNC_0(em_gmm_throughput_info_cnf, EM_THROUGHPUT_INFO_CNF ) /* 0x1D */ }; #endif /* FF_EM_MODE */ static const T_FUNC gmmrr_table[] = { MAK_FUNC_0(sync_gmmrr_cell_ind, GMMRR_CELL_IND), MAK_FUNC_N(primitive_not_supported, 0 ), MAK_FUNC_0(kern_gmmrr_page_ind, GMMRR_PAGE_IND), MAK_FUNC_0(kern_gmmrr_cs_page_ind, GMMRR_CS_PAGE_IND), MAK_FUNC_0(kern_gmmrr_suspend_cnf, GMMRR_SUSPEND_CNF), MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ),/* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_0(kern_gmmrr_cr_ind, GMMRR_CR_IND), }; static const T_FUNC cgrlc_table[] = /* TCS 2.1 */ { /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_N(primitive_not_supported, 0 ), /* TCS 2.1 */ MAK_FUNC_0(kern_cgrlc_status_ind, CGRLC_STATUS_IND ), /* TCS 2.1 */ MAK_FUNC_0(kern_cgrlc_test_mode_cnf, CGRLC_TEST_MODE_CNF ), /* TCS 2.1 */ MAK_FUNC_0(rdy_cgrlc_trigger_ind, CGRLC_TRIGGER_IND ), /* TCS 2.1 */ MAK_FUNC_0(rdy_cgrlc_standby_state_ind, CGRLC_STANDBY_STATE_IND ), /* TCS 2.1 */ MAK_FUNC_0(rdy_cgrlc_ready_state_ind, CGRLC_READY_STATE_IND ), /* TCS 2.1 */ }; /* TCS 2.1 */ #ifndef GMM_TCS4 static const T_FUNC gmmsm_table[] = { MAK_FUNC_0(kern_gmmsm_establish_req, GMMSM_ESTABLISH_REQ), MAK_FUNC_S(tx_gmmsm_unitdata_req, GMMSM_UNITDATA_REQ), MAK_FUNC_0(kern_gmmsm_sequence_res, GMMSM_SEQUENCE_RES), }; #else static const T_FUNC mmpm_table[] = { #ifdef REL99 MAK_FUNC_0(kern_gmmsm_pdp_status_req, MMPM_PDP_CONTEXT_STATUS_REQ), #else MAK_FUNC_0(primitive_not_supported, MMPM_PDP_CONTEXT_STATUS_REQ), #endif MAK_FUNC_N(primitive_not_supported, 0), MAK_FUNC_N(primitive_not_supported, 0), MAK_FUNC_0(kern_gmmsm_sequence_res, MMPM_SEQUENCE_RES), MAK_FUNC_S(tx_gmmsm_unitdata_req, MMPM_UNITDATA_REQ), }; #endif /* #ifndef GMM_TCS4 */ static const T_FUNC gmmsms_table[] = { MAK_FUNC_0(kern_gmmsms_reg_state_req, GMMSMS_REG_STATE_REQ) }; LOCAL const T_FUNC sim_table[] = { MAK_FUNC_0 (primitive_not_supported , SIM_READ_CNF ), /* 0x00 */ MAK_FUNC_0 (primitive_not_supported , SIM_UPDATE_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_READ_RECORD_CNF ), MAK_FUNC_N (primitive_not_supported , 0 ), MAK_FUNC_0 (primitive_not_supported , SIM_UPDATE_RECORD_CNF ), MAK_FUNC_N (primitive_not_supported , 0 ), MAK_FUNC_N (primitive_not_supported , 0 ), MAK_FUNC_N (primitive_not_supported , 0 ), MAK_FUNC_0 (primitive_not_supported , SIM_INCREMENT_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_VERIFY_PIN_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_CHANGE_PIN_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_DISABLE_PIN_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_ENABLE_PIN_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_UNBLOCK_CNF ), MAK_FUNC_0 (kern_sim_authentication_cnf , SIM_AUTHENTICATION_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_MMI_INSERT_IND ), MAK_FUNC_0 (primitive_not_supported , SIM_MM_INSERT_IND ), MAK_FUNC_0 (kern_sim_remove_ind , SIM_REMOVE_IND ), MAK_FUNC_0 (primitive_not_supported , SIM_SYNC_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_ACTIVATE_CNF ), MAK_FUNC_0 (primitive_not_supported , SIM_SMS_INSERT_IND ), /* 0x14 */ MAK_FUNC_0 (primitive_not_supported , SIM_TOOLKIT_IND ), /* 0x15 */ MAK_FUNC_0 (primitive_not_supported , SIM_TOOLKIT_CNF ), /* 0x16 */ MAK_FUNC_0 (primitive_not_supported , SIM_ACTIVATE_IND ), /* 0x17 */ MAK_FUNC_0 (primitive_not_supported , SIM_MM_INFO_IND ), /* 0x18 GMM GlumPs*/ MAK_FUNC_0 (primitive_not_supported , SIM_ACCESS_CNF ), /* 0x19 */ MAK_FUNC_0 (primitive_not_supported , SIM_FILE_UPDATE_IND ), /* 0x1a */ MAK_FUNC_0 (kern_sim_gmm_insert_ind , SIM_GMM_INSERT_IND ), /* 0x1b */ }; static const T_FUNC ll_table[] = { MAK_FUNC_0(primitive_not_supported, LL_RESET_IND), MAK_FUNC_S(primitive_not_supported, LL_ESTABLISH_CNF), MAK_FUNC_S(primitive_not_supported, LL_ESTABLISH_IND), MAK_FUNC_0(primitive_not_supported, LL_RELEASE_CNF), MAK_FUNC_0(primitive_not_supported, LL_RELEASE_IND), MAK_FUNC_S(primitive_not_supported, LL_XID_CNF), MAK_FUNC_S(primitive_not_supported, LL_XID_IND), MAK_FUNC_0(primitive_not_supported, LL_READY_IND), MAK_FUNC_0(primitive_not_supported, LL_UNITREADY_IND), MAK_FUNC_0(primitive_not_supported, LL_DATA_CNF), MAK_FUNC_S(primitive_not_supported, LL_DATA_IND), MAK_FUNC_S(rx_ll_unitdata_ind, LL_UNITDATA_IND) }; static const T_FUNC llgmm_table[] = { MAK_FUNC_0(kern_llgmm_status_ind, LLGMM_STATUS_IND), MAK_FUNC_0(kern_llgmm_tlli_ind, LLGMM_TLLI_IND) }; static const T_FUNC mmgmm_table[] = { MAK_FUNC_0(sync_mmgmm_reg_cnf, MMGMM_REG_CNF), MAK_FUNC_0(sync_mmgmm_reg_rej, MMGMM_REG_REJ), MAK_FUNC_0(sync_mmgmm_nreg_ind, MMGMM_NREG_IND), MAK_FUNC_0(kern_mmgmm_nreg_cnf, MMGMM_NREG_CNF), MAK_FUNC_0(kern_mmgmm_plmn_ind, MMGMM_PLMN_IND), MAK_FUNC_0(kern_mmgmm_auth_rej_ind, MMGMM_AUTH_REJ_IND), MAK_FUNC_0(kern_mmgmm_cm_establish_ind, MMGMM_CM_ESTABLISH_IND), MAK_FUNC_0(kern_mmgmm_cm_release_ind, MMGMM_CM_RELEASE_IND), MAK_FUNC_0(sync_mmgmm_activate_ind, MMGMM_ACTIVATE_IND), MAK_FUNC_0(kern_mmgmm_t3212_val_ind, MMGMM_T3212_VAL_IND), MAK_FUNC_0(kern_mmgmm_info_ind, MMGMM_INFO_IND), MAK_FUNC_0(kern_mmgmm_cm_emergency_ind, MMGMM_CM_EMERGENCY_IND), MAK_FUNC_0(kern_mmgmm_lup_accept_ind, MMGMM_LUP_ACCEPT_IND), MAK_FUNC_0(kern_mmgmm_lup_needed_ind, MMGMM_LUP_NEEDED_IND), MAK_FUNC_0(kern_mmgmm_ciphering_ind, MMGMM_CIPHERING_IND), MAK_FUNC_0(kern_mmgmm_tmsi_ind, MMGMM_TMSI_IND), MAK_FUNC_0(kern_mmgmm_ahplmn_ind, MMGMM_AHPLMN_IND) }; /*==== PRIVATE FUNCTIONS ====================================================*/ /* +------------------------------------------------------------------------------ | Function : primitive_not_supported +------------------------------------------------------------------------------ | Description : This function handles unsupported primitives. | | Parameters : - | | Return : - | +------------------------------------------------------------------------------ */ LOCAL void primitive_not_supported (void *data) { TRACE_FUNCTION ("primitive_not_supported"); PFREE (data); } /*==== PUBLIC FUNCTIONS =====================================================*/ /* +------------------------------------------------------------------------------ | Function : pei_primitive +------------------------------------------------------------------------------ | Description : This function is called by the frame when a primitive is | received and needs to be processed. | | | | GMMREG | | | | | | GMMSM | GMMSM GMMAA UPLINK | | | | | | +---v-----v-----v-----v----+ | | | | MMGMM ----> GMM | | | | | +---^--------^--------^----+ | | | | | | | LLGMM DOWNLINK | | GMMRR | | | | | SIM | | | | | Parameters : prim - Pointer to the received primitive | | Return : PEI_OK - function succeeded | PEI_ERROR - function failed | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_primitive (void * primptr) { TRACE_FUNCTION ("pei_primitive"); #ifdef TRACE_FUNC #ifdef IDENTATION gmm_data->deep=0; #endif #endif if (primptr NEQ NULL) { T_PRIM *prim = (T_PRIM *)primptr; ULONG opc = prim->custom.opc; USHORT n; const T_FUNC *table; /* * This must be called for Partition Pool supervision. Will be replaced * by another macro some time. */ VSI_PPM_REC (&prim->custom, __FILE__, __LINE__); GMM_TRACE_GMM_DATA(GMM_DEBUG_PRINT_MASK_STATE); PTRACE_IN (opc); switch (SAP_NR(opc)) { case GMMREG_UL: table = gmmreg_table; n = TAB_SIZE (gmmreg_table); break; case GMMRR_DL: table = gmmrr_table; n = TAB_SIZE (gmmrr_table); break; case SAP_NR(CGRLC_DL): /* TCS 2.1 */ table = cgrlc_table; /* TCS 2.1 */ n = TAB_SIZE (cgrlc_table); /* TCS 2.1 */ break; /* TCS 2.1 */ #ifndef GMM_TCS4 case GMMSM_UL: table = gmmsm_table; n = TAB_SIZE (gmmsm_table); break; #else case SAP_NR(MMPM_UL): table = mmpm_table; n = TAB_SIZE (mmpm_table); break; #endif case GMMSMS_UL: table = gmmsms_table; n = TAB_SIZE (gmmsms_table); break; case SAP_NR(SIM_UL):/*lint !e778 (Info -- Constant expression evaluates to 0 in operation '&') */ table = sim_table; n = TAB_SIZE (sim_table); break; case LL_DL: table = ll_table; n = TAB_SIZE (ll_table); break; case LLGMM_DL: table = llgmm_table; n = TAB_SIZE (llgmm_table); break; case MMGMM_DL: table = mmgmm_table; n = TAB_SIZE (mmgmm_table); break; #ifdef FF_EM_MODE case EM_Ul: table = em_ul_table; n = TAB_SIZE (em_ul_table); break; case EM_Dl: table = em_dl_table; n = TAB_SIZE (em_dl_table); break; #endif /* FF_EM_MODE */ default: TRACE_ERROR("pei_primitive. Unknown SAP"); table = NULL; n = 0; break; } if (table != NULL) { if (PRIM_NR(opc) < n) { table += PRIM_NR(opc); #ifdef PALLOC_TRANSITION P_SDU(prim) = table->soff ? (T_sdu*) (((char*)&prim->data) + table->soff) : 0; #ifndef NO_COPY_ROUTING P_LEN(prim) = table->size + sizeof (T_PRIM_HEADER); #endif /* NO_COPY_ROUTING */ #endif /* PALLOC_TRANSITION */ /******************************************************* * SAVE prim *******************************************************/ if( gmm_pei_handle_save( prim, &save_queue, save_tab, table->func ) == PEI_SIGNAL_NOT_SAVED ) { UBYTE old_kern_state = gmm_data->kern.state; /******************************************************* * SAVE prim *******************************************************/ JUMP (table->func) (P2D(prim)); /******************************************************* * SAVE prim *******************************************************/ if( gmm_data->kern.state != old_kern_state ) { gmm_pei_handle_queue(&save_queue, save_tab); } } else { TRACE_2_INFO ("S:%2d SAVE of Primitive 0x%x", gmm_data->kern.state, opc ); } /******************************************************* * End SAVE prim *******************************************************/ } else { primitive_not_supported (P2D(prim)); } return PEI_OK; } /* * primitive is not a GSM primitive - forward it to the environment */ if (opc & SYS_MASK) vsi_c_primitive (VSI_CALLER prim); else { PFREE (P2D(prim)); return PEI_ERROR; } } return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_init +------------------------------------------------------------------------------ | Description : This function is called by the frame. It is used to initialise | the entitiy. | | Parameters : handle - task handle | | Return : PEI_OK - entity initialised | PEI_ERROR - entity not (yet) initialised | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_init (T_HANDLE handle) { TRACE_FUNCTION ("pei_init"); /* * Initialize task handle */ GMM_handle = handle; /* * Open communication channels */ if (hCommSMS < VSI_OK) { if ((hCommSMS = vsi_c_open (VSI_CALLER SMS_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommSM < VSI_OK) { if ((hCommSM = vsi_c_open (VSI_CALLER SM_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommGRLC < VSI_OK) /* TCS 2.1 */ { /* TCS 2.1 */ if ((hCommGRLC = vsi_c_open (VSI_CALLER GRLC_NAME)) < VSI_OK) /* TCS 2.1 */ return PEI_ERROR; /* TCS 2.1 */ } /* TCS 2.1 */ if (hCommGRR < VSI_OK) { if ((hCommGRR = vsi_c_open (VSI_CALLER GRR_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommLLC < VSI_OK) { if ((hCommLLC = vsi_c_open (VSI_CALLER LLC_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommSIM < VSI_OK) { if ((hCommSIM = vsi_c_open (VSI_CALLER SIM_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommMM < VSI_OK) { if ((hCommMM = vsi_c_open (VSI_CALLER MM_NAME)) < VSI_OK) return PEI_ERROR; } if (hCommMMI < VSI_OK) { if ((hCommMMI = vsi_c_open (VSI_CALLER ACI_NAME)) < VSI_OK) /* TCS 2.1 */ return PEI_ERROR; } if (hCommGMM < VSI_OK) { if ((hCommGMM = vsi_c_open (VSI_CALLER GMM_NAME)) < VSI_OK) return PEI_ERROR; } #ifdef GMM_TCS4 if (hCommUPM < VSI_OK) { if ((hCommUPM = vsi_c_open (VSI_CALLER UPM_NAME)) < VSI_OK) return PEI_ERROR; } #endif /* * Initialize global pointer llc_data. This is required to access all * entity data. */ gmm_data = &gmm_data_base; /* * Initialite ccd */ ccd_init (); #ifdef FF_EM_MODE em_init_gmm_event_trace(); #endif /* FF_EM_MODE */ /* * Initialize entity data (call init function of every service) */ kern_init(); rxgmm_init(); txgmm_init(); rdy_init(); sync_gmm_init(); GMM_TRACE_GMM_DATA(GMM_DEBUG_PRINT_MASK_FULL); return (PEI_OK); } /* +------------------------------------------------------------------------------ | Function : pei_timeout +------------------------------------------------------------------------------ | Description : This function is called by the frame when a timer has expired. | | Parameters : index - timer index | | Return : PEI_OK - timeout processed | PEI_ERROR - timeout not processed | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_timeout (USHORT index) { UBYTE old_kern_state; TRACE_FUNCTION ("pei_timeout"); old_kern_state = gmm_data->kern.state; /* * Process timeout */ switch (index) { case kern_T3302: /* * T3302 expired. */ kern_t3302 (); break; case kern_T3310: /* * T3310 expired. */ kern_t3310 (); break; case kern_T3311: /* * T3311 expired. */ kern_t3311 (); break; case kern_T3321: /* * T3321 expired. */ kern_t3321 (); break; case rdy_T3312: /* * T3312 expired. */ kern_t3312 (); break; case kern_TPOWER_OFF: kern_tpower_off(); break; case kern_TLOCAL_DETACH: kern_tlocal_detach(); break; case sync_TSYNC: sync_tsync(); break; default: TRACE_ERROR("Unknown Timeout"); return PEI_ERROR; } if( gmm_data->kern.state != old_kern_state ) { gmm_pei_handle_queue( &save_queue, save_tab); } return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_signal +------------------------------------------------------------------------------ | Description : This function is called by the frame when a signal has been | received. | | Parameters : opc - signal operation code | *data - pointer to primitive | | Return : PEI_OK - signal processed | PEI_ERROR - signal not processed | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_signal (ULONG opc, void *data) { TRACE_FUNCTION ("pei_signal"); /* * Process signal */ switch (opc) { default: TRACE_ERROR("Unknown Signal OPC"); break; }/*lint !e764 (Info -- switch statement does not have a case) */ return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_exit +------------------------------------------------------------------------------ | Description : This function is called by the frame when the entity is | terminated. All open resources are freed. | | Parameters : - | | Return : PEI_OK - exit sucessful | PEI_ERROR - exit not sueccessful | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_exit (void) { TRACE_FUNCTION ("pei_exit"); /* * Close communication channels */ vsi_c_close (VSI_CALLER hCommSMS); hCommSMS = VSI_ERROR; vsi_c_close (VSI_CALLER hCommSM); hCommSM = VSI_ERROR; vsi_c_close (VSI_CALLER hCommGRLC); /* TCS 2.1 */ hCommGRLC = VSI_ERROR; /* TCS 2.1 */ vsi_c_close (VSI_CALLER hCommGRR); hCommGRR = VSI_ERROR; vsi_c_close (VSI_CALLER hCommLLC); hCommLLC = VSI_ERROR; vsi_c_close (VSI_CALLER hCommSIM); hCommSIM = VSI_ERROR; vsi_c_close (VSI_CALLER hCommMM); hCommMM = VSI_ERROR; vsi_c_close (VSI_CALLER hCommMMI); hCommMMI = VSI_ERROR; vsi_c_close (VSI_CALLER hCommGMM); hCommGMM = VSI_ERROR; /* * delete queues */ gmm_pei_delete_queue(&save_queue); /* * close ccd */ ccd_exit (); return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_run +------------------------------------------------------------------------------ | Description : This function is called by the frame when entering the main | loop. This fucntion is only required in the active variant. | | This function is not used. | | Parameters : handle - Communication handle | | Return : PEI_OK - sucessful | PEI_ERROR - not successful | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_run (T_HANDLE TaskHandle, T_HANDLE ComHandle ) { return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : gmm_tok_key +------------------------------------------------------------------------------ | Description : This function is used by pei_config in windows test | environment for string tokenizing for CHECK STATE command, e.g. | COMMAND("GMM CONFIG CHECK_STATE=<REG_NORMAL_SERVICE>"); | | | Parameters : | | Return : | | +------------------------------------------------------------------------------ */ #ifndef _TARGET_ typedef struct KW_STATE_DATA { char keyword[60]; SHORT code; } KW_STATE_DATA; LOCAL SHORT gmm_tok_key (KW_STATE_DATA * keytab, char * keyword) { /* * Empty string terminates */ while (keytab->keyword[0]) { if (strcmp (keytab->keyword, keyword ) == 0) return (keytab->code); keytab++; } return (TOK_NOT_FOUND); } #endif /* +------------------------------------------------------------------------------ | Function : pei_config +------------------------------------------------------------------------------ | Description : This function is called by the frame when a primitive is | received indicating dynamic configuration. | | This function is not used in this entity. | | Parameters : handle - Communication handle | | Return : PEI_OK - sucessful | PEI_ERROR - not successful | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_config (char *inString) { TRACE_FUNCTION ("pei_config"); TRACE_FUNCTION (inString); #ifndef NCONFIG /* * Parse next keyword and number of variables */ if(!strcmp(inString,"PERIODIC_LAU")) { PALLOC (mmgmm_lup_needed_ind, MMGMM_LUP_NEEDED_IND); mmgmm_lup_needed_ind->reason = MMGMM_T3212; /* TCS 2.1 */ TRACE_EVENT( "Info: Periodic LAU requested by MM"); PSEND (hCommGMM, mmgmm_lup_needed_ind); } else if(!strcmp(inString,"PERIODIC_RAU")) { kern_t3312(); } else if(!strcmp(inString,"REATTACH")) { PALLOC (gmmrr_page_ind, GMMRR_PAGE_IND); gmmrr_page_ind->page_id=GMMRR_IMSI; PSEND (hCommGMM, gmmrr_page_ind); } else if(!strcmp(inString,"CELL")) { PALLOC (gmmrr_cell_ind, GMMRR_CELL_IND); gmmrr_cell_ind->cell_info.service_state=GMMRR_SERVICE_FULL; gmmrr_cell_ind->cell_info.cell_env.rai.lac=0x2506; gmmrr_cell_ind->cell_info.cell_env.rai.rac=0x71; gmmrr_cell_ind->cell_info.net_mode=gmm_data->config.nmo; PSEND (hCommGMM, gmmrr_cell_ind); } else if(!strcmp(inString,"NMO_I")) { gmm_data->config.nmo = GMMRR_NET_MODE_I; } else if(!strcmp(inString,"NMO_II")) { gmm_data->config.nmo = GMMRR_NET_MODE_II; } else if(!strcmp(inString,"NMO_III")) { gmm_data->config.nmo = GMMRR_NET_MODE_III; } else if(!strcmp(inString,"GMM_INFO")) { PALLOC (gmmreg_info_ind, GMMREG_INFO_IND); PSEND (hCommMMI, gmmreg_info_ind); } else if(!strcmp(inString,"RESET_SIM")) { gmm_data->sim_gprs_invalid = TRUE; kern_sim_del_locigprs (); kern_sim_gmm_update(); kern_mm_auth_rej(); { PALLOC (sim_update_req, SIM_UPDATE_REQ); sim_update_req->source = SRC_GMM; /* req_id is not filled since response is not handled */ sim_update_req->v_path_info = FALSE; sim_update_req->datafield = SIM_FPLMN; sim_update_req->length = 12; memset (sim_update_req->trans_data,0xff,12); sim_update_req->offset = 0; PSEND (hCommSIM, sim_update_req); } { PALLOC (sim_update_req, SIM_UPDATE_REQ); sim_update_req->source = SRC_GMM; /* req_id is not filled since response is not handled */ sim_update_req->v_path_info = FALSE; sim_update_req->datafield = SIM_LOCI; sim_update_req->length = 11; memset (sim_update_req->trans_data,0xff,8); sim_update_req->trans_data[8]=0xfe; sim_update_req->trans_data[9]=0x0; sim_update_req->trans_data[10]=GU2_NOT_UPDATED; sim_update_req->offset = 0; PSEND (hCommSIM, sim_update_req); } } else if(!strcmp(inString,"ANITE")) { gmm_data->anite = TRUE; } else if(!strcmp(inString,"CIPHER_OFF")) { gmm_data->config.cipher_on = 0x00; TRACE_EVENT ("ciphering switched OFF"); } else if(!strcmp(inString,"CIPHER_ON")) { gmm_data->config.cipher_on |= 0x01; } else if(!strcmp(inString,"PREUSE_OFF")) { gmm_data->config.preuse_off = TRUE; } #ifdef REL99 else if(!strcmp(inString,"CL_SGSN_REL_98_OR_OLDER")) /* TCS 4.0 */ { /* TCS 4.0 */ /*gmm_data->config.sgsnr_flag = R_98NW; */ cl_nwrl_set_sgsn_release(PS_SGSN_98_OLDER); /*CL function*/ /* TCS 4.0 */ } /* TCS 4.0 */ else if(!strcmp(inString,"CL_SGSN_REL_99_ONWARDS")) /* TCS 4.0 */ { /* TCS 4.0 */ /* gmm_data->config.sgsnr_flag = R_99NW; */ cl_nwrl_set_sgsn_release(PS_SGSN_99_ONWARDS); /*CL function*/ /* TCS 4.0 */ } /* TCS 4.0 */ else if (!strcmp(inString,"CELL_NOTIFY_ON")) /* TCS 4.0 */ { /* TCS 4.0 */ gmm_data->config.cell_notification = FIRST_CELL_NOTIFY; /* TCS 4.0 */ } /* TCS 4.0 */ else if (!strcmp(inString, "CELL_NOTIFY_OFF")) /* TCS 4.0 */ { /* TCS 4.0 */ gmm_data->config.cell_notification = NO_CELL_NOTIFY; /* TCS 4.0 */ } /* TCS 4.0 */ #endif #ifdef _SIMULATION_ else if(!strcmp(inString, "NEXT_TIMEOUT")) { T_TIME old_value = 0; T_TIME new_value = 0; USHORT timer; USHORT timeout = TIMER_MAX; /* Find next timer to timeout */ for(timer = 0; timer < TIMER_MAX; timer++) { if ( VSI_OK == vsi_t_status ( GMM_handle ,timer, &new_value )) { if (new_value >0 ) { if((old_value==0)|| (new_value < old_value)) { old_value = new_value; timeout = timer; } } } } /* Force timeout */ if(TIMER_MAX != timeout ) { TRACE_1_INFO("gmm_pei_config - forcing timeout:%d", timeout); vsi_t_stop ( GMM_handle, timeout); for(timer = 0; timer < TIMER_MAX ; timer++) { if ( VSI_OK == vsi_t_status ( GMM_handle ,timer, &new_value )) { if (timer!=timeout ) { if (new_value>0 && new_value-old_value >0 ) { vsi_t_start ( GMM_handle , timer, new_value-old_value ); } } } } pei_timeout(timeout); } } #endif #define GMM_CONFIG_DRX 1 #define GMM_CONFIG_GEA 2 #ifndef _TARGET_ #define GMM_CONFIG_CHECK_STATE 3 #endif #define GMM_DRX "DRX" #define GMM_GEA "GEA" #ifndef _TARGET_ #define GMM_CHECK_STATE "CHECK_STATE" #define GMM_NULL_NO_IMSI "NULL_NO_IMSI" #define GMM_NULL_IMSI "NULL_IMSI" #define GMM_DEREG_INITIATED "DEREG_INITIATED" #define GMM_DEREG_ATTEMPTING_TO_ATTACH "DEREG_ATTEMPTING_TO_ATTACH" #define GMM_DEREG_NO_CELL_AVAILABLE "DEREG_NO_CELL_AVAILABLE" #define GMM_DEREG_LIMITED_SERVICE "DEREG_LIMITED_SERVICE" #define GMM_DEREG_NO_IMSI "DEREG_NO_IMSI" #define GMM_DEREG_PLMN_SEARCH "DEREG_PLMN_SEARCH" #define GMM_DEREG_SUSPENDED "DEREG_SUSPENDED" #define GMM_REG_INITIATED "REG_INITIATED" #define GMM_REG_NO_CELL_AVAILABLE "REG_NO_CELL_AVAILABLE" #define GMM_REG_LIMITED_SERVICE "REG_LIMITED_SERVICE" #define GMM_REG_ATTEMPTING_TO_UPDATE_MM "REG_ATTEMPTING_TO_UPDATE_MM " #define GMM_REG_ATTEMPTING_TO_UPDATE "REG_ATTEMPTING_TO_UPDATE" #define GMM_REG_RESUMING "REG_RESUMING" #define GMM_REG_SUSPENDED "REG_SUSPENDED" #define GMM_REG_NORMAL_SERVICE "REG_NORMAL_SERVICE" #define GMM_RAU_INITIATED "RAU_INITIATED" #define GMM_RAU_WAIT_FOR_NPDU_LIST "RAU_WAIT_FOR_NPDU_LIST" #define GMM_REG_IMSI_DETACH_INITIATED "REG_IMSI_DETACH_INITIATED" #define GMM_DEREG_SUSPENDING "DEREG_SUSPENDING" #define GMM_DEREG_RESUMING "DEREG_RESUMING" #define GMM_REG_SUSPENDING "REG_SUSPENDING" #define GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ "NULL_NO_IMSI_LIMITED_SERVICE_REQ" #define GMM_NULL_IMSI_LIMITED_SERVICE_REQ "NULL_IMSI_LIMITED_SERVICE_REQ" #define GMM_REG_TEST_MODE "REG_TEST_MODE" #define GMM_NULL_PLMN_SEARCH "NULL_PLMN_SEARCH" #define GMM_REG_TEST_MODE_NO_IMSI "REG_TEST_MODE_NO_IMSI " #endif { LOCAL KW_DATA kwtab[] = { GMM_DRX, GMM_CONFIG_DRX, GMM_GEA, GMM_CONFIG_GEA, #ifndef _TARGET_ GMM_CHECK_STATE, GMM_CONFIG_CHECK_STATE, #endif "", 0 }; #ifndef _TARGET_ LOCAL KW_STATE_DATA kw_state_tab[] = { GMM_NULL_NO_IMSI ,KERN_GMM_NULL_NO_IMSI, GMM_NULL_IMSI ,KERN_GMM_NULL_IMSI, GMM_DEREG_INITIATED ,KERN_GMM_DEREG_INITIATED, GMM_DEREG_ATTEMPTING_TO_ATTACH ,KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH, GMM_DEREG_NO_CELL_AVAILABLE ,KERN_GMM_DEREG_NO_CELL_AVAILABLE, GMM_DEREG_LIMITED_SERVICE ,KERN_GMM_DEREG_LIMITED_SERVICE, GMM_DEREG_NO_IMSI ,KERN_GMM_DEREG_NO_IMSI, GMM_DEREG_PLMN_SEARCH ,KERN_GMM_DEREG_PLMN_SEARCH, GMM_DEREG_SUSPENDED ,KERN_GMM_DEREG_SUSPENDED, GMM_REG_INITIATED ,KERN_GMM_REG_INITIATED, GMM_REG_NO_CELL_AVAILABLE ,KERN_GMM_REG_NO_CELL_AVAILABLE, GMM_REG_LIMITED_SERVICE ,KERN_GMM_REG_LIMITED_SERVICE, GMM_REG_ATTEMPTING_TO_UPDATE_MM ,KERN_GMM_REG_ATTEMPTING_TO_UPDATE_MM , GMM_REG_ATTEMPTING_TO_UPDATE ,KERN_GMM_REG_ATTEMPTING_TO_UPDATE, GMM_REG_RESUMING ,KERN_GMM_REG_RESUMING, GMM_REG_SUSPENDED ,KERN_GMM_REG_SUSPENDED, GMM_REG_NORMAL_SERVICE ,KERN_GMM_REG_NORMAL_SERVICE, GMM_RAU_INITIATED ,KERN_GMM_RAU_INITIATED, GMM_RAU_WAIT_FOR_NPDU_LIST ,KERN_GMM_RAU_WAIT_FOR_NPDU_LIST, GMM_REG_IMSI_DETACH_INITIATED ,KERN_GMM_REG_IMSI_DETACH_INITIATED, GMM_DEREG_SUSPENDING ,KERN_GMM_DEREG_SUSPENDING, GMM_DEREG_RESUMING ,KERN_GMM_DEREG_RESUMING, GMM_REG_SUSPENDING ,KERN_GMM_REG_SUSPENDING, GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ ,KERN_GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ, GMM_NULL_IMSI_LIMITED_SERVICE_REQ ,KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ, GMM_REG_TEST_MODE ,KERN_GMM_REG_TEST_MODE, GMM_NULL_PLMN_SEARCH ,KERN_GMM_NULL_PLMN_SEARCH, GMM_REG_TEST_MODE_NO_IMSI ,KERN_GMM_REG_TEST_MODE_NO_IMSI , "", 0 }; #endif SHORT valno; char *keyw; char *val[10]; tok_init (inString); while((valno = tok_next(&keyw,val)) NEQ TOK_EOCS) { switch ((tok_key((KW_DATA *)kwtab, keyw))) { case GMM_CONFIG_DRX: if (3==valno) { TRACE_EVENT ("use of DRX <split_pg_cycle_code,split_on_ccch,non_drx_timer>"); gmm_data->drx_parameter.split_pg_cycle_code = atoi (val[0]); gmm_data->drx_parameter.split_on_ccch = atoi (val[1]); gmm_data->drx_parameter.non_drx_timer = atoi (val[2]); } else { TRACE_ERROR("[PEI_CONFIG]: use CONFIG DRX <1,2,3>"); } break; case GMM_CONFIG_GEA: if (1==valno) { TRACE_EVENT ("GEA=<bit_field of wanted GEA in dec>"); gmm_data->config.cipher_on |= atoi (val[0]); TRACE_1_INFO("GEA2=%d", (gmm_data->config.cipher_on & 0x02)>0); TRACE_1_INFO("GEA3=%d", (gmm_data->config.cipher_on & 0x04)>0); TRACE_1_INFO("GEA4=%d", (gmm_data->config.cipher_on & 0x08)>0); TRACE_1_INFO("GEA5=%d", (gmm_data->config.cipher_on & 0x10)>0); TRACE_1_INFO("GEA6=%d", (gmm_data->config.cipher_on & 0x20)>0); TRACE_1_INFO("GEA7=%d", (gmm_data->config.cipher_on & 0x40)>0); } else { TRACE_ERROR("[PEI_CONFIG]: use CONFIG GEA=<0-255>//255 means all GEA wanted"); } break; #ifndef _TARGET_ case GMM_CONFIG_CHECK_STATE: if(1==valno) { if (gmm_tok_key ((KW_STATE_DATA *)kw_state_tab, val[0])!=GET_STATE(KERN)) { PALLOC ( cgrlc_status_ind, CGRLC_STATUS_IND ); /* TCS 2.1 */ PSEND ( hCommGMM, cgrlc_status_ind ); /* TCS 2.1 */ TRACE_1_OUT_PARA( "neq %s", val[0]); TRACE_ERROR("state wrong"); } else { TRACE_1_INFO("state %s ok",val[0]); } } else { TRACE_ERROR("[PEI_CONFIG]: USE CONFIG CHECK_STATE <state>"); } break; #endif default: break; } } } #endif return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_monitor +------------------------------------------------------------------------------ | Description : This function is called by the frame in case sudden entity | specific data is requested (e.g. entity Version). | | Parameters : out_monitor - return the address of the data to be | monitoredCommunication handle | | Return : PEI_OK - sucessful (address in out_monitor is valid) | PEI_ERROR - not successful | +------------------------------------------------------------------------------ */ LOCAL SHORT pei_monitor (void ** out_monitor) { TRACE_FUNCTION ("pei_monitor"); /* * Version = "0.S" (S = Step). */ gmm_mon.version = "GMM 0.1"; *out_monitor = &gmm_mon; return PEI_OK; } /* +------------------------------------------------------------------------------ | Function : pei_create +------------------------------------------------------------------------------ | Description : This function is called by the frame when the process is | created. | | Parameters : out_name - Pointer to the buffer in which to locate | the name of this entity | | Return : PEI_OK - entity created successfuly | PEI_ERROR - entity could not be created | +------------------------------------------------------------------------------ */ GLOBAL SHORT pei_create (T_PEI_INFO **info) { static T_PEI_INFO pei_info = { "GMM", /* name */ { /* pei-table */ pei_init, pei_exit, pei_primitive, pei_timeout, pei_signal, pei_run, pei_config, pei_monitor }, 2048, /* stack size */ 25, /* queue entries */ 190, /* priority (1->low, 255->high) */ TIMER_MAX, /* number of timers */ 0x03|PRIM_NO_SUSPEND /* flags: bit 0 active(0) body/passive(1) */ }; /* bit 1 com by copy(0)/reference(1) */ TRACE_FUNCTION ("pei_create"); /* * Close Resources if open */ if (first_access) first_access = FALSE; else pei_exit(); /* * Export startup configuration data */ *info = &pei_info; return (PEI_OK); } /* +------------------------------------------------------------------------------ | Function : gmm_pei_handle_queue +------------------------------------------------------------------------------ | Description : This function searches for the first stored primitive, which | must not be saved further in current state. | | Parameters : state - current state of the instance | queue - PtrPtr to the hanger of the instance save queue | table - Ptr to the state/signals-to-save table | inst_data - Ptr to instance data +------------------------------------------------------------------------------ */ LOCAL void gmm_pei_handle_queue( T_SAVE_QUEUE** queue, const T_SAVE_TAB* table) { /* search for a T_SAVE_TAB entry which fits to current state */ if( *queue ) while( table->state != PEI_END_SAVETAB && table->state != gmm_data->kern.state ) table++; while( *queue ) { T_SAVE_QUEUE* current = *queue; ULONG opc = ((T_PRIM_HEADER*)current->prim)->opc; USHORT n = 0; if( table->state != PEI_END_SAVETAB ) { /* search for this signals in savelist of this state */ while( n < GMM_MAX_SIGNALS_SAVED && table->signal[n] && table->signal[n] != opc ) n++; } if( table->signal[n] != opc ) { TRACE_1_INFO ("Pimitive 0x%x send from SAVE queue", ((T_PRIM_HEADER*)current->prim)->opc ); /* this signal must not further be stored -> handle it now */ /* first remove it from save queue, because of recursion!! */ *queue = current->next; gmm_pei_handle_prim(current->func, current->prim ); /* and free memory after last use */ MFREE( current ); /* recursion! handle at maximum one prim at once -> job done */ return; } /* goto next queued signal */ queue = &((*queue)->next); } } /* +------------------------------------------------------------------------------ | Function : gmm_pei_delete_queue +------------------------------------------------------------------------------ | Description : This function removes all stored primitives from the queue and | frees the memory. | | Parameters : queue - PtrPtr to the hanger of the instance save queue +------------------------------------------------------------------------------ */ GLOBAL void gmm_pei_delete_queue( T_SAVE_QUEUE** queue ) { while( *queue ) { T_SAVE_QUEUE* current = *queue; TRACE_1_INFO( "Pimitive 0x%x deleted from SAVE queue", ((T_PRIM_HEADER*)current->prim)->opc ); *queue = current->next; PFREE( P2D(current->prim) ); MFREE( current ); } } /* +------------------------------------------------------------------------------ | Function : gmm_pei_handle_prim +------------------------------------------------------------------------------ | Description : This function calls the handle function of the signal | | Parameters : func - Function, which should handle the signal | inst_data - Ptr to instance data | *prim - Ptr to primitive +------------------------------------------------------------------------------ */ LOCAL void gmm_pei_handle_prim( T_VOID_FUNC func, void* prim ) { JUMP(func)( P2D(prim)); gmm_pei_handle_queue( &save_queue, save_tab); } /* +------------------------------------------------------------------------------ | Function : gmm_pei_handle_save +------------------------------------------------------------------------------ | Description : This function saves the prim pointer to the save queue, if | this is necessary in current state. | | Parameters : *prim - Ptr to primitive | state - Current state of the instance | queue - PtrPtr to the hanger of the instance save queue | table - Ptr to the state/signals-to-save table | func - Function, which should handle the signal | | Returns : PEI_SIGNAL_SAVED - if signal is stored to save queue | PEI_SIGNAL_NOT_SAVED - else +------------------------------------------------------------------------------ */ LOCAL BOOL gmm_pei_handle_save( void* prim, T_SAVE_QUEUE** queue, const T_SAVE_TAB* table, T_VOID_FUNC func ) { ULONG opc = ((T_PRIM_HEADER*)prim)->opc; while( table->state != PEI_END_SAVETAB ) { if( table->state == gmm_data->kern.state ) { UBYTE n = 0; /* check for signals to save */ while( n < GMM_MAX_SIGNALS_SAVED && table->signal[n] ) { if( table->signal[n] == opc ) { /* store signal to end of save queue */ while( *queue ) queue = &((*queue)->next); MALLOC( *queue, sizeof(T_SAVE_QUEUE) ); if( *queue ) { (*queue)->prim = prim; (*queue)->func = func; (*queue)->next = NULL; } else { TRACE_ERROR( "Out of memory in mm_pei_handle_save()" ); return PEI_SIGNAL_NOT_SAVED; } return PEI_SIGNAL_SAVED; } /* goto next signal */ n++; } break; } /* gote next entry */ table++; } return PEI_SIGNAL_NOT_SAVED; } /*==== END OF FILE ==========================================================*/