void L2LAPDm::receiveIFrame(const L2Frame& frame) { // Caller should hold mLock. // See GSM 04.06 5.4.1.4. mEstablishmentInProgress = false; OBJLOG(INFO) << "state=" << mState << " NS=" << frame.NS() << " NR=" << frame.NR() << " " << frame; // vISDN datalink.c:lapd_handle_iframe // GSM 04.06 5.5.2, 5.7.1 // Q.921 5.6.2, 5.8.1 switch (mState) { case ContentionResolution: mState=LinkEstablished; // continue to next case... case LinkEstablished: processAck(frame.NR()); if (frame.NS()==mVR) { mVR = (mVR+1)%8; bufferIFrameData(frame); sendSFrameRR(frame.PF()); } else { // GSM 04.06 5.7.1. // Q.921 5.8.1. sendSFrameREJ(frame.PF()); } case LinkReleased: // GSM 04.06 5.4.5 break; default: // ignore break; } }
void L2LAPDm::receiveSFrameREJ(const L2Frame& frame) { // Caller should hold mLock. OBJLOG(INFO) << "state=" << mState << " " << frame; // GSM 04.06 3.8.6, 5.5.4 // Q.921 3.7.6, 5.6.4. // vISDN datalink.c:lapd_handle_s_frame_rej. switch (mState) { case ContentionResolution: mState = LinkEstablished; // continue to next case... case LinkEstablished: // FIXME -- The spec says to do this but it breaks multiframe transmission. //mVS = mVA = frame.NR(); processAck(frame.NR()); if (frame.PF()) { if (frame.CR()!=mC) sendSFrameRR(true); else { unexpectedMessage(); return; } } // Since k=1, there's really nothing to retransmit, // other than what was just rejected, so kust stop sending it. sendIdle(); break; default: // ignore break; } // Send an idle frame to clear any repeating junk on the channel. sendIdle(); }
void L2LAPDm::receiveSFrameRR(const L2Frame& frame) { // Caller should hold mLock. OBJLOG(INFO) << "state=" << mState << " " << frame; // GSM 04.06 3.8.5. // Q.921 3.6.6. // vISDN datalink.c:lapd_handle_sframe_rr // Again, since LAPDm allows only one outstanding frame // (k=1), this is a lot simpler than in LAPD. switch (mState) { case ContentionResolution: mState = LinkEstablished; // continue to next case... case LinkEstablished: // "inquiry response procedure" // Never actually seen that happen in GSM... if ((frame.CR()!=mC) && (frame.PF())) { sendSFrameRR(true); } processAck(frame.NR()); break; default: // ignore return; } }