FreeCalypso > hg > fc-tourmaline
view src/g23m-fad/rlp/rlp_kerf.c @ 281:a75eefbf8be4
Phone boot with PWON: weed out short button presses
Every standard end user phone has a design provision, most naturally
implemented in firmware, whereby the PWON button effects a boot only
if it is held down long enough - short presses of this PWON button
are detected, assumed to be spurious and cause the fw to power back off
instead of proceeding with boot. The present change introduces this
standard function in FreeCalypso.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 24 Sep 2021 02:03:08 +0000 |
parents | fa8dc04885d8 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-F&D (8411) | Modul : RLP_KERF +----------------------------------------------------------------------------- | 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 defines the procedures and functions for | the component Radio Link Protocol of the mobile station +----------------------------------------------------------------------------- */ #ifndef RLP_KERF_C #define RLP_KERF_C #endif #define ENTITY_RLP /*==== INCLUDES ===================================================*/ #include <string.h> #include "typedefs.h" #include "pconst.cdg" #include "vsi.h" #include "macdef.h" #include "pconst.cdg" #include "custom.h" #include "gsm.h" #include "cnf_rlp.h" #include "mon_rlp.h" #include "prim.h" #include "pei.h" #include "tok.h" #include "ccdapi.h" #include "rlp.h" /*==== CONST =======================================================*/ /*==== TYPES =======================================================*/ /*==== VAR EXPORT ==================================================*/ /*==== VAR LOCAL ===================================================*/ /*==== FUNCTIONS ===================================================*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_initTRCVS | +--------------------------------------------------------------------+ PURPOSE : Initialise the TCRVS table */ LOCAL void ker_initTRCVS(T_RCVS_ENTRY *rcvsTab) { T_FRAME_NUM lookUp; TRACE_FUNCTION ("ker_initTRCVS()"); for (lookUp = 0; lookUp < MAX_SREJ_COUNT; lookUp++) { rcvsTab[lookUp].isFree = TRUE; rcvsTab[lookUp].slot = INVALID_IDX; rcvsTab[lookUp].trcvs_running = FALSE; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_init | +--------------------------------------------------------------------+ PURPOSE : initialise the rlp data for the kernel process */ GLOBAL void ker_init(void) { TRACE_FUNCTION ("ker_init()"); rlp_data->tul_rcv_running = FALSE; ker_initTRCVS(rlp_data->ker.rcvsTab); rlp_data->ker.DM_State = IS_IDLE; rlp_data->ker.DM_FBit = 0; rbm_reset(&rlp_data->rbm); INIT_STATE(KER, RLP_ADM_AND_DETACHED); INIT_STATE(KERXID_C, ISW_IDLE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_get_xid_data | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_get_xid_data ( T_RLP_FRAMEDATA *raw_data, UBYTE index, T_RLP_XID_IND *xid_data, BOOL ms_is_initiator, ULONG *used_flags ) { UBYTE p_type; UBYTE length; UBYTE comp_request; #ifdef _SIMULATION_ USHORT rcvd; char trc_buf[80]; UBYTE i, idx; strcpy (trc_buf, "get XID "); idx = strlen(trc_buf); #endif TRACE_FUNCTION ("ker_get_xid_data()"); rlp_data->ker.Rlp_Vers = DEF_RLP_VERS; rlp_data->ker.K_ms_iwf = DEF_K_MS_IWF; rlp_data->ker.K_iwf_ms = DEF_K_IWF_MS; rlp_data->ker.T1 = rlp_data->ker.Def_T1; rlp_data->ker.T2 = DEF_T2; rlp_data->ker.N2 = DEF_N2; rlp_data->ker.Pt = DEF_PT; rlp_data->ker.P0 = DEF_P0; rlp_data->ker.P1 = DEF_P1; rlp_data->ker.P2 = DEF_P2; *used_flags = 0L; while (index < rlp_data->ker.FrameSize - HEADER_LEN - TRAILER_LEN) { length = raw_data[index] % 16; p_type = (raw_data[index] - length) / 16; if (p_type EQ XID_T_NULL) break; #ifdef _SIMULATION_ for (i = 0; i < length+1; i++) { /*lint -e661 : Possible access of out-of-bounds pointer (1 beyond end of data) by operator 'unary * */ HEX_BYTE (raw_data[index+i], &trc_buf[idx]); /*lint +e661 */ idx+=2; } #endif switch (p_type) { case XID_T_T1: rlp_data->ker.T1 = TIME_EXT2INT(raw_data[index+1]); #ifdef _SIMULATION_ rcvd = rlp_data->ker.T1; #endif if (rlp_data->ker.T1 < rlp_data->ker.Orig_T1) rlp_data->ker.T1 = rlp_data->ker.Orig_T1; *used_flags |= UF_SET_T1; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID T1 : %d -> %d", rcvd, rlp_data->ker.T1); #endif break; case XID_T_RLP_VERS: rlp_data->ker.Rlp_Vers = raw_data[index+1]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.Rlp_Vers; #endif if (rlp_data->ker.Rlp_Vers > ORIG_RLP_VERS) rlp_data->ker.Rlp_Vers = ORIG_RLP_VERS; *used_flags |= UF_SET_RLP_VERS; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID RLPV : %d -> %d", rcvd, rlp_data->ker.Rlp_Vers); #endif break; case XID_T_T2: rlp_data->ker.T2 = TIME_EXT2INT(raw_data[index+1]); #ifdef _SIMULATION_ rcvd = rlp_data->ker.T2; #endif if (rlp_data->ker.T2 < rlp_data->ker.Orig_T2) rlp_data->ker.T2 = rlp_data->ker.Orig_T2; *used_flags |= UF_SET_T2; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID T2 : %d -> %d", rcvd, rlp_data->ker.T2); #endif break; case XID_T_K_MS_IWF: rlp_data->ker.K_ms_iwf = raw_data[index+1]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.K_ms_iwf; #endif if (rlp_data->ker.K_ms_iwf > rlp_data->ker.Orig_K_ms_iwf) rlp_data->ker.K_ms_iwf = rlp_data->ker.Orig_K_ms_iwf; if (rlp_data->ker.Connected) sbm_set_wind_size (rlp_data->ker.K_ms_iwf); *used_flags |= UF_SET_K_MS_IWF; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID KMI : %d -> %d", rcvd, rlp_data->ker.K_ms_iwf); #endif break; case XID_T_N2: rlp_data->ker.N2 = raw_data[index+1]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.N2; #endif if (rlp_data->ker.N2 < rlp_data->ker.Orig_N2) rlp_data->ker.N2 = rlp_data->ker.Orig_N2; sbm_set_retrans (rlp_data->ker.N2); *used_flags |= UF_SET_N2; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID N2 : %d -> %d", rcvd, rlp_data->ker.N2); #endif break; case XID_T_K_IWF_MS: rlp_data->ker.K_iwf_ms = raw_data[index+1]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.K_iwf_ms; #endif if (rlp_data->ker.K_iwf_ms > rlp_data->ker.Orig_K_iwf_ms) rlp_data->ker.K_iwf_ms = rlp_data->ker.Orig_K_iwf_ms; if (rlp_data->ker.Connected) if (rbm_set_wind_size (rlp_data->ker.K_iwf_ms)) { ker_reset_all_t_rcvs (); srm_reset(); } *used_flags |= UF_SET_K_IWF_MS; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID KIM : %d -> %d", rcvd, rlp_data->ker.K_iwf_ms); #endif break; case XID_T_COMPR: comp_request = raw_data[index+1] % 16; rlp_data->ker.Pt = (raw_data[index+1] - comp_request) / 16; #ifdef _SIMULATION_ TRACE_EVENT_P1("RCVD XID PT : %d", rlp_data->ker.Pt); #endif switch (comp_request) { case 0: rlp_data->ker.P0 = RLP_COMP_DIR_NONE; break; case 1: if (ms_is_initiator) { if (rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_RECEIVE OR rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_NONE) rlp_data->ker.P0 = RLP_COMP_DIR_NONE; else rlp_data->ker.P0 = RLP_COMP_DIR_TRANSMIT; } else { if (rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_TRANSMIT OR rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_NONE) rlp_data->ker.P0 = RLP_COMP_DIR_NONE; else rlp_data->ker.P0 = RLP_COMP_DIR_RECEIVE; } break; case 2: if (ms_is_initiator) { if (rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_TRANSMIT OR rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_NONE) rlp_data->ker.P0 = RLP_COMP_DIR_NONE; else rlp_data->ker.P0 = RLP_COMP_DIR_RECEIVE; } else { if (rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_RECEIVE OR rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_NONE) rlp_data->ker.P0 = RLP_COMP_DIR_NONE; else rlp_data->ker.P0 = RLP_COMP_DIR_TRANSMIT; } break; case 3: rlp_data->ker.P0 = rlp_data->ker.Orig_P0; break; } #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID P0: %d -> %d", comp_request, rlp_data->ker.P0); #endif rlp_data->ker.P1 = (raw_data[index+3] * 256) + raw_data[index+2]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.P1; #endif if (rlp_data->ker.P1 > rlp_data->ker.Orig_P1) rlp_data->ker.P1 = rlp_data->ker.Orig_P1; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID P1: %d -> %d", rcvd, rlp_data->ker.P1); #endif rlp_data->ker.P2 = raw_data[index+4]; #ifdef _SIMULATION_ rcvd = rlp_data->ker.P2; #endif if (rlp_data->ker.P2 > rlp_data->ker.Orig_P2) rlp_data->ker.P2 = rlp_data->ker.Orig_P2; *used_flags |= UF_SET_COMPR; #ifdef _SIMULATION_ TRACE_EVENT_P2("RCVD XID P2 : %d -> %d", rcvd, rlp_data->ker.P2); #endif break; } index += (length+1); } xid_data->rlp_vers = rlp_data->ker.Rlp_Vers; xid_data->k_ms_iwf = rlp_data->ker.K_ms_iwf; xid_data->k_iwf_ms = rlp_data->ker.K_iwf_ms; xid_data->t1 = TIME_INT2EXT (rlp_data->ker.T1); xid_data->t2 = TIME_INT2EXT (rlp_data->ker.T2); xid_data->n2 = rlp_data->ker.N2; xid_data->pt = rlp_data->ker.Pt; xid_data->p0 = rlp_data->ker.P0; xid_data->p1 = rlp_data->ker.P1; xid_data->p2 = rlp_data->ker.P2; #ifdef _SIMULATION_ trc_buf[idx] = '\0'; TRACE_EVENT (trc_buf); #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_put_xid_data | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_put_xid_data ( T_RLP_FRAMEPTR l_Data, /* buffer for data */ UBYTE index, /* start index in buffer */ ULONG l_uf, /* valid parameters */ BOOL ms_is_initiator, /* MS is sending XID*/ UBYTE l_rlp_version, /* negotiated vers. */ T_FRAME_NUM l_k_iwf_ms, /* winSize ms->iwf */ T_FRAME_NUM l_k_ms_iwf, /* winSize iwf->ms */ USHORT l_t1, /* ack timer value */ UBYTE l_n2, /* num restransmiss */ USHORT l_t2, /* reply delay */ UBYTE l_pt, /* type data compr. */ UBYTE l_p0, /* v42bis comp. req */ USHORT l_p1, /* num possible code*/ UBYTE l_p2 /* max encod. strlen*/ ) { register ULONG i; TRACE_FUNCTION ("ker_put_xid_data()"); i = index; if (((l_uf & UF_SET_RLP_VERS) EQ 0) OR (l_rlp_version < 1)) { l_uf &= ~UF_SET_COMPR; } if (l_uf & UF_SET_RLP_VERS) { l_Data[i] = (XID_T_RLP_VERS * 16) + XID_L_RLP_VERS; l_Data[i+1] = l_rlp_version; #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID RLPV : %d", l_rlp_version); #endif i += (XID_L_RLP_VERS + 1); } if (l_uf & UF_SET_K_IWF_MS) { l_Data[i] = (XID_T_K_IWF_MS * 16) + XID_L_K_IWF_MS; l_Data[i+1] = (UBYTE) l_k_iwf_ms; #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID KIM : %d", l_k_iwf_ms); #endif i += (XID_L_K_IWF_MS + 1); } if (l_uf & UF_SET_K_MS_IWF) { l_Data[i] = (XID_T_K_MS_IWF * 16) + XID_L_K_MS_IWF; l_Data[i+1] = (UBYTE) l_k_ms_iwf; #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID KMI : %d", l_k_ms_iwf); #endif i += (XID_L_K_MS_IWF + 1); } if (l_uf & UF_SET_T1) { l_Data[i] = (XID_T_T1 * 16) + XID_L_T1; l_Data[i+1] = TIME_INT2EXT (l_t1); #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID T1 : %d", l_t1); #endif i += (XID_L_T1 + 1); } if (l_uf & UF_SET_N2) { l_Data[i] = (XID_T_N2 * 16) + XID_L_N2; l_Data[i+1] = l_n2; #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID N2 : %d", l_n2); #endif i += (XID_L_N2 + 1); } if (l_uf & UF_SET_T2) { l_Data[i] = (XID_T_T2 * 16) + XID_L_T2; l_Data[i+1] = TIME_INT2EXT (l_t2); #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID T2 : %d", l_t2); #endif i += (XID_L_T2 + 1); } if ( (l_uf & UF_SET_COMPR) AND !rlp_data->ker.Connected) { l_Data[i] = (XID_T_COMPR * 16) + XID_L_COMPR; switch (l_p0) { case RLP_COMP_DIR_NONE: l_Data[i+1] = l_pt * 16; break; case RLP_COMP_DIR_TRANSMIT: if (ms_is_initiator) l_Data[i+1] = (l_pt*16) + 1; else l_Data[i+1] = (l_pt*16) + 2; break; case RLP_COMP_DIR_RECEIVE: if (ms_is_initiator) l_Data[i+1] = (l_pt*16) + 2; else l_Data[i+1] = (l_pt*16) + 1; break; case RLP_COMP_DIR_BOTH: l_Data[i+1] = (l_pt*16) + 3; break; } l_Data[i+2] = (l_p1 % 256); l_Data[i+3] = (l_p1 / 256); l_Data[i+4] = l_p2; #ifdef _SIMULATION_ TRACE_EVENT_P1("SEND XID PT: %d", l_pt); TRACE_EVENT_P2("SEND XID P0: %d -> %d", l_p0, l_Data[i+1] % 4); TRACE_EVENT_P1("SEND XID P1: %d", l_p1); TRACE_EVENT_P1("SEND XID P2: %d", l_p2); #endif i += (XID_L_COMPR + 1); } #ifdef _SIMULATION_ { char trc_buf[80]; U8 j, k; strcpy (trc_buf, "put XID "); k = strlen(trc_buf); for (j = index; j < i; j++) { /*lint -e661 : Possible access of out-of-bounds pointer (1 beyond end of data) by operator 'unary * */ HEX_BYTE (l_Data[j], &trc_buf[k]); /*lint +e661 */ k += 2; } trc_buf[k] = '\0'; TRACE_EVENT (trc_buf); } #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_check_low_water | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_check_low_water(void) { TRACE_FUNCTION ("ker_check_low_water()"); if (sbm_space_in_buf () >= rlp_data->ker.FramesPerPrim) { if (rlp_data->ker.UL_Snd_State EQ IW_IDLE) { PALLOC (rlp_ready_ind, RLP_READY_IND); PSENDX (L2R, rlp_ready_ind); rlp_data->ker.UL_Snd_State = IW_WAIT; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_get_send_frame | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_get_send_frame ( T_FRAME_DESC *frameDesc, T_FRAME_NUM *frameNo, BOOL *frameFound ) { BOOL framesCouldBeSent; TRACE_FUNCTION ("ker_get_send_frame()"); if (rlp_data->ker.RRReady) { sbm_get_frame ( frameDesc, frameNo, &framesCouldBeSent, frameFound ); if (framesCouldBeSent) ker_check_low_water (); } else { /* * remote receiver can not accept data */ *frameFound = FALSE; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_startTRCVS | +--------------------------------------------------------------------+ PURPOSE : Start the timer TRCVS for a slot */ LOCAL void ker_startTRCVS(T_FRAME_NUM slot) { T_FRAME_NUM lookUp; TRACE_FUNCTION ("ker_startTRCVS()"); for (lookUp = 0; lookUp < MAX_SREJ_COUNT; lookUp++) { if (rlp_data->ker.rcvsTab[lookUp].isFree) { rlp_data->ker.rcvsTab[lookUp].slot = slot; TIMERSTART(lookUp, rlp_data->ker.T1); rlp_data->ker.rcvsTab[lookUp].trcvs_running = TRUE; rlp_data->ker.rcvsTab[lookUp].isFree = FALSE; return; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_srej_sreji_cmd | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_srej_sreji_cmd(T_FRAME_NUM slot) { T_FRAME_DESC frameDesc; T_FRAME_NUM frame; BOOL frameFound; rlp_data->ker.DTX_SF = DTX_N; TRACE_FUNCTION ("ker_send_srej_sreji_cmd()"); if (rlp_data->ker.Poll_xchg NEQ IW_WAIT AND rlp_data->ker.Poll_State EQ ISW_SEND) { sig_ker_snd_srej_req (1, 1, slot); rbm_set_rslot_wait (slot); ker_startTRCVS (slot); srm_count (slot); rlp_data->ker.SREJ_Count++; rlp_data->ker.Poll_Count++; rlp_data->ker.Poll_State = ISW_WAIT; rlp_data->ker.Poll_xchg = IW_WAIT; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { ker_get_send_frame (&frameDesc, &frame, &frameFound); if (frameFound) { sig_ker_snd_srej_i_req (1, 0, slot, frame, &frameDesc); rbm_set_rslot_wait (slot); ker_startTRCVS (slot); srm_count (slot); rlp_data->ker.SREJ_Count++; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { sig_ker_snd_srej_req (1, 0, slot); rbm_set_rslot_wait (slot); ker_startTRCVS (slot); srm_count (slot); rlp_data->ker.SREJ_Count++; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rej_reji_cmd | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_rej_reji_cmd ( T_FRAME_NUM vr ) { T_FRAME_DESC frameDesc; T_FRAME_NUM frame; BOOL frameFound; TRACE_FUNCTION ("ker_send_rej_reji_cmd()"); rlp_data->ker.DTX_SF = DTX_N; if (rlp_data->ker.Poll_xchg NEQ IW_WAIT AND rlp_data->ker.Poll_State EQ ISW_SEND) { sig_ker_snd_rej_req (1, 1, vr); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.REJ_State = ISW_WAIT; TIMERSTART ( TRCVR_HANDLE, rlp_data->ker.T1 ); rlp_data->ker.Poll_Count++; rlp_data->ker.Poll_State = ISW_WAIT; rlp_data->ker.Poll_xchg = IW_WAIT; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { ker_get_send_frame (&frameDesc, &frame, &frameFound); if (frameFound) { sig_ker_snd_rej_i_req (1, 0, vr, frame, &frameDesc); TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else sig_ker_snd_rej_req (1, 0, vr); TIMERSTART(TRCVR_HANDLE, rlp_data->ker.T1); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.REJ_State = ISW_WAIT; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rnr_rnri_cmd | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_rnr_rnri_cmd ( T_FRAME_NUM vr ) { T_FRAME_DESC frameDesc; T_FRAME_NUM frame; BOOL frameFound; TRACE_FUNCTION ("ker_send_rnr_rnri_cmd()"); if (rlp_data->ker.Poll_xchg NEQ IW_WAIT AND rlp_data->ker.Poll_State EQ ISW_SEND) { sig_ker_snd_rnr_req (1, 1, vr, 0); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.Poll_Count++; rlp_data->ker.Poll_State = ISW_WAIT; rlp_data->ker.Poll_xchg = IW_WAIT; rlp_data->ker.DTX_SF = DTX_N; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { ker_get_send_frame (&frameDesc, &frame, &frameFound); if (frameFound) { sig_ker_snd_rnr_i_req (1, 0, vr, frame, &frameDesc); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.DTX_SF = DTX_N; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { if (rlp_data->ker.Ackn_State EQ IS_IDLE AND rlp_data->ker.DTX_SF EQ DTX_RNR AND rlp_data->ker.DTX_VR EQ vr) { sig_ker_snd_rnr_req (1, 0, vr, 1); } else { sig_ker_snd_rnr_req (1, 0, vr, 0); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.DTX_SF = DTX_RNR; rlp_data->ker.DTX_VR = vr; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rr_rri_cmd | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_rr_rri_cmd ( T_FRAME_NUM vr ) { T_FRAME_DESC frameDesc; T_FRAME_NUM frame; BOOL frameFound; TRACE_FUNCTION ("ker_send_rr_rri_cmd()"); if (rlp_data->ker.Poll_xchg NEQ IW_WAIT AND rlp_data->ker.Poll_State EQ ISW_SEND) { #ifdef ENABLE_DTX sig_ker_snd_rr_req (1, 1, vr, 0); #else sig_ker_snd_rr_req (1, 1, vr); #endif rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.Poll_Count++; rlp_data->ker.Poll_State = ISW_WAIT; rlp_data->ker.Poll_xchg = IW_WAIT; rlp_data->ker.DTX_SF = DTX_N; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); } else { ker_get_send_frame (&frameDesc, &frame, &frameFound); if (frameFound) { sig_ker_snd_rr_i_req (1, 0, vr, frame, &frameDesc); rlp_data->ker.Ackn_State = IS_IDLE; TIMERSTART (TT_HANDLE, rlp_data->ker.T1); rlp_data->ker.DTX_SF = DTX_N; } else { if (rlp_data->ker.Ackn_State EQ IS_IDLE AND rlp_data->ker.DTX_SF EQ DTX_RR AND rlp_data->ker.DTX_VR EQ vr) { #ifdef ENABLE_DTX sig_ker_snd_rr_req (1, 0, vr, 1); #else sig_ker_snd_rr_req (1, 0, vr); #endif } else { #ifdef ENABLE_DTX sig_ker_snd_rr_req (1, 0, vr, 0); #else sig_ker_snd_rr_req (1, 0, vr); #endif rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.DTX_SF = DTX_RR; rlp_data->ker.DTX_VR = vr; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rnr_rnri_resp | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_rnr_rnri_resp ( T_FRAME_NUM vr ) { TRACE_FUNCTION ("ker_send_rnr_rnri_resp()"); sig_ker_snd_rnr_req (0, 1, vr, 0); rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.Ackn_FBit = 0; rlp_data->ker.DTX_SF = DTX_N; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rr_rri_resp | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_send_rr_rri_resp(T_FRAME_NUM vr) { TRACE_FUNCTION ("ker_send_rr_rri_resp()"); #ifdef ENABLE_DTX sig_ker_snd_rr_req (0, 1, vr, 0); #else sig_ker_snd_rr_req (0, 1, vr); #endif rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.Ackn_FBit = 0; rlp_data->ker.DTX_SF = DTX_N; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_copy_frame_to_sdu | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_copy_frame_to_sdu ( T_RLP_FRAMEPTR frame, T_sdu *sdu ) { TRACE_FUNCTION ("ker_copy_frame_to_sdu()"); memcpy (sdu->buf+(sdu->o_buf>>3), frame, rlp_data->ker.FrameSize); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_copy_sdu_to_frame | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_copy_sdu_to_frame(T_sdu *sdu, T_RLP_FRAMEPTR frame, USHORT n) { TRACE_FUNCTION ("ker_copy_sdu_to_frame()"); memcpy(frame, sdu->buf + (sdu->o_buf>>3) + (n * rlp_data->ker.FrameSize), rlp_data->ker.FrameSize); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_get_frame_desc | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_get_frame_desc ( T_RLP_FRAMEPTR frame, T_FRAME_DESC *frameDesc ) { TRACE_FUNCTION ("ker_get_frame_desc()"); frameDesc->Adr[0] = frame; frameDesc->Len[0] = rlp_data->ker.FrameSize; frameDesc->Adr[1] = (UBYTE *) NULL; frameDesc->Len[1] = 0; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_handle_prim_send | +--------------------------------------------------------------------+ PURPOSE : */ LOCAL void ker_handle_prim_send(void) { TRACE_FUNCTION ("ker_handle_prim_send()"); if (rlp_data->ker.UL_Rcv_State EQ IW_WAIT) { T_RLP_DATA_IND *rlp_data_ind; rbm_get_prim(&rlp_data_ind, &rlp_data->ker.LRReady, &rlp_data->ker.LRFull); PSENDX (L2R, rlp_data_ind); rlp_data->ker.UL_Rcv_State = IW_IDLE; TIMERSTOP (TUL_RCV_HANDLE); rlp_data->tul_rcv_running = FALSE; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_stopTRCVS | +--------------------------------------------------------------------+ PURPOSE : search the rcvs entry for a given timer handle. The function stops the timer and returns the corresponding slot. */ LOCAL void ker_stopTRCVS ( T_FRAME_NUM slot ) { T_FRAME_NUM lookUp; TRACE_FUNCTION ("ker_stopTRCVS()"); for (lookUp = 0; lookUp < MAX_SREJ_COUNT; lookUp++) { if (!rlp_data->ker.rcvsTab[lookUp].isFree AND rlp_data->ker.rcvsTab[lookUp].slot EQ slot) { TIMERSTOP(lookUp); rlp_data->ker.rcvsTab[lookUp].trcvs_running = FALSE; rlp_data->ker.rcvsTab[lookUp].isFree = TRUE; return; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_i_handler | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL BOOL ker_i_handler(T_FRAME_NUM ns) { TRACE_FUNCTION ("ker_i_handler()"); if (rlp_data->ker.LRFull) { /* * ignore improper frame * cBit and fBit are not considered * at this stage */ return TRUE; } else { BOOL valid, expected, resetTimer, primToSend; T_FRAME_NUM count; rbm_ns_check (ns, &valid, &expected); /* * ns not within window? */ if (!valid) { /* * ignore improper frame */ return TRUE; } TIMERSTOP (TUL_RCV_HANDLE); /* optimisation trial... */ /* TRACE_EVENT("TIMERSTART TUL_RCV ker_i_handler"); */ TIMERSTART(TUL_RCV_HANDLE, rlp_data->ker.T_ul); if (expected) { rbm_accept_current_frame (); rbm_set_rslot_rcvd (ns, &resetTimer); if (resetTimer) { ker_stopTRCVS (ns); rlp_data->ker.SREJ_Count--; srm_clear (ns); } rbm_buffer_all_in_sequence_frames ( ns, &primToSend, &rlp_data->ker.LRReady, &rlp_data->ker.LRFull ); if (primToSend) ker_handle_prim_send (); rlp_data->ker.REJ_State = ISW_IDLE; TIMERSTOP (TRCVR_HANDLE); rlp_data->ker.Ackn_State = IS_SEND; return FALSE; } else { if (rlp_data->ker.REJ_State NEQ ISW_IDLE) return TRUE; /* * ignore out of sequence frames */ rbm_count_missing_i_frames (ns, &count); if (rlp_data->ker.SREJ_Count + (count-1) <=MAX_SREJ_COUNT) { rbm_move_current_frame (ns); rbm_set_rslot_rcvd (ns, &resetTimer); if (resetTimer) { ker_stopTRCVS (ns); rlp_data->ker.SREJ_Count--; srm_clear (ns); } rbm_mark_missing_i_frames_srej (ns); return FALSE; } else { rlp_data->ker.REJ_State = ISW_SEND; return FALSE; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_init_link_vars | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_init_link_vars ( void ) { TRACE_FUNCTION ("ker_init_link_vars()"); rlp_data->ker.UL_Rcv_State = IW_IDLE; rlp_data->ker.UL_Snd_State = IW_IDLE; rlp_data->ker.Ackn_State = IS_IDLE; rlp_data->ker.Poll_State = ISW_IDLE; rlp_data->ker.Poll_Count = 0; rlp_data->ker.Poll_xchg = IW_IDLE; rlp_data->ker.REJ_State = ISW_IDLE; rlp_data->ker.SABM_State = ISW_IDLE; rlp_data->ker.DISC_State = ISW_IDLE; rlp_data->ker.RRReady = TRUE; rlp_data->ker.LRReady = TRUE; rlp_data->ker.LRFull = FALSE; rlp_data->ker.SREJ_Count = 0; rlp_data->ker.Connected = TRUE; rlp_data->ker.DTX_SF = DTX_N; sbm_init ( rlp_data->ker.K_ms_iwf, rlp_data->ker.FrameSize, rlp_data->ker.N2 ); rbm_init ( rlp_data->ker.K_iwf_ms, rlp_data->ker.FrameSize, rlp_data->ker.FramesPerPrim ); srm_init (); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_requestxid | +--------------------------------------------------------------------+ PURPOSE : This function is invoked to request an XID command. Some variables are set, so that with next RA_READY_IND a XID command is sent. */ LOCAL void ker_requestxid(void) { TRACE_FUNCTION ("ker_requestxid()"); SET_STATE(KERXID_C, ISW_SEND); rlp_data->ker.XID_Count = 0; rlp_data->ker.XID_C_PBit = 1; ker_put_xid_data ( rlp_data->ker.XID_C_Frame + HEADER_LEN, 0, UF_ALL, TRUE, ORIG_RLP_VERS, rlp_data->ker.Orig_K_iwf_ms, rlp_data->ker.Orig_K_ms_iwf, rlp_data->ker.Orig_T1, rlp_data->ker.Orig_N2, rlp_data->ker.Orig_T2, rlp_data->ker.Orig_Pt, rlp_data->ker.Orig_P0, rlp_data->ker.Orig_P1, rlp_data->ker.Orig_P2 ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERP | | STATE : code ROUTINE : ker_init_xid_data | +--------------------------------------------------------------------+ PURPOSE : initialize XID data from attach request */ GLOBAL void ker_init_xid_data ( T_RLP_ATTACH_REQ *rlp_attach_req ) { TRACE_FUNCTION ("ker_init_xid_data()"); rlp_data->ker.Orig_K_ms_iwf = (U8)rlp_attach_req->k_ms_iwf; rlp_data->ker.K_ms_iwf = DEF_K_MS_IWF; rlp_data->ker.Orig_K_iwf_ms = (U8)rlp_attach_req->k_iwf_ms; rlp_data->ker.K_iwf_ms = DEF_K_IWF_MS; rlp_data->ker.Orig_T1 = TIME_EXT2INT (rlp_attach_req->t1); rlp_data->ker.T1 = rlp_data->ker.Def_T1; /* * >>>> According to GSM 11.10 V4.17.1 and V5.4.0 the default value must be used. * >>>> Later versions specify, that the value is used, which MS wants to negotiate. */ /* use t1 immediately without negotiation, if it is greater than the default */ /* if (rlp_data->ker.Orig_T1 > rlp_data->ker.T1) { rlp_data->ker.T1 = rlp_data->ker.Orig_T1; } */ /* rlp_data->ker.Orig_T2 = TIME_EXT2INT (rlp_attach_req->t2); */ rlp_data->ker.Orig_T2 = 200; rlp_data->ker.T2 = DEF_T2; rlp_data->ker.Orig_N2 = rlp_attach_req->n2; rlp_data->ker.N2 = DEF_N2; rlp_data->ker.Orig_Pt = rlp_attach_req->pt; rlp_data->ker.Pt = DEF_PT; rlp_data->ker.Orig_P0 = rlp_attach_req->p0; rlp_data->ker.P0 = DEF_P0; rlp_data->ker.Orig_P1 = rlp_attach_req->p1; rlp_data->ker.P1 = DEF_P1; rlp_data->ker.Orig_P2 = rlp_attach_req->p2; rlp_data->ker.P2 = DEF_P2; rlp_data->ker.Rlp_Vers = ORIG_RLP_VERS; if( !(rlp_data->ker.Orig_P0 EQ RLP_COMP_DIR_NONE AND rlp_data->ker.Orig_K_ms_iwf EQ DEF_K_MS_IWF AND rlp_data->ker.Orig_K_iwf_ms EQ DEF_K_IWF_MS AND rlp_data->ker.Orig_T1 EQ rlp_data->ker.Def_T1 AND /* rlp_data->ker.Orig_T2 EQ DEF_T2 AND */ rlp_data->ker.Orig_N2 EQ DEF_N2 AND rlp_data->ker.Orig_Pt EQ DEF_PT AND rlp_data->ker.Orig_P0 EQ DEF_P0 AND rlp_data->ker.Orig_P1 EQ DEF_P1 AND rlp_data->ker.Orig_P2 EQ DEF_P2 )) { ker_requestxid (); } else { PALLOC (rlp_xid_ind, RLP_XID_IND); rlp_xid_ind->rlp_vers = rlp_data->ker.Rlp_Vers; rlp_xid_ind->k_ms_iwf = rlp_data->ker.K_ms_iwf; rlp_xid_ind->k_iwf_ms = rlp_data->ker.K_iwf_ms; rlp_xid_ind->t1 = TIME_INT2EXT (rlp_data->ker.T1); rlp_xid_ind->t2 = TIME_INT2EXT (rlp_data->ker.T2); rlp_xid_ind->n2 = rlp_data->ker.N2; rlp_xid_ind->pt = rlp_data->ker.Pt; rlp_xid_ind->p0 = rlp_data->ker.P0; rlp_xid_ind->p1 = rlp_data->ker.P1; rlp_xid_ind->p2 = rlp_data->ker.P2; PSENDX (L2R, rlp_xid_ind); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_trace_rlp_frame | +--------------------------------------------------------------------+ PURPOSE : traces the elements from the given RLP frame */ #ifdef TRACE_RLP_FRAME GLOBAL void ker_trace_rlp_frame ( T_RLP_FRAMEPTR frame ) { T_BIT cBit; T_BIT pFBit; T_FRAME_NUM nr; T_FRAME_NUM ns; T_RLP_DEBUG *deb = &rlp_data->deb; TRACE_FUNCTION ("ker_trace_rlp_frame()"); cBit = (T_BIT) (frame[0] & 1); ns = (T_FRAME_NUM) ((frame[0] >> 3) | ((frame[1] & 1)<<5)); pFBit = (T_BIT) ((frame[1] & 2)>>1); deb->idx=0; deb->trc_buf[deb->idx++] = 'U'; deb->trc_buf[deb->idx++] = ':'; switch (ns) { case 62: /* S-Frame */ { T_SF sFrame; nr = (T_FRAME_NUM) ((frame[1]>>2) & 0x3f); deb->trc_buf[deb->idx++] = 'S'; deb->trc_buf[deb->idx++] = 'r'; DEC_BYTE (nr, &deb->trc_buf[deb->idx]); deb->idx+=3; deb->trc_buf[deb->idx++] = ' '; sFrame = (T_SF) ((frame[0]>>1) & 0x03); /* * maybe optimize with a table!! */ switch (sFrame) { case SF_RR: memcpy(&deb->trc_buf[deb->idx], "RR ",3); break; case SF_RNR: memcpy(&deb->trc_buf[deb->idx], "RNR",3); break; case SF_REJ: memcpy(&deb->trc_buf[deb->idx], "REJ",3); break; case SF_SREJ: memcpy(&deb->trc_buf[deb->idx], "SRJ",3); break; default: memcpy(&deb->trc_buf[deb->idx], "***",3); break; } deb->idx+=3; break; } case 63: /* U-Frame */ { T_UF uFrame; uFrame = (T_UF) ((frame[1]>>2) & 0x1f); deb->trc_buf[deb->idx++] = 'U'; deb->trc_buf[deb->idx++] = ' '; /* * maybe optimize with a table!! */ switch (uFrame) { case UF_NULL: return; case UF_UI: memcpy(&deb->trc_buf[deb->idx], "UI ",4); break; case UF_DM: memcpy(&deb->trc_buf[deb->idx], "DM ",4); break; case UF_SABM: memcpy(&deb->trc_buf[deb->idx], "SABM",4); break; case UF_DISC: memcpy(&deb->trc_buf[deb->idx], "DISC",4); break; case UF_UA: memcpy(&deb->trc_buf[deb->idx], "UA ",4); break; case UF_XID: memcpy(&deb->trc_buf[deb->idx], "XID ",4); break; case UF_TEST: memcpy(&deb->trc_buf[deb->idx], "TEST",4); break; case UF_REMAP: memcpy(&deb->trc_buf[deb->idx], "RMAP",4); break; default: memcpy(&deb->trc_buf[deb->idx], "****",4); break; } nr = 0; deb->idx += 4; break; } default: /* I+S-Frame */ { T_SF sFrame; nr = (T_FRAME_NUM) ((frame[1]>>2) & 0x3f); sFrame = (T_SF) ((frame[0]>>1) & 0x03); deb->trc_buf[deb->idx++] = 'I'; deb->trc_buf[deb->idx++] = 'r'; DEC_BYTE (nr, &deb->trc_buf[deb->idx]); deb->idx+=3; deb->trc_buf[deb->idx++] = 's'; DEC_BYTE (ns, &deb->trc_buf[deb->idx]); deb->idx+=3; deb->trc_buf[deb->idx++] = ' '; /* * maybe optimize with a table!! */ switch (sFrame) { case SF_RR: memcpy(&deb->trc_buf[deb->idx], "RR ",3); break; case SF_RNR: memcpy(&deb->trc_buf[deb->idx], "RNR",3); break; case SF_REJ: memcpy(&deb->trc_buf[deb->idx], "REJ",3); break; case SF_SREJ: memcpy(&deb->trc_buf[deb->idx], "SRJ",3); break; default: memcpy(&deb->trc_buf[deb->idx], "***",3); break; } deb->idx += 3; break; } } deb->trc_buf[deb->idx++] = ' '; deb->trc_buf[deb->idx++] = ((cBit) ? 'C' : 'R'); deb->trc_buf[deb->idx++] = ((cBit) ? 'P' : 'F'); deb->trc_buf[deb->idx++] = ' '; HEX_BYTE (frame[1], &deb->trc_buf[deb->idx]); deb->idx+=2; HEX_BYTE (frame[0], &deb->trc_buf[deb->idx]); deb->idx+=2; deb->trc_buf[deb->idx++] = ' '; HEX_BYTE (frame[2], &deb->trc_buf[deb->idx]); deb->idx+=2; HEX_BYTE (frame[3], &deb->trc_buf[deb->idx]); deb->idx+=2; deb->trc_buf[deb->idx] = '\0'; TRACE_EVENT (deb->trc_buf); } #endif /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_resetTRCVS | +--------------------------------------------------------------------+ PURPOSE : Resets all running timer in the TCRVS table */ LOCAL void ker_resetTRCVS ( void ) { T_FRAME_NUM lookUp; TRACE_FUNCTION ("ker_resetTRCVS()"); for (lookUp = 0; lookUp < MAX_SREJ_COUNT; lookUp++) { if (!rlp_data->ker.rcvsTab[lookUp].isFree AND rlp_data->ker.rcvsTab[lookUp].trcvs_running) { TIMERSTOP (lookUp); rlp_data->ker.rcvsTab[lookUp].trcvs_running = FALSE; rlp_data->ker.rcvsTab[lookUp].isFree = TRUE; rlp_data->ker.rcvsTab[lookUp].slot = INVALID_IDX; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_reset_all_t_rcvs | +--------------------------------------------------------------------+ PURPOSE : Resets the timer for each rcvs slot. */ GLOBAL void ker_reset_all_t_rcvs ( void ) { TRACE_FUNCTION ("ker_reset_all_t_rcvs()"); ker_resetTRCVS (); rlp_data->ker.SREJ_Count = 0; srm_reset (); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_s_handler | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_s_handler ( T_BIT cBit, T_BIT pFBit, T_SF sf, T_FRAME_NUM nr, BOOL *retransError ) { BOOL allFramesAck = FALSE; TRACE_FUNCTION ("ker_s_handler()"); *retransError = FALSE; if (cBit EQ 1 AND pFBit EQ 1) { rlp_data->ker.Ackn_State = IS_SEND; rlp_data->ker.Ackn_FBit = 1; rbm_reset_all_r_states (); ker_reset_all_t_rcvs (); rlp_data->ker.REJ_State = ISW_IDLE; TIMERSTOP (TRCVR_HANDLE); } if (rlp_data->ker.Poll_State NEQ ISW_IDLE) { if (pFBit EQ 0 OR sf EQ SF_REJ OR sf EQ SF_SREJ ) return; sbm_rej_from_n (nr, retransError); rlp_data->ker.Poll_State = ISW_IDLE; rlp_data->ker.Poll_xchg = IW_IDLE; rlp_data->ker.Poll_Count = 0; if (*retransError) { ker_reset_all_t_rcvs (); rbm_reset_srej_slots (); TIMERSTOP (TRCVR_HANDLE); TIMERSTOP (TT_HANDLE); rlp_data->ker.DISC_State = ISW_SEND; rlp_data->ker.DISC_Count = 0; if (rlp_data->ker.Poll_xchg EQ IW_IDLE) rlp_data->ker.DISC_PBit = 1; else rlp_data->ker.DISC_PBit = 0; ker_deinit_link_vars(); rlp_data->ker.DISC_Ind = TRUE; return; } } switch (sf) { case SF_RR: allFramesAck = sbm_ack_upto_n(nr); if (rlp_data->ker.RRReady EQ FALSE) { TRACE_EVENT ("Remote RR"); } rlp_data->ker.RRReady = TRUE; break; case SF_RNR: allFramesAck = sbm_ack_upto_n(nr); if (rlp_data->ker.RRReady EQ TRUE) { TRACE_EVENT ("Remote RNR"); } rlp_data->ker.RRReady = FALSE; break; case SF_REJ: allFramesAck = sbm_ack_upto_n(nr); sbm_rej_from_n (nr, retransError); if(*retransError) { ker_reset_all_t_rcvs (); rbm_reset_srej_slots (); TIMERSTOP (TRCVR_HANDLE); TIMERSTOP (TT_HANDLE); rlp_data->ker.DISC_State = ISW_SEND; rlp_data->ker.DISC_Count = 0; if (rlp_data->ker.Poll_xchg EQ IW_IDLE) rlp_data->ker.DISC_PBit = 1; else rlp_data->ker.DISC_PBit = 0; ker_deinit_link_vars(); rlp_data->ker.DISC_Ind = TRUE; return; } if (rlp_data->ker.RRReady EQ FALSE) { TRACE_EVENT ("Remote RR"); } rlp_data->ker.RRReady = TRUE; break; case SF_SREJ: sbm_srej_frame (nr); TIMERSTOP (TT_HANDLE); return; } if (allFramesAck) { TIMERSTOP (TT_HANDLE); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_data | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_send_data(void) { T_EXT_FRAME_NUM slot; T_FRAME_NUM vr; TRACE_FUNCTION ("ker_send_data()"); if (rlp_data->ker.UA_State EQ IS_SEND) { sig_ker_snd_ua_req (rlp_data->ker.UA_FBit); rlp_data->ker.UA_State = IS_IDLE; } else { vr = rbm_get_vr(); if (rlp_data->ker.Ackn_FBit EQ 1) { if (rlp_data->ker.LRReady) ker_send_rr_rri_resp (vr); else ker_send_rnr_rnri_resp (vr); } else { switch (rlp_data->ker.REJ_State) { case ISW_SEND: ker_send_rej_reji_cmd (vr); break; default: slot = rbm_check_slots_srej(); if (slot EQ INVALID_IDX) { if (rlp_data->ker.LRReady) ker_send_rr_rri_cmd (vr); else ker_send_rnr_rnri_cmd (vr); } else ker_send_srej_sreji_cmd (slot); break; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_txu | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL BOOL ker_send_txu ( void ) { TRACE_FUNCTION ("ker_send_txu()"); if (rlp_data->ker.TEST_R_State EQ IS_SEND) { sig_ker_snd_test_req ( 0, rlp_data->ker.TEST_R_FBit, &rlp_data->ker.TEST_R_FrameDesc ); rlp_data->ker.TEST_R_State = IS_IDLE; return TRUE; } if (rlp_data->ker.XID_R_State EQ IS_SEND) { TRACE_EVENT ("Snd XID R"); sig_ker_snd_xid_req ( 0, 1, &rlp_data->ker.XID_R_FrameDesc ); rlp_data->ker.XID_R_State = IS_IDLE; return TRUE; } if (GET_STATE(KERXID_C) EQ ISW_SEND) { if (rlp_data->ker.Poll_xchg NEQ IW_WAIT) { TRACE_EVENT ("Snd XID C"); sig_ker_snd_xid_req ( 1, 1, &rlp_data->ker.XID_C_FrameDesc ); SET_STATE(KERXID_C, ISW_WAIT); TIMERSTART(TXID_HANDLE, rlp_data->ker.T1); rlp_data->ker.Poll_xchg = IW_WAIT; return TRUE; } } if (rlp_data->ker.UI_State EQ IS_SEND) { sig_ker_snd_ui_req ( 1, 0, &rlp_data->ker.UI_FrameDesc ); rlp_data->ker.UI_State = IS_IDLE; return TRUE; } return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_deinit_link_vars | +--------------------------------------------------------------------+ PURPOSE : deinitialize send/receive buffer manager, */ GLOBAL void ker_deinit_link_vars ( void ) { TRACE_FUNCTION ("ker_deinit_link_vars()"); rlp_data->ker.Connected = FALSE; sbm_deinit (); rbm_deinit (); srm_deinit (); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_rlp_error_ind | +--------------------------------------------------------------------+ PURPOSE : send a error cause to L2R */ GLOBAL void ker_send_rlp_error_ind(USHORT cause) { PALLOC (rlp_error_ind, RLP_ERROR_IND); TRACE_FUNCTION ("ker_send_rlp_error_ind()"); TRACE_EVENT_P1("RLP Error : %d", cause); rlp_error_ind->cause = cause; PSENDX (L2R, rlp_error_ind); ker_deinit_link_vars (); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_getSlotTRCVS | +--------------------------------------------------------------------+ PURPOSE : search the rcvs entry for a given timer handle. The function returns the corresponding slot. The entry is freed. This function is used in the timeout handling functions of the entity. */ GLOBAL T_FRAME_NUM ker_getSlotTRCVS (USHORT index) { rlp_data->ker.rcvsTab[index].trcvs_running = FALSE; rlp_data->ker.rcvsTab[index].isFree = TRUE; return rlp_data->ker.rcvsTab[index].slot; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_fill_remap_frame | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_fill_remap_frame ( T_FRAME_NUM vr ) { TRACE_FUNCTION ("ker_fill_remap_frame()"); rlp_data->ker.REMAP_Frame[HEADER_LEN + 0] = vr * 4; rlp_data->ker.REMAP_Frame[HEADER_LEN + 1] = 0; ker_put_xid_data ( rlp_data->ker.REMAP_Frame + HEADER_LEN, 2, UF_ALL, TRUE, ORIG_RLP_VERS, rlp_data->ker.Orig_K_iwf_ms, rlp_data->ker.Orig_K_ms_iwf, rlp_data->ker.Orig_T1, rlp_data->ker.Orig_N2, rlp_data->ker.Orig_T2, rlp_data->ker.Orig_Pt, rlp_data->ker.Orig_P0, rlp_data->ker.Orig_P1, rlp_data->ker.Orig_P2 ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_send_remap_data | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL BOOL ker_send_remap_data ( void ) { T_RLP_DATA_REQ *prim; TRACE_FUNCTION ("ker_send_remap_data()"); if (sbm_recall_prim (&prim)) { PPASS (prim, rlp_remap_data_ind, RLP_REMAP_DATA_IND); rlp_remap_data_ind->data_size = rlp_data->ker.OldFrameSize - HEADER_LEN - TRAILER_LEN; PSENDX (L2R, rlp_remap_data_ind); return TRUE; } return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-F&D (8411) MODULE : RLP_KERF | | STATE : code ROUTINE : ker_set_frame_size | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void ker_set_frame_size ( UBYTE rate ) { TRACE_FUNCTION ("ker_set_frame_size()"); switch(rate) { case RLP_FULLRATE_14400: rlp_data->ker.Def_T1 = DEF_T1_FR14400; rlp_data->ker.FrameSize = FRAME_SIZE_LONG; break; case RLP_FULLRATE_9600: rlp_data->ker.Def_T1 = DEF_T1_FR9600; rlp_data->ker.FrameSize = FRAME_SIZE_SHORT; break; case RLP_FULLRATE_4800: rlp_data->ker.Def_T1 = DEF_T1_FR4800; rlp_data->ker.FrameSize = FRAME_SIZE_SHORT; break; case RLP_HALFRATE_4800: rlp_data->ker.Def_T1 = DEF_T1_HR4800; rlp_data->ker.FrameSize = FRAME_SIZE_SHORT; break; } rlp_data->ker.FramesPerPrim = (rlp_data->ker.BytesPerPrim + rlp_data->ker.FrameSize - 1) / rlp_data->ker.FrameSize; sig_ker_snd_set_frame_size_req (rlp_data->ker.FrameSize); }