7 A Linux/Unix toolset and driver for Nokia mobile phones.
9 Released under the terms of the GNU GPL, see file COPYING for more details.
11 The development of RLP protocol is sponsored by SuSE CR, s.r.o. (Pavel use
12 the SIM card from SuSE for testing purposes).
14 Actual implementation of RLP protocol. Based on GSM 04.22 version 7.1.0,
15 downloadable from www.etsi.org (if you register with them)
26 #include "data/rlp-common.h"
27 #include "data/rlp-crc24.h"
28 #include "gsm-common.h" /* For GSM error and RLP send function. */
29 #include "misc.h" /* For u8, u32 etc. */
32 #define INLINE __inline
37 /* Our state machine which handles all of nine possible states of RLP
39 static void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header);
41 /* This is the type we are just handling. */
42 static RLP_FrameTypes CurrentFrameType;
44 /* Current state of RLP state machine. */
45 static RLP_State CurrentState=RLP_S0; /* We start at ADM and Detached */
47 /* Next state of RLP state machine. */
48 static RLP_State NextState;
50 /* Pointer to Send function that sends frame to phone. */
51 static bool (*RLPSendFunction)(RLP_F96Frame *frame, bool out_dtx);
53 /* Pointer to Passup function which returns data/inds */
54 static int (*RLP_Passup)(RLP_UserInds ind, u8 *buffer, int length);
57 /* State variables - see GSM 04.22, Annex A, section A.1.2 */
59 static RLP_StateVariable UA_State;
61 static RLP_StateVariable UI_State;
63 static RLP_StateVariable Ackn_State;
64 static RLP_StateVariable Poll_State;
65 static RLP_StateVariable Poll_xchg;
66 static RLP_StateVariable SABM_State;
67 static RLP_StateVariable DISC_State;
68 static RLP_StateVariable DM_State; /* FIXME - not handled */
70 static RLP_StateVariable XID_C_State;
72 static RLP_StateVariable XID_R_State;
74 static RLP_StateVariable TEST_R_State;
84 static RLP_FrameTypes DTX_SF;
88 static RLP_Data R[RLP_M];
89 static RLP_Data S[RLP_M];
91 static RLP_StateVariable SABM_State;
92 static int SABM_Count;
94 static RLP_UserRequestStore UserRequests;
96 static u8 Poll_Count=0;
98 /* For now timing is done based on a frame reception rate of 20ms */
99 /* Serge has measured it as 18.4ms */
100 #define RLP_T_Scaling 2
102 /* Timers - a value of -1 means not set */
103 /* To set, timer is loaded with RLP_Timeout1_Limit/RLP_T_Scaling. */
104 /* Each received frame (including NULLS / errors) any >0 timer is decrease */
107 static int T_RCVS[RLP_M];
109 static bool UA_FBit=true;
110 static bool Ackn_FBit=false;
111 static bool DM_FBit=false; /* FIXME - not handled */
112 static bool RRReady=false;
113 static bool LRReady=true; /* FIXME - not handled (as if we couldn't keep up with 9600bps :-) */
114 static bool DISC_PBit=false;
116 static u8 LastStatus=0xff; /* Last Status byte */
119 /* RLP Parameters. FIXME: Reset these - e.g. when entering state 0 */
121 static u8 RLP_SEND_WS = RLP_M-1;
122 static u8 RLP_RCV_WS = RLP_M-1;
123 static u8 RLP_Timeout1_Limit = 55;
124 static u8 RLP_N2 = 15; /* Maximum number of retransmisions. GSM spec says 6 here, but
125 Nokia will XID this. */
127 static u8 RLP_VersionNumber=0;
131 /****** Externally called functions ********/
132 /*******************************************/
135 /* Function to initialise RLP code. Main purpose for now is
136 to set the address of the RLP send function in the API code. */
138 void RLP_Initialise(bool (*rlp_send_function)(RLP_F96Frame *frame, bool out_dtx), int (*rlp_passup)(RLP_UserInds ind, u8 *buffer, int length))
142 RLPSendFunction = rlp_send_function;
143 RLP_Passup=rlp_passup;
144 UserRequests.Conn_Req=false;
145 UserRequests.Attach_Req=false;
146 UserRequests.Conn_Req_Neg=false;
147 UserRequests.Reset_Resp=false;
148 UserRequests.Disc_Req=false;
151 for (i=0;i<RLP_M;i++) T_RCVS[i]=-1;
163 RLP_SEND_WS = RLP_M-1;
164 RLP_RCV_WS = RLP_M-1;
165 RLP_Timeout1_Limit = 55;
172 /* Set a user event */
173 /* Called by user program for now */
175 void RLP_SetUserRequest(RLP_UserRequests type, bool value) {
179 UserRequests.Conn_Req=value;
182 UserRequests.Attach_Req=value;
185 UserRequests.Conn_Req_Neg=value;
188 UserRequests.Reset_Resp=value;
191 UserRequests.Disc_Req=value;
201 /***** Internal functions **********/
202 /***********************************/
205 /* Check whether a user event is set */
207 static bool RLP_GetUserRequest(RLP_UserRequests type) {
209 bool result=false, *x;
213 x=&UserRequests.Conn_Req;
216 x=&UserRequests.Attach_Req;
219 x=&UserRequests.Conn_Req_Neg;
222 x=&UserRequests.Reset_Resp;
225 x=&UserRequests.Disc_Req;
240 static void RLP_SetTimer(int *timer)
242 *timer=(int)(RLP_Timeout1_Limit/RLP_T_Scaling);
246 /* Previous sequence number. */
247 static INLINE u8 Decr(u8 x)
255 /* Next sequence number. */
256 static INLINE u8 Incr(u8 x)
264 /* Difference between sequence numbers. */
266 /* FIXME: Not used now, so I have commented it out. PJ
267 * static INLINE u8 Diff(u8 x, u8 y)
270 * return (result >= 0) ? result : result + RLP_M;
274 /* Check value is within range */
275 static bool InWindow(u8 val, u8 lower, u8 upper)
277 /* allow for one level of wrapping round */
278 if (lower>=RLP_M) lower-=RLP_M;
279 if (upper>=RLP_M) upper-=RLP_M;
280 if (val>=RLP_M) val-=RLP_M;
282 /* .......L*****U....... */
284 return (val >= lower) && (val <= upper);
286 /* ******U.........L***** */
287 return (val <= upper) || (val >= lower);
290 static void RLP_Init_link_vars(void)
300 RRReady=true; /* This seems a bit strange but it's what the spec says... */
307 for(i=0;i<RLP_M;i++) {
315 static void RLP_AddRingBufferDataToSlots(void)
320 while ((S[VD].State==_idle)
321 && ((size=RLP_Passup(GetData,buffer,24))!=0)) {
322 memset(S[VD].Data,0xff,25); /* FIXME - this isn't necessary - but makes debugging easier! */
327 else S[VD].Data[0]=size;
329 memcpy(&S[VD].Data[1],buffer,size);
331 if (size!=24) S[VD].Data[size+1]=0x1f;
341 /* FIXME: Remove this after finishing. */
343 static void X(RLP_F96Frame *frame) {
348 printf("byte[%2d]: %02x\n", i, *( (u8 *)frame+i));
355 static void ResetAllT_RCVS(void)
359 for (i=0;i<RLP_M;i++) T_RCVS[i]=-1;
364 /* This function is used for sending RLP frames to the phone. */
366 static void RLP_SendF96Frame(RLP_FrameTypes FrameType,
367 bool OutCR, bool OutPF,
369 u8 *OutData, u8 OutDTX)
378 #define SetCRBit frame.Header[0]|=0x01;
379 #define SetPFBit frame.Header[1]|=0x02;
381 #define ClearCRBit frame.Header[0]&=(~0x01);
382 #define ClearPFBit frame.Header[1]&=(~0x02);
384 /* If Command/Response bit is set, set it in the header. */
389 /* If Poll/Final bit is set, set it in the header. */
394 /* If OutData is not specified (ie. is NULL) we want to clear frame.Data
395 array for the user. */
398 frame.Data[0]=0x00; // 0x1f
405 frame.Data[i]=OutData[i];
408 #define PackM(x) frame.Header[1]|=((x)<<2);
409 #define PackS(x) frame.Header[0]|=((x)<<1);
410 #define PackNR frame.Header[1]|=(OutNR<<2);
411 #define PackNS frame.Header[0]|=(OutNS<<3);frame.Header[1]|=(OutNS>>5);
415 /* Unnumbered frames. Be careful - some commands are used as commands
416 only, so we have to set C/R bit later. We should not allow user for
417 example to send SABM as response because in the spec is: The SABM
418 encoding is used as command only. */
422 frame.Header[0]|=0xf8; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
423 frame.Header[1]|=0x01; /* 1 P/F M1 M2 M3 M4 M5 X */
425 SetCRBit; /* The SABM encoding is used as a command only. */
426 SetPFBit; /* It is always used with the P-bit set to "1". */
434 frame.Header[0]|=0xf8;
435 frame.Header[1]|=0x01;
437 ClearCRBit; /* The UA encoding is used as a response only. */
445 frame.Header[0]|=0xf8;
446 frame.Header[1]|=0x01;
448 SetCRBit; /* The DISC encoding is used as a command only. */
456 frame.Header[0]|=0xf8;
457 frame.Header[1]|=0x01;
459 ClearCRBit; /* The DM encoding is used as a response only. */
467 frame.Header[0]|=0xf8;
468 frame.Header[1]|=0x01;
476 frame.Header[0]|=0xf8;
477 frame.Header[1]|=0x01;
485 frame.Header[0]|=0xf8;
486 frame.Header[1]|=0x01;
488 SetPFBit; /* XID frames are always used with the P/F-bit set to "1". */
496 frame.Header[0]|=0xf8;
497 frame.Header[1]|=0x01;
505 frame.Header[0]|=0xf8;
506 frame.Header[1]|=0x01;
508 ClearPFBit; /* REMAP frames are always used with P/F-bit set to "0". */
516 frame.Header[0]|=0xf0; /* See page 11 of the GSM 04.22 spec - 0 X X 1 1 1 1 1 */
517 frame.Header[1]|=0x01; /* 1 P/F ...N(R)... */
527 frame.Header[0]|=0xf0;
528 frame.Header[1]|=0x01;
538 frame.Header[0]|=0xf0;
539 frame.Header[1]|=0x01;
549 frame.Header[0]|=0xf0;
550 frame.Header[1]|=0x01;
597 /* Store FCS in the frame. */
598 RLP_CalculateCRC24Checksum((u8 *)&frame, 27, frame.FCS);
603 RLPSendFunction(&frame, OutDTX);
607 static void RLP_DecodeF96Header(RLP_F96Frame *frame, RLP_F96Header *header);
609 /* Check_input_PDU in Serge's code. */
611 void RLP_DisplayF96Frame(RLP_F96Frame *frame)
614 RLP_F96Header header;
617 for (count=0;count<RLP_M;count++) if (T_RCVS[count]>=0) T_RCVS[count]--;
619 CurrentFrameType=RLPFT_BAD;
622 /* no frame provided, drop through to state machine anyway */
623 } else if (RLP_CheckCRC24FCS((u8 *)frame, 30) == true) {
625 /* Here we have correct RLP frame so we can parse the field of the header
628 RLP_DecodeF96Header(frame, &header);
630 switch (header.Type) {
632 case RLPFT_U: /* Unnumbered frames. */
635 fprintf(stdout, "Unnumbered Frame [$%02x%02x] M=%02x ", frame->Header[0],
643 if (header.CR == 0 || header.PF == 0) break;
646 fprintf(stdout, "Set Asynchronous Balanced Mode (SABM) ");
649 CurrentFrameType=RLPFT_U_SABM;
654 if (header.CR == 1) break;
657 fprintf(stdout, "Unnumbered Acknowledge (UA) ");
660 CurrentFrameType=RLPFT_U_UA;
665 if (header.CR == 0) break;
668 fprintf(stdout, "Disconnect (DISC) ");
671 CurrentFrameType=RLPFT_U_DISC;
676 if (header.CR == 1) break;
679 fprintf(stdout, "Disconnected Mode (DM) ");
681 CurrentFrameType=RLPFT_U_DM;
688 fprintf(stdout, "Unnumbered Information (UI) ");
691 CurrentFrameType=RLPFT_U_UI;
698 fprintf(stdout, "Exchange Information (XID) \n");
699 RLP_DisplayXID(frame->Data);
702 CurrentFrameType=RLPFT_U_XID;
709 fprintf(stdout, "Test (TEST) ");
712 CurrentFrameType=RLPFT_U_TEST;
719 fprintf(stdout, "Null information (NULL) ");
722 CurrentFrameType=RLPFT_U_NULL;
729 fprintf(stdout, "Remap (REMAP) ");
732 CurrentFrameType=RLPFT_U_REMAP;
739 fprintf(stdout, _("Unknown!!! "));
742 CurrentFrameType=RLPFT_BAD;
749 case RLPFT_S: /* Supervisory frames. */
752 fprintf(stdout, "Supervisory Frame [$%02x%02x] S=0x%x N(R)=%d ",
764 fprintf(stdout, "RR");
767 CurrentFrameType=RLPFT_S_RR;
774 fprintf(stdout, "REJ");
777 CurrentFrameType=RLPFT_S_REJ;
784 fprintf(stdout, "RNR");
787 CurrentFrameType=RLPFT_S_RNR;
794 fprintf(stdout, "SREJ");
797 CurrentFrameType=RLPFT_S_SREJ;
804 fprintf(stdout, _("BAD"));
807 CurrentFrameType=RLPFT_BAD;
818 fprintf(stdout, "Info+Supervisory Frame [$%02x%02x] S=0x%x N(S)=%d N(R)=%d ",
831 fprintf(stdout, "RR");
834 CurrentFrameType=RLPFT_SI_RR;
841 fprintf(stdout, "REJ");
844 CurrentFrameType=RLPFT_SI_REJ;
851 fprintf(stdout, "RNR");
854 CurrentFrameType=RLPFT_SI_RNR;
861 fprintf(stdout, "SREJ");
864 CurrentFrameType=RLPFT_SI_SREJ;
871 fprintf(stdout, "BAD");
874 CurrentFrameType=RLPFT_BAD;
884 /* Command/Response and Poll/Final bits. */
886 fprintf(stdout, " C/R=%d P/F=%d", header.CR, header.PF);
893 if (CurrentFrameType!=RLPFT_U_NULL) {
895 fprintf(stdout, "\n");
897 for (count = 0; count < 25; count ++) {
899 if (isprint(frame->Data[count]))
900 fprintf(stdout, "[%02x%c]", frame->Data[count], frame->Data[count]);
902 fprintf(stdout, "[%02x ]", frame->Data[count]);
905 fprintf(stdout, "\n");
913 fprintf (stdout, " FCS: %02x %02x %02x\n\n", frame->FCS[0],
924 /* RLP Checksum failed - don't we need some statistics about these
925 failures? Nothing is printed, because in the first stage of connection
926 there are too many bad RLP frames... */
929 fprintf(stdout, _("Frame FCS is bad. Ignoring...\n"));
934 MAIN_STATE_MACHINE(frame, &header);
943 /* FIXME: real TEST_Handling - we do not handle TEST yet. */
945 static void TEST_Handling() {
950 /* FIXME: better XID_handling - but this will answer a XID command. */
952 static bool XID_Handling (RLP_F96Frame *frame, RLP_F96Header *header) {
958 if (CurrentFrameType == RLPFT_U_XID) {
962 while (frame->Data[count] !=0) {
964 type=frame->Data[count] >> 4;
965 length=frame->Data[count] & 0x0f;
970 case 0x01: /* RLP Version Number */
971 RLP_VersionNumber=frame->Data[count];
974 case 0x02: /* Interworking Function (IWF) to Mobile Station (MS) window size */
975 if (frame->Data[count]>=1 && frame->Data[count]<RLP_M)
976 RLP_RCV_WS=frame->Data[count];
979 case 0x03: /* MS to IWF window size */
980 if (frame->Data[count]>=1 && frame->Data[count]<RLP_M)
981 RLP_SEND_WS=frame->Data[count];
984 case 0x04: /* Acknowledgement Timer (T1). */
985 RLP_Timeout1_Limit=frame->Data[count];
988 case 0x05: /* Retransmission attempts (N2). */
989 RLP_N2=frame->Data[count];
992 case 0x06: /* Reply delay (T2). */
993 RLP_T2=frame->Data[count];
996 case 0x07: /* Compression - not yet! */
1004 /* Now reassemble a reply */
1007 memset(frame->Data,0x00,25); /* Makes debugging easier */
1009 /* Version Number - force to 0 for now */
1010 RLP_VersionNumber=0;
1011 frame->Data[count++]=0x11;
1012 frame->Data[count++]=RLP_VersionNumber;
1015 frame->Data[count++]=0x21;
1016 frame->Data[count++]=RLP_RCV_WS;
1017 frame->Data[count++]=0x31;
1018 frame->Data[count++]=RLP_SEND_WS;
1020 /* Acknowledgement Timer (T1). */
1021 frame->Data[count++]=0x41;
1022 frame->Data[count++]=RLP_Timeout1_Limit;
1024 /* Retransmission attempts (N2). */
1025 frame->Data[count++]=0x51;
1026 frame->Data[count++]=RLP_N2;
1028 /* Reply delay (T2). */
1029 frame->Data[count++]=0x61;
1030 frame->Data[count++]=RLP_T2;
1032 XID_R_State = _send;
1041 static bool Send_TXU(RLP_F96Frame *frame, RLP_F96Header *header) {
1044 // fprintf(stdout, _("Send_TXU()\n"));
1045 // fprintf(stdout, _("XID_R_State=%d\n"), XID_R_State);
1050 if (RLP_UserEvent(TEST_R_State)) {
1051 RLP_SendF96Frame(RLPFT_U_TEST, false, TEST_R_FBit, 0, 0, TEST_R_Data, false);
1058 if (XID_R_State == _send && frame) {
1059 RLP_SendF96Frame(RLPFT_U_XID, false, true, 0, 0, frame->Data, false);
1060 XID_R_State = _idle;
1066 else if ((XID_C_State == _send ) && (Poll_xchg == _idle)) {
1067 RLP_SendF96Frame(RLPFT_U_XID, true, true, 0, 0, XID_C_Data, false);
1068 XID_C_State = _wait;
1072 } else if (RLP_UserEvent(UI_State)) {
1073 RLP_SendF96Frame(RLPFT_U_UI, true, false, 0, 0, NULL, false);
1085 static void RLP_DeliverAllInSeqIF()
1091 if ((R[VR].Data[0] & 0xE0)!=LastStatus) {
1092 LastStatus=(R[VR].Data[0] & 0xE0);
1093 RLP_Passup(StatusChange,&LastStatus,0);
1097 i=R[VR].Data[0] & 0x1f;
1101 /* FIXME - should check for more data in the frame */
1103 RLP_Passup(Data,R[VR].Data+1,j);
1108 } while (R[VR].State==_rcvd);
1112 /* Mark any missing information frames between VR and Ns*/
1113 static void RLP_MarkMissingIF(u8 Ns)
1116 for (i=VR; i!=Ns; i=Incr(i)) {
1117 if (R[i].State==_idle) R[i].State=_srej; /* bug in spec, fig A.23 */
1122 /* Information frame handler */
1124 static bool RLP_I_Handler(RLP_F96Frame *frame, RLP_F96Header *header)
1127 if ((header->CR) && (header->PF))
1130 /* If the window size is 61, a received frame must have a sequence
1131 number between VR and VR+60 */
1133 if (!InWindow(header->Ns,VR,VR+RLP_RCV_WS-1))
1136 if (header->Ns==VR) {
1137 /* This is not in the spec but I think it is necessary */
1138 if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1;
1140 memcpy(R[VR].Data,frame->Data,25);
1141 RLP_DeliverAllInSeqIF();
1144 else { /* Out of sequence, cause a SREJ */
1145 if (R[header->Ns].State==_wait) T_RCVS[header->Ns]=-1;
1146 R[header->Ns].State=_rcvd;
1147 memcpy(R[header->Ns].Data,frame->Data,25);
1148 RLP_MarkMissingIF(header->Ns);
1155 /* Mark acknowledged send frames */
1157 static void RLP_AdvanceVA(u8 Nr)
1166 /* Decrease VS back down to Nr since these have not been acknowledged */
1168 static void RLP_DecreaseVS(u8 Nr)
1176 /* Supervisory frame handling */
1178 static void RLP_S_Handler(RLP_F96Frame *frame, RLP_F96Header *header)
1182 if ((header->CR) && (header->PF)) {
1183 /* Special exchange (ie. error) - counter? */
1185 fprintf(stdout, "Got Poll command\n");
1189 for (i=0; i<RLP_M; i++) R[i].State=_idle;
1192 if (Poll_State!=_idle) {
1193 if (header->PF==0) return;
1194 if ((CurrentFrameType==RLPFT_S_SREJ) || (CurrentFrameType==RLPFT_S_REJ) ||
1195 (CurrentFrameType==RLPFT_SI_SREJ) || (CurrentFrameType==RLPFT_SI_REJ)) return;
1196 RLP_DecreaseVS(header->Nr);
1200 switch (CurrentFrameType){
1204 RLP_AdvanceVA(header->Nr);
1209 RLP_AdvanceVA(header->Nr);
1214 RLP_AdvanceVA(header->Nr);
1216 RLP_DecreaseVS(header->Nr);
1220 S[header->Nr].State=_send;
1232 /* Find the first SREJ frame */
1234 static bool RLP_SREJSlot(u8 *x)
1238 for (i=Incr(VR); i!=VR; i=Incr(i)) if (R[i].State==_srej) {
1248 /* Check if any SREJ frames need sending, if not send the next in line */
1250 static bool RLP_PrepareDataToTransmit(u8 *p)
1254 for (i=VA; i!=VS; i=Incr(i))
1255 if (S[i].State==_send) {
1260 if (S[VS].State!=_send) return false;
1261 if (!InWindow(VS,VA,VA+RLP_SEND_WS-1))
1271 /* Send a SREJ command */
1273 static void RLP_SendSREJ(u8 x)
1277 if ((Poll_xchg==_idle) && (Poll_State==_send)) {
1280 fprintf(stdout, "Sending SREJ with poll\n");
1283 RLP_SendF96Frame(RLPFT_S_SREJ, true, true, x , 0 , NULL, false);
1285 RLP_SetTimer(&T_RCVS[x]);
1291 else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1293 fprintf(stdout, "Sending SREJ for %d along with frame %d\n",x,k);
1295 RLP_SendF96Frame(RLPFT_SI_SREJ, true, false, x , k , S[k].Data, false);
1297 RLP_SetTimer(&T_RCVS[x]);
1302 fprintf(stdout, "Sending SREJ for %d\n",x);
1304 RLP_SendF96Frame(RLPFT_S_SREJ, true, false, x , 0 , NULL, false);
1306 RLP_SetTimer(&T_RCVS[x]);
1311 /* Send a command */
1313 static void RLP_Send_XX_Cmd(RLP_FrameTypes type)
1317 if ((Poll_xchg!=_wait) && (Poll_State==_send)) {
1318 RLP_SendF96Frame(type, true, true, VR , 0 , NULL, false);
1320 fprintf(stdout, "Sending Comd %x with Poll\n",type);
1328 else if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1330 fprintf(stdout, "Sending Comd %x with frame %d\n",type,k);
1332 RLP_SendF96Frame(type+4, true, false, VR , k , S[k].Data, false);
1339 fprintf(stdout, "Sending Comd %x\n",type);
1341 RLP_SendF96Frame(type, true, false, VR , 0 , NULL, false);
1344 DTX_VR=VR; /* As v7.1.0 spec */
1349 /* Send a Response */
1351 static void RLP_Send_XX_Resp(RLP_FrameTypes type)
1355 if (RRReady && RLP_PrepareDataToTransmit(&k)) {
1357 fprintf(stdout, "Sending Resp %x with frame %d\n",type+4,k);
1359 RLP_SendF96Frame(type+4, false, true, VR , k , S[k].Data, false);
1366 fprintf(stdout, "Sending Resp %x\n",type);
1368 RLP_SendF96Frame(type, false, true, VR , 0 , NULL, false);
1375 /* Decide which frame to use and send it - currently only used in state 4 */
1377 static void RLP_SendData()
1381 if (UA_State==_send) {
1382 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0 , 0 , NULL, false);
1385 else if (Ackn_FBit==true) {
1387 printf("About to send Poll resp\n");
1389 if (LRReady) RLP_Send_XX_Resp(RLPFT_S_RR);
1390 else RLP_Send_XX_Resp(RLPFT_S_RNR);
1392 else if (RLP_SREJSlot(&x)) RLP_SendSREJ(x);
1393 else if (LRReady) RLP_Send_XX_Cmd(RLPFT_S_RR);
1394 else RLP_Send_XX_Cmd(RLPFT_S_RNR);
1397 static void MAIN_STATE_MACHINE(RLP_F96Frame *frame, RLP_F96Header *header) {
1400 switch (CurrentState) {
1402 /***** RLP State 0. *****/
1404 /* ADM and Detached.
1406 This is the initial state after power on.
1408 As long as the RLP entity is "Detached", DISC(P) and/or SABM at the
1409 lower interface is acted upon by sending DM(P) or DM(1). Any other
1410 stimulus at the lower interface is ignored.
1412 This state can be exited only with Attach_Req. */
1417 fprintf(stdout, _("RLP state 0.\n"));
1420 switch (CurrentFrameType) {
1423 RLP_SendF96Frame(RLPFT_U_DM, false, header->PF, 0, 0, NULL, false);
1427 RLP_SendF96Frame(RLPFT_U_DM, false, true, 0, 0, NULL, false);
1431 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1432 if (RLP_GetUserRequest(Attach_Req)) {
1441 /***** RLP State 1. *****/
1443 /* ADM and Attached.
1445 The RLP entity is ready to established a connection, either by
1446 initiating the connection itself (Conn_Req) or by responding to an
1447 incoming connection request (SABM).
1449 Upon receiving a DISC PDU, the handling of the UA response is
1455 fprintf(stdout, _("RLP state 1.\n"));
1458 if (!XID_Handling(frame, header)) {
1460 switch(CurrentFrameType) {
1467 RLP_Passup(Conn_Ind,NULL,0);
1476 case RLPFT_BAD: /* If we get a bad frame we can still respond with SABM */
1478 if (RLP_GetUserRequest(Conn_Req)) {
1487 if (!Send_TXU(frame, header)) {
1489 if (UA_State == _send) {
1490 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1494 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1498 /***** RLP State 2. *****/
1503 fprintf(stdout, _("RLP state 2.\n"));
1506 if (!XID_Handling(frame, header)) {
1508 switch(CurrentFrameType) {
1537 fprintf(stdout, _("UA received in RLP state 2.\n"));
1540 if (SABM_State == _wait && header->PF) {
1549 if (SABM_State == _wait && header->PF) {
1551 // Conn_Conf_Neg=true;
1557 if (T == RLP_Timeout1_Limit) {
1559 if (SABM_Count>RLP_N2)
1567 if (!Send_TXU(frame, header)) {
1569 if (SABM_State == _send && Poll_xchg == _idle) {
1570 RLP_SendF96Frame(RLPFT_U_SABM, true, true, 0, 0, NULL, false);
1576 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1579 if (RLP_GetUserRequest(Disc_Req)) {
1583 DISC_PBit=(Poll_xchg==_idle);
1589 /***** RLP State 3. *****/
1594 fprintf(stdout, _("RLP state 3.\n"));
1597 if (!XID_Handling(frame, header)) {
1599 switch(CurrentFrameType) {
1606 RLP_Passup(Disc_Ind,NULL,0);
1613 if (RLP_GetUserRequest(Conn_Req)) {
1617 RLP_Init_link_vars();
1618 } else if (RLP_GetUserRequest(Conn_Req_Neg)) {
1619 DM_State=_send; /* FIXME - code to handle DM_State - missing from spec? */
1627 if (!Send_TXU(frame, header)) {
1629 if (UA_State == _send) {
1630 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1634 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1638 if (RLP_GetUserRequest(Disc_Req)) {
1642 DISC_PBit=(Poll_xchg==_idle);
1648 /***** RLP State 4. *****/
1653 fprintf(stdout, _("RLP state 4.\n"));
1656 if (!XID_Handling(frame, header)) {
1658 switch (CurrentFrameType) {
1666 RLP_Passup(Disc_Ind,NULL,0);
1674 RLP_Passup(Reset_Ind,NULL,0);
1681 /* Should check here for unsolicited Fbit */
1682 /* Spec says: "Nr must be within the set of not yet
1683 acknowledged I-frames or it must be the next possible
1684 frame number." That's VA..VS-1 or VS, i.e. VA..VS */
1685 if (!InWindow(header->Nr,VA,VS))
1687 RLP_S_Handler(frame,header);
1693 /* Should check here for unsolicited Fbit */
1694 if (!InWindow(header->Nr,VA,VS))
1696 if (!RLP_I_Handler(frame,header)) RLP_S_Handler(frame,header);
1703 for (i=0;i<RLP_M;i++) if (T_RCVS[i]==0) {
1705 fprintf(stdout, "T_RCVS[%d] Timeout in State 4\n",i);
1712 fprintf(stdout, "T Timeout in State 4\n");
1716 if (Poll_State==_idle) {
1721 if (Poll_Count>RLP_N2) {
1723 fprintf(stdout, "N2 Errors in State 4\n");
1731 if (!Send_TXU(frame,header)) {
1732 if (UA_State == _send) {
1733 RLP_SendF96Frame(RLPFT_U_UA, false, UA_FBit, 0, 0, NULL, false);
1736 else RLP_SendData();
1740 /* Load any data from the Send ringbuffer into the send slots */
1741 RLP_AddRingBufferDataToSlots();
1744 // if (CurrentFrameType!=RLPFT_BAD)
1745 fprintf(stdout, "VD=%d, VA=%d, VS=%d, VR=%d\n",VD,VA,VS,VR);
1746 #ifdef RLP_DEBUG_STATE
1750 if(UA_State!=_idle) printf("[UA_State %d]",UA_State);
1751 if(UI_State!=_idle) printf("[UI_State %d]",UI_State);
1752 if(Ackn_State!=_idle) printf("[Ackn_State %d]",Ackn_State);
1753 if(Poll_State!=_idle) printf("[Poll_State %d]",Poll_State);
1754 if(Poll_xchg!=_idle) printf("[Poll_xchg %d]",Poll_xchg);
1755 if(SABM_State!=_idle) printf("[SABM_State %d]",SABM_State);
1756 if(DISC_State!=_idle) printf("[DISC_State %d]",DISC_State);
1757 if(DM_State!=_idle) printf("[DM_State %d]",DM_State);
1758 if(XID_C_State!=_idle) printf("[XID_C_State %d]",XID_C_State);
1759 if(XID_R_State!=_idle) printf("[XID_R_State %d]",XID_R_State);
1760 if(TEST_R_State!=_idle) printf("[TEST_R_State %d]",TEST_R_State);
1763 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",S[zzz].State);
1765 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",R[zzz].State);
1766 printf("\nT: %d, T_RCVS: ",T);
1767 for (zzz=0; zzz<RLP_M; zzz++) printf("%d ",T_RCVS[zzz]);
1774 if (RLP_GetUserRequest(Disc_Req)) {
1779 DISC_PBit=(Poll_xchg==_idle);
1786 /***** RLP State 5. *****/
1791 fprintf(stdout, _("RLP state 5.\n"));
1794 if (!XID_Handling(frame, header)) {
1796 switch (CurrentFrameType) {
1800 if ((DISC_State==_wait) && (DISC_PBit==header->PF)) {
1801 if (DISC_PBit==true) Poll_xchg=_idle;
1817 if (!Send_TXU(frame,header)) {
1818 if ((DISC_State!=_wait) && !((DISC_PBit==true) && (Poll_xchg==_wait))) {
1819 RLP_SendF96Frame(RLPFT_U_DISC, true, DISC_PBit, 0, 0, NULL, false);
1820 if (DISC_PBit==true) Poll_xchg=_wait;
1826 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1830 if (DISC_PBit==1) Poll_xchg=_idle;
1832 if (DISC_Count>RLP_N2) {
1835 fprintf(stdout, "N2 error in State 5!\n");
1844 /***** RLP State 6. *****/
1845 /* We should only get here after a Reset_Req which is not yet supported */
1850 fprintf(stdout, _("RLP state 6 - not yet implemented!\n"));
1853 if (!XID_Handling(frame, header)) {
1855 switch (CurrentFrameType) {
1862 if (!Send_TXU(frame,header)) {
1865 if (RLP_GetUserRequest(Disc_Req)) {
1869 DISC_PBit=(Poll_xchg==_idle);
1876 /***** RLP State 7. *****/
1881 fprintf(stdout, _("RLP state 7.\n"));
1884 if (!XID_Handling(frame, header)) {
1886 switch (CurrentFrameType) {
1888 RLP_Passup(Disc_Ind,NULL,0);
1898 if (RLP_GetUserRequest(Reset_Resp)){
1901 RLP_Init_link_vars();
1905 if (!Send_TXU(frame,header)) {
1906 RLP_SendF96Frame(RLPFT_U_NULL, false, false, 0, 0, NULL, false);
1909 if (RLP_GetUserRequest(Disc_Req)) {
1913 DISC_PBit=(Poll_xchg==_idle);
1923 fprintf(stdout, _("DEBUG: Unknown RLP state!\n"));
1929 CurrentState=NextState;
1933 /* Given a pointer to an RLP XID frame, display contents in human readable
1934 form. Note for now only Version 0 and 1 are supported. Fields can appear
1935 in any order and are delimited by a zero type field. This function is the
1936 exact implementation of section 5.2.2.6, Exchange Identification, XID of
1937 the GSM specification 04.22. */
1941 static void RLP_DisplayXID(u8 *frame)
1944 int count = 25; /* Sanity check */
1947 fprintf(stdout, "XID: ");
1949 while ((*frame !=0) && (count >= 0)) {
1952 length = *frame & 0x0f;
1956 case 0x01: /* RLP Version Number, probably 1 for Nokia. */
1959 fprintf(stdout, "Ver %d ", *frame);
1962 case 0x02: /* IWF to MS window size */
1965 fprintf(stdout, "IWF-MS %d ", *frame);
1968 case 0x03: /* MS to IWF window size. */
1971 fprintf(stdout, "MS-IWF %d ", *frame);
1974 case 0x04: /* Acknowledgement Timer (T1). */
1977 fprintf(stdout, "T1 %dms ", *frame * 10);
1980 case 0x05: /* Retransmission attempts (N2). */
1983 fprintf(stdout, "N2 %d ", *frame);
1986 case 0x06: /* Reply delay (T2). */
1989 fprintf(stdout, "T2 %dms ", *frame * 10);
1992 case 0x07: /* Compression. */
1995 fprintf(stdout, "Comp [Pt=%d ", (*frame >> 4) );
1996 fprintf(stdout, "P0=%d ", (*frame & 0x03) );
1999 fprintf(stdout, "P1l=%d ", *frame);
2001 fprintf(stdout, "P1h=%d ", *frame);
2004 fprintf(stdout, "P2=%d] ", *frame);
2010 fprintf(stdout, "Unknown! type=%02x, length=%02x", type, length);
2021 #endif /* RLP_DEBUG */
2023 /* Given a pointer to an F9.6 Frame, split data out into component parts of
2024 header and determine frame type. */
2026 static void RLP_DecodeF96Header(RLP_F96Frame *frame, RLP_F96Header *header)
2029 /* Poll/Final bit. */
2031 if ((frame->Header[1] & 0x02))
2036 /* Command/Response bit. */
2038 if ((frame->Header[0] & 0x01))
2043 /* Send Sequence Number. */
2045 header->Ns = frame->Header[0] >> 3;
2047 if ((frame->Header[1] & 0x01))
2048 header->Ns |= 0x20; /* Most significant bit. */
2050 /* Determine frame type. See the section 5.2.1 in the GSM 04.22
2053 switch (header->Ns) {
2055 case 0x3f: /* Frames of type U, unnumbered frames. */
2057 /* U frames have M1, ..., M5 stored in the place of N(R). */
2059 header->Type = RLPFT_U;
2060 header->M = (frame->Header[1] >> 2) & 0x1f;
2061 return; /* For U frames, we do not need N(R) and bits S1 and S2. */
2063 case 0x3e: /* Frames of type S, supervisory frames. */
2065 header->Type = RLPFT_S;
2068 default: /* Frames of type I+S, numbered information transfer ans
2069 supervisory frames combined. */
2071 header->Type = RLPFT_IS;
2075 /* Receive Sequence Number N(R). */
2076 header->Nr = frame->Header[1] >> 2;
2078 /* Status bits (S1 and S2). */
2079 header->S = (frame->Header[0] >> 1) & 0x03;