FreeCalypso > hg > fc-magnetite
view src/g23m-gprs/gmm/gmm_kernf.c @ 217:2f17574d7001
src/g23m-aci/aci/ati_cmd.c: CST extension mechanism reinstated
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 15 Oct 2016 06:27:58 +0000 |
parents | 219afcfc6250 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GPRS (8441) | Modul : gmm_kernf.c +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This modul is part of the entity GMM and implements all | procedures and functions as described in the | SDL-documentation (KERN-statemachine) +----------------------------------------------------------------------------- */ #ifndef GMM_KERNF_C #define GMM_KERNF_C #endif #define ENTITY_GMM /*==== INCLUDES =============================================================*/ #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 "ccdapi.h" /* to get CCD API */ #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 "gmm.h" /* to get the global entity definitions */ #include "gmm_kernf.h" /* to get some local definitions */ #include "gmm_kernl.h" /* to get some local definitions */ #include "gmm_f.h" #include <string.h> /* to get memset */ #include "pcm.h" #include "gmm_rxf.h" #include "gmm_rxs.h" #include "gmm_txf.h" #include "gmm_rdyf.h" #include "gmm_syncs.h" #include "gmm_kernp.h" #include "gmm_rdys.h" #include "gmm_syncf.h" #include "gmm_em.h" /* To get Engineering Mode functions */ #ifdef _TARGET_ #include "ffs/ffs.h" #endif #include "cl_imei.h" /* IMEI common library */ #include <stdlib.h> #include <stdio.h> /* for sprintf */ /*==== CONST ================================================================*/ /*==== LOCAL VARS ===========================================================*/ /*==== PRIVATE FUNCTIONS ====================================================*/ /*==== PUBLIC FUNCTIONS =====================================================*/ /* +------------------------------------------------------------------------------ | Function : kern_gmmreg_info_ind +------------------------------------------------------------------------------ | Description : The function kern_gmmreg_info_ind forwards the info comming | from the net to the MMI entity | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmreg_info_ind ( void) { GMM_TRACE_FUNCTION( "kern_gmmreg_info_ind" ); { MCAST(gmm_information, GMM_INFORMATION); /* Agilent Issue OMAPS00148436 WA */ if (!gmm_information->v_full_network_name && !gmm_information->v_short_network_name && !gmm_information->v_time_zone && !gmm_information->v_time_zone_and_time) { TRACE_EVENT ("GMM_INFORMATION message doesn't contain valid information"); GMM_RETURN; } { PALLOC (gmmreg_info_ind, GMMREG_INFO_IND); /* T_GMMREG_INFO_IND */ /* * Set PLMN, this will be used if network name is given */ gmmreg_info_ind->plmn.v_plmn = TRUE; memcpy (gmmreg_info_ind->plmn.mcc, gmm_data->kern.attach_cap.rai_accepted.mcc, SIZE_MCC); memcpy (gmmreg_info_ind->plmn.mnc, gmm_data->kern.attach_cap.rai_accepted.mnc, SIZE_MNC); /* * Set full network name, if present */ if (gmm_information->v_full_network_name) { gmmreg_info_ind->full_net_name_gmm.v_name = TRUE; gmmreg_info_ind->full_net_name_gmm.dcs /* TCS 2.1 */ = gmm_information->full_network_name.code; gmmreg_info_ind->full_net_name_gmm.add_ci = gmm_information->full_network_name.add_ci; gmmreg_info_ind->full_net_name_gmm.num_spare = gmm_information->full_network_name.nr_sparebits; memset(gmmreg_info_ind->full_net_name_gmm.text, 0, MMR_MAX_TEXT_LEN); gmmreg_info_ind->full_net_name_gmm.c_text = MINIMUM (MMR_MAX_TEXT_LEN, gmm_information->full_network_name.c_text_string); memcpy (gmmreg_info_ind->full_net_name_gmm.text, gmm_information->full_network_name.text_string, gmmreg_info_ind->full_net_name_gmm.c_text); } else { gmmreg_info_ind->full_net_name_gmm.v_name = FALSE; } /* Set short network name, if present */ if (gmm_information->v_short_network_name) { gmmreg_info_ind->short_net_name_gmm.v_name = TRUE; gmmreg_info_ind->short_net_name_gmm.dcs = gmm_information->short_network_name.code; /* TCS 2.1 */ gmmreg_info_ind->short_net_name_gmm.add_ci = gmm_information->short_network_name.add_ci; gmmreg_info_ind->short_net_name_gmm.num_spare = gmm_information->short_network_name.nr_sparebits; memset(gmmreg_info_ind->short_net_name_gmm.text, 0, MMR_MAX_TEXT_LEN); gmmreg_info_ind->short_net_name_gmm.c_text = MINIMUM (MMR_MAX_TEXT_LEN, gmm_information->short_network_name.c_text_string); memcpy (gmmreg_info_ind->short_net_name_gmm.text, gmm_information->short_network_name.text_string, gmmreg_info_ind->short_net_name_gmm.c_text); } else { gmmreg_info_ind->short_net_name_gmm.v_name = FALSE; } /* Set network time zone, if present */ if (gmm_information->v_time_zone) { gmmreg_info_ind->net_time_zone.v_time_zone = TRUE; gmmreg_info_ind->net_time_zone.time_zone = gmm_information->time_zone.time_zone_value; } else { gmmreg_info_ind->net_time_zone.v_time_zone = FALSE; } /* Set network time zone and time, if present */ if (gmm_information->v_time_zone_and_time) { gmmreg_info_ind->net_time_zone.v_time_zone = TRUE; gmmreg_info_ind->net_time_zone.time_zone = gmm_information->time_zone_and_time.time_zone_value; gmmreg_info_ind->net_time.v_time = TRUE; gmmreg_info_ind->net_time.year = 10 * gmm_information->time_zone_and_time.year[0] + gmm_information->time_zone_and_time.year[1]; gmmreg_info_ind->net_time.month = 10 * gmm_information->time_zone_and_time.month[0] + gmm_information->time_zone_and_time.month[1]; gmmreg_info_ind->net_time.day = 10 * gmm_information->time_zone_and_time.day[0] + gmm_information->time_zone_and_time.day[1]; gmmreg_info_ind->net_time.hour = 10 * gmm_information->time_zone_and_time.hour[0] + gmm_information->time_zone_and_time.hour[1]; gmmreg_info_ind->net_time.minute = 10 * gmm_information->time_zone_and_time.minute[0] + gmm_information->time_zone_and_time.minute[1]; gmmreg_info_ind->net_time.second = 10 * gmm_information->time_zone_and_time.second[0] + gmm_information->time_zone_and_time.second[1]; } else { gmmreg_info_ind->net_time.v_time = FALSE; } #ifdef REL99 if (gmm_information->v_daylight_save_time) /* TCS 4.0 */ { /* TCS 4.0 */ gmmreg_info_ind->net_daylight_save_time = /* TCS 4.0 */ gmm_information->daylight_save_time.save_time_value; /* TCS 4.0 */ } /* TCS 4.0 */ else /* TCS 4.0 */ { /* TCS 4.0 */ gmmreg_info_ind->net_daylight_save_time = GMMREG_ADJ_NO; /* TCS 4.0 */ } /* TCS 4.0 */ #endif PSEND ( hCommMMI, gmmreg_info_ind); } } GMM_RETURN; } /* kern_gmmreg_info_ind() */ /* +------------------------------------------------------------------------------ | Function : kern_calculate_digits +------------------------------------------------------------------------------ | Description : Derives tm mobile identiti for the AIR | | COPIED FROM : MM mm_mmf.c : mm_calculate_digits | | Parameters : mobile_identity - used in the AIR message | +------------------------------------------------------------------------------ */ LOCAL UBYTE kern_calculate_digits (UBYTE *digits) { UBYTE i = 0; GMM_TRACE_FUNCTION ("kern_calculate_digits()"); while (digits[i] < 0x0A AND i < 16) i++; GMM_RETURN_ (i); } /* +------------------------------------------------------------------------------ | Function : kern_mmgmmreg_attach_cnf +------------------------------------------------------------------------------ | Description : This procedure sends the gmmreg_attach_cnf primitiv to ACI | | Parameters : attach_type - attach type | mmgmm_reg_req - the primitiv | +------------------------------------------------------------------------------ */ GLOBAL void kern_mmgmmreg_attach_cnf ( UBYTE attach_type, UBYTE search_running, T_MMGMM_REG_CNF * mmgmm_reg_cnf ) { GMM_TRACE_FUNCTION( "kern_mmgmmreg_attach_cnf" ); TRACE_1_INFO ("Info: MM lac: %x", mmgmm_reg_cnf->lac); switch (gmm_data->kern.sig_cell_info.gmm_status) { case GMMRR_SERVICE_LIMITED: case GMMRR_SERVICE_NONE: search_running=SEARCH_NOT_RUNNING; break; default: case GMMRR_SERVICE_FULL: break; } gmm_data->kern.mm_cell_env.cid = mmgmm_reg_cnf->cid; gmm_data->kern.mm_cell_env.rai.lac = mmgmm_reg_cnf->lac; gmm_data->kern.mm_cell_env.rai.plmn = mmgmm_reg_cnf->plmn; GMM_TRACE_GMM_DATA(GMM_DEBUG_PRINT_MASK_CID); { PALLOC ( gmmreg_attach_cnf, GMMREG_ATTACH_CNF ); gmmreg_attach_cnf->attach_type = attach_type; /* * gmmreg_attach_cnf->plmn = gmm_data->mm_plmn= mmgmm_reg_cnf->plmn; */ gmmreg_attach_cnf->plmn = mmgmm_reg_cnf->plmn; gmmreg_attach_cnf->search_running = search_running; gmmreg_attach_cnf->lac = mmgmm_reg_cnf->lac; gmmreg_attach_cnf->rac = gmm_data->kern.sig_cell_info.env.rai.rac; //gmmreg_attach_cnf->cid = gmm_data->kern.sig_cell_info.env.cid; // #HM# gmmreg_attach_cnf->cid = mmgmm_reg_cnf->cid; // #HM# gmmreg_attach_cnf->gprs_indicator = gmm_data->kern.sig_cell_info.gmm_status; gmmreg_attach_cnf->bootup_cause = REG_END; #ifdef GMM_TCS4 gmmreg_attach_cnf->rt = gmm_data->kern.sig_cell_info.rt; // TCS 4.0 #endif #ifdef TRACE_EVE { switch (attach_type) { case GMMREG_AT_COMB: TRACE_EVENT ("MS is combined attached."); break; case GMMREG_AT_IMSI: TRACE_EVENT ("MS is GSM-only attached."); break; case GMMREG_AT_GPRS: TRACE_EVENT ("MS is GPRS-only attached."); break; default: TRACE_ERROR ("MS is attached with wrong attach type."); break; } TRACE_7_PARA("%x%x%x, %x%x%x, lac %x", gmmreg_attach_cnf->plmn.mcc[0], gmmreg_attach_cnf->plmn.mcc[1], gmmreg_attach_cnf->plmn.mcc[2], gmmreg_attach_cnf->plmn.mnc[0], gmmreg_attach_cnf->plmn.mnc[1], gmmreg_attach_cnf->plmn.mnc[2], gmmreg_attach_cnf->lac); } #endif PSEND ( hCommMMI, gmmreg_attach_cnf ); gmm_data->kern.attach_cap.gmmreg = FALSE; } GMM_RETURN; } /* kern_mmgmmreg_attach_cnf () */ /* +------------------------------------------------------------------------------ | Function : kern_gmmreg_attach_cnf +------------------------------------------------------------------------------ | Description : This procedure sends the gmmreg_attach_cnf primitiv to ACI | | Parameters : attach_type - attach type | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmreg_attach_cnf ( UBYTE attach_type) { GMM_TRACE_FUNCTION( "kern_gmmreg_attach_cnf" ); kern_gmmreg_attach_cnf_sr(attach_type,SEARCH_NOT_RUNNING); GMM_RETURN; } /* kern_gmmreg_attach_cnf () */ /* +------------------------------------------------------------------------------ | Function : kern_gmmreg_attach_cnf_sr +------------------------------------------------------------------------------ | Description : This procedure sends the gmmreg_attach_cnf primitiv to ACI | | Parameters : attach_type - attach type | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmreg_attach_cnf_sr ( UBYTE attach_type, UBYTE search_running) { GMM_TRACE_FUNCTION( "kern_gmmreg_attach_cnf_sr" ); TRACE_2_OUT_PARA("%s, %s", search_running==SEARCH_RUNNING? "searching":"finished", attach_type==GMMREG_AT_COMB? "comb": attach_type==GMMREG_AT_GPRS?"gprs": attach_type==GMMREG_AT_IMSI?"gsm": "unknown tpe" ); { PALLOC ( gmmreg_attach_cnf, GMMREG_ATTACH_CNF ); gmmreg_attach_cnf->attach_type = attach_type; gmmreg_attach_cnf->plmn.v_plmn = TRUE; gmmreg_attach_cnf->search_running= search_running; memcpy ( gmmreg_attach_cnf->plmn.mcc, gmm_data->kern.sig_cell_info.env.rai.plmn.mcc, SIZE_MCC); memcpy ( gmmreg_attach_cnf->plmn.mnc, gmm_data->kern.sig_cell_info.env.rai.plmn.mnc, SIZE_MNC); gmmreg_attach_cnf->lac = gmm_data->kern.sig_cell_info.env.rai.lac; gmmreg_attach_cnf->rac = gmm_data->kern.sig_cell_info.env.rai.rac; gmmreg_attach_cnf->cid = gmm_data->kern.sig_cell_info.env.cid; gmmreg_attach_cnf->gprs_indicator = gmm_data->kern.sig_cell_info.gmm_status; gmmreg_attach_cnf->bootup_cause = REG_END; #ifdef GMM_TCS4 gmmreg_attach_cnf->rt = gmm_data->kern.sig_cell_info.rt; /* TCS 4.0 */ #endif PSEND ( hCommMMI, gmmreg_attach_cnf ); gmm_data->kern.attach_cap.gmmreg = FALSE; /* * ACI does not realize GSM detach if search running has been set * in kern_mmgmm_nreg_cnf */ if (GMMRR_NET_MODE_III==gmm_data->kern.sig_cell_info.net_mode && GMMREG_CLASS_BG== gmm_data->kern.attach_cap.mobile_class && GMMREG_AT_GPRS==attach_type) { kern_gmmreg_detach (GMMREG_DT_IMSI, GMMCS_LIMITED_SERVICE, /* TCS 2.1 */ SEARCH_NOT_RUNNING, GMMCS_LIMITED_SERVICE); } } GMM_RETURN; } /* kern_gmmreg_attach_cnf_sr () */ /* +------------------------------------------------------------------------------ | Function : kern_gmmreg_detach +------------------------------------------------------------------------------ | Description : This procedure sends the gmmreg_detach primitiv to ACI | | Parameters : detach_type - detach type | cause - error cause | search_running - cell search still running or not | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmreg_detach ( UBYTE detach_type, USHORT service, UBYTE search_running, USHORT cause) { UBYTE mm_state; GMM_TRACE_FUNCTION( "kern_gmmreg_detach" ); mm_state = GET_STATE(MM); if (GMMREG_DT_GPRS==detach_type && ( GMM_MM_DEREG==mm_state || GMM_MM_REG_NO_CELL_AVAILABLE==mm_state || GMM_MM_REG_INITATED_VIA_GPRS==mm_state || MMGMM_LIMITED_SERVICE==gmm_data->kern.sig_cell_info.mm_status ) ) { detach_type = GMMREG_DT_COMB; } TRACE_3_OUT_PARA("%s, cause: 0x%x, %s", detach_type==GMMREG_DT_COMB? "comb": detach_type==GMMREG_DT_IMSI? "gsm": detach_type==GMMREG_DT_GPRS?"gprs": detach_type==GMMREG_DT_POWER_OFF?"power off": detach_type==GMMREG_DT_SIM_REMOVED?"sim removed": detach_type==GMMREG_DT_LIMITED_SERVICE?"limited": detach_type==GMMREG_DT_SOFT_OFF?"soft off": "unknown type" , cause, (search_running==GMMREG_SEARCH_RUNNING?"searching":"finished")); if ( gmm_data->kern.detach_cap.gmmreg ) { PALLOC ( gmmreg_detach_cnf, GMMREG_DETACH_CNF ); gmmreg_detach_cnf->detach_type = gmm_data->kern.detach_cap.detach_type; PSEND ( hCommMMI, gmmreg_detach_cnf ); } else { if ( gmm_data->kern.attach_cap.gmmreg ) { if (GMMREG_CLASS_CG==gmm_data->kern.attach_cap.mobile_class && GMMREG_DT_IMSI==detach_type) { kern_gmmreg_attach_cnf_sr(GMMREG_AT_GPRS, search_running); } else { PALLOC ( gmmreg_attach_rej, GMMREG_ATTACH_REJ ); gmmreg_attach_rej->detach_type = detach_type; gmmreg_attach_rej->cause = cause; gmmreg_attach_rej->search_running = search_running; gmmreg_attach_rej->service = service; PSEND ( hCommMMI, gmmreg_attach_rej ); } if (GMMREG_SEARCH_NOT_RUNNING==search_running) { gmm_data->kern.attach_cap.gmmreg=FALSE; } } else /* if ! gmmreg */ { /* * If gmmsm == TRUE means, we are in GMM_REGISTERED_INITIATED state. * That means, if ACI did not send an attach request ACI need not * to be informed, otherwise we are attached in ACI has to be informed */ #ifndef GMM_TCS4 if ( !gmm_data->kern.attach_cap.gmmsm ) #endif { PALLOC ( gmmreg_detach_ind, GMMREG_DETACH_IND ); gmmreg_detach_ind->detach_type = detach_type; gmmreg_detach_ind->cause = cause; gmmreg_detach_ind->search_running = search_running; gmmreg_detach_ind->service = service; PSEND ( hCommMMI, gmmreg_detach_ind ); } } } gmm_data->kern.detach_cap.gmmreg=FALSE; /* * Clear data before Power Off */ if (GMMREG_DT_POWER_OFF==detach_type) { /* * every servce i reinitilized that the test sysem may run * with out real power off */ kern_init(); rxgmm_init(); txgmm_init(); rdy_init(); sync_gmm_init(); /* * In kern_init the deep is set to 0 for MACRO GMM_RETURN */ return; } GMM_RETURN; } /* kern_gmmreg_detach () */ /* +------------------------------------------------------------------------------ | Function : kern_llgmm_assign_tlli +------------------------------------------------------------------------------ | Description : This procedure assigned the given TLLI parameter to LLC | | Parameters : new_tlli_type - type of new TLLI (random, local ,..) | old_tlli_type - type of old TLLI | +------------------------------------------------------------------------------ */ GLOBAL void kern_llgmm_assign_tlli ( T_TLLI_TYPE new_tlli_type, T_TLLI_TYPE old_tlli_type ) { GMM_TRACE_FUNCTION( "kern_llgmm_assign_tlli" ); if( GMM_LLC_STATE_UNASSIGNED EQ gmm_data->kern.attach_cap.llc_state ) { gmm_data->kern.attach_cap.llc_state = GMM_LLC_STATE_ASSIGNED; } { PALLOC ( llgmm_assign_req, LLGMM_ASSIGN_REQ ); llgmm_assign_req->old_tlli = gmm_get_tlli ( old_tlli_type ); if ( GMMRR_TMSI_INVALID == gmm_data->ptmsi.current ) { /* * <R.GMM.TLLIUSE.M.005> */ llgmm_assign_req->new_tlli = gmm_get_tlli ( RANDOM_TLLI ); } else { llgmm_assign_req->new_tlli = gmm_get_tlli ( new_tlli_type ); } if (NO_KEY== gmm_data->kern.auth_cap.cksn) { memset (llgmm_assign_req->llgmm_kc.key, 0x0, MAX_KC); } else { memcpy ( llgmm_assign_req->llgmm_kc.key, gmm_data->kern.auth_cap.kc, MAX_KC ); } llgmm_assign_req->ciphering_algorithm = LLGMM_CIPHER_NA; TRACE_2_OUT_PARA("TLLI old: 0x%X, new: 0x%X", llgmm_assign_req->old_tlli,llgmm_assign_req->new_tlli); PSEND ( hCommLLC, llgmm_assign_req ); } GMM_RETURN; } /* kern_llgmm_assign_tlli() */ /* +------------------------------------------------------------------------------ | Function : kern_llgmm_assign +------------------------------------------------------------------------------ | Description : This procedure assigned the current TLLI parameter to LLC | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_llgmm_assign ( void ) { GMM_TRACE_FUNCTION( "kern_llgmm_assign" ); kern_llgmm_assign_tlli ( CURRENT_TLLI, OLD_TLLI ); GMM_RETURN; } /* kern_llgmm_assign() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmsm_establish_rej +------------------------------------------------------------------------------ | Description : This procedure informs SM that gprs is off. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmsm_establich_rej ( void ) { GMM_TRACE_FUNCTION( "kern_gmmsm_stablich_rej" ); #ifdef GMM_TCS4 { PALLOC (mmpm_detach_ind, MMPM_DETACH_IND); mmpm_detach_ind->ps_cause = kern_make_new_cause(); /*For reattach, overwrite the cause from kern_make_new_cause()*/ if (GMM_DT_RE_ATTACH == gmm_data->kern.detach_cap.detach_type) { mmpm_detach_ind->ps_cause.ctrl_value = CAUSE_is_from_mm; mmpm_detach_ind->ps_cause.value.mm_cause = (U16)CAUSE_MM_DETACH_WITH_REATTACH; } PSEND ( hCommSM, mmpm_detach_ind); } #else /*New TI DK primitive should be sent*/ if ( gmm_data->kern.attach_cap.gmmsm ) { PALLOC ( gmmsm_establish_rej, GMMSM_ESTABLISH_REJ ); gmmsm_establish_rej->sm_cause = gmm_data->kern.detach_cap.error_cause; PSEND ( hCommSM, gmmsm_establish_rej ); } else // if !gmmsm { // <R.GMM.PRELIND.M.001> PALLOC ( gmmsm_release_ind, GMMSM_RELEASE_IND); PSEND ( hCommSM, gmmsm_release_ind ); } #endif GMM_RETURN; } /* kern_gmmsm_establish_rej() */ /* +------------------------------------------------------------------------------ | Function : kern_llgmm_unassign +------------------------------------------------------------------------------ | Description : This procedure unassigned all TLLIs in LLC | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_llgmm_unassign ( void ) { GMM_TRACE_FUNCTION( "kern_llgmm_unassign" ); switch (gmm_data->kern.attach_cap.llc_state) { case GMM_LLC_STATE_UNASSIGNED: GMM_RETURN; default: case GMM_LLC_STATE_ASSIGNED: case GMM_LLC_STATE_SUSPENED: case GMM_LLC_STATE_SUSPENED_RAU: gmm_data->kern.attach_cap.llc_state = GMM_LLC_STATE_UNASSIGNED; break; } /* * PTMSI is still valid for next attach * gmm_data->ptmsi.current = GMMRR_TMSI_INVALID; */ gmm_data->ptmsi.new_grr = GMMRR_TMSI_INVALID; gmm_data->tlli.old=gmm_data->tlli.current; gmm_data->tlli.current_type = INVALID_TLLI; gmm_data->tlli.current=GMMRR_TMSI_INVALID; TRACE_0_OUT_PARA("Unassign"); { PALLOC ( gmmrr_assign_req, GMMRR_ASSIGN_REQ ); gmmrr_assign_req->old_tlli = GMMRR_TLLI_INVALID; gmmrr_assign_req->new_tlli = GMMRR_TLLI_INVALID; gmmrr_assign_req->old_ptmsi = GMMRR_TMSI_INVALID; gmmrr_assign_req->new_ptmsi = GMMRR_TMSI_INVALID; gmmrr_assign_req->imsi = gmm_data->imsi; gmmrr_assign_req->rai.plmn.v_plmn=TRUE; memcpy (gmmrr_assign_req->rai.plmn.mcc, gmm_data->kern.attach_cap.rai_accepted.mcc, SIZE_MCC); memcpy (gmmrr_assign_req->rai.plmn.mnc, gmm_data->kern.attach_cap.rai_accepted.mnc, SIZE_MNC); gmmrr_assign_req->rai.lac = gmm_data->kern.attach_cap.rai_accepted.lac; gmmrr_assign_req->rai.rac = gmm_data->kern.attach_cap.rai_accepted.rac; PSEND ( hCommGRR, gmmrr_assign_req ); } { PALLOC (llgmm_assign_req, LLGMM_ASSIGN_REQ); /* gmm_data->tlli.current_type=INVALID_TLLI; */ llgmm_assign_req->old_tlli = LLGMM_TLLI_INVALID; llgmm_assign_req->new_tlli = LLGMM_TLLI_INVALID; memset (llgmm_assign_req->llgmm_kc.key,0, sizeof (llgmm_assign_req->llgmm_kc.key)); llgmm_assign_req->ciphering_algorithm = LLGMM_CIPHER_NO_ALGORITHM; kern_reset_cipher (); PSEND ( hCommLLC, llgmm_assign_req ); } GMM_RETURN; } /* kern_llgmm_unassign() */ /* +------------------------------------------------------------------------------ | Function : kern_llgmm_suspend +------------------------------------------------------------------------------ | Description : This procedure suspends LLC | | Parameters : susp_cause - cause off suspension | +------------------------------------------------------------------------------ */ GLOBAL void kern_llgmm_suspend ( UBYTE susp_cause) { U8 cell_state=GMMREG_CS_CALL; #ifdef GMM_TCS4 U8 mm_cause = CAUSE_MM_DEDICATED_MODE; #endif GMM_TRACE_FUNCTION( "kern_llgmm_suspend" ); /* * if LLC is in suspended RAU it means that GRR has opned the GMM queue * so we have to remember. */ switch (gmm_data->kern.attach_cap.llc_state) { case GMM_LLC_STATE_SUSPENED_RAU: GMM_RETURN; case GMM_LLC_STATE_UNASSIGNED: TRACE_ERROR ("suspending of LLC in state unassigned ignored"); GMM_RETURN; default: case GMM_LLC_STATE_ASSIGNED: case GMM_LLC_STATE_SUSPENED: break; } switch (susp_cause) { case LLGMM_CALL: TRACE_0_OUT_PARA("call"); cell_state=GMMREG_CS_CALL; #ifdef GMM_TCS4 mm_cause = CAUSE_MM_DEDICATED_MODE; #endif break; case LLGMM_LIMITED: TRACE_0_OUT_PARA("limited"); cell_state=GMMREG_LIMITED_SERVICE; #ifdef GMM_TCS4 mm_cause = CAUSE_MM_LIMITED_SERVICE; #endif break; case LLGMM_NO_GPRS_SERVICE: TRACE_0_OUT_PARA("no_service"); cell_state=GMMREG_GPRS_NOT_SUPPORTED; #ifdef GMM_TCS4 mm_cause = CAUSE_MM_NO_SERVICE; #endif break; case LLGMM_RAU: cell_state=GMMREG_TRY_TO_UPDATE; #ifdef GMM_TCS4 mm_cause = CAUSE_MM_TRY_TO_UPDATE; #endif if(GET_STATE(CU) EQ CU_CELL_RES_SENT || GET_STATE(CU) EQ CU_REQUESTED_CELL_RES_SENT) { susp_cause= LLGMM_PERIODIC_RAU; /* NO break; */ } else { gmm_data->kern.attach_cap.llc_state=GMM_LLC_STATE_SUSPENED_RAU; TRACE_0_OUT_PARA("rau"); break; } /* GS, how would you solve it with V8?*/ case LLGMM_PERIODIC_RAU: if (GMM_LLC_STATE_SUSPENED==gmm_data->kern.attach_cap.llc_state) { GMM_RETURN; } else { TRACE_0_OUT_PARA("periodic rau"); cell_state=GMMREG_TRY_TO_UPDATE; #ifdef GMM_TCS4 mm_cause = CAUSE_MM_TRY_TO_UPDATE; #endif } break; default: TRACE_ERROR("llc_susp unexpected"); break; } if (GMM_LLC_STATE_SUSPENED_RAU!=gmm_data->kern.attach_cap.llc_state) { gmm_data->kern.attach_cap.llc_state= GMM_LLC_STATE_SUSPENED; } { PALLOC (llgmm_suspend_req, LLGMM_SUSPEND_REQ); llgmm_suspend_req->susp_cause = susp_cause; PSEND ( hCommLLC, llgmm_suspend_req ); } { PALLOC(gmmreg_suspend_ind, GMMREG_SUSPEND_IND); gmmreg_suspend_ind->cell_state= cell_state; PSEND(hCommMMI,gmmreg_suspend_ind); } #ifdef GMM_TCS4 { PALLOC(mmpm_suspend_ind, MMPM_SUSPEND_IND); mmpm_suspend_ind->ps_cause.ctrl_value = CAUSE_is_from_mm; mmpm_suspend_ind->ps_cause.value.mm_cause = mm_cause; PSEND(hCommSM,mmpm_suspend_ind); } #endif GMM_RETURN; } /* kern_llgmm_suspend() */ /* +------------------------------------------------------------------------------ | Function : kern_llgmm_resume +------------------------------------------------------------------------------ | Description : This procedure resumes LLC | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_llgmm_resume ( void ) { GMM_TRACE_FUNCTION( "kern_llgmm_resume" ); switch(gmm_data->kern.attach_cap.llc_state) { case GMM_LLC_STATE_SUSPENED_RAU: case GMM_LLC_STATE_SUSPENED: { PALLOC (llgmm_resume_req, LLGMM_RESUME_REQ); gmm_data->kern.attach_cap.llc_state=GMM_LLC_STATE_ASSIGNED; PSEND ( hCommLLC, llgmm_resume_req ); } { PALLOC (gmmreg_resume_ind, GMMREG_RESUME_IND); PSEND ( hCommMMI, gmmreg_resume_ind ); } #ifdef GMM_TCS4 { PALLOC(mmpm_resume_ind, MMPM_RESUME_IND); PSEND(hCommSM,mmpm_resume_ind); } #endif break; case GMM_LLC_STATE_ASSIGNED: default: break; case GMM_LLC_STATE_UNASSIGNED: TRACE_ERROR("resuming LLC in state unassigned"); kern_llgmm_assign(); break; } kern_gmmrr_stop_waiting_for_transmission(); GMM_RETURN; } /* kern_llgmm_suspend() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_enable +------------------------------------------------------------------------------ | Description : The function kern_enable() | disables GRR and activates MM to act as a class CC mobile. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_enable ( void ) { GMM_TRACE_FUNCTION ("kern_gmmrr_enable()"); gmm_data->kern.attach_cap.mobile_class_changed = FALSE; { PALLOC ( gmmrr_enable_req, GMMRR_ENABLE_REQ ); TRACE_EVENT ("GRR is on"); gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_ON; gmmrr_enable_req->mobile_class = gmm_data->kern.attach_cap.mobile_class; gmmrr_enable_req->acc_contr_class = gmm_data->acc_contr_class; if (DRX_NOT_USED==gmm_data->drx_parameter.split_pg_cycle_code) { gmmrr_enable_req->split_pg_cycle = 704/* GMMREG_NO_DRX*/; } else if (gmm_data->drx_parameter.split_pg_cycle_code<65) { gmmrr_enable_req->split_pg_cycle = gmm_data->drx_parameter.split_pg_cycle_code; } else if (gmm_data->drx_parameter.split_pg_cycle_code<=98) { const USHORT cycle_array[] = { 71, 72, 74, 75, 77, 79, 80, 83, 86, 88, 90, 92, 96, 101, 103, 107, 112,116, 118, 128, 141, 144, 150, 160, 171, 176, 192, 214, 224, 235, 256, 288, 320, 352 }; gmmrr_enable_req->split_pg_cycle = cycle_array[gmm_data->drx_parameter.split_pg_cycle_code-65]; } else { gmmrr_enable_req->split_pg_cycle = 1; } if( gmm_data->drx_parameter.split_on_ccch EQ SPLIT_NO ) { gmmrr_enable_req->spgc_ccch_supp = GMMRR_SPGC_CCCH_SUPP_NO; } else { gmmrr_enable_req->spgc_ccch_supp = GMMRR_SPGC_CCCH_SUPP_YES; } gmmrr_enable_req->gmmrr_non_drx_timer = gmm_data->drx_parameter.non_drx_timer; PSEND ( hCommGRR, gmmrr_enable_req ); } GMM_RETURN; } /* kern_gmmrr_ensable () */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_disable +------------------------------------------------------------------------------ | Description : The function kern_gmmrr_disable switches off GRR | | Parameters : cm_estasblish_res - OK or NOT to establish the CM | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_disable ( void ) { GMM_TRACE_FUNCTION ("kern_gmmrr_disable()"); TRACE_EVENT ("GRR is off"); /*gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_CC;*/ gmm_data->kern.attach_cap.attach_type &= ~GMMREG_AT_GPRS; gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_OFF; gmm_data->kern.suspension_type &= ~GMM_SUSP_LOCAL_DETACH; /* This code is applicable only for Release 99 */ #ifdef REL99 gmm_data->ptmsi_signature.available = FALSE; gmm_data->ptmsi_signature.value = INVALID_PTMSI_SIGNATURE; #endif kern_llgmm_unassign(); { PALLOC ( gmmrr_disable_req, GMMRR_DISABLE_REQ ); PSEND ( hCommGRR, gmmrr_disable_req ); } /* kern_mm_activate_mm (); */ GMM_RETURN; } /* kern_gmmrr_disable () */ /* +------------------------------------------------------------------------------ | Function : kern_mm_cm_establish_res +------------------------------------------------------------------------------ | Description : The function mm_cm_establish_res is a response whether a CS call | is possible or not | | Parameters : cm_estasblish_res - OK or NOT to establish the CM | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_cm_establish_res ( UBYTE cm_establish_res ) { GMM_TRACE_FUNCTION ("kern_mm_cm_establish_res ()"); { PALLOC ( mmgmm_cm_establish_res, MMGMM_CM_ESTABLISH_RES); mmgmm_cm_establish_res->cm_establish_res = cm_establish_res; gmm_data->kern.suspension_type &= ~GMM_SUSP_CALL; PSEND ( hCommMM, mmgmm_cm_establish_res ); } GMM_RETURN; } /* kern_mm_establish_res () */ /* +------------------------------------------------------------------------------ | Function : kern_mm_cm_emergency_res +------------------------------------------------------------------------------ | Description : The function mm_cm_emrgency_res is a response whether a | emergnecy call is possible or not | | Parameters : cm_estasblish_res - OK or NOT to establish the CM | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_cm_emergency_res ( UBYTE cm_establish_res ) { GMM_TRACE_FUNCTION ("kern_mm_cm_emergency_res ()"); { PALLOC ( mmgmm_cm_emergency_res, MMGMM_CM_EMERGENCY_RES); mmgmm_cm_emergency_res->cm_establish_res = cm_establish_res; PSEND ( hCommMM, mmgmm_cm_emergency_res ); gmm_data->kern.suspension_type &= ~GMM_SUSP_EM_CALL; } GMM_RETURN; } /* kern_mm_emergency_res () */ /* +------------------------------------------------------------------------------ | Function : kern_mm_net_req +------------------------------------------------------------------------------ | Description : The function kern_mm_net_req sends the promitve to MM | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_net_req ( void ) { GMM_TRACE_FUNCTION( "kern_mm_net_req" ); { PALLOC ( mmgmm_net_req, MMGMM_NET_REQ ); PSEND ( hCommMM, mmgmm_net_req); } GMM_RETURN; } /* kern_mm_net_req() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_start_t3212 +------------------------------------------------------------------------------ | Description : This procedure is called: "If the detach type information | element value indicates "GPRS detach without switching off ?and | the MS is attached for GPRS and non-GPRS services and the | network operates in network operation mode I, then if in the MS | the timer T3212 is not already running, the timer T3212 shall be | set to its initial value and restarted after the DETACH REQUEST | message has been sent." | | <R.GMM.DINITM.M.007> | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_start_t3212 ( void ) { GMM_TRACE_FUNCTION( "kern_mm_start_t3212" ); { PALLOC ( mmgmm_start_t3212_req, MMGMM_START_T3212_REQ ); PSEND ( hCommMM, mmgmm_start_t3212_req); } GMM_RETURN; } /* kern_mm_start_t3212() */ /* +------------------------------------------------------------------------------ | Function : kern_ssim_authentication_req +------------------------------------------------------------------------------ | Description : The function kern_sim_authentication_req | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_sim_authentication_req ( UBYTE *random, UBYTE cksn ) { GMM_TRACE_FUNCTION( "kern_sim_authentication_req" ); { PALLOC (sim_authentication_req, SIM_AUTHENTICATION_REQ); sim_authentication_req->source = SRC_GMM; #ifdef GMM_TCS4 sim_authentication_req->req_id = gmm_data->kern.auth_cap.last_auth_req_id; #endif memcpy ( sim_authentication_req->rand, random, MAX_RAND); sim_authentication_req->cksn = cksn; PSEND (hCommSIM, sim_authentication_req); } GMM_RETURN; } /* kern_mm_authentication_req() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_attach_started +------------------------------------------------------------------------------ | Description : The function kern_mm_attach_started sends the primitive | mmgmm_attach_started_req to MM | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_attach_started ( void ) { GMM_TRACE_FUNCTION( "kern_mm_attach_started" ); SET_STATE ( MM, GMM_MM_REG_INITATED_VIA_GPRS); { PALLOC ( mmgmm_attach_started_req, MMGMM_ATTACH_STARTED_REQ ); PSEND ( hCommMM, mmgmm_attach_started_req); } GMM_RETURN; } /* kern_mm_attach_started() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_auth_rej +------------------------------------------------------------------------------ | Description : The function kern_mm_atuth_rej sends the primitive | mmgmm_auth_req to MM | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_auth_rej ( void ) { GMM_TRACE_FUNCTION( "kern_mm_auth_rej" ); { PALLOC ( mmgmm_auth_rej_req, MMGMM_AUTH_REJ_REQ ); PSEND ( hCommMM, mmgmm_auth_rej_req); } GMM_RETURN; } /* kern_mm_attach_rej() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_attach_rej +------------------------------------------------------------------------------ | Description : The function kern_mm_attach_rej sends the primitive | mmgmm_attach_rej_req to MM. The primitive is always sent if | responce from MM is expected, .i.e no MMGMM_NREG_CNF | | Parameters : error_cause - the error cause given by the net or | MMGMM_AAC_OVER_5 if attach_attempt_counter is greater or equal | than 5 | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_attach_rej ( USHORT error_cause ) { GMM_TRACE_FUNCTION( "kern_mm_attach_rej" ); //if (GMM_MM_REG_INITATED_VIA_GPRS==gmm_data->mm_imsi_attached) { PALLOC ( mmgmm_attach_rej_req, MMGMM_ATTACH_REJ_REQ ); /* * Anite B2 TC 44.2.1.2.8 */ SET_STATE ( MM, GMM_MM_DEREG); mmgmm_attach_rej_req-> cause = error_cause; /* TCS 2.1 */ PSEND ( hCommMM, mmgmm_attach_rej_req); } /* else { kern_mm_imsi_detach_ind ( error_cause, MMGMM_DETACH_DONE); } */ GMM_RETURN; } /* kern_mm_attach_rej() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_attach_acc +------------------------------------------------------------------------------ | Description : The function kern_mm_attach_acc sends the promitve to MM. | | Parameters : mobile_identity - TMSI given by the network | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_attach_acc ( BOOL v_mobile_identity, /* TCS 2.1 */ T_mobile_identity * mobile_identity, /* TCS 2.1 */ BOOL v_eqv_plmn_list, /* TCS 2.1 */ T_eqv_plmn_list * eqv_plmn_list /* TCS 2.1 */ ) /* TCS 2.1 */ { GMM_TRACE_FUNCTION( "kern_mm_attach_acc" ); /* * HM: This catches never... * Patch HM 07-Aug-01, make GMM2503 pass >>> * GMM thinks it performs a combined attach in network mode I, * but the truth is we came from network mode I and are now * performing the non-combined procedures in network mode II. */ if ( GMM_MM_REG_INITATED_VIA_GPRS == GET_STATE(MM) ) /* Patch HM 07-Aug-01, make GMM2503 pass <<< */ { PALLOC ( mmgmm_attach_acc_req, MMGMM_ATTACH_ACC_REQ ); sig_kern_sync_set_mm_state ( MMGMM_FULL_SERVICE ); gmm_data->kern.mm_cell_env.rai.lac = gmm_data->kern.sig_cell_info.env.rai.lac; gmm_data->kern.mm_cell_env.rai.plmn = gmm_data->kern.sig_cell_info.env.rai.plmn; mmgmm_attach_acc_req->v_tmsi = v_mobile_identity; mmgmm_attach_acc_req->lac = gmm_data->kern.mm_cell_env.rai.lac; mmgmm_attach_acc_req->plmn.v_plmn = TRUE; memcpy(mmgmm_attach_acc_req->plmn.mnc,gmm_data->kern.mm_cell_env.rai.plmn.mnc,SIZE_MNC); memcpy (mmgmm_attach_acc_req->plmn.mcc, gmm_data->kern.mm_cell_env.rai.plmn.mcc,SIZE_MCC); mmgmm_attach_acc_req->tmsi = (v_mobile_identity?gmm_data->tmsi:MMGMM_TMSI_INVALID); mmgmm_attach_acc_req->v_equ_plmn_list = v_eqv_plmn_list; /* TCS 2.1 */ if (v_eqv_plmn_list) /* TCS 2.1 */ memcpy(&mmgmm_attach_acc_req->equ_plmn_list, eqv_plmn_list, sizeof(T_equ_plmn_list)); /* TCS 2.1 */ PSEND ( hCommMM, mmgmm_attach_acc_req); } else { PALLOC ( mmgmm_allowed_req, MMGMM_ALLOWED_REQ ); mmgmm_allowed_req->lac = gmm_data->kern.attach_cap.rai_accepted.lac; mmgmm_allowed_req->plmn.v_plmn = TRUE; memcpy(mmgmm_allowed_req->plmn.mnc,gmm_data->kern.attach_cap.rai_accepted.mnc,SIZE_MNC); memcpy (mmgmm_allowed_req->plmn.mcc, gmm_data->kern.attach_cap.rai_accepted.mcc,SIZE_MCC); mmgmm_allowed_req->v_equ_plmn_list = v_eqv_plmn_list; /* TCS 2.1 */ if (v_eqv_plmn_list) /* TCS 2.1 */ memcpy(&mmgmm_allowed_req->equ_plmn_list, eqv_plmn_list, sizeof(T_equ_plmn_list)); /* TCS 2.1 */ PSEND ( hCommMM, mmgmm_allowed_req); } GMM_RETURN; } /* kern_mm_attach_acc() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_reg_req +------------------------------------------------------------------------------ | Description : The function kern_mm_reg_req sends the primitive | MMGMM_REG_REQ to MM | | Parameters : | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_reg_req (U8 reg_type, U8 bootup_act) { GMM_TRACE_FUNCTION( "kern_mm_reg_req" ); { PALLOC ( mmgmm_reg_req, MMGMM_REG_REQ ); /* T_MMGMM_REG_REQ */ mmgmm_reg_req->reg_type = reg_type; mmgmm_reg_req->service_mode = gmm_data->kern.attach_cap.service_mode; mmgmm_reg_req->mobile_class = gmm_data->kern.attach_cap.mobile_class; mmgmm_reg_req->bootup_act = bootup_act; PSEND ( hCommMM, mmgmm_reg_req ); } GMM_RETURN; } /* kern_mm_attach_rej() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_activate_rr +------------------------------------------------------------------------------ | Description : The MMGMM_ACTIVATE_REQ is used to initiate GPRS Cell Selection | in RR. Cell selection for CS only is triggered implicitly be | activating MM (i.e. the MS is operates as a class CC mobile) by | sending the primitive discribed in function kern_mm_activate_mm | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_activate_rr ( void ) { GMM_TRACE_FUNCTION ("kern_mm_activate_rr()"); if (gmm_data->kern.attach_cap.network_selection_mode EQ MODE_AUTO) { kern_mm_reg_req (REG_CELL_SEARCH_ONLY, NORMAL_REG); } else { PALLOC ( mmgmm_plmn_res, MMGMM_PLMN_RES ); /* T_MMGMM_PLMN_RES */ mmgmm_plmn_res->plmn = gmm_data->kern.attach_cap.plmn_requested; mmgmm_plmn_res->reg_type = REG_CELL_SEARCH_ONLY; mmgmm_plmn_res->mobile_class = gmm_data->kern.attach_cap.mobile_class; PSEND ( hCommMM, mmgmm_plmn_res ); } kern_gmmrr_enable(); GMM_RETURN; } /* kern_mm_activate_rr () */ /* +------------------------------------------------------------------------------ | Function : kern_mm_activate_mm +------------------------------------------------------------------------------ | Description : The MM_ACTIVATE_MM_REQ is used to request MM to act as | an GSM-only mobile. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_activate_mm ( void ) { GMM_TRACE_FUNCTION ("kern_mm_activate_mm()"); if (GMMREG_CLASS_CG!=gmm_data->kern.attach_cap.mobile_class) { /* * remember lau initiated */ gmm_data->kern.attach_cap.mm_lau_attempted = TRUE; if (gmm_data->kern.attach_cap.network_selection_mode EQ MODE_AUTO) { kern_mm_reg_req (REG_GPRS_INACTIVE, NORMAL_REG); } else { PALLOC ( mmgmm_plmn_res, MMGMM_PLMN_RES ); /* T_MMGMM_PLMN_RES */ mmgmm_plmn_res->plmn = gmm_data->kern.attach_cap.plmn_requested; mmgmm_plmn_res->reg_type = REG_GPRS_INACTIVE; mmgmm_plmn_res->mobile_class = gmm_data->kern.attach_cap.mobile_class; PSEND ( hCommMM, mmgmm_plmn_res ); } } GMM_RETURN; } /* kern_mm_activate_rr () */ /* +------------------------------------------------------------------------------ | Function : kern_local_detach_open_proc +------------------------------------------------------------------------------ | Description : The function kern_local_detach_open_proc() calls all open | issues to be done upon receiving GMMRR_SUSPEND_CNF | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_local_detach_open_proc (void ) { GMM_TRACE_FUNCTION( "kern_local_detach_open_proc" ); TRACE_1_INFO ("open %d",gmm_data->kern.detach_cap.local_detach_open_proc); switch ( gmm_data->kern.detach_cap.local_detach_open_proc) { case GMM_LOCAL_DETACH_PROC_RESUME: kern_resume_grr_der(); break; case GMM_LOCAL_DETACH_PROC_ENTER_NULL_IMSI: SET_STATE (KERN, KERN_GMM_NULL_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); /* If GMM entered No Cell Available & after coming back to GSM only N/W, the user does a manual * detach, then it is necessary for GMM to disable GRR & enable GSM only mode through MM */ kern_gmmrr_disable(); kern_mm_activate_mm(); break; case GMM_LOCAL_DETACH_PROC_ENTER_NULL_NO_IMSI: SET_STATE (KERN, KERN_GMM_NULL_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); break; case GMM_LOCAL_DETACH_PROC_ENTER_NULL_IMSI_LIMITED_SERVICE_REQ: SET_STATE (KERN, KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ); EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ); break; case GMM_LOCAL_DETACH_PROC_ENTER_REG_NORMAL: kern_enter_reg_normal(); break; case GMM_LOCAL_DETACH_PROC_ENTER_DEREG: kern_enter_der(); break; case GMM_LOCAL_DETACH_PROC_UNASSIGN: kern_llgmm_unassign(); kern_resume_grr_der(); break; case GMM_LOCAL_DETACH_PROC_SUSP_LAU: gmm_data->kern.suspension_type &= ~GMM_SUSP_LOCAL_DETACH; kern_mm_lau(); break; case GMM_LOCAL_DETACH_PROC_RE_ATTACH: TRACE_0_OUT_PARA("Unassign"); gmm_data->tlli.old=gmm_data->tlli.current; gmm_data->tlli.current_type = INVALID_TLLI; gmm_data->tlli.current=GMMRR_TMSI_INVALID; gmm_data->kern.attach_cap.llc_state = GMM_LLC_STATE_UNASSIGNED; { PALLOC (llgmm_assign_req, LLGMM_ASSIGN_REQ); gmm_data->tlli.current_type=INVALID_TLLI; llgmm_assign_req->old_tlli = LLGMM_TLLI_INVALID; llgmm_assign_req->new_tlli = LLGMM_TLLI_INVALID; memset (llgmm_assign_req->llgmm_kc.key,0, sizeof (llgmm_assign_req->llgmm_kc.key)); kern_reset_cipher (); llgmm_assign_req->ciphering_algorithm = LLGMM_CIPHER_NO_ALGORITHM; PSEND ( hCommLLC, llgmm_assign_req ); } kern_resume_grr_der(); //kern_attach_reset(); //kern_attach(); break; case GMM_LOCAL_DETACH_PROC_RAU: kern_rau(); break; case GMM_LOCAL_DETACH_PROC_DISABLE: if (gmm_data->sim_gprs_invalid) { SET_STATE ( KERN, KERN_GMM_NULL_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); } else { SET_STATE ( KERN, KERN_GMM_NULL_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); } kern_gmmrr_disable(); kern_mm_activate_mm (); break; case GMM_LOCAL_DETACH_PROC_COMB_DISABLE: SET_STATE ( KERN, KERN_GMM_NULL_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); gmm_data->kern.attach_cap.attach_type = GMMREG_AT_NOT_KNOWN; kern_gmmrr_disable(); kern_mm_activate_mm (); break; case GMM_LOCAL_DETACH_PROC_AUTH_FAILED: SET_STATE ( KERN, KERN_GMM_DEREG_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); gmm_data->kern.attach_cap.attach_type = GMMREG_AT_NOT_KNOWN; kern_gmmrr_disable(); kern_mm_imsi_detach_ind ( GMMCS_AUTHENTICATION_REJECTED, /* TCS 2.1 */ GET_STATE(MM)==GMM_MM_DEREG? MMGMM_DETACH_DONE: MMGMM_PERFORM_DETACH, gmm_data->kern.detach_cap.detach_type ); break; case GMM_LOCAL_DETACH_PROC_SIM_REMOVED: SET_STATE ( KERN, KERN_GMM_DEREG_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); gmm_data->kern.attach_cap.attach_type = GMMREG_AT_NOT_KNOWN; kern_gmmrr_disable(); kern_mm_imsi_detach_ind ( GMMCS_SIM_REMOVED, /* TCS 2.1 */ GET_STATE(MM)==GMM_MM_DEREG? MMGMM_DETACH_DONE: MMGMM_PERFORM_DETACH, gmm_data->kern.detach_cap.detach_type); break; case GMM_LOCAL_DETACH_PROC_POWER_OFF: SET_STATE (KERN, KERN_GMM_DEREG_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); vsi_t_stop ( GMM_handle, kern_TPOWER_OFF); kern_gmmrr_disable(); kern_mm_imsi_detach_ind ( GMMCS_POWER_OFF, /* TCS 2.1 */ GET_STATE(MM)==GMM_MM_DEREG? MMGMM_DETACH_DONE: MMGMM_PERFORM_DETACH, gmm_data->kern.detach_cap.detach_type); break; case GMM_LOCAL_DETACH_PROC_SOFT_OFF: if (gmm_data->sim_gprs_invalid) { SET_STATE (KERN, KERN_GMM_DEREG_NO_IMSI); EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); } else { SET_STATE (KERN, KERN_GMM_NULL_IMSI); EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); } vsi_t_stop ( GMM_handle, kern_TPOWER_OFF); kern_gmmrr_disable(); kern_mm_imsi_detach_ind ( GMMCS_POWER_OFF, /* TCS 2.1 */ GET_STATE(MM)==GMM_MM_DEREG? MMGMM_DETACH_DONE: MMGMM_PERFORM_DETACH, gmm_data->kern.detach_cap.detach_type); break; case GMM_LOCAL_DETACH_PROC_NOT_CHANGED: case GMM_LOCAL_DETACH_PROC_NOTHING: default: if (GMM_GRR_STATE_SUSPENDED==gmm_data->kern.attach_cap.grr_state) { kern_resume_grr_der(); } break; } gmm_data->kern.detach_cap.local_detach_open_proc=GMM_LOCAL_DETACH_PROC_NOTHING; GMM_RETURN; } /* kern_kern_local_detach_open_proc () */ /* +------------------------------------------------------------------------------ | Function : kern_local_detach +------------------------------------------------------------------------------ | Description : The function kern_local_detach() .... | | Parameters : error_cause - error cause | | gmm_data->kern.detach_cap.detach_type MUST be set ! | +------------------------------------------------------------------------------ */ GLOBAL void kern_local_detach ( USHORT error_cause, BOOL det_acc_sent, T_LOCAL_DETACH_PROC local_detach_open_proc ) { /* * compiler cl470.exe test: replace local variable detach_type with * gmm_data...detach_type * => you may get an assembler error (because switch condition * modified within case statement ??) */ UBYTE detach_type = gmm_data->kern.detach_cap.detach_type; UBYTE kern_gmm_save_state = GET_STATE(KERN); GMM_TRACE_FUNCTION( "kern_local_detach" ); if (GMM_LOCAL_DETACH_PROC_NOT_CHANGED!=local_detach_open_proc) { gmm_data->kern.detach_cap.local_detach_open_proc=local_detach_open_proc; } else { if(GMM_LOCAL_DETACH_PROC_NOTHING EQ gmm_data->kern.detach_cap.local_detach_open_proc) { TRACE_ERROR ("GMM_LOCAL_DETACH_PROC_NOTHING called"); } } if ( gmm_data->kern.local_detached) /*local_detach_done */ { TRACE_0_INFO ("kern_local_detach() called already"); gmm_data->kern.local_detached = FALSE; kern_local_detach_open_proc(); GMM_RETURN; } gmm_data->kern.local_detached = TRUE; switch (detach_type) { case GMMREG_DT_IMSI: break; case GMMREG_DT_POWER_OFF: SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); kern_gmmsm_establich_rej(); if (det_acc_sent) { gmm_data->kern.suspension_type |= GMM_SUSP_LOCAL_DETACH; sig_kern_rdy_start_timer_req( kern_TPOWER_OFF, TPOWER_OFF_VALUE); } else { vsi_t_start ( GMM_handle , kern_TPOWER_OFF, TPOWER_OFF_VALUE); kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LOCAL_DETACH); } break; default: SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); kern_gmmsm_establich_rej(); if (det_acc_sent) { gmm_data->kern.suspension_type |= GMM_SUSP_LOCAL_DETACH; sig_kern_rdy_start_timer_req( kern_TLOCAL_DETACH, TLOCAL_DETACH_VALUE); } else { kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LOCAL_DETACH); } break; } /* * LABEL UNASSIGN_GMMREG */ vsi_t_stop ( GMM_handle , kern_T3321); switch ( detach_type ) { case GMM_DT_RE_ATTACH: GMM_RETURN; case GMMREG_DT_LIMITED_SERVICE: case GMMREG_DT_SIM_REMOVED: gmm_data->kern.detach_cap.local_detach_open_proc= (GMMCS_AUTHENTICATION_REJECTED== error_cause? /* TCS 2.1 */ GMM_LOCAL_DETACH_PROC_AUTH_FAILED: GMM_LOCAL_DETACH_PROC_SIM_REMOVED); kern_gmmreg_detach (gmm_data->kern.detach_cap.detach_type, error_cause, GMMREG_SEARCH_NOT_RUNNING, error_cause); break; case GMMREG_DT_POWER_OFF: case GMMREG_DT_SOFT_OFF: /* If GPRS is already suspended and power switch off is to be done, * kern_local_detach_open_proc() will not be called as GMM will not receive * GMMRR_SUSPEND_CNF from GRR, as GRR is already suspended */ if (kern_gmm_save_state EQ KERN_GMM_REG_SUSPENDED) { gmm_data->kern.local_detached = FALSE; kern_local_detach_open_proc(); } break; case GMMREG_DT_IMSI: kern_mm_attach_rej ( error_cause ); kern_gmmreg_detach (gmm_data->kern.detach_cap.detach_type, error_cause, GMMREG_SEARCH_NOT_RUNNING, error_cause); gmm_data->kern.local_detached = FALSE; kern_local_detach_open_proc(); break; case GMMREG_DT_COMB: kern_mm_attach_rej ( error_cause ); kern_gmmreg_detach (gmm_data->kern.detach_cap.detach_type, error_cause, GMMREG_SEARCH_NOT_RUNNING, error_cause); break; case GMMREG_DT_DISABLE_GPRS: gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_CC; gmm_data->kern.attach_cap.attach_type &= ~GMMREG_AT_GPRS; /* NO break; */ case GMMREG_DT_GPRS: break; default: TRACE_ERROR ( "Unexpected detach_type in DETACH LABEL" ); break; } GMM_RETURN; } /* kern_local_detach() */ /* +------------------------------------------------------------------------------ | Function : kern_get_imeisv +------------------------------------------------------------------------------ | Description : The function kern_get_imeisv | copied from MM: void csf_read_imei (T_imsi *imei) | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_get_imeisv (T_gmobile_identity *imei) { UBYTE buf[CL_IMEI_SIZE]; GMM_TRACE_FUNCTION( "kern_get_imeisv" ); #ifdef TDSGEN imei->identity_digit[0] = 0x04; imei->identity_digit[1] = 0x04; imei->identity_digit[2] = 0x06; imei->identity_digit[3] = 0x00; imei->identity_digit[4] = 0x01; imei->identity_digit[5] = 0x09; imei->identity_digit[6] = 0x01; imei->identity_digit[7] = 0x09; imei->identity_digit[8] = 0x07; imei->identity_digit[9] = 0x05; imei->identity_digit[10] = 0x00; imei->identity_digit[11] = 0x07; imei->identity_digit[12] = 0x05; imei->identity_digit[13] = 0x09; imei->identity_digit[14] = 0x00; imei->identity_digit[15] = 0x00;/* Software Version Number */ #else /* TDSGEN */ /* * Get IMEISV from IMEI common library */ cl_get_imeisv(CL_IMEI_SIZE, buf, CL_IMEI_GET_SECURE_IMEI); imei->identity_digit[0] = (buf [0] >> 4) & 0x0F; /* TAC 8 byte */ imei->identity_digit[1] = buf [0] & 0x0F; imei->identity_digit[2] = (buf [1] >> 4) & 0x0F; imei->identity_digit[3] = buf [1] & 0x0F; imei->identity_digit[4] = (buf [2] >> 4) & 0x0F; imei->identity_digit[5] = buf [2] & 0x0F; imei->identity_digit[6] = (buf [3] >> 4) & 0x0F; imei->identity_digit[7] = buf [3] & 0x0F; imei->identity_digit[8] = (buf [4] >> 4) & 0x0F; /* SNR 6 byte */ imei->identity_digit[9] = buf [4] & 0x0F; imei->identity_digit[10] = (buf [5] >> 4) & 0x0F; imei->identity_digit[11] = buf [5] & 0x0F; imei->identity_digit[12] = (buf [6] >> 4) & 0x0F; imei->identity_digit[13] = buf [6] & 0x0F; imei->identity_digit[14] = (buf [7] >> 4) & 0x0F; /* SV 2 byte */ imei->identity_digit[15] = buf [7] & 0x0F; TRACE_EVENT_P8("GMM INFO IMEI: TAC %1x%1x%1x%1x%1x%1x%1x%1x", imei->identity_digit[0], imei->identity_digit[1], imei->identity_digit[2], imei->identity_digit[3], imei->identity_digit[4], imei->identity_digit[5], imei->identity_digit[6], imei->identity_digit[7]); TRACE_EVENT_P6("GMM INFO IMEI: SNR %1x%1x%1x%1x%1x%1x", imei->identity_digit[8], imei->identity_digit[9], imei->identity_digit[10], imei->identity_digit[11], imei->identity_digit[12], imei->identity_digit[13]); TRACE_EVENT_P2("GMM INFO IMEI: SV %1x%1x", imei->identity_digit[14], imei->identity_digit[15]); #endif /* not defined TDSGEN */ imei->v_identity_digit = TRUE; imei->c_identity_digit = 16; imei->type_of_identity = ID_TYPE_IMEISV; imei->odd_even = 0; GMM_RETURN; } /* kern_get_imeisv() */ /* +------------------------------------------------------------------------------ | Function : kern_get_imei +------------------------------------------------------------------------------ | Description : The function kern_get_imei | copied from MM: void csf_read_imei (T_imsi *imei) | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_get_imei (T_gmobile_identity *imei) { GMM_TRACE_FUNCTION( "kern_get_imei" ); kern_get_imeisv(imei); /* * get imeisv returns 16 digits, but imei has only 14 digits * thus clear last byte: */ imei->identity_digit[14] = 0; imei->identity_digit[15] = 0; imei->v_identity_digit = TRUE; imei->c_identity_digit = 15; imei->type_of_identity = ID_TYPE_IMEI; imei->odd_even = 1; GMM_RETURN; } /* kern_get_imei() */ /* +------------------------------------------------------------------------------ | Function : kern_read_pcm +------------------------------------------------------------------------------ | Description : The function kern_read_pcm | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_read_pcm ( void ) { #ifdef _TARGET_ T_GMM_FFS ffsBuffer; T_FFS_SIZE size = ffs_fread("/GPRS/gmm", &ffsBuffer, sizeof(ffsBuffer)); TRACE_FUNCTION( "kern_read_pcm" ); if ( size != sizeof(ffsBuffer) ) { if ( size < 0 ) { TRACE_EVENT_P1("FFS can not read \"/GPRS/gmm\" (%d)", size); } else { TRACE_EVENT_P2("FFS contains old file of \"/GPRS/gmm\": %dBytes long, but %dBytes expected", size, sizeof(ffsBuffer)); } } else { gmm_data->config.cipher_on = ffsBuffer.cipher_on; 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); } #endif /* NOT DEFINED _SIMULATION_ */ return; } /* +------------------------------------------------------------------------------ | Function : kern_build_ms_network_capability +------------------------------------------------------------------------------ | Description : The function kern_build_ms_network_capability() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_build_ms_network_capability (T_ms_network_capability *ms_network_capability) { T_mob_class_2 mob_class_2; EXTERN void rr_csf_get_classmark2 (T_mob_class_2 *mob_class_2); GMM_TRACE_FUNCTION ("kern_build_ms_network_capability()"); rr_csf_get_classmark2 (&mob_class_2); #ifdef REL99 // HM 20-Jun-2003 Release 1999 >>> // Ensure these IEs are not accidently included in the uplink message // until Release 1999 is completely implemented in GMM memset (ms_network_capability, 0, sizeof (T_ms_network_capability)); // HM 20-Jun-2003 Release 1999 <<< #endif if (gmm_data->config.cipher_on) { ms_network_capability->gea_1 = GEA_1_YES; TRACE_EVENT ("ciphering on requested"); } else { ms_network_capability->gea_1 = GEA_1_NO; TRACE_EVENT ("ciphering off requested"); } ms_network_capability->ss_screening_indicator = mob_class_2.ss_screen; ms_network_capability->sm_capabilities_gsm = mob_class_2.mt_pp_sms; ms_network_capability->sm_capabilities_gprs = SM_CAP_GPRS_YES; ms_network_capability->ucs2_support = UCS2_YES; /* * R99 definitions must be set to 0 */ ms_network_capability->solsa_capability = NO; #ifdef REL99 ms_network_capability->rev_level_ind = REV_LEVEL_IND_99_YES; ms_network_capability->pfc_feature_mode = YES; #else ms_network_capability->rev_level_ind = REV_LEVEL_IND_99_NO; ms_network_capability->pfc_feature_mode = NO; #endif /* * end of R99 definitions */ ms_network_capability->ext_gea_bits.gea_2 = (gmm_data->config.cipher_on & 0x02)>0; ms_network_capability->ext_gea_bits.gea_3 = (gmm_data->config.cipher_on & 0x04)>0; ms_network_capability->ext_gea_bits.gea_4 = (gmm_data->config.cipher_on & 0x08)>0; ms_network_capability->ext_gea_bits.gea_5 = (gmm_data->config.cipher_on & 0x10)>0; ms_network_capability->ext_gea_bits.gea_6 = (gmm_data->config.cipher_on & 0x20)>0; ms_network_capability->ext_gea_bits.gea_7 = (gmm_data->config.cipher_on & 0x40)>0; #ifdef TDSGEN ms_network_capability->sm_capabilities_gsm = SM_CAP_GSM_NO; ms_network_capability->ss_screening_indicator = 0; #endif GMM_RETURN; } /* kern_build_ms_network_capability () */ /* +------------------------------------------------------------------------------ | Function : kern_init +------------------------------------------------------------------------------ | Description : The function kern_init() .... | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_init ( void ) { int i; TRACE_FUNCTION( "kern_init" ); /*gmm_data->gprs_enabled = TRUE;*/ /* * Initialise service KERN with state KERN_READY. */ INIT_STATE ( KERN, KERN_GMM_NULL_NO_IMSI ); #ifdef TRACE_FUNC #ifdef IDENTATION gmm_data->deep=0; #endif #endif gmm_data->anite = FALSE; gmm_data->tlli.current = LLGMM_TLLI_INVALID; gmm_data->tlli.old = LLGMM_TLLI_INVALID; gmm_data->kern.local_detached = FALSE; gmm_data->tlli.current_type = INVALID_TLLI; INIT_STATE ( MM, GMM_MM_DEREG); gmm_data->gu = GU3_ROAMING_NOT_ALLOWED; gmm_data->acc_contr_class = 0; gmm_data->kern.gprs_indicator = GMM_GPRS_SUPP_NO; #ifdef GMM_TCS4 gmm_data->sync.sig_cell_info.rt = RT_GSM; /* TCS 4.0 */ #endif gmm_data->kern.attach_cap.attach_acc_after_po = FALSE; TRACE_EVENT ("GRR is off"); gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_OFF; /* * set all kc values to 0xff */ memset (gmm_data->kern.auth_cap.kc, 0x00, MAX_KC); gmm_data->kern.auth_cap.ciphering_algorithm = LLGMM_CIPHER_NO_ALGORITHM; /* * multiple outstanding SIM_AUTHENTICATION_REQ messages reset the counter */ gmm_data->kern.auth_cap.last_auth_req_id = NOT_PRESENT_8BIT; gmm_data->config.cipher_on = 0x01; gmm_data->cipher = FALSE; gmm_data->config.preuse_off = FALSE; gmm_data->ptmsi.new_grr = GMMRR_TMSI_INVALID; gmm_data->ptmsi.current = GMMRR_TMSI_INVALID; gmm_data->ptmsi.old = GMMRR_TMSI_INVALID; gmm_data->tmsi = GMMRR_TMSI_INVALID; gmm_data->config.nmo = 0xff; /* * set the dafault timer vlaues needed in service kern */ gmm_data->kern.t3310_val = T3310_VALUE; gmm_data->kern.t3311_val = T3311_VALUE; gmm_data->kern.t3321_val = T3321_VALUE; /* * T3302 is loaded with the same value which is used to load T3212. */ gmm_data->kern.t3302_val = T3302_VALUE; gmm_data->kern.timeout_t3312 = FALSE; vsi_t_stop ( GMM_handle, kern_T3310); vsi_t_stop ( GMM_handle, kern_T3311); vsi_t_stop ( GMM_handle, kern_T3321); vsi_t_stop ( GMM_handle, kern_TPOWER_OFF); vsi_t_stop ( GMM_handle, kern_TLOCAL_DETACH); /* * which kind of attach will be used is unknown this time * nobody requested an attach */ gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_BG; gmm_data->kern.attach_cap.mobile_class_changed = FALSE; gmm_data->kern.attach_cap.attach_type = GMMREG_AT_NOT_KNOWN; gmm_data->kern.attach_cap.service_mode = SERVICE_MODE_LIMITED; gmm_data->kern.attach_cap.gmmreg = FALSE; #ifndef GMM_TCS4 gmm_data->kern.attach_cap.gmmsm = FALSE; #endif gmm_data->kern.detach_cap.network = FALSE; gmm_data->kern.detach_cap.gmmreg = FALSE; gmm_data->kern.detach_cap.local_detach_open_proc=GMM_LOCAL_DETACH_PROC_NOTHING; gmm_data->kern.detach_cap.error_cause = GMMCS_INT_NOT_PRESENT; /* TCS 2.1 */ gmm_data->kern.suspension_type = GMM_SUSP_NONE; /* * the DRX parameter are hardware dependend * TI is not supporting DRX * <R.GMM.AGINIT.M.006> */ #ifdef _SIMULATION_ gmm_data->drx_parameter.split_pg_cycle_code = 92 /* 95 DRX_NOT_USED */; #ifdef TDSGEN gmm_data->drx_parameter.split_pg_cycle_code = 16; #endif #else /* #ifdef _SIMULATION_ */ gmm_data->drx_parameter.split_pg_cycle_code = 16 /* 95 DRX_NOT_USED */; #endif /* #ifdef _SIMULATION_ */ gmm_data->drx_parameter.split_on_ccch = SPLIT_NO; gmm_data->drx_parameter.non_drx_timer = DRX_2_SEC; /* * resets the attach and rau attempt counter */ gmm_data->kern.aac = 0; gmm_data->kern.attach_cap.rau_initiated = GMM_NO_RAU; gmm_data->kern.attach_cap.enter_attempting_to_update_after_lau=FALSE; gmm_data->kern.sig_cell_info.env.rai.rac = GMMREG_RA_INVALID; gmm_data->kern.sig_cell_info.env.rai.lac = GMMRR_LA_INVALID; gmm_data->kern.sig_cell_info.gmm_status = GMMRR_SERVICE_UNKNOWN ; /* Initalize gmm status value */ #ifdef _SIMULATION_ gmm_data->kern.mm_cell_env.rai.rac = GMMREG_RA_INVALID; gmm_data->kern.mm_cell_env.rai.lac = GMMRR_LA_INVALID; gmm_data->kern.detach_cap.detach_type = VAL_DETACH_TYPE___DEF; #endif /* * Cel ID */ gmm_data->kern.cell_id.lac = (USHORT)GMMREG_LA_INVALID; gmm_data->kern.cell_id.rac = (UBYTE)GMMREG_RA_INVALID; INIT_STATE (CU,CU_CELL_RES_SENT); gmm_data->kern.attach_cap.llc_state=GMM_LLC_STATE_UNASSIGNED; gmm_data->kern.gmmrr_resume_sent = FALSE; gmm_data->kern.attach_cap.grr_via_llc_suspended=FALSE; gmm_data->kern.attach_cap.mm_lau_attempted=FALSE; for(i=0; i<MAX_LIST_OF_FORBIDDEN_PLMNS_FOR_GPRS_SERVICE; i++) { memset(gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mcc, 0xFF, SIZE_MCC); memset(gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mnc, 0xFF, SIZE_MNC); } kern_read_pcm(); #ifdef REL99 /* Used to indicate to LLC if it should use NULL frame for * performing cell updates. Cell notification is disabled by * default. This field is changed only if the SGSN indicates * that it supports cell notification */ gmm_data->cell_notification = NO_CELL_NOTIFY; /* TCS 4.0 */ /* Initialise all the pdp context status to invalid untill GMM gets a valid status from SM */ gmm_data->kern.attach_cap.pdp_context_status = INVALID_PDP_CONTEXT_STATUS; /* TCS 4.0 */ #endif return; } /* kern_init() */ /* +------------------------------------------------------------------------------ | Function : kern_attach_reset +------------------------------------------------------------------------------ | Description : This procedure is called in cell updatingn procedure, if RA | was changed an the ATTACH procedurehas to re-initialized. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_attach_reset ( void ) { GMM_TRACE_FUNCTION( "kern_attach_reset" ); /* * resets the counter for TIMER t3310 */ gmm_data->kern.ct3310 = 0; /* * I reuse timer T3310 also for T3330 */ vsi_t_stop ( GMM_handle, kern_T3310); vsi_t_stop ( GMM_handle, kern_T3311); gmm_data->kern.aac = 0; gmm_data->kern.detach_cap.network = FALSE; GMM_RETURN; } /* kern_attach_reset() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_detach_started +------------------------------------------------------------------------------ | Description : The function kern_mm_detach_started indicates MM that the | GSM detach procedure is started by GMM. MM has to enter state | MM-IMSI-DETACH-PENDING. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_detach_started ( void ) { GMM_TRACE_FUNCTION( "kern_mm_detach_started" ); switch( gmm_data->kern.detach_cap.detach_type) { case GMMREG_DT_SIM_REMOVED : if (GMM_MM_DEREG == GET_STATE(MM)) { break; } /* NO break;*/ case GMMREG_DT_IMSI: case GMMREG_DT_COMB: if (GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) { PALLOC ( mmgmm_detach_started_req, MMGMM_DETACH_STARTED_REQ); PSEND ( hCommMM, mmgmm_detach_started_req ); } break; default: break; } GMM_RETURN; } /* kern_detach_started() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_imsi_detach_ind +------------------------------------------------------------------------------ | Description : The function kern_mm_imsi_detach()handles the IMSI detach. | | Parameters : detach_done - indicates whether GMM has already done the IMSI | detach or not. | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_imsi_detach_ind ( USHORT error_cause, BOOL detach_done, UBYTE detach_type ) { GMM_TRACE_FUNCTION( "kern_mm_imsi_detach_ind" ); { PALLOC ( mmgmm_nreg_req, MMGMM_NREG_REQ); /* T_MMGMM_NREG_REQ */ mmgmm_nreg_req->cause = error_cause; /* TCS 2.1 */ mmgmm_nreg_req->detach_done = detach_done; SET_STATE ( MM, GMM_MM_DEREG ); TRACE_1_OUT_PARA("detach_done %d",detach_done); switch ( detach_type ) { case GMMREG_DT_SIM_REMOVED: mmgmm_nreg_req->detach_cause = CS_SIM_REM; /* TCS 2.1 */ break; case GMMREG_DT_POWER_OFF: mmgmm_nreg_req->detach_cause = CS_POW_OFF; /* TCS 2.1 */ break; case GMMREG_DT_SOFT_OFF: mmgmm_nreg_req->detach_cause = CS_SOFT_OFF; /* TCS 2.1 */ break; default: mmgmm_nreg_req->detach_cause = CS_DISABLE; /* TCS 2.1 */ break; } gmm_data->kern.suspension_type &= ~GMM_SUSP_IMSI_DETACH; PSEND ( hCommMM, mmgmm_nreg_req ); } GMM_RETURN; } /* kern_imsi_detach_ind () */ /* +------------------------------------------------------------------------------ | Function : kern_mm_imsi_detach +------------------------------------------------------------------------------ | Description : The function kern_mm_imsi_detach()handles the IMSI detach. | | Parameters : detach_done - indicates whether GMM has already done the IMSI | detach or not. | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_imsi_detach ( void ) { GMM_TRACE_FUNCTION( "kern_mm_imsi_detach" ); kern_mm_imsi_detach_ind (GMMCS_INT_NOT_PRESENT, MMGMM_PERFORM_DETACH, gmm_data->kern.detach_cap.detach_type); /* TCS 2.1 */ GMM_RETURN; } /* kern_imsi_detach() */ /* +------------------------------------------------------------------------------ | Function : kern_mm_lau +------------------------------------------------------------------------------ | Description : This procedure start the LAU procedure in entity MM | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_mm_lau ( void ) { GMM_TRACE_FUNCTION( "kern_mm_lau" ); gmm_data->kern.attach_cap.mm_lau_attempted=TRUE; gmm_data->kern.suspension_type &= ~GMM_SUSP_LAU; if (gmm_data->kern.attach_cap.network_selection_mode EQ MODE_AUTO) { kern_mm_reg_req (REG_REMOTE_CONTROLLED, NORMAL_REG); } else { PALLOC ( mmgmm_plmn_res, MMGMM_PLMN_RES ); /* T_MMGMM_PLMN_RES */ mmgmm_plmn_res->plmn = gmm_data->kern.attach_cap.plmn_requested; mmgmm_plmn_res->reg_type = REG_REMOTE_CONTROLLED; mmgmm_plmn_res->mobile_class = gmm_data->kern.attach_cap.mobile_class; PSEND ( hCommMM, mmgmm_plmn_res ); } GMM_RETURN; } /* kern_mm_lau() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_assign +------------------------------------------------------------------------------ | Description : The function kern_gmmrr_assign() | | This procedure assigned the current TLLI parameter to GRR | entities | | Parameters : void | | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_assign ( void ) { GMM_TRACE_FUNCTION( "kern_gmmrr_assign" ); { PALLOC ( gmmrr_assign_req, GMMRR_ASSIGN_REQ ); gmmrr_assign_req->new_tlli = gmm_get_tlli ( CURRENT_TLLI ); gmmrr_assign_req->old_tlli = gmm_get_tlli ( OLD_TLLI ); if (GMMRR_TLLI_INVALID==gmmrr_assign_req->new_tlli) { gmmrr_assign_req->old_ptmsi = GMMRR_TMSI_INVALID; gmmrr_assign_req->new_ptmsi = GMMRR_TMSI_INVALID; } else { gmmrr_assign_req->old_ptmsi = gmm_data->ptmsi.old; gmmrr_assign_req->new_ptmsi = gmm_data->ptmsi.new_grr; } gmmrr_assign_req->imsi = gmm_data->imsi; gmmrr_assign_req->rai.plmn.v_plmn=TRUE; memcpy (gmmrr_assign_req->rai.plmn.mcc, gmm_data->kern.attach_cap.rai_accepted.mcc, SIZE_MCC); memcpy (gmmrr_assign_req->rai.plmn.mnc, gmm_data->kern.attach_cap.rai_accepted.mnc, SIZE_MNC); gmmrr_assign_req->rai.lac = gmm_data->kern.attach_cap.rai_accepted.lac; gmmrr_assign_req->rai.rac = gmm_data->kern.attach_cap.rai_accepted.rac; TRACE_3_OUT_PARA("PTMSI old: 0x%X new: 0x%X,curent:0x%X ",gmmrr_assign_req->old_ptmsi, gmmrr_assign_req->new_ptmsi, gmm_data->ptmsi.current); PSEND ( hCommGRR, gmmrr_assign_req ); } GMM_RETURN; } /* kern_gmmrr_assign() */ /* +------------------------------------------------------------------------------ | Function : kern_local_atach +------------------------------------------------------------------------------ | Description : The function kern_local_attach() | | This procedure assigned the given TLLI parameter to the other | entities | | Parameters : new_tlli_type - type of new TLLI (random, local ,..) | old_tlli_type - type of old TLLI | +------------------------------------------------------------------------------ */ GLOBAL void kern_local_attach ( T_TLLI_TYPE new_tlli_type, T_TLLI_TYPE old_tlli_type ) { GMM_TRACE_FUNCTION( "kern_local_attach" ); kern_llgmm_assign_tlli ( new_tlli_type, old_tlli_type ); kern_gmmrr_assign(); GMM_RETURN; } /* kern_local_attach() */ /* +------------------------------------------------------------------------------ | Function : kern_ptmsi_negotiated +------------------------------------------------------------------------------ | Description : This procedure is called if an AIR message is received which | contains an optional PTMSI IE. i.e. in the ATTACH_ACCEPT or | RAU_ACCEPT message. It stores the P-TMSI and the | P-TMSI Signature, if available into the SIM and changes the | update state to GU1 UPDATED and triggers the cell update | procedure by calling LLGMM_TRIGGER_REQ, if needed. Otherwise, | if P-TMSI was negotiated CU is triggered outside of this | procedure by transmitting CONFIRM message. At the end of this | procedure the new genereted TLLI is passed to the other layers | | Parameters : v_mobile_identity - flag from AIR if ptmsi is available | mobile_identity - ptmsi from AIR | v_ptmsi_signature - flag from AIR if psignature is available | ptmsi_signature - ptmsi signature from AIR | +------------------------------------------------------------------------------ */ GLOBAL void kern_tmsi_negotiated ( BOOL v_tmsi, T_mobile_identity *tmsi, BOOL v_ptmsi, T_gmobile_identity *ptmsi, BOOL v_ptmsi_signature, T_p_tmsi_signature *p_tmsi_signature ) { GMM_TRACE_FUNCTION ("kern_tmsi_negotiated()"); /* * save the available flags */ gmm_data->ptmsi_signature.available = v_ptmsi_signature; if ( v_ptmsi ) { if ( !ptmsi->v_tmsi ) { TRACE_ERROR ( "PTMSI IE received from air without ptmsi value, perhaps IMSI reseived" ); sig_kern_rx_gmm_status(ERRCS_IE_INVALID); } else { /* * store the given PTMSI */ gmm_data->ptmsi.old = gmm_data->ptmsi.current, gmm_data->ptmsi.new_grr = gmm_data->ptmsi.current = kern_get_tmsi ((T_mobile_identity *)ptmsi ); } } if ( v_tmsi ) { if ( !tmsi->v_tmsi ) { TRACE_EVENT ( "TMSI IE received from air without ptmsi value, perhaps IMSI reseived" ); /* * <R.GMM.ACSUBOTH.M.011> * If the message contains an IMSI (i.e. the MS is not allocated any TMSI) * than the MS shall delete any TMSI. */ gmm_data->tmsi =MMGMM_TMSI_INVALID; } else { /* * store the given TMSI */ gmm_data->tmsi = kern_get_tmsi ((T_mobile_identity *)tmsi ); } } /* * After the rocedure the local TLLI have to be used * * set all TLLIs and saves the current TLLI as old TLLI */ gmm_set_current_tlli ( LOCAL_TLLI ) ; if ( v_ptmsi_signature ) { /* * <R.GMM.AGACCEPT.M.020>, <R.GMM.AGACCEPT.M.021>, * <R.GMM.AGACCEPT.M.022>, <R.GMM.RNACCEPT.M.014> */ gmm_data->ptmsi_signature.value = p_tmsi_signature->p_tmsi_signature_value; } /* * <R.GMM.AGACCEPT.M017>, <R.GMM.AGACCEPT.M019>, * <R.GMM.AGACCEPT.M022>,<R.GMM.AGACCEPT.M023> */ gmm_data->gu = GU1_UPDATED; kern_sim_gmm_update(); vsi_o_ttrace(VSI_CALLER TC_EVENT,"Info: GU: %i", gmm_data->gu+1); if ( GMM_PERIODIC_RAU != gmm_data->kern.attach_cap.rau_initiated || ptmsi->v_tmsi || tmsi->v_tmsi ) { /* * in attach and RAU the TLLI as to change from foreign to local tlli */ kern_local_attach ( CURRENT_TLLI, OLD_TLLI ); } else { /* * AniteB2 44.2.3.1.5 * RR has to transmit the last assigned RAI with GPRS resumption */ kern_gmmrr_assign(); } GMM_RETURN; } /* kern_ptmsi_negotiated */ /* +------------------------------------------------------------------------------ | Function : kern_sim_del_locigprs +------------------------------------------------------------------------------ | Description : This procedure resets all location infos on sim | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_sim_del_locigprs ( void ) { GMM_TRACE_FUNCTION ("kern_sim_del_locigprs()"); gmm_data->ptmsi.current = GMMRR_TMSI_INVALID; gmm_data->ptmsi.new_grr = GMMRR_TMSI_INVALID; gmm_data->ptmsi.old = GMMRR_TMSI_INVALID; gmm_data->ptmsi_signature.available = FALSE; gmm_data->ptmsi_signature.value = INVALID_PTMSI_SIGNATURE; gmm_data->kern.attach_cap.rai_accepted.lac = 0xfffe; /* INVALID */ gmm_data->kern.attach_cap.rai_accepted.rac = 0xff; /* INVALID */ memset (gmm_data->kern.auth_cap.kc, 0xFF, MAX_KC); gmm_data->kern.auth_cap.cksn = NO_KEY; GMM_RETURN; } /* kern_sim_del_locigprs */ /* +------------------------------------------------------------------------------ | Function : kern_sim_gmm_update +------------------------------------------------------------------------------ | Description : This procedure sends the primitive SIM_GU_UPDATE_REQ to SIM. | The primitive is allocated within this function and the | parameters of the primitive are filled in with the actually | set global variables of GMM. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_sim_gmm_update () { GMM_TRACE_FUNCTION ("kern_sim_gmm_update()"); { PALLOC ( sim_gmm_update_req, SIM_GMM_UPDATE_REQ ); kern_set_loc_info (sim_gmm_update_req); kern_set_kc_cksn (sim_gmm_update_req); sim_gmm_update_req->att_status = gmm_data->kern.attach_cap.attach_acc_after_po; PSEND ( hCommSIM, sim_gmm_update_req ); } GMM_RETURN; } /* kern_sim_gmm_update */ /* +------------------------------------------------------------------------------ | Function : kern_read_imsi +------------------------------------------------------------------------------ | Description : This procedure reads the imsi from primitive | sim_gmm_insert_ind | | copied from mm_regF.c in MM | | Parameters : sim_gmm_insert_ind - primitiv pointer | +------------------------------------------------------------------------------ */ GLOBAL void kern_read_imsi (T_SIM_GMM_INSERT_IND *sim_gmm_insert_ind) { USHORT i; UBYTE digit; UBYTE length; ULONG init_value=25; #ifdef NEW_FRAME T_TIME time_val; #else /* NEW_FRAME */ T_VSI_TVALUE time_val; #endif /* NEW_FRAME */ GMM_TRACE_FUNCTION ("kern_read_imsi ()"); gmm_data->imsi.v_mid = TRUE; gmm_data->imsi.id_type = TYPE_IMSI; gmm_data->imsi.tmsi_dig = 0; length = (sim_gmm_insert_ind->imsi_field.c_field-1)*2; if (sim_gmm_insert_ind->imsi_field.field[0] & 0x08) { length++; } for (i = 0; i < length; i++) { digit = (i & 1) ? sim_gmm_insert_ind->imsi_field.field[(i + 1) / 2] & 0x0f : (sim_gmm_insert_ind->imsi_field.field[(i + 1) / 2] & 0xf0) >> 4; gmm_data->imsi.id[i] = digit; init_value += digit*digit; } gmm_data->imsi.id[i] = 0xff; vsi_t_time (VSI_CALLER &time_val); srand ((USHORT)(init_value*time_val)); GMM_RETURN; } /*kern_read_imsi*/ /* +------------------------------------------------------------------------------ | Function : kern_get_tmsi +------------------------------------------------------------------------------ | Description : This procedure translate the timer value given by ACI to | an air message struct | | | Parameters : mobile_identity - PTMSI received from AIR | +------------------------------------------------------------------------------ */ GLOBAL ULONG kern_get_tmsi (T_mobile_identity * mobile_identity ) { ULONG ptmsi; GMM_TRACE_FUNCTION( "kern_get_tmsi" ); ptmsi = (mobile_identity->tmsi.b_tmsi[0] << 24)+ (mobile_identity->tmsi.b_tmsi[1] << 16)+ (mobile_identity->tmsi.b_tmsi[2] << 8)+ mobile_identity->tmsi.b_tmsi[3]; GMM_RETURN_ (ptmsi); } /* kern_get_tmsi */ /* +------------------------------------------------------------------------------ | Function : kern_get_mobile_identity +------------------------------------------------------------------------------ | Description : Derives the mobile identiti for the AIR | | COPIED FROM : MM mm_mmf.c : mm_fill_identity | | Parameters : type_of_identity - tpe of identity | gmobile_identity - used in the AIR message | +------------------------------------------------------------------------------ */ GLOBAL void kern_get_mobile_identity ( UBYTE type_of_identity, T_gmobile_identity* gmobile_identity ) { GMM_TRACE_FUNCTION ("kern_get_mobile_identity()"); memset (gmobile_identity, 0, sizeof (T_mobile_identity)); switch (type_of_identity) { case ID_TYPE_IMEISV: kern_get_imeisv ( gmobile_identity); break; case ID_TYPE_IMEI: kern_get_imei ( gmobile_identity); break; case ID_TYPE_TMSI: kern_ulong2mobile_identity (gmm_data->ptmsi.current, gmobile_identity); break; default: TRACE_ERROR ("undefined type of Identity"); /* * NO break; */ case ID_TYPE_IMSI: gmobile_identity->v_tmsi = FALSE; gmobile_identity->type_of_identity = ID_TYPE_IMSI; gmobile_identity->v_identity_digit = TRUE; gmobile_identity->c_identity_digit = kern_calculate_digits (gmm_data->imsi.id); gmobile_identity->odd_even = gmobile_identity->c_identity_digit & 1; memcpy (gmobile_identity->identity_digit, gmm_data->imsi.id, 16); break; } GMM_RETURN; } /* kern_get_mobile_identity() */ /* +------------------------------------------------------------------------------ | Function : kern_read_kc_cksn +------------------------------------------------------------------------------ | Description : Reads the location information delivered by the SIM card | into the registration memory structures. | | COPIED FROM : MM mm_regf.c : reg_read_kc_cksn | | Parameters : T_loc_info - the the loc_inf field from sim_gmm_inserted_ind | +------------------------------------------------------------------------------ */ GLOBAL void kern_read_kc_cksn (T_SIM_GMM_INSERT_IND *sim_gmm_insert_ind) { GMM_TRACE_FUNCTION ("kern_read_kc_cksn ()"); switch (gmm_data->gu) { case GU2_NOT_UPDATED: /* * GSM: 04.08, Ch.4.1.3.2 GPRS update status * * GU2: NOT UPDATED * The last GPRS attach or routing area updating attempt failed procedurally, * i.e. no response was received from the network. This includes the cases of * failures or congestion inside the network. * In this case, the SIM may contain the RAI of the routing area (RA) to which * the subscriber was attached, and possibly also a valid P-TMSI, * GPRS GSM ciphering key, GPRS UMTS ciphering key, GPRS UMTS integrity key * and GPRS ciphering key sequence number. For compatibility reasons, all these * fields shall be set to the "deleted" value if the RAI is deleted. However, the * presence of other values shall not be considered an error by the MS. */ if ( GMMRR_LA_INVALID != gmm_data->kern.attach_cap.rai_accepted.lac) { break; } /* NO break */ case GU3_ROAMING_NOT_ALLOWED: case GU3_PLMN_NOT_ALLOWED: /* * GSM: 04.08, Ch.4.3.2.4: * "When the deletion of the sequence number is described this also means * that the associated key shall be considered as invalid." * GSM: 04.08, Ch.4.7.7.4: * "If the sequence number is deleted, * the associated key shall be considered as invalid." */ gmm_data->kern.auth_cap.cksn = NO_KEY; memset (gmm_data->kern.auth_cap.kc, 0xFF, MAX_KC); break; default: gmm_data->kern.auth_cap.cksn = sim_gmm_insert_ind->kc_n.kc[MAX_KC]; if (NO_KEY == gmm_data->kern.auth_cap.cksn) { memset (gmm_data->kern.auth_cap.kc, 0xFF, MAX_KC); } else { /* * copy parameter from SIM card */ memcpy (gmm_data->kern.auth_cap.kc, sim_gmm_insert_ind->kc_n.kc, MAX_KC); } break; } GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_set_kc_cksn +------------------------------------------------------------------------------ | Description : sets the kc and cksn delivered by the SIM card | into the registration memory structures. | | COPIED FROM : MM mm_regf.c : reg_read_kc_cksn | | Parameters : T_loc_info - the the loc_inf field from sim_gmm_inserted_ind | +------------------------------------------------------------------------------ */ GLOBAL void kern_set_kc_cksn (T_SIM_GMM_UPDATE_REQ *sim_gmm_update_req) { GMM_TRACE_FUNCTION ("kern_set_kc_cksn ()"); sim_gmm_update_req->cksn = gmm_data->kern.auth_cap.cksn; memcpy (sim_gmm_update_req->kc, gmm_data->kern.auth_cap.kc, MAX_KC); GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_read_log_info +------------------------------------------------------------------------------ | Description : Reads the location information delivered by the SIM card | into the registration memory structures. | | COPIED FROM : MM mm_regf.c : reg_read_log_info | | Parameters : T_loc_info - the the loc_inf field from sim_gmm_inserted_ind | +------------------------------------------------------------------------------ */ GLOBAL void kern_read_loc_info (T_SIM_GMM_INSERT_IND *sim_gmm_insert_ind) { GMM_TRACE_FUNCTION ("kern_read_loc_info ()"); gmm_data->tmsi = (sim_gmm_insert_ind->loc_info.loc[0] << 24) + (sim_gmm_insert_ind->loc_info.loc[1] << 16) + (sim_gmm_insert_ind->loc_info.loc[2] << 8) + sim_gmm_insert_ind->loc_info.loc[3]; gmm_data->ptmsi.new_grr = gmm_data->ptmsi.current = (sim_gmm_insert_ind->gprs_loc_info.loc[0] << 24) + (sim_gmm_insert_ind->gprs_loc_info.loc[1] << 16) + (sim_gmm_insert_ind->gprs_loc_info.loc[2] << 8) + sim_gmm_insert_ind->gprs_loc_info.loc[3]; gmm_data->ptmsi_signature.value = (sim_gmm_insert_ind->gprs_loc_info.loc[4] << 16) + (sim_gmm_insert_ind->gprs_loc_info.loc[5] << 8) + sim_gmm_insert_ind->gprs_loc_info.loc[6]; gmm_data->ptmsi_signature.available = TRUE; gmm_data->kern.attach_cap.rai_accepted.mcc[0] = sim_gmm_insert_ind->gprs_loc_info.loc[7] & 0x0f; gmm_data->kern.attach_cap.rai_accepted.mcc[1] = sim_gmm_insert_ind->gprs_loc_info.loc[7] >> 4; gmm_data->kern.attach_cap.rai_accepted.mcc[2] = sim_gmm_insert_ind->gprs_loc_info.loc[8] & 0x0f; gmm_data->kern.attach_cap.rai_accepted.mnc[2] = sim_gmm_insert_ind->gprs_loc_info.loc[8] >> 4; gmm_data->kern.attach_cap.rai_accepted.mnc[0] = sim_gmm_insert_ind->gprs_loc_info.loc[9] & 0x0f; gmm_data->kern.attach_cap.rai_accepted.mnc[1] = sim_gmm_insert_ind->gprs_loc_info.loc[9] >> 4; gmm_data->kern.attach_cap.rai_accepted.lac = sim_gmm_insert_ind->gprs_loc_info.loc[10] * 256 + sim_gmm_insert_ind->gprs_loc_info.loc[11]; gmm_data->kern.attach_cap.rai_accepted.rac = sim_gmm_insert_ind->gprs_loc_info.loc[12]; gmm_data->gu = sim_gmm_insert_ind->gprs_loc_info.loc[13]; if ( GMMRR_LA_INVALID == gmm_data->kern.attach_cap.rai_accepted.lac) { kern_sim_del_locigprs (); } TRACE_9_PARA("TMSI %x, PTMSI %x, lac %x, rac %x, MCC: %x%x%x, MNC: %x%x", gmm_data->tmsi, gmm_data->ptmsi.current, gmm_data->kern.attach_cap.rai_accepted.lac, gmm_data->kern.attach_cap.rai_accepted.rac, gmm_data->kern.attach_cap.rai_accepted.mcc[0], gmm_data->kern.attach_cap.rai_accepted.mcc[1], gmm_data->kern.attach_cap.rai_accepted.mcc[2], gmm_data->kern.attach_cap.rai_accepted.mnc[0], gmm_data->kern.attach_cap.rai_accepted.mnc[1] ); if (gmm_data->gu > GU3_ROAMING_NOT_ALLOWED) { gmm_data->gu = GU2_NOT_UPDATED; } GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_set_loc_info +------------------------------------------------------------------------------ | Description : derives the log_info field for for sim inserted | | COPIED FROM : MM mm_regf.c : reg_set_log_info | | Parameters : sim_gmm_update_req - the primitive | +------------------------------------------------------------------------------ */ GLOBAL void kern_set_loc_info (T_SIM_GMM_UPDATE_REQ *sim_gmm_update_req) { GMM_TRACE_FUNCTION ("kern_set_loc_info ()"); sim_gmm_update_req->gprs_loc_info.c_loc = MAX_LOCIGPRS; sim_gmm_update_req->gprs_loc_info.loc[0] = (UBYTE)(gmm_data->ptmsi.current >> 24); sim_gmm_update_req->gprs_loc_info.loc[1] = (UBYTE)(gmm_data->ptmsi.current >> 16); sim_gmm_update_req->gprs_loc_info.loc[2] = (UBYTE)(gmm_data->ptmsi.current >> 8); sim_gmm_update_req->gprs_loc_info.loc[3] = (UBYTE)gmm_data->ptmsi.current; sim_gmm_update_req->gprs_loc_info.loc[4] = (UBYTE)(gmm_data->ptmsi_signature.value >> 16); sim_gmm_update_req->gprs_loc_info.loc[5] = (UBYTE)(gmm_data->ptmsi_signature.value >> 8); sim_gmm_update_req->gprs_loc_info.loc[6] = (UBYTE)gmm_data->ptmsi_signature.value; sim_gmm_update_req->gprs_loc_info.loc[7] = gmm_data->kern.attach_cap.rai_accepted.mcc[1] << 4; sim_gmm_update_req->gprs_loc_info.loc[7] += gmm_data->kern.attach_cap.rai_accepted.mcc[0]; sim_gmm_update_req->gprs_loc_info.loc[8] = gmm_data->kern.attach_cap.rai_accepted.mnc[2] << 4; sim_gmm_update_req->gprs_loc_info.loc[8] += gmm_data->kern.attach_cap.rai_accepted.mcc[2]; sim_gmm_update_req->gprs_loc_info.loc[9] = gmm_data->kern.attach_cap.rai_accepted.mnc[1] << 4; sim_gmm_update_req->gprs_loc_info.loc[9] += gmm_data->kern.attach_cap.rai_accepted.mnc[0]; sim_gmm_update_req->gprs_loc_info.loc[10] = gmm_data->kern.attach_cap.rai_accepted.lac >> 8; sim_gmm_update_req->gprs_loc_info.loc[11] = gmm_data->kern.attach_cap.rai_accepted.lac & 0xff; sim_gmm_update_req->gprs_loc_info.loc[12] = gmm_data->kern.attach_cap.rai_accepted.rac; sim_gmm_update_req->gprs_loc_info.loc[13] = gmm_data->gu; GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_ulong2mobile_identity +------------------------------------------------------------------------------ | Description : Derives tm mobile identiti for the AIR | | COPIED FROM : MM mm_mmf.c : mm_fill_identity | | Parameters : mobile_identity - used in the AIR message | +------------------------------------------------------------------------------ */ GLOBAL void kern_ulong2mobile_identity ( ULONG ptmsi, T_gmobile_identity* gmobile_identity ) { GMM_TRACE_FUNCTION ("kern_ulong2mobile_identity()"); memset (gmobile_identity, 0, sizeof (T_mobile_identity)); if ( GMMRR_TMSI_INVALID == gmm_data->ptmsi.current ) { /* * IMSI * <R.GMM.AGINIT.M.005> */ gmobile_identity->v_tmsi = FALSE; kern_get_mobile_identity ( ID_TYPE_IMSI, gmobile_identity ); } else /* !ptmsi.available */ { /* * PTMSI * <R.GMM.AGINIT.M.002> */ gmobile_identity->odd_even = EVEN; gmobile_identity->v_tmsi = TRUE; gmobile_identity->type_of_identity = ID_TYPE_TMSI; gmobile_identity->v_identity_digit = FALSE; gmobile_identity->tmsi.l_tmsi = 32; ccd_codeByte (gmobile_identity->tmsi.b_tmsi, 0, 8, (UBYTE)(ptmsi >> 24)); ccd_codeByte (gmobile_identity->tmsi.b_tmsi, 8, 8, (UBYTE)(ptmsi >> 16)); ccd_codeByte (gmobile_identity->tmsi.b_tmsi, 16, 8, (UBYTE)(ptmsi >> 8)); ccd_codeByte (gmobile_identity->tmsi.b_tmsi, 24, 8, (UBYTE) ptmsi); } GMM_RETURN; } /* kern_ulong2mobile_identity() */ /* +------------------------------------------------------------------------------ | Function : kern_kern_cell_changed +------------------------------------------------------------------------------ | Description : Returns TRUE if cell was changed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_cell_changed ( void ) { GMM_TRACE_FUNCTION ("kern_cell_changed()"); if ( gmm_data->kern.sig_cell_info.env.cid != gmm_data->kern.old_sig_cell_info.env.cid) { TRACE_EVENT("Info: cid changed"); GMM_RETURN_ (TRUE); } else { GMM_RETURN_ (kern_ra_crossed()); } } /* kern_lai_changed() */ /* +------------------------------------------------------------------------------ | Function : kern_kern_lai_changed +------------------------------------------------------------------------------ | Description : Returns TRUE if LA was changed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_lai_changed ( void ) { GMM_TRACE_FUNCTION ("kern_lai_changed()"); if ( gmm_data->kern.attach_cap.rai_accepted.lac != gmm_data->kern.sig_cell_info.env.rai.lac) { TRACE_3_INFO ("Info: LAI changed: changed lac: %x (%x) -> %x", gmm_data->kern.attach_cap.rai_accepted.lac, gmm_data->kern.old_sig_cell_info.env.rai.lac, gmm_data->kern.sig_cell_info.env.rai.lac); GMM_RETURN_ (TRUE); } else { if (kern_plmn_changed()) { GMM_RETURN_ (TRUE); } } GMM_RETURN_ (FALSE); } /* kern_lai_changed() */ /* +------------------------------------------------------------------------------ | Function : kern_kern_lau_needed +------------------------------------------------------------------------------ | Description : Returns TRUE if LAU is needed | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_lau_needed ( void ) { UBYTE mm_state; GMM_TRACE_FUNCTION ("kern_lau_needed()"); mm_state = GET_STATE(MM); TRACE_1_PARA ("sig_cell_info.mm_status %d", gmm_data->kern.sig_cell_info.mm_status); switch (gmm_data->kern.attach_cap.attach_type) { case GMMREG_AT_IMSI: case GMMREG_AT_COMB: GMM_RETURN_ ( ( GMM_MM_DEREG == mm_state || GMM_MM_REG_UPDATE_NEEDED == mm_state || MMGMM_WAIT_FOR_UPDATE == gmm_data->kern.sig_cell_info.mm_status || gmm_data->kern.sig_cell_info.env.rai.lac != gmm_data->kern.mm_cell_env.rai.lac || (memcmp (gmm_data->kern.sig_cell_info.env.rai.plmn.mnc, gmm_data->kern.mm_cell_env.rai.plmn.mnc, SIZE_MNC) != 0) || (memcmp (gmm_data->kern.sig_cell_info.env.rai.plmn.mcc, gmm_data->kern.mm_cell_env.rai.plmn.mcc, SIZE_MCC) != 0) ) && ( MMGMM_LIMITED_SERVICE != gmm_data->kern.sig_cell_info.mm_status) ); /* break; */ default: GMM_RETURN_ (FALSE); /* break; */ } } /* kern_lau_needed() */ /* +------------------------------------------------------------------------------ | Function : kern_ra_crossed +------------------------------------------------------------------------------ | Description : Returns TRUE if RA was crossed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_ra_crossed ( void ) { GMM_TRACE_FUNCTION ("kern_ra_crossed?"); if (gmm_data->kern.sig_cell_info.env.rai.rac != gmm_data->kern.old_sig_cell_info.env.rai.rac || gmm_data->kern.sig_cell_info.env.rai.lac != gmm_data->kern.old_sig_cell_info.env.rai.lac ) { TRACE_EVENT("Info: RA crossed"); GMM_RETURN_ (TRUE); } GMM_RETURN_(FALSE); } /* kern_rai_changed() */ /* +------------------------------------------------------------------------------ | Function : kern_rai_changed +------------------------------------------------------------------------------ | Description : Returns TRUE if RA was changed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_rai_changed ( void ) { GMM_TRACE_FUNCTION ("kern_rai_changed()"); if ( gmm_data->kern.sig_cell_info.env.rai.rac != gmm_data->kern.attach_cap.rai_accepted.rac ) { TRACE_0_INFO("RAI changed"); GMM_RETURN_ (TRUE); } GMM_RETURN_ (kern_lai_changed()); } /* kern_rai_changed() */ /* +------------------------------------------------------------------------------ | Function : kern_plmn_changed +------------------------------------------------------------------------------ | Description : Returns TRUE if PLMN was changed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_plmn_changed ( void ) { GMM_TRACE_FUNCTION ("kern_plmn_changed()"); if ( (memcmp (gmm_data->kern.sig_cell_info.env.rai.plmn.mnc, gmm_data->kern.attach_cap.rai_accepted.mnc, SIZE_MNC) != 0) || (memcmp (gmm_data->kern.sig_cell_info.env.rai.plmn.mcc, gmm_data->kern.attach_cap.rai_accepted.mcc, SIZE_MCC) != 0) ) { TRACE_0_INFO ("PLMN changed"); GMM_RETURN_ (TRUE); } else { GMM_RETURN_ (FALSE); } } /* kern_plmn_changed() */ /* +------------------------------------------------------------------------------ | Function : kern_set_rai +------------------------------------------------------------------------------ | Description : This Procedure sets the old rai and the new rai. | | Parameters : rai | +------------------------------------------------------------------------------ */ GLOBAL void kern_set_rai ( T_routing_area_identification * rai) { GMM_TRACE_FUNCTION ("kern_set_rai()"); /* * gmm_data->kern.attach_cap.rai_accepted has to be always the last valid assigned RAI * gmm_data->rai includes the last updated lac and or rac depending * on the net mode and the oroiginator: * net modeII: lac may only chaged by MM so that we know * whether we have to update LA or not either upon cell_ind(lac) or * activate_ind(lac) dependinig on what receives first. . * That means gmm_data->rai MUST NOT sent to the network it * can be wrong, i.e. new LAC but old RAC! Use always gmm_data->kern.attach_cap.rai_accepted * for transmission o the AIR. */ gmm_data->kern.attach_cap.rai_accepted = *rai; if (GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) { memcpy (gmm_data->kern.mm_cell_env.rai.plmn.mcc, rai->mcc, SIZE_MCC); memcpy (gmm_data->kern.mm_cell_env.rai.plmn.mnc, rai->mnc, SIZE_MNC); gmm_data->kern.mm_cell_env.rai.lac = rai->lac; gmm_data->kern.mm_cell_env.rai.rac = rai->rac; gmm_data->kern.mm_cell_env.cid = gmm_data->kern.sig_cell_info.env.cid; } GMM_RETURN; } /* kern_set_rai() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_suspend +------------------------------------------------------------------------------ | Description : The function kern_gmmrr_suspend() | | This procedure suspends GRR | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_suspend ( UBYTE susp_gprs, UBYTE gmmrr_susp_cause, UBYTE susp_type) { GMM_TRACE_FUNCTION( "kern_gmmrr_suspend" ); gmm_data->kern.suspension_type |= susp_type; TRACE_1_OUT_PARA ("susp_type: %x", gmm_data->kern.suspension_type); if (GMM_GRR_STATE_CR==gmm_data->kern.attach_cap.grr_state) { TRACE_0_INFO("suspension delayed untill cell_ind is received"); } else { PALLOC ( gmmrr_suspend_req, GMMRR_SUSPEND_REQ); gmmrr_suspend_req->susp_gprs = susp_gprs; gmmrr_suspend_req->gmmrr_susp_cause= gmmrr_susp_cause; /* START PATCH UBUOB ISSUE 8379 */ gmm_data->kern.gmmrr_resume_sent = FALSE; gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_SUSPENDING; /* END PATCH UBUOB ISSUE 8379 */ PSEND ( hCommGRR, gmmrr_suspend_req ); } GMM_RETURN; } /* kern_gmmrr_suspend() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_stop_waiting_for_transmission +------------------------------------------------------------------------------ | Description : The function kern_gmmrr_stop_waiting_for_transmission() | | Is sent after gmmrr_cell_ind if no RAU is needed. | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_stop_waiting_for_transmission (void) { GMM_TRACE_FUNCTION( "kern_gmmrr_stop_waiting_for_transmission" ); switch(GET_STATE(CU)) { case CU_NOT_REQUESTED: { PALLOC (gmmrr_cell_res, GMMRR_CELL_RES); gmmrr_cell_res->cu_cause=GMMRR_RA_DEFAULT; SET_STATE (CU, CU_CELL_RES_SENT); PSEND (hCommGRR, gmmrr_cell_res); } break; case CU_REQUESTED: { PALLOC (gmmrr_cell_res, GMMRR_CELL_RES); gmmrr_cell_res->cu_cause=GMMRR_RA_CU; PSEND (hCommGRR, gmmrr_cell_res); } /* NO break; */ case CU_REQUESTED_CELL_RES_SENT: SET_STATE (CU, CU_CELL_RES_SENT); kern_send_llgmm_trigger_req(); break; default: case CU_CELL_RES_SENT: break; } GMM_RETURN; } /* kern_gmmrr_suspend() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_attach_started +------------------------------------------------------------------------------ | Description : The function kern_attach_started() | | | Parameters : void | +------------------------------------------------------------------------------ */ /* * GMMRR_ATTACH_STARTED_REQ is used to inform GRR that routing area upodate or * attach procedure is started. This time span is closed with * GMMRR_ATTACH_FINISHED_REQ * GSM 04.60, ch. 5.5.1.5 Discontinuous reception (DRX): * "When initiating the MM procedures for GPRS attach and routeing area update * defined in 3GPP TS 04.08, the mobile station shall enter the MM non- DRX mode * period. This period ends when either of the messages GPRS ATTACH ACCEPT, * GPRS ATTACH REJECT, ROUTING AREA UPDATE ACCEPT or ROUTING AREA UPDATE REJECT * is received by the mobile station. This period also ends after timeout * waiting for any of these messages." */ GLOBAL void kern_gmmrr_attach_started (void) { GMM_TRACE_FUNCTION( "kern_gmmrr_attach_started" ); { PALLOC (gmmrr_attach_started_req, GMMRR_ATTACH_STARTED_REQ); gmm_data->kern.attach_cap.gmmrr_attach_finished_sent=FALSE; PSEND (hCommGRR, gmmrr_attach_started_req); } GMM_RETURN; } /* kern_gmmrr_attach_finished() */ /* +------------------------------------------------------------------------------ | Function : kern_gmmrr_attach_finished +------------------------------------------------------------------------------ | Description : The function kern_attach_finished() | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_gmmrr_attach_finished (void) { GMM_TRACE_FUNCTION( "kern_gmmrr_attach_finished" ); if(!gmm_data->kern.attach_cap.gmmrr_attach_finished_sent ) { PALLOC (gmmrr_attach_finished_req, GMMRR_ATTACH_FINISHED_REQ); gmm_data->kern.attach_cap.gmmrr_attach_finished_sent=TRUE; PSEND (hCommGRR, gmmrr_attach_finished_req); } GMM_RETURN; } /* kern_gmmrr_attach_finished() */ /* +------------------------------------------------------------------------------ | Function : kern_is_cell_forbidden +------------------------------------------------------------------------------ | Description : The function kern_is_cell_forbidden checks whether cell is | forbidden for GPRS or not | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL BOOL kern_is_cell_forbidden (void) { BOOL forbidden = (GMMRR_SERVICE_LIMITED== gmm_data->kern.sig_cell_info.gmm_status); int i; GMM_TRACE_FUNCTION( "kern_is_cell_forbidden" ); if (MMGMM_LIMITED_SERVICE == gmm_data->kern.sig_cell_info.mm_status) { TRACE_0_INFO ("mm is in limited"); GMM_RETURN_ (TRUE); } if(MODE_AUTO EQ gmm_data->kern.attach_cap.network_selection_mode /* START PATCH UBUOB ISSUE 8781 */ || !gmm_data->kern.attach_cap.gmmreg) /* END PATCH UBUOB ISSUE 8781 */ { for(i=0;!forbidden && (i<MAX_LIST_OF_FORBIDDEN_PLMNS_FOR_GPRS_SERVICE); i++) { forbidden = forbidden || ( (memcmp (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mcc, gmm_data->kern.sig_cell_info.env.rai.plmn.mcc, SIZE_MCC) == 0 ) && (memcmp (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mnc, gmm_data->kern.sig_cell_info.env.rai.plmn.mnc, SIZE_MNC) == 0 ) ); } } TRACE_1_INFO ("cell %s",forbidden?"forbidden":"allowed"); GMM_RETURN_(forbidden); } /* kern_gmmrr_attach_finished() */ /* +------------------------------------------------------------------------------ | Function : kern_remove_plmn_from_forbidden_list +------------------------------------------------------------------------------ | Description : The function kern_remove_plmn_from_forbidden_list | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_remove_plmn_from_forbidden_list (T_plmn plmn) { int i; GMM_TRACE_FUNCTION( "kern_remove_plmn_from_forbidden_list" ); for(i=0; i<MAX_LIST_OF_FORBIDDEN_PLMNS_FOR_GPRS_SERVICE; i++) { BOOL forbidden = ((memcmp (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mcc, plmn.mcc, SIZE_MCC) == 0 ) && (memcmp (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mnc, plmn.mnc, SIZE_MNC) == 0 ) ); if (forbidden) { memset(gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mcc, 0xFF, SIZE_MCC); memset(gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[i].mnc, 0xFF, SIZE_MNC); } } GMM_RETURN; } /* kern_gmmrr_attach_finished() */ /* +------------------------------------------------------------------------------ | Function : kern_send_gmmreg_cell_ind +------------------------------------------------------------------------------ | Description : The function kern_send_gmmreg_cell_ind informs MMI | that cell has changed or that we GSM is in full service again | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_send_gmmreg_cell_ind (void) { BOOL attach_cnf_to_be_sent; GMM_TRACE_FUNCTION( "kern_send_gmmreg_cell_ind" ); attach_cnf_to_be_sent = (MMGMM_FULL_SERVICE == gmm_data->kern.sig_cell_info.mm_status && ( ( ( kern_cell_changed() || gmm_data->kern.attach_cap.gmmreg ) && ( GMMRR_SERVICE_NONE != gmm_data->kern.sig_cell_info.gmm_status || GMMRR_SERVICE_NONE == gmm_data->kern.old_sig_cell_info.gmm_status ) ) /* OLD !!! */ || MMGMM_FULL_SERVICE != gmm_data->kern.old_sig_cell_info.mm_status ) ); switch( GET_STATE( KERN ) ) { case KERN_GMM_NULL_NO_IMSI: case KERN_GMM_NULL_NO_IMSI_LIMITED_SERVICE_REQ: case KERN_GMM_NULL_IMSI: case KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ: case KERN_GMM_NULL_PLMN_SEARCH: case KERN_GMM_DEREG_NO_IMSI: case KERN_GMM_DEREG_PLMN_SEARCH: case KERN_GMM_DEREG_NO_CELL_AVAILABLE: case KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH: case KERN_GMM_DEREG_LIMITED_SERVICE: case KERN_GMM_DEREG_RESUMING: case KERN_GMM_DEREG_SUSPENDING: case KERN_GMM_DEREG_SUSPENDED: if (attach_cnf_to_be_sent) { if ( GMMRR_NET_MODE_III==gmm_data->kern.sig_cell_info.net_mode && GMMREG_CLASS_BC== gmm_data->kern.attach_cap.mobile_class && !kern_lau_needed()) { kern_gmmreg_attach_cnf_sr(GMMREG_AT_IMSI, SEARCH_NOT_RUNNING); } else { switch (gmm_data->kern.sig_cell_info.gmm_status) { case GMMRR_SERVICE_LIMITED: case GMMRR_SERVICE_NONE: kern_gmmreg_attach_cnf_sr(GMMREG_AT_IMSI, SEARCH_NOT_RUNNING); break; default: case GMMRR_SERVICE_FULL: kern_gmmreg_attach_cnf_sr(GMMREG_AT_IMSI, (UBYTE)(gmm_data->sim_gprs_invalid? SEARCH_NOT_RUNNING:SEARCH_RUNNING)); break; } } } break; case KERN_GMM_DEREG_INITIATED: break; case KERN_GMM_REG_INITIATED: if (attach_cnf_to_be_sent) { kern_gmmreg_attach_cnf_sr(GMMREG_AT_IMSI,SEARCH_RUNNING); } break; default: TRACE_ERROR ("Unexpexcted state"); /* NO break */ case KERN_GMM_REG_ATTEMPTING_TO_UPDATE: case KERN_GMM_REG_NO_CELL_AVAILABLE: case KERN_GMM_REG_LIMITED_SERVICE: case KERN_GMM_REG_ATTEMPTING_TO_UPDATE_MM: case KERN_GMM_REG_RESUMING: case KERN_GMM_REG_SUSPENDED: case KERN_GMM_REG_SUSPENDING: case KERN_GMM_REG_IMSI_DETACH_INITIATED: case KERN_GMM_REG_TEST_MODE_NO_IMSI: case KERN_GMM_REG_TEST_MODE: case KERN_GMM_RAU_INITIATED: case KERN_GMM_RAU_WAIT_FOR_NPDU_LIST: if (attach_cnf_to_be_sent) { kern_gmmreg_attach_cnf(GMMREG_AT_COMB); } break; case KERN_GMM_REG_NORMAL_SERVICE: if (attach_cnf_to_be_sent) { kern_gmmreg_attach_cnf(GMMREG_AT_COMB); #ifdef REL99 if (gmm_data->kern.sig_cell_info.sgsnr_flag!= gmm_data->kern.old_sig_cell_info.sgsnr_flag) { PALLOC (mmpm_attach_ind, MMPM_ATTACH_IND); PSEND ( hCommSM, mmpm_attach_ind ); } #endif break; } } GMM_RETURN; } /* kern_gmmreg_cell_ind */ /* +------------------------------------------------------------------------------ | Function : kern_send_llgmm_trigger_req +------------------------------------------------------------------------------ | Description : Sends trigger request with the correct cause value | | Parameters : None | +------------------------------------------------------------------------------ */ GLOBAL void kern_send_llgmm_trigger_req(void) { GMM_TRACE_FUNCTION ("kern_send_llgmm_trigger_req()"); { PALLOC (llgmm_trigger_req, LLGMM_TRIGGER_REQ); #ifdef REL99 /* * If SGSN supports cell notification indicate that LLC * can use NULL frame for performing cell updates. * The first cell notification shouldn't use LLC NULL * frame. The following logic takes care of it. */ switch (gmm_data->cell_notification) /* TCS 4.0 */ { /* TCS 4.0 */ case FIRST_CELL_NOTIFY: /* TCS 4.0 */ /* * Next cell update can use LLC NULL frame */ gmm_data->cell_notification = NOT_FIRST_CELL_NOTIFY; /* TCS 4.0 */ /* * This cell update should not use LLC NULL frame */ llgmm_trigger_req->trigger_cause = LLGMM_TRICS_CELL_UPDATE; break; /* TCS 4.0 */ case NOT_FIRST_CELL_NOTIFY: /* TCS 4.0 */ /* * Cell notification supported and this is not the first cell update. * So LLC NULL frame can be used */ llgmm_trigger_req->trigger_cause = LLGMM_TRICS_CELL_UPDATE_NULL_FRAME; /* TCS 4.0 */ break; /* TCS 4.0 */ default: /* TCS 4.0 */ /* * cell notification not supported by SGSN */ llgmm_trigger_req->trigger_cause = LLGMM_TRICS_CELL_UPDATE; /* TCS 4.0 */ } /* TCS 4.0 */ #else llgmm_trigger_req->trigger_cause = LLGMM_TRICS_CELL_UPDATE; /* TCS 4.0 */ #endif PSEND ( hCommLLC, llgmm_trigger_req ); } GMM_RETURN; } /* kern_send_llgmm_trigger_req */ /* +------------------------------------------------------------------------------ | Function : kern_attach_rau_init +------------------------------------------------------------------------------ | Description : The function kern_attach_rau_init initilize RAU and attach procedure | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_attach_rau_init (void) { GMM_TRACE_FUNCTION( "kern_attach_rau_init" ); /* * PATCH UBUOB 22.7.07: multiple outstanding SIM_AUTHENTICATION_REQ messages * for safety reset the counter whenever a new attachment is started */ gmm_data->kern.auth_cap.last_auth_req_id = NOT_PRESENT_8BIT; /* START PATCH UBUOB ISSUE 8284 */ gmm_data->kern.detach_cap.error_cause = GMMCS_INT_NOT_PRESENT; /* TCS 2.1 */ /* END PATCH UBUOB ISSUE 8284 */ gmm_data->kern.attach_cap.t3310_value=0; vsi_t_stop ( GMM_handle , kern_T3310); /* #5899 */ /* * PATCH UBUOB 25.3.02: Stop timer T3302 when you are trying to ATTACH again * otherwise it may timeout in the middle of the procedure. Also this ATTACH * procedure may be successful and then T3302 also needs to be stopped. */ vsi_t_stop ( GMM_handle , kern_T3302); /* end patch */ /* * PATCH UBUOB 25.10.02: there are cases where T3311 also needs to be stopped: * GMM receives CGRLC_STATUS_IND(access not allowed due to cell change), starts T3311 (TCS 2.1) * GMMRR_CELL_IND(cell changed), RAU restarted, but forgot to stop T3311 * trace 25a_night_cell_change_no_patch */ vsi_t_stop ( GMM_handle , kern_T3311); /* end patch ubuob 25.10.02 */ sig_kern_rdy_stop_t3302_req(); /* * patch ubuob 23.10.02: flag needs to be cleared when initiating RAU or ATTACH * and not at end */ SET_STATE (GU,GU_UPDATE_NOT_NEEDED); /* end patch ubuob */ GMM_RETURN; } /* kern_attach_rau_init */ /* +------------------------------------------------------------------------------ | Function : kern_make_cause +------------------------------------------------------------------------------ | Description : The function kern_make_cause() | | An internal 16 bit cause is generated from the cause received | from the network. The reject causes indicating a retry in a new | cell are translated to a single value. In case no cause was sent | by the network a special internal value is returned to handle this. | | Parameters : valid flag, network cause value | +------------------------------------------------------------------------------ */ GLOBAL USHORT kern_make_cause (BOOL cause_valid, UBYTE network_cause) { GMM_TRACE_FUNCTION ("kern_make_cause"); if (cause_valid) { if (network_cause >= 0x30 AND /* TCS 2.1 */ network_cause <= 0x3F) /* TCS 2.1 */ { /* TCS 2.1 */ GMM_RETURN_ (GMMCS_RETRY_IN_NEW_CELL); /* TCS 2.1 */ } /* TCS 2.1 */ else /* TCS 2.1 */ { /* TCS 2.1 */ GMM_RETURN_ (CAUSE_MAKE (DEFBY_STD, /* TCS 2.1 */ ORIGSIDE_NET, /* TCS 2.1 */ GMM_ORIGINATING_ENTITY, /* TCS 2.1 */ network_cause)); /* TCS 2.1 */ } /* TCS 2.1 */ } else { GMM_RETURN_ (GMMCS_NET_CAUSE_NOT_PRESENT); } } #ifdef GMM_TCS4 /* +------------------------------------------------------------------------------ | Function : kern_make_new_cause +------------------------------------------------------------------------------ | Description : The function kern_make_new_cause() | | An internal 16 bit cause is generated from the cause received | from the network. The reject causes indicating a retry in a new | cell are translated to a single value. In case no cause was sent | by the network a special internal value is returned to handle this. | | Parameters : valid flag, network cause value | +------------------------------------------------------------------------------ */ GLOBAL T_CAUSE_ps_cause kern_make_new_cause ( void ) { T_CAUSE_ps_cause ps_cause; GMM_TRACE_FUNCTION ("kern_make_cause"); ps_cause.ctrl_value = CAUSE_is_from_mm; switch (gmm_data->kern.detach_cap.error_cause) { case GMMCS_INT_NOT_PRESENT: case GMMCS_NET_CAUSE_NOT_PRESENT : case MMCS_INT_NOT_PRESENT: ps_cause.value.mm_cause = CAUSE_MM_NO_ERROR; break; default: ps_cause.ctrl_value = CAUSE_is_from_nwmm; ps_cause.value.nwmm_cause = gmm_data->kern.detach_cap.error_cause&0xff; /* TCS 4.0 */ break; case MMCS_UNSPECIFIED: case GMMCS_INT_PROTOCOL_ERROR: ps_cause.value.mm_cause = CAUSE_MM_PROTOCOL_ERROR; break; case GMMCS_SUCCESS: ps_cause.value.mm_cause = CAUSE_MM_SUCCESS; break; case GMMCS_AAC_UNDER_5: case GMMCS_AAC_OVER_5: ps_cause.value.mm_cause = CAUSE_MM_TRY_TO_UPDATE; break; case MMCS_AUTHENTICATION_REJECTED: case GMMCS_AUTHENTICATION_REJECTED: ps_cause.value.mm_cause = CAUSE_MM_AUTHENTICATION_REJECTED; break; case MMCS_SIM_REMOVED: case GMMCS_SIM_REMOVED: ps_cause.value.mm_cause = CAUSE_MM_SIM_REMOVED; break; case GMMCS_POWER_OFF: ps_cause.value.mm_cause = CAUSE_MM_POWER_OFF; break; case GMMCS_LIMITED_SERVICE: ps_cause.value.mm_cause = CAUSE_MM_LIMITED_SERVICE; break; case MMCS_SUCCESS: ps_cause.value.mm_cause = CAUSE_MM_SUCCESS; break; case MMCS_NO_REGISTRATION: ps_cause.value.mm_cause = CAUSE_MM_NO_REGISTRATION; break; case MMCS_TIMER_RECOVERY: ps_cause.value.mm_cause = CAUSE_MM_TIMER_RECOVERY; break; case MMCS_NO_REESTABLISH: ps_cause.value.mm_cause = CAUSE_MM_NO_REESTABLISH; break; case MMCS_INT_PREEM: ps_cause.value.mm_cause = CAUSE_MM_INT_PREEM; break; case MMCS_PLMN_NOT_IDLE_MODE: ps_cause.value.mm_cause = CAUSE_MM_PLMN_NOT_IDLE_MODE; break; } GMM_RETURN_ (ps_cause); } #endif /* +------------------------------------------------------------------------------ | Function : kern_call_undone_mm_proc_der +------------------------------------------------------------------------------ | Description : This function starts all undone MM procedures after finishing the last | MM procedure | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_call_undone_mm_proc_der ( void ) { GMM_TRACE_FUNCTION( "kern_call_undone_mm_proc_der" ); if (!gmm_data->kern.suspension_type) /* * default branch */ { kern_resume_grr_der(); GMM_RETURN; } if (GMM_SUSP_EM_CALL & gmm_data->kern.suspension_type) { kern_mm_cm_emergency_res(MMGMM_ESTABLISH_OK); } else if (GMM_SUSP_LAU & gmm_data->kern.suspension_type) { kern_mm_lau(); } else if (GMM_SUSP_CALL & gmm_data->kern.suspension_type) { kern_mm_cm_establish_res(MMGMM_ESTABLISH_OK); } else if (GMM_SUSP_IMSI_DETACH & gmm_data->kern.suspension_type) { kern_mm_imsi_detach(); } else if (GMM_SUSP_LOCAL_DETACH & gmm_data->kern.suspension_type) { kern_local_detach ( GMMCS_INT_NOT_PRESENT, FALSE, GMM_LOCAL_DETACH_PROC_NOT_CHANGED); /* TCS 2.1 */ } GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_call_undone_mm_proc_reg +------------------------------------------------------------------------------ | Description : This function starts all undone MM procedures after finishing the last | MM procedure | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_call_undone_mm_proc_reg ( void ) { GMM_TRACE_FUNCTION( "kern_call_undone_mm_proc_reg" ); if (GMM_SUSP_NONE == gmm_data->kern.suspension_type) /* * default branch */ { kern_resume_grr_reg(); GMM_RETURN; } if (GMM_SUSP_EM_CALL & gmm_data->kern.suspension_type) { kern_mm_cm_emergency_res(MMGMM_ESTABLISH_OK); } else if (GMM_SUSP_LAU & gmm_data->kern.suspension_type) { kern_mm_lau(); } else if (GMM_SUSP_CALL & gmm_data->kern.suspension_type) { kern_mm_cm_establish_res(MMGMM_ESTABLISH_OK); } else if (GMM_SUSP_IMSI_DETACH & gmm_data->kern.suspension_type) { kern_mm_imsi_detach(); } else if (GMM_SUSP_LOCAL_DETACH & gmm_data->kern.suspension_type) { kern_local_detach ( GMMCS_INT_NOT_PRESENT, FALSE, GMM_LOCAL_DETACH_PROC_NOT_CHANGED); /* TCS 2.1 */ } GMM_RETURN; } /* +------------------------------------------------------------------------------ | Function : kern_reset_cipher +------------------------------------------------------------------------------ | Description : This function deletes the ciphering parameters | | Parameters : void | +------------------------------------------------------------------------------ */ GLOBAL void kern_reset_cipher ( void ) { GMM_TRACE_FUNCTION( "kern_reset_cipher" ); /* * 3GPP,24.008: * 4.7.7.2 Authentication and ciphering response by the MS * * The RAND and RES values stored in the mobile station shall be deleted: * - if the mobile station enters the GMM states GMM-DEREGISTERED or GMM-NULL. */ /* * 3GPP,24.008: * 4.7.7.4 GPRS ciphering key sequence number * * If the GPRS ciphering key sequence number is deleted, the associated GPRS GSM * ciphering key , GPRS UMTS ciphering key and GPRS UMTS integrity key shall be deleted * (i.e. the established GSM security context or the UMTS security context is no longer * valid). */ TRACE_EVENT ("ciphering OFF"); gmm_data->cipher = FALSE; GMM_RETURN; }