📄 irlap_event.c
字号:
self->retry_count = 0; /* Wait for turnaround time to give a chance to the other * device to be ready to receive us. * Note : the time to switch speed is typically larger * than the turnaround time, but as we don't have the other * side speed switch time, that's our best guess... * Jean II */ irlap_wait_min_turn_around(self, &self->qos_tx); /* This frame will actually be sent at the new speed */ irlap_send_rr_frame(self, CMD_FRAME); /* The timer is set to half the normal timer to quickly * detect a failure to negociate the new connection * parameters. IrLAP 6.11.3.2, note 3. * Note that currently we don't process this failure * properly, as we should do a quick disconnect. * Jean II */ irlap_start_final_timer(self, self->final_timeout/2); irlap_next_state(self, LAP_NRM_P); irlap_connect_confirm(self, skb); break; case RECV_DM_RSP: /* FALLTHROUGH */ case RECV_DISC_CMD: del_timer(&self->final_timer); irlap_next_state(self, LAP_NDM); irlap_disconnect_indication(self, LAP_DISC_INDICATION); break; default: IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__, event, irlap_event[event]); ret = -1; break; } return ret;}/* * Function irlap_state_offline (self, event, skb, info) * * OFFLINE state, not used for now! * */static int irlap_state_offline(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info){ IRDA_DEBUG( 0, "%s(), Unknown event\n", __FUNCTION__); return -1;}/* * Function irlap_state_xmit_p (self, event, skb, info) * * XMIT, Only the primary station has right to transmit, and we * therefore do not expect to receive any transmissions from other * stations. * */static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info){ int ret = 0; switch (event) { case SEND_I_CMD: /* * Only send frame if send-window > 0. */ if ((self->window > 0) && (!self->remote_busy)) { int nextfit;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW struct sk_buff *skb_next; /* With DYNAMIC_WINDOW, we keep the window size * maximum, and adapt on the packets we are sending. * At 115k, we can send only 2 packets of 2048 bytes * in a 500 ms turnaround. Without this option, we * would always limit the window to 2. With this * option, if we send smaller packets, we can send * up to 7 of them (always depending on QoS). * Jean II */ /* Look at the next skb. This is safe, as we are * the only consumer of the Tx queue (if we are not, * we have other problems) - Jean II */ skb_next = skb_peek(&self->txq); /* Check if a subsequent skb exist and would fit in * the current window (with respect to turnaround * time). * This allow us to properly mark the current packet * with the pf bit, to avoid falling back on the * second test below, and avoid waiting the * end of the window and sending a extra RR. * Note : (skb_next != NULL) <=> (skb_queue_len() > 0) * Jean II */ nextfit = ((skb_next != NULL) && ((skb_next->len + skb->len) <= self->bytes_left)); /* * The current packet may not fit ! Because of test * above, this should not happen any more !!! * Test if we have transmitted more bytes over the * link than its possible to do with the current * speed and turn-around-time. */ if((!nextfit) && (skb->len > self->bytes_left)) { IRDA_DEBUG(0, "%s(), Not allowed to transmit" " more bytes!\n", __FUNCTION__); /* Requeue the skb */ skb_queue_head(&self->txq, skb_get(skb)); /* * We should switch state to LAP_NRM_P, but * that is not possible since we must be sure * that we poll the other side. Since we have * used up our time, the poll timer should * trigger anyway now, so we just wait for it * DB */ /* * Sorry, but that's not totally true. If * we send 2000B packets, we may wait another * 1000B until our turnaround expire. That's * why we need to be proactive in avoiding * coming here. - Jean II */ return -EPROTO; } /* Substract space used by this skb */ self->bytes_left -= skb->len;#else /* CONFIG_IRDA_DYNAMIC_WINDOW */ /* Window has been adjusted for the max packet * size, so much simpler... - Jean II */ nextfit = !skb_queue_empty(&self->txq);#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ /* * Send data with poll bit cleared only if window > 1 * and there is more frames after this one to be sent */ if ((self->window > 1) && (nextfit)) { /* More packet to send in current window */ irlap_send_data_primary(self, skb); irlap_next_state(self, LAP_XMIT_P); } else { /* Final packet of window */ irlap_send_data_primary_poll(self, skb); /* * Make sure state machine does not try to send * any more frames */ ret = -EPROTO; }#ifdef CONFIG_IRDA_FAST_RR /* Peer may want to reply immediately */ self->fast_RR = FALSE;#endif /* CONFIG_IRDA_FAST_RR */ } else { IRDA_DEBUG(4, "%s(), Unable to send! remote busy?\n", __FUNCTION__); skb_queue_head(&self->txq, skb_get(skb)); /* * The next ret is important, because it tells * irlap_next_state _not_ to deliver more frames */ ret = -EPROTO; } break; case POLL_TIMER_EXPIRED: IRDA_DEBUG(3, "%s(), POLL_TIMER_EXPIRED <%ld>\n", __FUNCTION__, jiffies); irlap_send_rr_frame(self, CMD_FRAME); /* Return to NRM properly - Jean II */ self->window = self->window_size;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW /* Allowed to transmit a maximum number of bytes again. */ self->bytes_left = self->line_capacity;#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ irlap_start_final_timer(self, self->final_timeout); irlap_next_state(self, LAP_NRM_P); break; case DISCONNECT_REQUEST: del_timer(&self->poll_timer); irlap_wait_min_turn_around(self, &self->qos_tx); irlap_send_disc_frame(self); irlap_flush_all_queues(self); irlap_start_final_timer(self, self->final_timeout); self->retry_count = 0; irlap_next_state(self, LAP_PCLOSE); break; case DATA_REQUEST: /* Nothing to do, irlap_do_event() will send the packet * when we return... - Jean II */ break; default: IRDA_DEBUG(0, "%s(), Unknown event %s\n", __FUNCTION__, irlap_event[event]); ret = -EINVAL; break; } return ret;}/* * Function irlap_state_pclose (event, skb, info) * * PCLOSE state */static int irlap_state_pclose(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info){ int ret = 0; IRDA_DEBUG(1, "%s()\n", __FUNCTION__); IRDA_ASSERT(self != NULL, return -1;); IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;); switch (event) { case RECV_UA_RSP: /* FALLTHROUGH */ case RECV_DM_RSP: del_timer(&self->final_timer); /* Set new link parameters */ irlap_apply_default_connection_parameters(self); /* Always switch state before calling upper layers */ irlap_next_state(self, LAP_NDM); irlap_disconnect_indication(self, LAP_DISC_INDICATION); break; case FINAL_TIMER_EXPIRED: if (self->retry_count < self->N3) { irlap_wait_min_turn_around(self, &self->qos_tx); irlap_send_disc_frame(self); irlap_start_final_timer(self, self->final_timeout); self->retry_count++; /* Keep state */ } else { irlap_apply_default_connection_parameters(self); /* Always switch state before calling upper layers */ irlap_next_state(self, LAP_NDM); irlap_disconnect_indication(self, LAP_NO_RESPONSE); } break; default: IRDA_DEBUG(1, "%s(), Unknown event %d\n", __FUNCTION__, event); ret = -1; break; } return ret;}/* * Function irlap_state_nrm_p (self, event, skb, info) * * NRM_P (Normal Response Mode as Primary), The primary station has given * permissions to a secondary station to transmit IrLAP resonse frames * (by sending a frame with the P bit set). The primary station will not * transmit any frames and is expecting to receive frames only from the * secondary to which transmission permissions has been given. */static int irlap_state_nrm_p(struct irlap_cb *self, IRLAP_EVENT event, struct sk_buff *skb, struct irlap_info *info){ int ret = 0; int ns_status; int nr_status; switch (event) { case RECV_I_RSP: /* Optimize for the common case */ /* FIXME: must check for remote_busy below */#ifdef CONFIG_IRDA_FAST_RR /* * Reset the fast_RR so we can use the fast RR code with * full speed the next time since peer may have more frames * to transmitt */ self->fast_RR = FALSE;#endif /* CONFIG_IRDA_FAST_RR */ IRDA_ASSERT( info != NULL, return -1;); ns_status = irlap_validate_ns_received(self, info->ns); nr_status = irlap_validate_nr_received(self, info->nr); /* * Check for expected I(nformation) frame */ if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) { /* Update Vr (next frame for us to receive) */ self->vr = (self->vr + 1) % 8; /* Update Nr received, cleanup our retry queue */ irlap_update_nr_received(self, info->nr); /* * Got expected NR, so reset the * retry_count. This is not done by IrLAP spec, * which is strange! */ self->retry_count = 0; self->ack_required = TRUE; /* poll bit cleared? */ if (!info->pf) { /* Keep state, do not move this line */ irlap_next_state(self, LAP_NRM_P); irlap_data_indication(self, skb, FALSE); } else { /* No longer waiting for pf */ del_timer(&self->final_timer); irlap_wait_min_turn_around(self, &self->qos_tx); /* Call higher layer *before* changing state * to give them a chance to send data in the * next LAP frame. * Jean II */ irlap_data_indication(self, skb, FALSE); /* XMIT states are the most dangerous state * to be in, because user requests are * processed directly and may change state. * On the other hand, in NDM_P, those * requests are queued and we will process * them when we return to irlap_do_event(). * Jean II */ irlap_next_state(self, LAP_XMIT_P); /* This is the last frame. * Make sure it's always called in XMIT state. * - Jean II */ irlap_start_poll_timer(self, self->poll_timeout); } break; } /* Unexpected next to send (Ns) */ if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED)) { if (!info->pf) { irlap_update_nr_received(self, info->nr); /* * Wait until the last frame before doing * anything */ /* Keep state */ irlap_next_state(self, LAP_NRM_P); } else { IRDA_DEBUG(4, "%s(), missing or duplicate frame!\n", __FUNCTION__); /* Update Nr received */ irlap_update_nr_received(self, info->nr); irlap_wait_min_turn_around(self, &self->qos_tx); irlap_send_rr_frame(self, CMD_FRAME); self->ack_required = FALSE; irlap_start_final_timer(self, self->final_timeout); irlap_next_state(self, LAP_NRM_P); } break; } /* * Unexpected next to receive (Nr) */ if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED)) { if (info->pf) { self->vr = (self->vr + 1) % 8; /* Update Nr received */ irlap_update_nr_received(self, info->nr); /* Resend rejected frames */ irlap_resend_rejected_frames(self, CMD_FRAME); self->ack_required = FALSE; /* Make sure we account for the time * to transmit our frames. See comemnts * in irlap_send_data_primary_poll(). * Jean II */ irlap_start_final_timer(self, 2 * self->final_timeout); /* Keep state, do not move this line */ irlap_next_state(self, LAP_NRM_P); irlap_data_indication(self, skb, FALSE); } else { /* * Do not resend frames until the last * frame has arrived from the other * device. This is not documented in * IrLAP!! */ self->vr = (self->vr + 1) % 8; /* Update Nr received */ irlap_update_nr_received(self, info->nr); self->ack_required = FALSE; /* Keep state, do not move this line!*/ irlap_next_state(self, LAP_NRM_P); irlap_data_indication(self, skb, FALSE); } break; } /* * Unexpected next to send (Ns) and next to receive (Nr) * Not documented by IrLAP! */ if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_UNEXPECTED)) { IRDA_DEBUG(4, "%s(), unexpected nr and ns!\n", __FUNCTION__); if (info->pf) { /* Resend rejected frames */ irlap_resend_rejected_frames(self, CMD_FRAME); /* Give peer some time to retransmit! * But account for our own Tx. */ irlap_start_final_timer(self, 2 * self->final_timeout); /* Keep state, do not move this line */ irlap_next_state(self, LAP_NRM_P); } else { /* Update Nr received */ /* irlap_update_nr_received( info->nr); */ self->ack_required = FALSE; } break; } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -