📄 rlp-common.c
字号:
} else if (Ackn_FBit == true) { rlpprintf("About to send Poll resp\n"); if (LRReady) RLP_Send_XX_Resp(RLP_FT_S_RR); else RLP_Send_XX_Resp(RLP_FT_S_RNR); } else if (RLP_SREJSlot(&x)) RLP_SendSREJ(x); else if (LRReady) RLP_Send_XX_Cmd(RLP_FT_S_RR); else RLP_Send_XX_Cmd(RLP_FT_S_RNR);}void MAIN_STATE_MACHINE(gn_rlp_f96_frame *frame, rlp_f96_header *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: dprintf("RLP state 0.\n"); switch (CurrentFrameType) { case RLP_FT_U_DISC: RLP_SendF96Frame(RLP_FT_U_DM, false, header->PF, 0, 0, NULL, false); break; case RLP_FT_U_SABM: RLP_SendF96Frame(RLP_FT_U_DM, false, true, 0, 0, NULL, false); break; default: RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false); if (rlp_user_request_get(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: dprintf("RLP state 1.\n"); if (!XID_Handling(frame, header)) { switch(CurrentFrameType) { case RLP_FT_U_TEST: TEST_Handling(); break; case RLP_FT_U_SABM: RLP_Passup(Conn_Ind, NULL, 0); NextState = RLP_S3; break; case RLP_FT_U_DISC: UA_State = _send; UA_FBit = header->PF; break; case RLP_FT_BAD: /* If we get a bad frame we can still respond with SABM */ default: if (rlp_user_request_get(Conn_Req)) { SABM_State = _send; SABM_Count = 0; NextState = RLP_S2; } break; } } if (!Send_TXU(frame, header)) { if (UA_State == _send) { RLP_SendF96Frame(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false); UA_State = _idle; } else RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false); } break; /***** RLP State 2. *****/ case RLP_S2: dprintf("RLP state 2.\n"); if (!XID_Handling(frame, header)) { switch(CurrentFrameType) { case RLP_FT_U_TEST: TEST_Handling(); break; case RLP_FT_U_SABM: /* Conn_Conf = true; */ T = -1; UA_State = _send; UA_FBit = true; RLP_Init_link_vars(); NextState = RLP_S4; break; case RLP_FT_U_DISC: T = -1; RLP_Passup(Disc_Ind, NULL, 0); UA_State = _send; UA_FBit = header->PF; NextState = RLP_S1; break; case RLP_FT_U_UA: dprintf("UA received in RLP state 2.\n"); if (SABM_State == _wait && header->PF) { T = -1; /* Conn_Conf = true; */ RLP_Init_link_vars(); NextState = RLP_S4; } break; case RLP_FT_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 || T == 0) { 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(RLP_FT_U_SABM, true, true, 0, 0, NULL, false); SABM_State = _wait; SABM_Count++; Poll_xchg = _wait; RLP_SetTimer(&T); } else RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false); } if (rlp_user_request_get(Disc_Req)) { T = -1; DISC_State = _send; DISC_Count = 0; DISC_PBit = (Poll_xchg == _idle); NextState = 5; } break; /***** RLP State 3. *****/ case RLP_S3: dprintf("RLP state 3.\n"); if (!XID_Handling(frame, header)) { switch(CurrentFrameType) { case RLP_FT_U_TEST: TEST_Handling(); break; case RLP_FT_U_DISC: RLP_Passup(Disc_Ind, NULL, 0); UA_State = _send; UA_FBit = header->PF; NextState = RLP_S1; break; default: if (rlp_user_request_get(Conn_Req)) { UA_State = _send; UA_FBit = true; NextState = RLP_S4; RLP_Init_link_vars(); } else if (rlp_user_request_get(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(RLP_FT_U_UA, false, UA_FBit, 0, 0, NULL, false); UA_State = _idle; } else RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false); } if (rlp_user_request_get(Disc_Req)) { T = -1; DISC_State = _send; DISC_Count = 0; DISC_PBit = (Poll_xchg == _idle); NextState = 5; } break; /***** RLP State 4. *****/ case RLP_S4: dprintf("RLP state 4.\n"); if (!XID_Handling(frame, header)) { switch (CurrentFrameType) { case RLP_FT_U_TEST: TEST_Handling(); break; case RLP_FT_U_DISC: T = -1; ResetAllT_RCVS(); RLP_Passup(Disc_Ind, NULL, 0); UA_State = _send; UA_FBit = header->PF; NextState = RLP_S1; break; case RLP_FT_U_SABM: T = -1; ResetAllT_RCVS(); RLP_Passup(Reset_Ind, NULL, 0); NextState = RLP_S7; break; case RLP_FT_S_RR: case RLP_FT_S_RNR: case RLP_FT_S_REJ: case RLP_FT_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 RLP_FT_SI_RR: case RLP_FT_SI_RNR: case RLP_FT_SI_REJ: case RLP_FT_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; i < RLP_M; i++) if (T_RCVS[i] == 0) { rlpprintf("T_RCVS[%d] Timeout in State 4\n", i); R[i].State = _srej; } if (T == 0) { T = -1; rlpprintf("T Timeout in State 4\n"); Poll_xchg = _idle; if (Poll_State == _idle) { Poll_State = _send; Poll_Count = 0; } else { if (Poll_Count > RLP_N2) rlpprintf("N2 Errors in State 4\n"); Poll_State = _send; Poll_Count++; } } if (!Send_TXU(frame, header)) { if (UA_State == _send) { RLP_SendF96Frame(RLP_FT_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(); rlpprintf("VD=%d, VA=%d, VS=%d, VR=%d\n", VD, VA, VS, VR);#ifdef RLP_DEBUG_STATE { int zzz; if (UA_State != _idle) rlpprintf("[UA_State %d]", UA_State); if (UI_State != _idle) rlpprintf("[UI_State %d]", UI_State); if (Ackn_State != _idle) rlpprintf("[Ackn_State %d]", Ackn_State); if (Poll_State != _idle) rlpprintf("[Poll_State %d]", Poll_State); if (Poll_xchg != _idle) rlpprintf("[Poll_xchg %d]", Poll_xchg); if (SABM_State != _idle) rlpprintf("[SABM_State %d]", SABM_State); if (DISC_State != _idle) rlpprintf("[DISC_State %d]", DISC_State); if (DM_State != _idle) rlpprintf("[DM_State %d]", DM_State); if (XI_R_State != _idle) rlpprintf("[XI_R_State %d]", XI_R_State); if (XID_C_State != _idle) rlpprintf("[XID_C_State %d]", XID_C_State); if (XID_R_State != _idle) rlpprintf("[XID_R_State %d]", XID_R_State); if (TEST_R_State != _idle) rlpprintf("[TEST_R_State %d]", TEST_R_State); rlpprintf("S: "); for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", S[zzz].State); rlpprintf("\nR: "); for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", R[zzz].State); rlpprintf("\nT: %d, T_RCVS: ", T); for (zzz = 0; zzz < RLP_M; zzz++) rlpprintf("%d ", T_RCVS[zzz]); rlpprintf("\n"); }#endif if (rlp_user_request_get(Disc_Req)) { T = -1; ResetAllT_RCVS(); DISC_State = _send; DISC_Count = 0; DISC_PBit = (Poll_xchg == _idle); NextState = 5; } break; /***** RLP State 5. *****/ case RLP_S5: dprintf("RLP state 5.\n"); if (!XID_Handling(frame, header)) { switch (CurrentFrameType) { case RLP_FT_U_UA: case RLP_FT_U_DM: if ((DISC_State == _wait) && (DISC_PBit == header->PF)) { if (DISC_PBit == true) Poll_xchg = _idle; T = -1; NextState = 1; } break; case RLP_FT_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(RLP_FT_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(RLP_FT_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) rlpprintf("N2 error in State 5!\n"); DISC_State = _send; } break; /***** RLP State 6. *****/ /* We should only get here after a Reset_Req which is not yet supported */ case RLP_S6: dprintf("RLP state 6 - not yet implemented!\n"); if (!XID_Handling(frame, header)) { switch (CurrentFrameType) { default: break; } } if (!Send_TXU(frame,header)) { } if (rlp_user_request_get(Disc_Req)) { T = -1; DISC_State = _send; DISC_Count = 0; DISC_PBit = (Poll_xchg == _idle); NextState = 5; } break; /***** RLP State 7. *****/ case RLP_S7: dprintf("RLP state 7.\n"); if (!XID_Handling(frame, header)) { switch (CurrentFrameType) { case RLP_FT_U_DISC: RLP_Passup(Disc_Ind, NULL, 0); UA_State = _send; UA_FBit = header->PF; NextState = RLP_S1; break; default: break; } } if (rlp_user_request_get(Reset_Resp)) { UA_State = _send; UA_FBit = 1; RLP_Init_link_vars(); NextState = RLP_S4; } if (!Send_TXU(frame, header)) { RLP_SendF96Frame(RLP_FT_U_NULL, false, false, 0, 0, NULL, false); } if (rlp_user_request_get(Disc_Req)) { T = -1; DISC_State = _send; DISC_Count = 0; DISC_PBit = (Poll_xchg == _idle); NextState = 5; } break; default: dprintf("DEBUG: Unknown RLP state!\n"); 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_xid_display(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++; } fprintf(stdout, "\n"); return;}/* Given a pointer to an F9.6 Frame, split data out into component parts of header and determine frame type. */void rlp_f96_header_decode(gn_rlp_f96_frame *frame, rlp_f96_header *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 = RLP_FT_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 = RLP_FT_S; break; default: /* Frames of type I+S, numbered information transfer ans supervisory frames combined. */ header->Type = RLP_FT_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -