7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Copyright (C) 1999, 2000 Hugh Blemings & Pavel JanÃk ml.
11 Released under the terms of the GNU GPL, see file COPYING for more details.
13 The development of RLP protocol is sponsored by SuSE CR, s.r.o. (Pavel use
14 the SIM card from SuSE for testing purposes).
16 Actual implementation of RLP protocol. Based on GSM 04.22 version 7.1.0,
17 downloadable from www.etsi.org (if you register with them)
20 Revision 1.1.1.1 2001/11/25 21:59:08 short
21 :pserver:cvs@pserver.samba.org:/cvsroot - gnokii - Sun Nov 25 22:56 CET 2001
23 Revision 1.5 2001/03/26 23:39:36 pkot
25 - Windows INLINE patch (Manfred Jonsson)
26 - patch to configure.in to compile under FreeBSD (Panagiotis Astithas)
29 Revision 1.4 2001/03/13 01:23:18 pkot
30 Windows updates (Manfred Jonsson)
32 Revision 1.3 2001/02/21 19:57:00 chris
33 More fiddling with the directory layout
35 Revision 1.2 2001/02/17 22:40:51 chris
46 #include "data/rlp-common.h"
47 #include "data/rlp-crc24.h"
48 #include "gsm-common.h" /* For GSM error and RLP send function. */
49 #include "misc.h" /* For u8, u32 etc. */
52 #define INLINE __inline
57 /* Our state machine which handles all of nine possible states of RLP
59 void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header);
61 /* This is the type we are just handling. */
62 RLP_FrameTypes CurrentFrameType;
64 /* Current state of RLP state machine. */
65 RLP_State CurrentState=RLP_S0; /* We start at ADM and Detached */
67 /* Next state of RLP state machine. */
70 /* Pointer to Send function that sends frame to phone. */
71 bool (*RLPSendFunction)(RLP_F96Frame *frame, bool out_dtx);
73 /* Pointer to Passup function which returns data/inds */
74 int (*RLP_Passup)(RLP_UserInds ind, u8 *buffer, int length);
77 /* State variables - see GSM 04.22, Annex A, section A.1.2 */
79 RLP_StateVariable UA_State;
80 RLP_StateVariable UI_State;
81 RLP_StateVariable Ackn_State;
82 RLP_StateVariable Poll_State;
83 RLP_StateVariable Poll_xchg;
84 RLP_StateVariable SABM_State;
85 RLP_StateVariable DISC_State;
86 RLP_StateVariable DM_State; /* FIXME - not handled */
87 RLP_StateVariable XI_R_State;
88 RLP_StateVariable XID_C_State;
89 RLP_StateVariable XID_R_State;
90 RLP_StateVariable TEST_R_State;
99 RLP_FrameTypes DTX_SF;
106 RLP_StateVariable SABM_State;
109 RLP_UserRequestStore UserRequests;
113 /* For now timing is done based on a frame reception rate of 20ms */
114 /* Serge has measured it as 18.4ms */
115 #define RLP_T_Scaling 2
117 /* Timers - a value of -1 means not set */
118 /* To set, timer is loaded with RLP_Timeout1_Limit/RLP_T_Scaling. */
119 /* Each received frame (including NULLS / errors) any >0 timer is decrease */
125 bool Ackn_FBit=false;
126 bool DM_FBit=false; /* FIXME - not handled */
128 bool LRReady=true; /* FIXME - not handled (as if we couldn't keep up with 9600bps :-) */
129 bool DISC_PBit=false;
131 u8 LastStatus=0xff; /* Last Status byte */
134 /* RLP Parameters. FIXME: Reset these - e.g. when entering state 0 */
136 u8 RLP_SEND_WS = RLP_M-1;
137 u8 RLP_RCV_WS = RLP_M-1;
138 u8 RLP_Timeout1_Limit = 55;
139 u8 RLP_N2 = 15; /* Maximum number of retransmisions. GSM spec says 6 here, but
140 Nokia will XID this. */
142 u8 RLP_VersionNumber=0;
146 /****** Externally called functions ********/
147 /*******************************************/
150 /* Function to initialise RLP code. Main purpose for now is
151 to set the address of the RLP send function in the API code. */
153 void RLP_Initialise(bool (*rlp_send_function)(RLP_F96Frame *frame, bool out_dtx), int (*rlp_passup)(RLP_UserInds ind, u8 *buffer, int length))
157 RLPSendFunction = rlp_send_function;
158 RLP_Passup=rlp_passup;
159 UserRequests.Conn_Req=false;
160 UserRequests.Attach_Req=false;
161 UserRequests.Conn_Req_Neg=false;
162 UserRequests.Reset_Resp=false;
163 UserRequests.Disc_Req=false;
166 for (i=0;i<RLP_M;i++) T_RCVS[i]=-1;
178 RLP_SEND_WS = RLP_M-1;
179 RLP_RCV_WS = RLP_M-1;
180 RLP_Timeout1_Limit = 55;
187 /* Set a user event */
188 /* Called by user program for now */
190 void RLP_SetUserRequest(RLP_UserRequests type, bool value) {
194 UserRequests.Conn_Req=value;
197 UserRequests.Attach_Req=value;
200 UserRequests.Conn_Req_Neg=value;
203 UserRequests.Reset_Resp=value;
206 UserRequests.Disc_Req=value;
216 /***** Internal functions **********/
217 /***********************************/
220 /* Check whether a user event is set */
222 bool RLP_GetUserRequest(RLP_UserRequests type) {
224 bool result=false, *x;
228 x=&UserRequests.Conn_Req;
231 x=&UserRequests.Attach_Req;
234 x=&UserRequests.Conn_Req_Neg;
237 x=&UserRequests.Reset_Resp;
240 x=&UserRequests.Disc_Req;
255 void RLP_SetTimer(int *timer)
257 *timer=(int)(RLP_Timeout1_Limit/RLP_T_Scaling);
261 /* Previous sequence number. */
262 static INLINE u8 Decr(u8 x)
270 /* Next sequence number. */
271 static INLINE u8 Incr(u8 x)
279 /* Difference between sequence numbers. */
281 /* FIXME: Not used now, so I have commented it out. PJ
282 * static INLINE u8 Diff(u8 x, u8 y)
285 * return (result >= 0) ? result : result + RLP_M;
289 /* Check value is within range */
290 static bool InWindow(u8 val, u8 lower, u8 upper)
292 /* allow for one level of wrapping round */
293 if (lower>=RLP_M) lower-=RLP_M;
294 if (upper>=RLP_M) upper-=RLP_M;
295 if (val>=RLP_M) val-=RLP_M;
297 /* .......L*****U....... */
299 return (val >= lower) && (val <= upper);
301 /* ******U.........L***** */
302 return (val <= upper) || (val >= lower);
305 void RLP_Init_link_vars(void)
315 RRReady=true; /* This seems a bit strange but it's what the spec says... */
322 for(i=0;i<RLP_M;i++) {
330 void RLP_AddRingBufferDataToSlots(void)
335 while ((S[VD].State==_idle)
336 && ((size=RLP_Passup(GetData,buffer,24))!=0)) {
337 memset(S[VD].Data,0xff,25); /* FIXME - this isn't necessary - but makes debugging easier! */
342 else S[VD].Data[0]=size;
344 memcpy(&S[VD].Data[1],buffer,size);
346 if (size!=24) S[VD].Data[size+1]=0x1f;
354 /* FIXME: Remove this after finishing. */
356 void X(RLP_F96Frame *frame) {
361 printf("byte[%2d]: %02x\n", i, *( (u8 *)frame+i));
367 void ResetAllT_RCVS(void)
371 for (i=0;i<RLP_M;i++) T_RCVS[i]=-1;
376 /* This function is used for sending RLP frames to the phone. */
378 void RLP_SendF96Frame(RLP_FrameTypes FrameType,
379 bool OutCR, bool OutPF,
381 u8 *OutData, u8 OutDTX)
390 #define SetCRBit frame.Header[0]|=0x01;
391 #define SetPFBit frame.Header[1]|=0x02;
393 #define ClearCRBit frame.Header[0]&=(~0x01);
394 #define ClearPFBit frame.Header[1]&=(~0x02);
396 /* If Command/Response bit is set, set it in the header. */
401 /* If Poll/Final bit is set, set it in the header. */
406 /* If OutData is not specified (ie. is NULL) we want to clear frame.Data
407 array for the user. */
410 frame.Data[0]=0x00; // 0x1f
417 frame.Data[i]=OutData[i];
420 #define PackM(x) frame.Header[1]|=((x)<<2);
421 #define PackS(x) frame.Header[0]|=((x)<<1);
422 #define PackNR frame.Header[1]|=(OutNR<<2);
423 #define PackNS frame.Header[0]|=(OutNS<<3);frame.Header[1]|=(OutNS>>5);
427 /* Unnumbered frames. Be careful - some commands are used as commands
428 only, so we have to set C/R bit later. We should not allow user for
429 example to send SABM as response because in the spec is: The SABM
430 encoding is used as command only. */
434 frame.Header[0]|=0xf8; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
435 frame.Header[1]|=0x01; /* 1 P/F M1 M2 M3 M4 M5 X */
437 SetCRBit; /* The SABM encoding is used as a command only. */
438 SetPFBit; /* It is always used with the P-bit set to "1". */
446 frame.Header[0]|=0xf8;
447 frame.Header[1]|=0x01;
449 ClearCRBit; /* The UA encoding is used as a response only. */
457 frame.Header[0]|=0xf8;
458 frame.Header[1]|=0x01;
460 SetCRBit; /* The DISC encoding is used as a command only. */
468 frame.Header[0]|=0xf8;
469 frame.Header[1]|=0x01;
471 ClearCRBit; /* The DM encoding is used as a response only. */
479 frame.Header[0]|=0xf8;
480 frame.Header[1]|=0x01;
488 frame.Header[0]|=0xf8;
489 frame.Header[1]|=0x01;
497 frame.Header[0]|=0xf8;
498 frame.Header[1]|=0x01;
500 SetPFBit; /* XID frames are always used with the P/F-bit set to "1". */
508 frame.Header[0]|=0xf8;
509 frame.Header[1]|=0x01;
517 frame.Header[0]|=0xf8;
518 frame.Header[1]|=0x01;
520 ClearPFBit; /* REMAP frames are always used with P/F-bit set to "0". */
528 frame.Header[0]|=0xf0; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
529 frame.Header[1]|=0x01; /* 1 P/F ...N(R)... */
539 frame.Header[0]|=0xf0;
540 frame.Header[1]|=0x01;
550 frame.Header[0]|=0xf0;
551 frame.Header[1]|=0x01;
561 frame.Header[0]|=0xf0;
562 frame.Header[1]|=0x01;
609 /* Store FCS in the frame. */
610 RLP_CalculateCRC24Checksum((u8 *)&frame, 27, frame.FCS);
615 RLPSendFunction(&frame, OutDTX);
619 /* Check_input_PDU in Serge's code. */
621 void RLP_DisplayF96Frame(RLP_F96Frame *frame)
624 RLP_F96Header header;
627 for (count=0;count<RLP_M;count++) if (T_RCVS[count]>=0) T_RCVS[count]--;
629 CurrentFrameType=RLPFT_BAD;
632 /* no frame provided, drop through to state machine anyway */
633 } else if (RLP_CheckCRC24FCS((u8 *)frame, 30) == true) {
635 /* Here we have correct RLP frame so we can parse the field of the header
638 RLP_DecodeF96Header(frame, &header);
640 switch (header.Type) {
642 case RLPFT_U: /* Unnumbered frames. */
645 fprintf(stdout, "Unnumbered Frame [$%02x%02x] M=%02x ", frame->Header[0],
653 if (header.CR == 0 || header.PF == 0) break;
656 fprintf(stdout, "Set Asynchronous Balanced Mode (SABM) ");
659 CurrentFrameType=RLPFT_U_SABM;
664 if (header.CR == 1) break;
667 fprintf(stdout, "Unnumbered Acknowledge (UA) ");
670 CurrentFrameType=RLPFT_U_UA;
675 if (header.CR == 0) break;
678 fprintf(stdout, "Disconnect (DISC) ");
681 CurrentFrameType=RLPFT_U_DISC;
686 if (header.CR == 1) break;
689 fprintf(stdout, "Disconnected Mode (DM) ");
691 CurrentFrameType=RLPFT_U_DM;
698 fprintf(stdout, "Unnumbered Information (UI) ");
701 CurrentFrameType=RLPFT_U_UI;
708 fprintf(stdout, "Exchange Information (XID) \n");
709 RLP_DisplayXID(frame->Data);
712 CurrentFrameType=RLPFT_U_XID;
719 fprintf(stdout, "Test (TEST) ");
722 CurrentFrameType=RLPFT_U_TEST;
729 fprintf(stdout, "Null information (NULL) ");
732 CurrentFrameType=RLPFT_U_NULL;
739 fprintf(stdout, "Remap (REMAP) ");
742 CurrentFrameType=RLPFT_U_REMAP;
749 fprintf(stdout, _("Unknown!!! "));
752 CurrentFrameType=RLPFT_BAD;
759 case RLPFT_S: /* Supervisory frames. */
762 fprintf(stdout, "Supervisory Frame [$%02x%02x] S=0x%x N(R)=%d ",
774 fprintf(stdout, "RR");
777 CurrentFrameType=RLPFT_S_RR;
784 fprintf(stdout, "REJ");
787 CurrentFrameType=RLPFT_S_REJ;
794 fprintf(stdout, "RNR");
797 CurrentFrameType=RLPFT_S_RNR;
804 fprintf(stdout, "SREJ");
807 CurrentFrameType=RLPFT_S_SREJ;
814 fprintf(stdout, _("BAD"));
817 CurrentFrameType=RLPFT_BAD;
828 fprintf(stdout, "Info+Supervisory Frame [$%02x%02x] S=0x%x N(S)=%d N(R)=%d ",
841 fprintf(stdout, "RR");
844 CurrentFrameType=RLPFT_SI_RR;
851 fprintf(stdout, "REJ");
854 CurrentFrameType=RLPFT_SI_REJ;
861 fprintf(stdout, "RNR");
864 CurrentFrameType=RLPFT_SI_RNR;
871 fprintf(stdout, "SREJ");
874 CurrentFrameType=RLPFT_SI_SREJ;
881 fprintf(stdout, "BAD");
884 CurrentFrameType=RLPFT_BAD;
894 /* Command/Response and Poll/Final bits. */
896 fprintf(stdout, " C/R=%d P/F=%d", header.CR, header.PF);
903 if (CurrentFrameType!=RLPFT_U_NULL) {
905 fprintf(stdout, "\n");
907 for (count = 0; count < 25; count ++) {
909 if (isprint(frame->Data[count]))
910 fprintf(stdout, "[%02x%c]", frame->Data[count], frame->Data[count]);
912 fprintf(stdout, "[%02x ]", frame->Data[count]);
915 fprintf(stdout, "\n");
923 fprintf (stdout, " FCS: %02x %02x %02x\n\n", frame->FCS[0],
934 /* RLP Checksum failed - don't we need some statistics about these
935 failures? Nothing is printed, because in the first stage of connection
936 there are too many bad RLP frames... */
939 fprintf(stdout, _("Frame FCS is bad. Ignoring...\n"));
944 MAIN_STATE_MACHINE(frame, &header);
953 /* FIXME: real TEST_Handling - we do not handle TEST yet. */
955 void TEST_Handling() {
960 /* FIXME: better XID_handling - but this will answer a XID command. */
962 bool XID_Handling (RLP_F96Frame *frame, RLP_F96Header *header) {
968 if (CurrentFrameType == RLPFT_U_XID) {
972 while (frame->Data[count] !=0) {
974 type=frame->Data[count] >> 4;
975 length=frame->Data[count] & 0x0f;
980 case 0x01: /* RLP Version Number */
981 RLP_VersionNumber=frame->Data[count];
984 case 0x02: /* Interworking Function (IWF) to Mobile Station (MS) window size */
985 if (frame->Data[count]>=1 && frame->Data[count]<RLP_M)
986 RLP_RCV_WS=frame->Data[count];
989 case 0x03: /* MS to IWF window size */
990 if (frame->Data[count]>=1 && frame->Data[count]<RLP_M)
991 RLP_SEND_WS=frame->Data[count];
994 case 0x04: /* Acknowledgement Timer (T1). */
995 RLP_Timeout1_Limit=frame->Data[count];
998 case 0x05: /* Retransmission attempts (N2). */
999 RLP_N2=frame->Data[count];
1002 case 0x06: /* Reply delay (T2). */
1003 RLP_T2=frame->Data[count];
1006 case 0x07: /* Compression - not yet! */
1014 /* Now reassemble a reply */
1017 memset(frame->Data,0x00,25); /* Makes debugging easier */
1019 /* Version Number - force to 0 for now */
1020 RLP_VersionNumber=0;
1021 frame->Data[count++]=0x11;
1022 frame->Data[count++]=RLP_VersionNumber;
1025 frame->Data[count++]=0x21;
1026 frame->Data[count++]=RLP_RCV_WS;
1027 frame->Data[count++]=0x31;
1028 frame->Data[count++]=RLP_SEND_WS;
1030 /* Acknowledgement Timer (T1). */
1031 frame->Data[count++]=0x41;
1032 frame->Data[count++]=RLP_Timeout1_Limit;
1034 /* Retransmission attempts (N2). */
1035 frame->Data[count++]=0x51;
1036 frame->Data[count++]=RLP_N2;
1038 /* Reply delay (T2). */
1039 frame->Data[count++]=0x61;
1040 frame->Data[count++]=RLP_T2;
1042 XID_R_State = _send;
1051 bool Send_TXU(RLP_F96Frame *frame, RLP_F96Header *header) {
1054 // fprintf(stdout, _("Send_TXU()\n"));
1055 // fprintf(stdout, _("XID_R_State=%d\n"), XID_R_State);
1060 if (RLP_UserEvent(TEST_R_State)) {
1061 RLP_SendF96Frame(RLPFT_U_TEST, false, TEST_R_FBit, 0, 0, TEST_R_Data, false);
1068 if (XID_R_State == _send && frame) {
1069 RLP_SendF96Frame(RLPFT_U_XID, false, true, 0, 0, frame->Data, false);
1070 XID_R_State = _idle;
1076 else if ((XID_C_State == _send ) && (Poll_xchg == _idle)) {
1077 RLP_SendF96Frame(RLPFT_U_XID, true, true, 0, 0, XID_C_Data, false);
1078 XID_C_State = _wait;
1082 } else if (RLP_UserEvent(UI_State)) {
1083 RLP_SendF96Frame(RLPFT_U_UI, true, false, 0, 0, NULL, false);
1095 void RLP_DeliverAllInSeqIF()
1101 if ((R[VR].Data[0] & 0xE0)!=LastStatus) {
1102 LastStatus=(R[VR].Data[0] & 0xE0);
1103 RLP_Passup(StatusChange,&LastStatus,0);
1107 i=R[VR].Data[0] & 0x1f;
1111 /* FIXME - should check for more data in the frame */
1113 RLP_Passup(Data,R[VR].Data+1,j);
1118 } while (R[VR].State==_rcvd);
1122 /* Mark any missing information frames between VR and Ns*/
1123 void RLP_MarkMissingIF(u8 Ns)
1126 for (i=VR; i!=Ns; i=Incr(i)) {
1127 if (R[i].State==_idle) R[i].State=_srej; /* bug in spec, fig A.23 */
1132 /* Information frame handler */
1134 bool RLP_I_Handler(RLP_F96Frame *frame, RLP_F96Header *header)
1137 if ((header->CR) && (header->PF))
1140 /* If the window size is 61, a received frame must have a sequence
1141 number between VR and VR+60 */
1143 if (!InWindow(header->Ns,VR,VR+RLP_RCV_WS-1))
1146 if (header->Ns==VR) {
1147 /* This is not in the spec but I think it is necessary */
1148 if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1;
1150 memcpy(R[VR].Data,frame->Data,25);
1151 RLP_DeliverAllInSeqIF();
1154 else { /* Out of sequence, cause a SREJ */
1155 if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1;
1156 R[header->Ns].State=_rcvd;
1157 memcpy(R[header->Ns].Data,frame->Data,25);
1158 RLP_MarkMissingIF(header->Ns);
1165 /* Mark acknowledged send frames */
1167 void RLP_AdvanceVA(u8 Nr)
1176 /* Decrease VS back down to Nr since these have not been acknowledged */
1178 void RLP_DecreaseVS(u8 Nr)
1186 /* Supervisory frame handling */
1188 void RLP_S_Handler(RLP_F96Frame *frame, RLP_F96Header *header)
1192 if ((header->CR) && (header->PF)) {
1193 /* Special exchange (ie. error) - counter? */
1195 fprintf(stdout, "Got Poll command\n");
1199 for (i=0; i<RLP_M; i++) R[i].State=_idle;
1202 if (Poll_State!=_idle) {
1203 if (header->PF==0) return;
1204 if ((CurrentFrameType==RLPFT_S_SREJ) || (CurrentFrameType==RLPFT_S_REJ) ||
1205 (CurrentFrameType==RLPFT_SI_SREJ) || (CurrentFrameType==RLPFT_SI_REJ)) return;
1206 RLP_DecreaseVS(header->Nr);
1210 switch (CurrentFrameType){
1214 RLP_AdvanceVA(header->Nr);
1219 RLP_AdvanceVA(header->Nr);
1224 RLP_AdvanceVA(header->Nr);
1226 RLP_DecreaseVS(header->Nr);
1230 S[header->Nr].State=_send;
1242 /* Find the first SREJ frame */
1244 bool RLP_SREJSlot(u8 *x)
1248 for (i=Incr(VR); i!=VR; i=Incr(i)) if (R[i].State==_srej) {
1258 /* Check if any SREJ frames need sending, if not send the next in line */
1260 bool RLP_PrepareDataToTransmit(u8 *p)
1264 for (i=VA; i!=VS; i=Incr(i))
1265 if (S[i].State==_send) {
1270 if (S[VS].State!=_send) return false;
1271 if (!InWindow(VS,VA,VA+RLP_SEND_WS-1))
1281 /* Send a SREJ command */
1283 void RLP_SendSREJ(u8 x)
1287 if ((Poll_xchg==_idle) && (Poll_State==_send)) {
1290 fprintf(stdout, "Sending SREJ with poll\n");
1293 RLP_SendF96Frame(RLPFT_S_SREJ, true, true, x , 0 , NULL, false);
1295 RLP_SetTimer(&T_RCVS[x]);
1301 else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1303 fprintf(stdout, "Sending SREJ for %d along with frame %d\n",x,k);
1305 RLP_SendF96Frame(RLPFT_SI_SREJ, true, false, x , k , S[k].Data, false);
1307 RLP_SetTimer(&T_RCVS[x]);
1312 fprintf(stdout, "Sending SREJ for %d\n",x);
1314 RLP_SendF96Frame(RLPFT_S_SREJ, true, false, x , 0 , NULL, false);
1316 RLP_SetTimer(&T_RCVS[x]);
1321 /* Send a command */
1323 void RLP_Send_XX_Cmd(RLP_FrameTypes type)
1327 if ((Poll_xchg!=_wait) && (Poll_State==_send)) {
1328 RLP_SendF96Frame(type, true, true, VR , 0 , NULL, false);
1330 fprintf(stdout, "Sending Comd %x with Poll\n",type);
1338 else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1340 fprintf(stdout, "Sending Comd %x with frame %d\n",type,k);
1342 RLP_SendF96Frame(type+4, true, false, VR , k , S[k].Data, false);
1349 fprintf(stdout, "Sending Comd %x\n",type);
1351 RLP_SendF96Frame(type, true, false, VR , 0 , NULL, false);
1354 DTX_VR=VR; /* As v7.1.0 spec */
1359 /* Send a Response */
1361 void RLP_Send_XX_Resp(RLP_FrameTypes type)
1365 if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1367 fprintf(stdout, "Sending Resp %x with frame %d\n",type+4,k);
1369 RLP_SendF96Frame(type+4, false, true, VR , k , S[k].Data, false);
1376 fprintf(stdout, "Sending Resp %x\n",type);
1378 RLP_SendF96Frame(type, false, true, VR , 0 , NULL, false);
1385 /* Decide which frame to use and send it - currently only used in state 4 */
1391 if (UA_State==_send) {
1392 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0 , 0 , NULL, false);
1395 else if (Ackn_FBit==true) {
1397 printf("About to send Poll resp\n");
1399 if (LRReady) RLP_Send_XX_Resp(RLPFT_S_RR);
1400 else RLP_Send_XX_Resp(RLPFT_S_RNR);
1402 else if (RLP_SREJSlot(&x)) RLP_SendSREJ(x);
1403 else if (LRReady) RLP_Send_XX_Cmd(RLPFT_S_RR);
1404 else RLP_Send_XX_Cmd(RLPFT_S_RNR);
1407 void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header) {
1410 switch (CurrentState) {
1412 /***** RLP State 0. *****/
1414 /* ADM and Detached.
1416 This is the initial state after power on.
1418 As long as the RLP entity is "Detached", DISC(P) and/or SABM at the
1419 lower interface is acted upon by sending DM(P) or DM(1). Any other
1420 stimulus at the lower interface is ignored.
1422 This state can be exited only with Attach_Req. */
1427 fprintf(stdout, _("RLP state 0.\n"));
1430 switch (CurrentFrameType) {
1433 RLP_SendF96Frame(RLPFT_U_DM, false, header->PF, 0, 0, NULL, false);
1437 RLP_SendF96Frame(RLPFT_U_DM, false, true, 0, 0, NULL, false);
1441 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1442 if (RLP_GetUserRequest(Attach_Req)) {
1451 /***** RLP State 1. *****/
1453 /* ADM and Attached.
1455 The RLP entity is ready to established a connection, either by
1456 initiating the connection itself (Conn_Req) or by responding to an
1457 incoming connection request (SABM).
1459 Upon receiving a DISC PDU, the handling of the UA response is
1465 fprintf(stdout, _("RLP state 1.\n"));
1468 if (!XID_Handling(frame, header)) {
1470 switch(CurrentFrameType) {
1477 RLP_Passup(Conn_Ind,NULL,0);
1486 case RLPFT_BAD: /* If we get a bad frame we can still respond with SABM */
1488 if (RLP_GetUserRequest(Conn_Req)) {
1497 if (!Send_TXU(frame, header)) {
1499 if (UA_State == _send) {
1500 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1504 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1508 /***** RLP State 2. *****/
1513 fprintf(stdout, _("RLP state 2.\n"));
1516 if (!XID_Handling(frame, header)) {
1518 switch(CurrentFrameType) {
1547 fprintf(stdout, _("UA received in RLP state 2.\n"));
1550 if (SABM_State == _wait && header->PF) {
1559 if (SABM_State == _wait && header->PF) {
1561 // Conn_Conf_Neg=true;
1567 if (T == RLP_Timeout1_Limit) {
1569 if (SABM_Count>RLP_N2)
1577 if (!Send_TXU(frame, header)) {
1579 if (SABM_State == _send && Poll_xchg == _idle) {
1580 RLP_SendF96Frame(RLPFT_U_SABM, true, true, 0, 0, NULL, false);
1586 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1589 if (RLP_GetUserRequest(Disc_Req)) {
1593 DISC_PBit=(Poll_xchg==_idle);
1599 /***** RLP State 3. *****/
1604 fprintf(stdout, _("RLP state 3.\n"));
1607 if (!XID_Handling(frame, header)) {
1609 switch(CurrentFrameType) {
1616 RLP_Passup(Disc_Ind,NULL,0);
1623 if (RLP_GetUserRequest(Conn_Req)) {
1627 RLP_Init_link_vars();
1628 } else if (RLP_GetUserRequest(Conn_Req_Neg)) {
1629 DM_State=_send; /* FIXME - code to handle DM_State - missing from spec? */
1637 if (!Send_TXU(frame, header)) {
1639 if (UA_State == _send) {
1640 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1644 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1648 if (RLP_GetUserRequest(Disc_Req)) {
1652 DISC_PBit=(Poll_xchg==_idle);
1658 /***** RLP State 4. *****/
1663 fprintf(stdout, _("RLP state 4.\n"));
1666 if (!XID_Handling(frame, header)) {
1668 switch (CurrentFrameType) {
1676 RLP_Passup(Disc_Ind,NULL,0);
1684 RLP_Passup(Reset_Ind,NULL,0);
1691 /* Should check here for unsolicited Fbit */
1692 /* Spec says: "Nr must be within the set of not yet
1693 acknowledged I-frames or it must be the next possible
1694 frame number." That's VA..VS-1 or VS, i.e. VA..VS */
1695 if (!InWindow(header->Nr,VA,VS))
1697 RLP_S_Handler(frame,header);
1703 /* Should check here for unsolicited Fbit */
1704 if (!InWindow(header->Nr,VA,VS))
1706 if (!RLP_I_Handler(frame,header)) RLP_S_Handler(frame,header);
1713 for (i=0;i<RLP_M;i++) if (T_RCVS[i]==0) {
1715 fprintf(stdout, "T_RCVS[%d] Timeout in State 4\n",i);
1722 fprintf(stdout, "T Timeout in State 4\n");
1726 if (Poll_State==_idle) {
1731 if (Poll_Count>RLP_N2) {
1733 fprintf(stdout, "N2 Errors in State 4\n");
1741 if (!Send_TXU(frame,header)) {
1742 if (UA_State == _send) {
1743 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1746 else RLP_SendData();
1750 /* Load any data from the Send ringbuffer into the send slots */
1751 RLP_AddRingBufferDataToSlots();
1754 // if (CurrentFrameType!=RLPFT_BAD)
1755 fprintf(stdout, "VD=%d, VA=%d, VS=%d, VR=%d\n",VD,VA,VS,VR);
1756 #ifdef RLP_DEBUG_STATE
1760 if(UA_State!=_idle) printf("[UA_State %d]",UA_State);
1761 if(UI_State!=_idle) printf("[UI_State %d]",UI_State);
1762 if(Ackn_State!=_idle) printf("[Ackn_State %d]",Ackn_State);
1763 if(Poll_State!=_idle) printf("[Poll_State %d]",Poll_State);
1764 if(Poll_xchg!=_idle) printf("[Poll_xchg %d]",Poll_xchg);
1765 if(SABM_State!=_idle) printf("[SABM_State %d]",SABM_State);
1766 if(DISC_State!=_idle) printf("[DISC_State %d]",DISC_State);
1767 if(DM_State!=_idle) printf("[DM_State %d]",DM_State);
1768 if(XI_R_State!=_idle) printf("[XI_R_State %d]",XI_R_State);
1769 if(XID_C_State!=_idle) printf("[XID_C_State %d]",XID_C_State);
1770 if(XID_R_State!=_idle) printf("[XID_R_State %d]",XID_R_State);
1771 if(TEST_R_State!=_idle) printf("[TEST_R_State %d]",TEST_R_State);
1774 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",S[zzz].State);
1776 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",R[zzz].State);
1777 printf("\nT: %d, T_RCVS: ",T);
1778 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",T_RCVS[zzz]);
1785 if (RLP_GetUserRequest(Disc_Req)) {
1790 DISC_PBit=(Poll_xchg==_idle);
1797 /***** RLP State 5. *****/
1802 fprintf(stdout, _("RLP state 5.\n"));
1805 if (!XID_Handling(frame, header)) {
1807 switch (CurrentFrameType) {
1811 if ((DISC_State==_wait) && (DISC_PBit==header->PF)) {
1812 if (DISC_PBit==true) Poll_xchg=_idle;
1828 if (!Send_TXU(frame,header)) {
1829 if ((DISC_State!=_wait) && !((DISC_PBit==true) && (Poll_xchg==_wait))) {
1830 RLP_SendF96Frame(RLPFT_U_DISC, true, DISC_PBit, 0, 0, NULL, false);
1831 if (DISC_PBit==true) Poll_xchg=_wait;
1837 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1841 if (DISC_PBit==1) Poll_xchg=_idle;
1843 if (DISC_Count>RLP_N2) {
1846 fprintf(stdout, "N2 error in State 5!\n");
1855 /***** RLP State 6. *****/
1856 /* We should only get here after a Reset_Req which is not yet supported */
1861 fprintf(stdout, _("RLP state 6 - not yet implemented!\n"));
1864 if (!XID_Handling(frame, header)) {
1866 switch (CurrentFrameType) {
1873 if (!Send_TXU(frame,header)) {
1876 if (RLP_GetUserRequest(Disc_Req)) {
1880 DISC_PBit=(Poll_xchg==_idle);
1887 /***** RLP State 7. *****/
1892 fprintf(stdout, _("RLP state 7.\n"));
1895 if (!XID_Handling(frame, header)) {
1897 switch (CurrentFrameType) {
1899 RLP_Passup(Disc_Ind,NULL,0);
1909 if (RLP_GetUserRequest(Reset_Resp)){
1912 RLP_Init_link_vars();
1916 if (!Send_TXU(frame,header)) {
1917 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1920 if (RLP_GetUserRequest(Disc_Req)) {
1924 DISC_PBit=(Poll_xchg==_idle);
1934 fprintf(stdout, _("DEBUG: Unknown RLP state!\n"));
1940 CurrentState=NextState;
1944 /* Given a pointer to an RLP XID frame, display contents in human readable
1945 form. Note for now only Version 0 and 1 are supported. Fields can appear
1946 in any order and are delimited by a zero type field. This function is the
1947 exact implementation of section 5.2.2.6, Exchange Identification, XID of
1948 the GSM specification 04.22. */
1950 void RLP_DisplayXID(u8 *frame)
1953 int count = 25; /* Sanity check */
1956 fprintf(stdout, "XID: ");
1958 while ((*frame !=0) && (count >= 0)) {
1961 length = *frame & 0x0f;
1965 case 0x01: /* RLP Version Number, probably 1 for Nokia. */
1968 fprintf(stdout, "Ver %d ", *frame);
1971 case 0x02: /* IWF to MS window size */
1974 fprintf(stdout, "IWF-MS %d ", *frame);
1977 case 0x03: /* MS to IWF window size. */
1980 fprintf(stdout, "MS-IWF %d ", *frame);
1983 case 0x04: /* Acknowledgement Timer (T1). */
1986 fprintf(stdout, "T1 %dms ", *frame * 10);
1989 case 0x05: /* Retransmission attempts (N2). */
1992 fprintf(stdout, "N2 %d ", *frame);
1995 case 0x06: /* Reply delay (T2). */
1998 fprintf(stdout, "T2 %dms ", *frame * 10);
2001 case 0x07: /* Compression. */
2004 fprintf(stdout, "Comp [Pt=%d ", (*frame >> 4) );
2005 fprintf(stdout, "P0=%d ", (*frame & 0x03) );
2008 fprintf(stdout, "P1l=%d ", *frame);
2010 fprintf(stdout, "P1h=%d ", *frame);
2013 fprintf(stdout, "P2=%d] ", *frame);
2019 fprintf(stdout, "Unknown! type=%02x, length=%02x", type, length);
2030 /* Given a pointer to an F9.6 Frame, split data out into component parts of
2031 header and determine frame type. */
2033 void RLP_DecodeF96Header(RLP_F96Frame *frame, RLP_F96Header *header)
2036 /* Poll/Final bit. */
2038 if ((frame->Header[1] & 0x02))
2043 /* Command/Response bit. */
2045 if ((frame->Header[0] & 0x01))
2050 /* Send Sequence Number. */
2052 header->Ns = frame->Header[0] >> 3;
2054 if ((frame->Header[1] & 0x01))
2055 header->Ns |= 0x20; /* Most significant bit. */
2057 /* Determine frame type. See the section 5.2.1 in the GSM 04.22
2060 switch (header->Ns) {
2062 case 0x3f: /* Frames of type U, unnumbered frames. */
2064 /* U frames have M1, ..., M5 stored in the place of N(R). */
2066 header->Type = RLPFT_U;
2067 header->M = (frame->Header[1] >> 2) & 0x1f;
2068 return; /* For U frames, we do not need N(R) and bits S1 and S2. */
2070 case 0x3e: /* Frames of type S, supervisory frames. */
2072 header->Type = RLPFT_S;
2075 default: /* Frames of type I+S, numbered information transfer ans
2076 supervisory frames combined. */
2078 header->Type = RLPFT_IS;
2082 /* Receive Sequence Number N(R). */
2083 header->Nr = frame->Header[1] >> 2;
2085 /* Status bits (S1 and S2). */
2086 header->S = (frame->Header[0] >> 1) & 0x03;