static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { int queued = 0; int modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX SABM(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } break; case LAPB_SABME: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX SABME(%d)\n", lapb->dev, frame->pf); #endif if (lapb->mode & LAPB_EXTENDED) { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); #endif lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; case LAPB_DISC: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif lapb_clear_queues(lapb); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_OK); break; case LAPB_DM: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX DM(%d)\n", lapb->dev, frame->pf); #endif #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S0\n", lapb->dev); #endif lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); break; case LAPB_RNR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX RNR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_RR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX RR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_REJ: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX REJ(%d) R%d\n", lapb->dev, frame->pf, frame->nr); #endif lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t1timer(lapb); lapb->n2count = 0; lapb_requeue_frames(lapb); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_I: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX I(%d) S%d R%d\n", lapb->dev, frame->pf, frame->ns, frame->nr); #endif if (!lapb_validate_nr(lapb, frame->nr)) { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb->vr) { int cn; cn = lapb_data_indication(lapb, skb); queued = 1; /* */ if (cn == NET_RX_DROP) { printk(KERN_DEBUG "LAPB: rx congestion\n"); break; } lapb->vr = (lapb->vr + 1) % modulus; lapb->condition &= ~LAPB_REJECT_CONDITION; if (frame->pf) lapb_enquiry_response(lapb); else { if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { lapb->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t2timer(lapb); } } } else { if (lapb->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 TX REJ(%d) R%d\n", lapb->dev, frame->pf, lapb->vr); #endif lapb->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } } break; case LAPB_FRMR: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX FRMR(%d) %02X " "%02X %02X %02X %02X\n", lapb->dev, frame->pf, skb->data[0], skb->data[1], skb->data[2], skb->data[3], skb->data[4]); #endif lapb_establish_data_link(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S1\n", lapb->dev); #endif lapb_requeue_frames(lapb); lapb->state = LAPB_STATE_1; break; case LAPB_ILLEGAL: #if LAPB_DEBUG > 1 printk(KERN_DEBUG "lapb: (%p) S3 RX ILLEGAL(%d)\n", lapb->dev, frame->pf); #endif lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); #if LAPB_DEBUG > 0 printk(KERN_DEBUG "lapb: (%p) S3 -> S4\n", lapb->dev); #endif lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (!queued) kfree_skb(skb); }
/* * State machine for state 3, Connected State. * The handling of the timer(s) is in file lapb_timer.c */ static void lapb_state3_machine(struct lapb_cb *lapb, struct sk_buff *skb, struct lapb_frame *frame) { int queued = 0; int modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: lapb_dbg(1, "(%p) S3 RX SABM(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } else { lapb_dbg(1, "(%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } break; case LAPB_SABME: lapb_dbg(1, "(%p) S3 RX SABME(%d)\n", lapb->dev, frame->pf); if (lapb->mode & LAPB_EXTENDED) { lapb_dbg(1, "(%p) S3 TX UA(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->condition = 0x00; lapb->n2count = 0; lapb->vs = 0; lapb->vr = 0; lapb->va = 0; lapb_requeue_frames(lapb); } else { lapb_dbg(1, "(%p) S3 TX DM(%d)\n", lapb->dev, frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); } break; case LAPB_DISC: lapb_dbg(1, "(%p) S3 RX DISC(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev); lapb_clear_queues(lapb); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_0; lapb_disconnect_indication(lapb, LAPB_OK); break; case LAPB_DM: lapb_dbg(1, "(%p) S3 RX DM(%d)\n", lapb->dev, frame->pf); lapb_dbg(0, "(%p) S3 -> S0\n", lapb->dev); lapb_clear_queues(lapb); lapb->state = LAPB_STATE_0; lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); break; case LAPB_RNR: lapb_dbg(1, "(%p) S3 RX RNR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_RR: lapb_dbg(1, "(%p) S3 RX RR(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_REJ: lapb_dbg(1, "(%p) S3 RX REJ(%d) R%d\n", lapb->dev, frame->pf, frame->nr); lapb->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t1timer(lapb); lapb->n2count = 0; lapb_requeue_frames(lapb); } else { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; } break; case LAPB_I: lapb_dbg(1, "(%p) S3 RX I(%d) S%d R%d\n", lapb->dev, frame->pf, frame->ns, frame->nr); if (!lapb_validate_nr(lapb, frame->nr)) { lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb->vr) { int cn; cn = lapb_data_indication(lapb, skb); queued = 1; /* * If upper layer has dropped the frame, we * basically ignore any further protocol * processing. This will cause the peer * to re-transmit the frame later like * a frame lost on the wire. */ if (cn == NET_RX_DROP) { pr_debug("rx congestion\n"); break; } lapb->vr = (lapb->vr + 1) % modulus; lapb->condition &= ~LAPB_REJECT_CONDITION; if (frame->pf) lapb_enquiry_response(lapb); else { if (!(lapb->condition & LAPB_ACK_PENDING_CONDITION)) { lapb->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t2timer(lapb); } } } else { if (lapb->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { lapb_dbg(1, "(%p) S3 TX REJ(%d) R%d\n", lapb->dev, frame->pf, lapb->vr); lapb->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; } } break; case LAPB_FRMR: lapb_dbg(1, "(%p) S3 RX FRMR(%d) %5ph\n", lapb->dev, frame->pf, skb->data); lapb_establish_data_link(lapb); lapb_dbg(0, "(%p) S3 -> S1\n", lapb->dev); lapb_requeue_frames(lapb); lapb->state = LAPB_STATE_1; break; case LAPB_ILLEGAL: lapb_dbg(1, "(%p) S3 RX ILLEGAL(%d)\n", lapb->dev, frame->pf); lapb->frmr_data = *frame; lapb->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); lapb_dbg(0, "(%p) S3 -> S4\n", lapb->dev); lapb_start_t1timer(lapb); lapb_stop_t2timer(lapb); lapb->state = LAPB_STATE_4; lapb->n2count = 0; break; } if (!queued) kfree_skb(skb); }
/* * State machine for state 3, Connected State. * The handling of the timer(s) is in file lapb_timer.c */ void lapb_state3_machine(struct lapb_cs * lapb, char * data, int data_size, struct lapb_frame * frame) { struct lapb_cs_internal * lapb_int = lapb_get_internal(lapb); //int queued = 0; int modulus = lapb_is_extended(lapb) ? LAPB_EMODULUS : LAPB_SMODULUS; switch (frame->type) { case LAPB_SABM: lapb->callbacks->debug(2, "[LAPB] S3 RX SABM(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_requeue_frames(lapb); lapb_start_t201timer(lapb); /* to kick data */ }; break; case LAPB_SABME: lapb->callbacks->debug(2, "[LAPB] S3 RX SABME(%d)", frame->pf); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_stop_t201timer(lapb); lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_requeue_frames(lapb); lapb_start_t201timer(lapb); /* to kick data */ } else { lapb->callbacks->debug(2, "[LAPB] S3 TX DM(%d)", frame->pf); lapb_send_control(lapb, LAPB_DM, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); }; break; case LAPB_DISC: lapb->callbacks->debug(2, "[LAPB] S3 RX DISC(%d)", frame->pf); lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_OK); lapb_reset(lapb, LAPB_STATE_0); break; case LAPB_DM: lapb->callbacks->debug(2, "[LAPB] S3 RX DM(%d)", frame->pf); lapb_requeue_frames(lapb); lapb_disconnect_indication(lapb, LAPB_NOTCONNECTED); lapb_reset(lapb, LAPB_STATE_0); break; case LAPB_RNR: lapb->callbacks->debug(2, "[LAPB] S3 RX RNR(%d) R%d", frame->pf, frame->nr); lapb_int->condition |= LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_RR: lapb->callbacks->debug(2, "[LAPB] S3 RX RR(%d) R%d", frame->pf, frame->nr); lapb_int->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_check_iframes_acked(lapb, frame->nr); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_REJ: lapb->callbacks->debug(2, "[LAPB] S3 RX REJ(%d) R%d", frame->pf, frame->nr); lapb_int->condition &= ~LAPB_PEER_RX_BUSY_CONDITION; lapb_check_need_response(lapb, frame->cr, frame->pf); if (lapb_validate_nr(lapb, frame->nr)) { lapb_frames_acked(lapb, frame->nr); lapb_stop_t201timer(lapb); lapb_requeue_frames(lapb); } else { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); }; break; case LAPB_I: if (lapb_int->condition & LAPB_FRMR_CONDITION) break; lapb->callbacks->debug(2, "[LAPB] S3 RX I(%d) S%d R%d", frame->pf, frame->ns, frame->nr); if (!lapb_validate_nr(lapb, frame->nr)) { lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_Z; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_int->RC = 0; lapb_start_t201timer(lapb); break; }; if (lapb_int->condition & LAPB_PEER_RX_BUSY_CONDITION) lapb_frames_acked(lapb, frame->nr); else lapb_check_iframes_acked(lapb, frame->nr); if (frame->ns == lapb_int->vr) { lapb_int->vr = (lapb_int->vr + 1) % modulus; lapb_int->condition |= LAPB_ACK_PENDING_CONDITION; int cn; if (lapb_is_extended(lapb)) cn = lapb_data_indication(lapb, data + 3, data_size - 3); else cn = lapb_data_indication(lapb, data + 2, data_size - 2); /* * If upper layer has dropped the frame, we * basically ignore any further protocol * processing. This will cause the peer * to re-transmit the frame later like * a frame lost on the wire. */ if (cn != 0) { lapb->callbacks->debug(1, "[LAPB] S3 Upper layer has dropped the frame"); break; }; //lapb_int->vr = (lapb_int->vr + 1) % modulus; lapb_int->condition &= ~LAPB_REJECT_CONDITION; if (lapb_int->condition & LAPB_ACK_PENDING_CONDITION) { /* Ack flag is still active */ if (frame->pf) lapb_enquiry_response(lapb); else { //if (!(lapb_int->condition & LAPB_ACK_PENDING_CONDITION)) { // lapb_int->condition |= LAPB_ACK_PENDING_CONDITION; lapb_start_t202timer(lapb); //}; //else // lapb->callbacks->debug(lapb, 1, "[LAPB] S3 lapb->condition=%d", lapb->condition); }; }; } else { if (lapb_int->condition & LAPB_REJECT_CONDITION) { if (frame->pf) lapb_enquiry_response(lapb); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX REJ(%d) R%d", frame->pf, lapb_int->vr); lapb_int->condition |= LAPB_REJECT_CONDITION; lapb_send_control(lapb, LAPB_REJ, frame->pf, LAPB_RESPONSE); lapb_int->condition &= ~LAPB_ACK_PENDING_CONDITION; }; }; break; case LAPB_FRMR: lapb->callbacks->debug(2, "[LAPB] S3 RX FRMR(%d) %02X %02X %02X %02X %02X", frame->pf, (_uchar)data[0], (_uchar)data[1], (_uchar)data[2], (_uchar)data[3], (_uchar)data[4]); if (lapb_int->condition & LAPB_FRMR_CONDITION) { /* FRMR Collision */ lapb->callbacks->debug(2, "[LAPB] S3 TX UA(%d)", frame->pf); lapb_send_control(lapb, LAPB_UA, frame->pf, LAPB_RESPONSE); break; }; lapb_int->condition = LAPB_FRMR_CONDITION; lapb_stop_t201timer(lapb); _ushort nr_tmp; if (lapb_is_extended(lapb)) nr_tmp = frame->control[1] >> 5; else nr_tmp = (_uchar)(data[3] >> 5) & 0x07; lapb_frames_acked(lapb, nr_tmp); lapb_requeue_frames(lapb); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; break; case LAPB_UA: lapb->callbacks->debug(2, "[LAPB] S3 RX UA(%d)", frame->pf); if (lapb_int->condition & LAPB_FRMR_CONDITION) { lapb_int->condition = 0x00; lapb_int->vs = 0; lapb_int->vr = 0; lapb_int->va = 0; lapb_start_t201timer(lapb); /* to kick data */ } else { /* Reset data link */ lapb_int->condition = LAPB_FRMR_CONDITION; lapb_requeue_frames(lapb); if (lapb_is_extended(lapb)) { lapb->callbacks->debug(2, "[LAPB] S3 TX SABME(1)"); lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); } else { lapb->callbacks->debug(2, "[LAPB] S3 TX SABM(1)"); lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); }; }; break; case LAPB_ILLEGAL: lapb->callbacks->debug(2, "[LAPB] S3 RX ILLEGAL(%d)", frame->pf); lapb_int->frmr_data = *frame; lapb_int->frmr_type = LAPB_FRMR_W; lapb_transmit_frmr(lapb); lapb_int->condition = LAPB_FRMR_CONDITION; lapb_int->state = LAPB_STATE_4; lapb_start_t201timer(lapb); lapb_stop_t202timer(lapb); break; };