X-Git-Url: https://git.jankratochvil.net/?a=blobdiff_plain;f=common%2Fdata%2Frlp-common.c;fp=common%2Fdata%2Frlp-common.c;h=0000000000000000000000000000000000000000;hb=472b70e710ac48afb0d2831c00d26043b1843047;hp=9c46e0d229330cf8b60ead3a41f35eab09eb0c75;hpb=833e1c7c90e13ceaba3dde8e7a36fcc8dfb1db3c;p=gnokii.git diff --git a/common/data/rlp-common.c b/common/data/rlp-common.c deleted file mode 100644 index 9c46e0d..0000000 --- a/common/data/rlp-common.c +++ /dev/null @@ -1,2069 +0,0 @@ -/* - - $Id$ - - G N O K I I - - A Linux/Unix toolset and driver for Nokia mobile phones. - - Released under the terms of the GNU GPL, see file COPYING for more details. - - The development of RLP protocol is sponsored by SuSE CR, s.r.o. (Pavel use - the SIM card from SuSE for testing purposes). - - Actual implementation of RLP protocol. Based on GSM 04.22 version 7.1.0, - downloadable from www.etsi.org (if you register with them) - -*/ - -#include -#include -#include -#include - -#include "data/rlp-common.h" -#include "data/rlp-crc24.h" -#include "gsm-common.h" /* For GSM error and RLP send function. */ -#include "misc.h" /* For u8, u32 etc. */ - -#ifdef WIN32 -#define INLINE __inline -#else -#define INLINE inline -#endif - -/* Our state machine which handles all of nine possible states of RLP - machine. */ -void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header); - -/* This is the type we are just handling. */ -RLP_FrameTypes CurrentFrameType; - -/* Current state of RLP state machine. */ -RLP_State CurrentState=RLP_S0; /* We start at ADM and Detached */ - -/* Next state of RLP state machine. */ -RLP_State NextState; - -/* Pointer to Send function that sends frame to phone. */ -bool (*RLPSendFunction)(RLP_F96Frame *frame, bool out_dtx); - -/* Pointer to Passup function which returns data/inds */ -int (*RLP_Passup)(RLP_UserInds ind, u8 *buffer, int length); - - -/* State variables - see GSM 04.22, Annex A, section A.1.2 */ - -RLP_StateVariable UA_State; -RLP_StateVariable UI_State; -RLP_StateVariable Ackn_State; -RLP_StateVariable Poll_State; -RLP_StateVariable Poll_xchg; -RLP_StateVariable SABM_State; -RLP_StateVariable DISC_State; -RLP_StateVariable DM_State; /* FIXME - not handled */ -RLP_StateVariable XI_R_State; -RLP_StateVariable XID_C_State; -RLP_StateVariable XID_R_State; -RLP_StateVariable TEST_R_State; - -u8 VR=0; -u8 VA=0; -u8 VS=0; -u8 VD=0; -u8 DISC_Count; - -u8 DTX_VR; -RLP_FrameTypes DTX_SF; - -#define RLP_M 62 - -RLP_Data R[RLP_M]; -RLP_Data S[RLP_M]; - -RLP_StateVariable SABM_State; -int SABM_Count; - -RLP_UserRequestStore UserRequests; - -u8 Poll_Count=0; - -/* For now timing is done based on a frame reception rate of 20ms */ -/* Serge has measured it as 18.4ms */ -#define RLP_T_Scaling 2 - -/* Timers - a value of -1 means not set */ -/* To set, timer is loaded with RLP_Timeout1_Limit/RLP_T_Scaling. */ -/* Each received frame (including NULLS / errors) any >0 timer is decrease */ - -int T; -int T_RCVS[RLP_M]; - -bool UA_FBit=true; -bool Ackn_FBit=false; -bool DM_FBit=false; /* FIXME - not handled */ -bool RRReady=false; -bool LRReady=true; /* FIXME - not handled (as if we couldn't keep up with 9600bps :-) */ -bool DISC_PBit=false; - -u8 LastStatus=0xff; /* Last Status byte */ - - -/* RLP Parameters. FIXME: Reset these - e.g. when entering state 0 */ - -u8 RLP_SEND_WS = RLP_M-1; -u8 RLP_RCV_WS = RLP_M-1; -u8 RLP_Timeout1_Limit = 55; -u8 RLP_N2 = 15; /* Maximum number of retransmisions. GSM spec says 6 here, but - Nokia will XID this. */ -u8 RLP_T2=0; -u8 RLP_VersionNumber=0; - - - -/****** Externally called functions ********/ -/*******************************************/ - - -/* Function to initialise RLP code. Main purpose for now is - to set the address of the RLP send function in the API code. */ - -void RLP_Initialise(bool (*rlp_send_function)(RLP_F96Frame *frame, bool out_dtx), int (*rlp_passup)(RLP_UserInds ind, u8 *buffer, int length)) -{ - int i; - - RLPSendFunction = rlp_send_function; - RLP_Passup=rlp_passup; - UserRequests.Conn_Req=false; - UserRequests.Attach_Req=false; - UserRequests.Conn_Req_Neg=false; - UserRequests.Reset_Resp=false; - UserRequests.Disc_Req=false; - CurrentState=RLP_S0; - T=-1; - for (i=0;i= 0) ? result : result + RLP_M; - * } -*/ - -/* Check value is within range */ -static bool InWindow(u8 val, u8 lower, u8 upper) -{ - /* allow for one level of wrapping round */ - if (lower>=RLP_M) lower-=RLP_M; - if (upper>=RLP_M) upper-=RLP_M; - if (val>=RLP_M) val-=RLP_M; - - /* .......L*****U....... */ - if (lower <= upper) - return (val >= lower) && (val <= upper); - - /* ******U.........L***** */ - return (val <= upper) || (val >= lower); -} - -void RLP_Init_link_vars(void) -{ - int i; - - Ackn_State=_idle; - Poll_State=_idle; - Poll_Count=0; - Poll_xchg=_idle; - SABM_State=_idle; - DISC_State=_idle; - RRReady=true; /* This seems a bit strange but it's what the spec says... */ - VA=0; - VR=0; - VS=0; - VD=0; - LastStatus=0xff; - - for(i=0;i23) { - S[VD].Data[0]=0x1e; - size=24; - } - else S[VD].Data[0]=size; - - memcpy(&S[VD].Data[1],buffer,size); - - if (size!=24) S[VD].Data[size+1]=0x1f; - - S[VD].State=_send; - VD=Incr(VD); - } -} - - -/* FIXME: Remove this after finishing. */ - -void X(RLP_F96Frame *frame) { - - int i; - - for (i=0; i<30; i++) - printf("byte[%2d]: %02x\n", i, *( (u8 *)frame+i)); - -} - - - -void ResetAllT_RCVS(void) -{ - - int i; - for (i=0;i>5); - - switch (FrameType) { - - /* Unnumbered frames. Be careful - some commands are used as commands - only, so we have to set C/R bit later. We should not allow user for - example to send SABM as response because in the spec is: The SABM - encoding is used as command only. */ - - case RLPFT_U_SABM: - - frame.Header[0]|=0xf8; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */ - frame.Header[1]|=0x01; /* 1 P/F M1 M2 M3 M4 M5 X */ - - SetCRBit; /* The SABM encoding is used as a command only. */ - SetPFBit; /* It is always used with the P-bit set to "1". */ - - PackM(RLPU_SABM); - - break; - - case RLPFT_U_UA: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - ClearCRBit; /* The UA encoding is used as a response only. */ - - PackM(RLPU_UA); - - break; - - case RLPFT_U_DISC: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - SetCRBit; /* The DISC encoding is used as a command only. */ - - PackM(RLPU_DISC); - - break; - - case RLPFT_U_DM: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - ClearCRBit; /* The DM encoding is used as a response only. */ - - PackM(RLPU_DM); - - break; - - case RLPFT_U_NULL: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - PackM(RLPU_NULL); - - break; - - case RLPFT_U_UI: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - PackM(RLPU_UI); - - break; - - case RLPFT_U_XID: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - SetPFBit; /* XID frames are always used with the P/F-bit set to "1". */ - - PackM(RLPU_XID); - - break; - - case RLPFT_U_TEST: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - PackM(RLPU_TEST); - - break; - - case RLPFT_U_REMAP: - - frame.Header[0]|=0xf8; - frame.Header[1]|=0x01; - - ClearPFBit; /* REMAP frames are always used with P/F-bit set to "0". */ - - PackM(RLPU_REMAP); - - break; - - case RLPFT_S_RR: - - frame.Header[0]|=0xf0; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */ - frame.Header[1]|=0x01; /* 1 P/F ...N(R)... */ - - PackNR; - - PackS(RLPS_RR); - - break; - - case RLPFT_S_REJ: - - frame.Header[0]|=0xf0; - frame.Header[1]|=0x01; - - PackNR; - - PackS(RLPS_REJ); - - break; - - case RLPFT_S_RNR: - - frame.Header[0]|=0xf0; - frame.Header[1]|=0x01; - - PackNR; - - PackS(RLPS_RNR); - - break; - - case RLPFT_S_SREJ: - - frame.Header[0]|=0xf0; - frame.Header[1]|=0x01; - - PackNR; - - PackS(RLPS_SREJ); - - break; - - case RLPFT_SI_RR: - - PackNR; - PackNS; - - PackS(RLPS_RR); - - break; - - case RLPFT_SI_REJ: - PackNR; - PackNS; - - PackS(RLPS_REJ); - - break; - - case RLPFT_SI_RNR: - - PackNR; - PackNS; - - PackS(RLPS_RNR); - - break; - - case RLPFT_SI_SREJ: - PackNR; - PackNS; - - PackS(RLPS_SREJ); - - break; - - default: - break; - } - - - /* Store FCS in the frame. */ - RLP_CalculateCRC24Checksum((u8 *)&frame, 27, frame.FCS); - - // X(&frame); - - if (RLPSendFunction) - RLPSendFunction(&frame, OutDTX); - -} - -/* Check_input_PDU in Serge's code. */ - -void RLP_DisplayF96Frame(RLP_F96Frame *frame) -{ - int count; - RLP_F96Header header; - - if (T>=0) T--; - for (count=0;count=0) T_RCVS[count]--; - - CurrentFrameType=RLPFT_BAD; - - if (!frame) { - /* no frame provided, drop through to state machine anyway */ - } else if (RLP_CheckCRC24FCS((u8 *)frame, 30) == true) { - - /* Here we have correct RLP frame so we can parse the field of the header - to out structure. */ - - RLP_DecodeF96Header(frame, &header); - - switch (header.Type) { - - case RLPFT_U: /* Unnumbered frames. */ - -#ifdef RLP_DEBUG - fprintf(stdout, "Unnumbered Frame [$%02x%02x] M=%02x ", frame->Header[0], - frame->Header[1], - header.M); -#endif - - switch (header.M) { - - case RLPU_SABM : - if (header.CR == 0 || header.PF == 0) break; - -#ifdef RLP_DEBUG - fprintf(stdout, "Set Asynchronous Balanced Mode (SABM) "); -#endif - - CurrentFrameType=RLPFT_U_SABM; - - break; - - case RLPU_UA: - if (header.CR == 1) break; - -#ifdef RLP_DEBUG - fprintf(stdout, "Unnumbered Acknowledge (UA) "); -#endif - - CurrentFrameType=RLPFT_U_UA; - - break; - - case RLPU_DISC: - if (header.CR == 0) break; - -#ifdef RLP_DEBUG - fprintf(stdout, "Disconnect (DISC) "); -#endif - - CurrentFrameType=RLPFT_U_DISC; - - break; - - case RLPU_DM: - if (header.CR == 1) break; - -#ifdef RLP_DEBUG - fprintf(stdout, "Disconnected Mode (DM) "); -#endif - CurrentFrameType=RLPFT_U_DM; - - break; - - case RLPU_UI: - -#ifdef RLP_DEBUG - fprintf(stdout, "Unnumbered Information (UI) "); -#endif - - CurrentFrameType=RLPFT_U_UI; - - break; - - case RLPU_XID: - -#ifdef RLP_DEBUG - fprintf(stdout, "Exchange Information (XID) \n"); - RLP_DisplayXID(frame->Data); -#endif - - CurrentFrameType=RLPFT_U_XID; - - break; - - case RLPU_TEST: - -#ifdef DEBUG - fprintf(stdout, "Test (TEST) "); -#endif - - CurrentFrameType=RLPFT_U_TEST; - - break; - - case RLPU_NULL: - -#ifdef DEBUG - fprintf(stdout, "Null information (NULL) "); -#endif - - CurrentFrameType=RLPFT_U_NULL; - - break; - - case RLPU_REMAP: - -#ifdef DEBUG - fprintf(stdout, "Remap (REMAP) "); -#endif - - CurrentFrameType=RLPFT_U_REMAP; - - break; - - default : - -#ifdef RLP_DEBUG - fprintf(stdout, _("Unknown!!! ")); -#endif - - CurrentFrameType=RLPFT_BAD; - - break; - - } - break; - - case RLPFT_S: /* Supervisory frames. */ - -#ifdef RLP_DEBUG - fprintf(stdout, "Supervisory Frame [$%02x%02x] S=0x%x N(R)=%d ", - frame->Header[0], - frame->Header[1], - header.S, - header.Nr); -#endif - - switch (header.S) { - - case RLPS_RR: - -#ifdef RLP_DEBUG - fprintf(stdout, "RR"); -#endif - - CurrentFrameType=RLPFT_S_RR; - - break; - - case RLPS_REJ: - -#ifdef RLP_DEBUG - fprintf(stdout, "REJ"); -#endif - - CurrentFrameType=RLPFT_S_REJ; - - break; - - case RLPS_RNR: - -#ifdef RLP_DEBUG - fprintf(stdout, "RNR"); -#endif - - CurrentFrameType=RLPFT_S_RNR; - - break; - - case RLPS_SREJ: - -#ifdef RLP_DEBUG - fprintf(stdout, "SREJ"); -#endif - - CurrentFrameType=RLPFT_S_SREJ; - - break; - - default: - -#ifdef DEBUG - fprintf(stdout, _("BAD")); -#endif - - CurrentFrameType=RLPFT_BAD; - - break; - - } - - break; - - default: - -#ifdef RLP_DEBUG - fprintf(stdout, "Info+Supervisory Frame [$%02x%02x] S=0x%x N(S)=%d N(R)=%d ", - frame->Header[0], - frame->Header[1], - header.S, - header.Ns, - header.Nr); -#endif - - switch (header.S) { - - case RLPS_RR: - -#ifdef RLP_DEBUG - fprintf(stdout, "RR"); -#endif - - CurrentFrameType=RLPFT_SI_RR; - - break; - - case RLPS_REJ: - -#ifdef RLP_DEBUG - fprintf(stdout, "REJ"); -#endif - - CurrentFrameType=RLPFT_SI_REJ; - - break; - - case RLPS_RNR: - -#ifdef RLP_DEBUG - fprintf(stdout, "RNR"); -#endif - - CurrentFrameType=RLPFT_SI_RNR; - - break; - - case RLPS_SREJ: - -#ifdef RLP_DEBUG - fprintf(stdout, "SREJ"); -#endif - - CurrentFrameType=RLPFT_SI_SREJ; - - break; - - default: - -#ifdef DEBUG - fprintf(stdout, "BAD"); -#endif - - CurrentFrameType=RLPFT_BAD; - - break; - } - - break; - } - -#ifdef RLP_DEBUG - - /* Command/Response and Poll/Final bits. */ - - fprintf(stdout, " C/R=%d P/F=%d", header.CR, header.PF); -#endif - -#ifdef DEBUG - - /* Information. */ - - if (CurrentFrameType!=RLPFT_U_NULL) { - - fprintf(stdout, "\n"); - - for (count = 0; count < 25; count ++) { - - if (isprint(frame->Data[count])) - fprintf(stdout, "[%02x%c]", frame->Data[count], frame->Data[count]); - else - fprintf(stdout, "[%02x ]", frame->Data[count]); - - if (count == 15) - fprintf(stdout, "\n"); - } - } - -#endif -#ifdef RLP_DEBUG - /* FCS. */ - - fprintf (stdout, " FCS: %02x %02x %02x\n\n", frame->FCS[0], - frame->FCS[1], - frame->FCS[2]); - - fflush(stdout); - -#endif - - } - else { - - /* RLP Checksum failed - don't we need some statistics about these - failures? Nothing is printed, because in the first stage of connection - there are too many bad RLP frames... */ - -#ifdef DEBUG - fprintf(stdout, _("Frame FCS is bad. Ignoring...\n")); -#endif - - } - - MAIN_STATE_MACHINE(frame, &header); - - /* - Y:= outblock(); - */ - - return; -} - -/* FIXME: real TEST_Handling - we do not handle TEST yet. */ - -void TEST_Handling() { -} - - - -/* FIXME: better XID_handling - but this will answer a XID command. */ - -bool XID_Handling (RLP_F96Frame *frame, RLP_F96Header *header) { - - u8 count; - u8 type; - u8 length; - - if (CurrentFrameType == RLPFT_U_XID) { - - count=0; - - while (frame->Data[count] !=0) { - - type=frame->Data[count] >> 4; - length=frame->Data[count] & 0x0f; - count++; - - switch (type) { - - case 0x01: /* RLP Version Number */ - RLP_VersionNumber=frame->Data[count]; - count+=length; - break; - case 0x02: /* Interworking Function (IWF) to Mobile Station (MS) window size */ - if (frame->Data[count]>=1 && frame->Data[count]Data[count]; - count+=length; - break; - case 0x03: /* MS to IWF window size */ - if (frame->Data[count]>=1 && frame->Data[count]Data[count]; - count+=length; - break; - case 0x04: /* Acknowledgement Timer (T1). */ - RLP_Timeout1_Limit=frame->Data[count]; - count+=length; - break; - case 0x05: /* Retransmission attempts (N2). */ - RLP_N2=frame->Data[count]; - count+=length; - break; - case 0x06: /* Reply delay (T2). */ - RLP_T2=frame->Data[count]; - count+=length; - break; - case 0x07: /* Compression - not yet! */ - break; - default: - count+=length; - break; - } - } - - /* Now reassemble a reply */ - - count=0; - memset(frame->Data,0x00,25); /* Makes debugging easier */ - - /* Version Number - force to 0 for now */ - RLP_VersionNumber=0; - frame->Data[count++]=0x11; - frame->Data[count++]=RLP_VersionNumber; - - /* Window sizes */ - frame->Data[count++]=0x21; - frame->Data[count++]=RLP_RCV_WS; - frame->Data[count++]=0x31; - frame->Data[count++]=RLP_SEND_WS; - - /* Acknowledgement Timer (T1). */ - frame->Data[count++]=0x41; - frame->Data[count++]=RLP_Timeout1_Limit; - - /* Retransmission attempts (N2). */ - frame->Data[count++]=0x51; - frame->Data[count++]=RLP_N2; - - /* Reply delay (T2). */ - frame->Data[count++]=0x61; - frame->Data[count++]=RLP_T2; - - XID_R_State = _send; - - return true; - } - - return false; -} - - -bool Send_TXU(RLP_F96Frame *frame, RLP_F96Header *header) { - -#ifdef DEBUG - // fprintf(stdout, _("Send_TXU()\n")); - // fprintf(stdout, _("XID_R_State=%d\n"), XID_R_State); -#endif - - /* - - if (RLP_UserEvent(TEST_R_State)) { - RLP_SendF96Frame(RLPFT_U_TEST, false, TEST_R_FBit, 0, 0, TEST_R_Data, false); - return true; - } - else - - */ - - if (XID_R_State == _send && frame) { - RLP_SendF96Frame(RLPFT_U_XID, false, true, 0, 0, frame->Data, false); - XID_R_State = _idle; - return true; - } - - /* - - else if ((XID_C_State == _send ) && (Poll_xchg == _idle)) { - RLP_SendF96Frame(RLPFT_U_XID, true, true, 0, 0, XID_C_Data, false); - XID_C_State = _wait; - T_XID = 1; - Poll_xchg = _wait; - return true; - } else if (RLP_UserEvent(UI_State)) { - RLP_SendF96Frame(RLPFT_U_UI, true, false, 0, 0, NULL, false); - return true; - } - - */ - - return false; -} - - -/* Deliver data */ - -void RLP_DeliverAllInSeqIF() -{ - int i,j; - - do { - - if ((R[VR].Data[0] & 0xE0)!=LastStatus) { - LastStatus=(R[VR].Data[0] & 0xE0); - RLP_Passup(StatusChange,&LastStatus,0); - } - - j=0; - i=R[VR].Data[0] & 0x1f; - if (i==0x1e) j=24; - if (i<0x18) j=i; - - /* FIXME - should check for more data in the frame */ - - RLP_Passup(Data,R[VR].Data+1,j); - - R[VR].State=_idle; - VR=Incr(VR); - - } while (R[VR].State==_rcvd); -} - - -/* Mark any missing information frames between VR and Ns*/ -void RLP_MarkMissingIF(u8 Ns) -{ - u8 i; - for (i=VR; i!=Ns; i=Incr(i)) { - if (R[i].State==_idle) R[i].State=_srej; /* bug in spec, fig A.23 */ - } -} - - -/* Information frame handler */ - -bool RLP_I_Handler(RLP_F96Frame *frame, RLP_F96Header *header) -{ - - if ((header->CR) && (header->PF)) - return true; - - /* If the window size is 61, a received frame must have a sequence - number between VR and VR+60 */ - - if (!InWindow(header->Ns,VR,VR+RLP_RCV_WS-1)) - return true; - - if (header->Ns==VR) { - /* This is not in the spec but I think it is necessary */ - if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1; - R[VR].State=_rcvd; - memcpy(R[VR].Data,frame->Data,25); - RLP_DeliverAllInSeqIF(); - Ackn_State=_send; - } - else { /* Out of sequence, cause a SREJ */ - if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1; - R[header->Ns].State=_rcvd; - memcpy(R[header->Ns].Data,frame->Data,25); - RLP_MarkMissingIF(header->Ns); - } - - return false; -} - - -/* Mark acknowledged send frames */ - -void RLP_AdvanceVA(u8 Nr) -{ - while (VA!=Nr) { - S[VA].State=_idle; - VA=Incr(VA); - } -} - - -/* Decrease VS back down to Nr since these have not been acknowledged */ - -void RLP_DecreaseVS(u8 Nr) -{ - while (VS!=Nr) { - VS=Decr(VS); - S[VS].State=_send; - } -} - -/* Supervisory frame handling */ - -void RLP_S_Handler(RLP_F96Frame *frame, RLP_F96Header *header) -{ - u8 i; - - if ((header->CR) && (header->PF)) { - /* Special exchange (ie. error) - counter? */ -#ifdef RLP_DEBUG - fprintf(stdout, "Got Poll command\n"); -#endif - Ackn_State=_send; - Ackn_FBit=true; - for (i=0; iPF==0) return; - if ((CurrentFrameType==RLPFT_S_SREJ) || (CurrentFrameType==RLPFT_S_REJ) || - (CurrentFrameType==RLPFT_SI_SREJ) || (CurrentFrameType==RLPFT_SI_REJ)) return; - RLP_DecreaseVS(header->Nr); - Poll_State=_idle; - Poll_xchg=_idle; - } - switch (CurrentFrameType){ - - case RLPFT_S_RR: - case RLPFT_SI_RR: - RLP_AdvanceVA(header->Nr); - RRReady=true; - break; - case RLPFT_S_RNR: - case RLPFT_SI_RNR: - RLP_AdvanceVA(header->Nr); - RRReady=false; - break; - case RLPFT_S_REJ: - case RLPFT_SI_REJ: - RLP_AdvanceVA(header->Nr); - RRReady=true; - RLP_DecreaseVS(header->Nr); - break; - case RLPFT_S_SREJ: - case RLPFT_SI_SREJ: - S[header->Nr].State=_send; - T=-1; - return; - default: - break; - } - - if (VA==VS) T=-1; - -} - - -/* Find the first SREJ frame */ - -bool RLP_SREJSlot(u8 *x) -{ - u8 i; - - for (i=Incr(VR); i!=VR; i=Incr(i)) if (R[i].State==_srej) { - *x=i; - return true; - } - - return false; -} - - - -/* Check if any SREJ frames need sending, if not send the next in line */ - -bool RLP_PrepareDataToTransmit(u8 *p) -{ - u8 i; - - for (i=VA; i!=VS; i=Incr(i)) - if (S[i].State==_send) { - *p=i; - S[i].State=_wait; - return true; - } - if (S[VS].State!=_send) return false; - if (!InWindow(VS,VA,VA+RLP_SEND_WS-1)) - return false; - *p=VS; - S[VS].State=_wait; - VS=Incr(VS); - return true; -} - - - -/* Send a SREJ command */ - -void RLP_SendSREJ(u8 x) -{ - u8 k; - - if ((Poll_xchg==_idle) && (Poll_State==_send)) { - -#ifdef RLP_DEBUG - fprintf(stdout, "Sending SREJ with poll\n"); -#endif - - RLP_SendF96Frame(RLPFT_S_SREJ, true, true, x , 0 , NULL, false); - R[x].State=_wait; - RLP_SetTimer(&T_RCVS[x]); - Poll_Count++; - Poll_State=_wait; - Poll_xchg=_wait; - RLP_SetTimer(&T); - } - else if (RRReady && RLP_PrepareDataToTransmit(&k)) { -#ifdef RLP_DEBUG - fprintf(stdout, "Sending SREJ for %d along with frame %d\n",x,k); -#endif - RLP_SendF96Frame(RLPFT_SI_SREJ, true, false, x , k , S[k].Data, false); - R[x].State=_wait; - RLP_SetTimer(&T_RCVS[x]); - RLP_SetTimer(&T); - } - else { -#ifdef RLP_DEBUG - fprintf(stdout, "Sending SREJ for %d\n",x); -#endif - RLP_SendF96Frame(RLPFT_S_SREJ, true, false, x , 0 , NULL, false); - R[x].State=_wait; - RLP_SetTimer(&T_RCVS[x]); - } -} - - -/* Send a command */ - -void RLP_Send_XX_Cmd(RLP_FrameTypes type) -{ - u8 k; - - if ((Poll_xchg!=_wait) && (Poll_State==_send)) { - RLP_SendF96Frame(type, true, true, VR , 0 , NULL, false); -#ifdef RLP_DEBUG - fprintf(stdout, "Sending Comd %x with Poll\n",type); -#endif - Ackn_State=_idle; - Poll_Count++; - Poll_State=_wait; - Poll_xchg=_wait; - RLP_SetTimer(&T); - } - else if (RRReady && RLP_PrepareDataToTransmit(&k)) { -#ifdef RLP_DEBUG - fprintf(stdout, "Sending Comd %x with frame %d\n",type,k); -#endif - RLP_SendF96Frame(type+4, true, false, VR , k , S[k].Data, false); - Ackn_State=_idle; - RLP_SetTimer(&T); - } - else { -#ifdef RLP_DEBUG - if (type!=9) - fprintf(stdout, "Sending Comd %x\n",type); -#endif - RLP_SendF96Frame(type, true, false, VR , 0 , NULL, false); - Ackn_State=_idle; - DTX_SF=type; - DTX_VR=VR; /* As v7.1.0 spec */ - } -} - - -/* Send a Response */ - -void RLP_Send_XX_Resp(RLP_FrameTypes type) -{ - u8 k; - - if (RRReady && RLP_PrepareDataToTransmit(&k)) { -#ifdef RLP_DEBUG - fprintf(stdout, "Sending Resp %x with frame %d\n",type+4,k); -#endif - RLP_SendF96Frame(type+4, false, true, VR , k , S[k].Data, false); - Ackn_State=_idle; - Ackn_FBit=false; - RLP_SetTimer(&T); - } - else { -#ifdef RLP_DEBUG - fprintf(stdout, "Sending Resp %x\n",type); -#endif - RLP_SendF96Frame(type, false, true, VR , 0 , NULL, false); - Ackn_State=_idle; - Ackn_FBit=false; - } -} - - -/* Decide which frame to use and send it - currently only used in state 4 */ - -void RLP_SendData() -{ - u8 x; - - if (UA_State==_send) { - RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0 , 0 , NULL, false); - UA_State=_idle; - } - else if (Ackn_FBit==true) { -#ifdef RLP_DEBUG - printf("About to send Poll resp\n"); -#endif - if (LRReady) RLP_Send_XX_Resp(RLPFT_S_RR); - else RLP_Send_XX_Resp(RLPFT_S_RNR); - } - else if (RLP_SREJSlot(&x)) RLP_SendSREJ(x); - else if (LRReady) RLP_Send_XX_Cmd(RLPFT_S_RR); - else RLP_Send_XX_Cmd(RLPFT_S_RNR); -} - -void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header) { - int i; - - switch (CurrentState) { - - /***** RLP State 0. *****/ - - /* ADM and Detached. - - This is the initial state after power on. - - As long as the RLP entity is "Detached", DISC(P) and/or SABM at the - lower interface is acted upon by sending DM(P) or DM(1). Any other - stimulus at the lower interface is ignored. - - This state can be exited only with Attach_Req. */ - - case RLP_S0: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 0.\n")); -#endif - - switch (CurrentFrameType) { - - case RLPFT_U_DISC: - RLP_SendF96Frame(RLPFT_U_DM, false, header->PF, 0, 0, NULL, false); - break; - - case RLPFT_U_SABM: - RLP_SendF96Frame(RLPFT_U_DM, false, true, 0, 0, NULL, false); - break; - - default: - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - if (RLP_GetUserRequest(Attach_Req)) { - NextState=RLP_S1; - UA_State=_idle; - } - break; - } - - break; - - /***** RLP State 1. *****/ - - /* ADM and Attached. - - The RLP entity is ready to established a connection, either by - initiating the connection itself (Conn_Req) or by responding to an - incoming connection request (SABM). - - Upon receiving a DISC PDU, the handling of the UA response is - initiated. */ - - case RLP_S1: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 1.\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch(CurrentFrameType) { - - case RLPFT_U_TEST: - TEST_Handling(); - break; - - case RLPFT_U_SABM: - RLP_Passup(Conn_Ind,NULL,0); - NextState=RLP_S3; - break; - - case RLPFT_U_DISC: - UA_State=_send; - UA_FBit=header->PF; - break; - - case RLPFT_BAD: /* If we get a bad frame we can still respond with SABM */ - default: - if (RLP_GetUserRequest(Conn_Req)) { - SABM_State=_send; - SABM_Count=0; - NextState=RLP_S2; - } - break; - } - - } - if (!Send_TXU(frame, header)) { - - if (UA_State == _send) { - RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false); - UA_State=_idle; - } - else - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - } - break; - - /***** RLP State 2. *****/ - - case RLP_S2: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 2.\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch(CurrentFrameType) { - - case RLPFT_U_TEST: - TEST_Handling(); - break; - - case RLPFT_U_SABM: - /* - T=0; - Conn_Conf=true; - UA_State=_send; - UA_FBit=true; - Init_Link_Vars; - NextState=4; - */ - break; - - case RLPFT_U_DISC: - /* - T=0; - DISC_Ind; - UA_State=_send; - UA_FBit=header->PF; - NextState=RLP_S1; - */ - break; - - case RLPFT_U_UA: -#ifdef DEBUG - fprintf(stdout, _("UA received in RLP state 2.\n")); -#endif - - if (SABM_State == _wait && header->PF) { - T=-1; - // Conn_Conf=true; - // Init_Link_Vars; - NextState=RLP_S4; - } - break; - - case RLPFT_U_DM: - if (SABM_State == _wait && header->PF) { - Poll_xchg=_idle; - // Conn_Conf_Neg=true; - NextState=RLP_S1; - } - break; - - default: - if (T == RLP_Timeout1_Limit) { - Poll_xchg=_idle; - if (SABM_Count>RLP_N2) - NextState=RLP_S8; - SABM_State=_send; - } - break; - } - } - - if (!Send_TXU(frame, header)) { - - if (SABM_State == _send && Poll_xchg == _idle) { - RLP_SendF96Frame(RLPFT_U_SABM, true, true, 0, 0, NULL, false); - SABM_State=_wait; - SABM_Count++; - Poll_xchg=_wait; - T=1; - } else - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - } - - if (RLP_GetUserRequest(Disc_Req)) { - T=-1; - DISC_State=_send; - DISC_Count=0; - DISC_PBit=(Poll_xchg==_idle); - NextState=5; - } - - break; - - /***** RLP State 3. *****/ - - case RLP_S3: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 3.\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch(CurrentFrameType) { - - case RLPFT_U_TEST: - TEST_Handling(); - break; - - case RLPFT_U_DISC: - RLP_Passup(Disc_Ind,NULL,0); - UA_State=_send; - UA_FBit=header->PF; - NextState=RLP_S1; - break; - - default: - if (RLP_GetUserRequest(Conn_Req)) { - UA_State=_send; - UA_FBit=true; - NextState=RLP_S4; - RLP_Init_link_vars(); - } else if (RLP_GetUserRequest(Conn_Req_Neg)) { - DM_State=_send; /* FIXME - code to handle DM_State - missing from spec? */ - DM_FBit=true; - NextState=RLP_S1; - } - break; - } - } - - if (!Send_TXU(frame, header)) { - - if (UA_State == _send) { - RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false); - UA_State=_idle; - } - else - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - } - - - if (RLP_GetUserRequest(Disc_Req)) { - T=-1; - DISC_State=_send; - DISC_Count=0; - DISC_PBit=(Poll_xchg==_idle); - NextState=5; - } - - break; - - /***** RLP State 4. *****/ - - case RLP_S4: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 4.\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch (CurrentFrameType) { - - case RLPFT_U_TEST: - TEST_Handling(); - break; - case RLPFT_U_DISC: - T=-1; - ResetAllT_RCVS(); - RLP_Passup(Disc_Ind,NULL,0); - UA_State=_send; - UA_FBit=header->PF; - NextState=RLP_S1; - break; - case RLPFT_U_SABM: - T=-1; - ResetAllT_RCVS(); - RLP_Passup(Reset_Ind,NULL,0); - NextState=RLP_S7; - break; - case RLPFT_S_RR: - case RLPFT_S_RNR: - case RLPFT_S_REJ: - case RLPFT_S_SREJ: - /* Should check here for unsolicited Fbit */ - /* Spec says: "Nr must be within the set of not yet - acknowledged I-frames or it must be the next possible - frame number." That's VA..VS-1 or VS, i.e. VA..VS */ - if (!InWindow(header->Nr,VA,VS)) - break; - RLP_S_Handler(frame,header); - break; - case RLPFT_SI_RR: - case RLPFT_SI_RNR: - case RLPFT_SI_REJ: - case RLPFT_SI_SREJ: - /* Should check here for unsolicited Fbit */ - if (!InWindow(header->Nr,VA,VS)) - break; - if (!RLP_I_Handler(frame,header)) RLP_S_Handler(frame,header); - break; - default: - break; - } - } - - for (i=0;iRLP_N2) { -#ifdef RLP_DEBUG - fprintf(stdout, "N2 Errors in State 4\n"); -#endif - } - Poll_State=_send; - Poll_Count++; - } - } - - if (!Send_TXU(frame,header)) { - if (UA_State == _send) { - RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false); - UA_State=_idle; - } - else RLP_SendData(); - } - - - /* Load any data from the Send ringbuffer into the send slots */ - RLP_AddRingBufferDataToSlots(); - -#ifdef RLP_DEBUG - // if (CurrentFrameType!=RLPFT_BAD) - fprintf(stdout, "VD=%d, VA=%d, VS=%d, VR=%d\n",VD,VA,VS,VR); -#ifdef RLP_DEBUG_STATE - { - int zzz; - - if(UA_State!=_idle) printf("[UA_State %d]",UA_State); - if(UI_State!=_idle) printf("[UI_State %d]",UI_State); - if(Ackn_State!=_idle) printf("[Ackn_State %d]",Ackn_State); - if(Poll_State!=_idle) printf("[Poll_State %d]",Poll_State); - if(Poll_xchg!=_idle) printf("[Poll_xchg %d]",Poll_xchg); - if(SABM_State!=_idle) printf("[SABM_State %d]",SABM_State); - if(DISC_State!=_idle) printf("[DISC_State %d]",DISC_State); - if(DM_State!=_idle) printf("[DM_State %d]",DM_State); - if(XI_R_State!=_idle) printf("[XI_R_State %d]",XI_R_State); - if(XID_C_State!=_idle) printf("[XID_C_State %d]",XID_C_State); - if(XID_R_State!=_idle) printf("[XID_R_State %d]",XID_R_State); - if(TEST_R_State!=_idle) printf("[TEST_R_State %d]",TEST_R_State); - - printf("S: "); - for (zzz=0; zzzPF)) { - if (DISC_PBit==true) Poll_xchg=_idle; - T=-1; - NextState=1; - } - break; - case RLPFT_U_DISC: - T=-1; - UA_State=_send; - UA_FBit=header->PF; - NextState=1; - break; - default: - break; - } - } - - if (!Send_TXU(frame,header)) { - if ((DISC_State!=_wait) && !((DISC_PBit==true) && (Poll_xchg==_wait))) { - RLP_SendF96Frame(RLPFT_U_DISC, true, DISC_PBit, 0, 0, NULL, false); - if (DISC_PBit==true) Poll_xchg=_wait; - DISC_State=_wait; - DISC_Count++; - RLP_SetTimer(&T); - } - else - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - } - - if (T==0) { - if (DISC_PBit==1) Poll_xchg=_idle; - DISC_Count++; - if (DISC_Count>RLP_N2) { - -#ifdef RLP_DEBUG - fprintf(stdout, "N2 error in State 5!\n"); -#endif - - } - DISC_State=_send; - } - - break; - - /***** RLP State 6. *****/ - /* We should only get here after a Reset_Req which is not yet supported */ - - case RLP_S6: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 6 - not yet implemented!\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch (CurrentFrameType) { - default: - break; - } - - } - - if (!Send_TXU(frame,header)) { - } - - if (RLP_GetUserRequest(Disc_Req)) { - T=-1; - DISC_State=_send; - DISC_Count=0; - DISC_PBit=(Poll_xchg==_idle); - NextState=5; - } - - break; - - - /***** RLP State 7. *****/ - - case RLP_S7: - -#ifdef DEBUG - fprintf(stdout, _("RLP state 7.\n")); -#endif - - if (!XID_Handling(frame, header)) { - - switch (CurrentFrameType) { - case RLPFT_U_DISC: - RLP_Passup(Disc_Ind,NULL,0); - UA_State=_send; - UA_FBit=header->PF; - NextState=RLP_S1; - break; - default: - break; - } - } - - if (RLP_GetUserRequest(Reset_Resp)){ - UA_State=_send; - UA_FBit=1; - RLP_Init_link_vars(); - NextState=RLP_S4; - } - - if (!Send_TXU(frame,header)) { - RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false); - } - - if (RLP_GetUserRequest(Disc_Req)) { - T=-1; - DISC_State=_send; - DISC_Count=0; - DISC_PBit=(Poll_xchg==_idle); - NextState=5; - } - - break; - - - default: - -#ifdef DEBUG - fprintf(stdout, _("DEBUG: Unknown RLP state!\n")); -#endif - - break; - } - - CurrentState=NextState; - -} - -/* Given a pointer to an RLP XID frame, display contents in human readable - form. Note for now only Version 0 and 1 are supported. Fields can appear - in any order and are delimited by a zero type field. This function is the - exact implementation of section 5.2.2.6, Exchange Identification, XID of - the GSM specification 04.22. */ - -void RLP_DisplayXID(u8 *frame) -{ - - int count = 25; /* Sanity check */ - u8 type, length; - - fprintf(stdout, "XID: "); - - while ((*frame !=0) && (count >= 0)) { - - type = *frame >> 4; - length = *frame & 0x0f; - - switch (type) { - - case 0x01: /* RLP Version Number, probably 1 for Nokia. */ - - frame += length; - fprintf(stdout, "Ver %d ", *frame); - break; - - case 0x02: /* IWF to MS window size */ - - frame += length; - fprintf(stdout, "IWF-MS %d ", *frame); - break; - - case 0x03: /* MS to IWF window size. */ - - frame += length; - fprintf(stdout, "MS-IWF %d ", *frame); - break; - - case 0x04: /* Acknowledgement Timer (T1). */ - - frame += length; - fprintf(stdout, "T1 %dms ", *frame * 10); - break; - - case 0x05: /* Retransmission attempts (N2). */ - - frame += length; - fprintf(stdout, "N2 %d ", *frame); - break; - - case 0x06: /* Reply delay (T2). */ - - frame += length; - fprintf(stdout, "T2 %dms ", *frame * 10); - break; - - case 0x07: /* Compression. */ - - frame ++; - fprintf(stdout, "Comp [Pt=%d ", (*frame >> 4) ); - fprintf(stdout, "P0=%d ", (*frame & 0x03) ); - - frame ++; - fprintf(stdout, "P1l=%d ", *frame); - frame ++; - fprintf(stdout, "P1h=%d ", *frame); - - frame ++; - fprintf(stdout, "P2=%d] ", *frame); - break; - - default: - - frame += length; - fprintf(stdout, "Unknown! type=%02x, length=%02x", type, length); - break; - - } - count --; - frame ++; - } - - return; -} - -/* Given a pointer to an F9.6 Frame, split data out into component parts of - header and determine frame type. */ - -void RLP_DecodeF96Header(RLP_F96Frame *frame, RLP_F96Header *header) -{ - - /* Poll/Final bit. */ - - if ((frame->Header[1] & 0x02)) - header->PF = true; - else - header->PF = false; - - /* Command/Response bit. */ - - if ((frame->Header[0] & 0x01)) - header->CR = true; - else - header->CR = false; - - /* Send Sequence Number. */ - - header->Ns = frame->Header[0] >> 3; - - if ((frame->Header[1] & 0x01)) - header->Ns |= 0x20; /* Most significant bit. */ - - /* Determine frame type. See the section 5.2.1 in the GSM 04.22 - specification. */ - - switch (header->Ns) { - - case 0x3f: /* Frames of type U, unnumbered frames. */ - - /* U frames have M1, ..., M5 stored in the place of N(R). */ - - header->Type = RLPFT_U; - header->M = (frame->Header[1] >> 2) & 0x1f; - return; /* For U frames, we do not need N(R) and bits S1 and S2. */ - - case 0x3e: /* Frames of type S, supervisory frames. */ - - header->Type = RLPFT_S; - break; - - default: /* Frames of type I+S, numbered information transfer ans - supervisory frames combined. */ - - header->Type = RLPFT_IS; - break; - } - - /* Receive Sequence Number N(R). */ - header->Nr = frame->Header[1] >> 2; - - /* Status bits (S1 and S2). */ - header->S = (frame->Header[0] >> 1) & 0x03; - - return; -} - -