⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irlap_event.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -