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

📄 irlap_event.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	return ret;}/* * Function irlap_state_nrm_s (event, skb, info) * *    NRM_S (Normal Response Mode as Secondary) state, in this state we are *    expecting to receive frames from the primary station * */static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event,			     struct sk_buff *skb, struct irlap_info *info){	int ns_status;	int nr_status;	int ret = 0;	IRDA_DEBUG(4, "%s(), event=%s\n", __FUNCTION__, irlap_event[ event]);	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);	switch (event) {	case RECV_I_CMD: /* Optimize for the common case */		/* FIXME: must check for remote_busy below */		IRDA_DEBUG(4, "%s(), event=%s nr=%d, vs=%d, ns=%d, "			   "vr=%d, pf=%d\n", __FUNCTION__,			   irlap_event[event], info->nr,			   self->vs, info->ns, self->vr, info->pf);		self->retry_count = 0;		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 */			irlap_update_nr_received(self, info->nr);			/*			 *  poll bit cleared?			 */			if (!info->pf) {				self->ack_required = TRUE;				/*				 *  Starting WD-timer here is optional, but				 *  not recommended. Note 6 IrLAP p. 83				 */#if 0				irda_start_timer(WD_TIMER, self->wd_timeout);#endif				/* Keep state, do not move this line */				irlap_next_state(self, LAP_NRM_S);				irlap_data_indication(self, skb, FALSE);				break;			} else {				/*				 *  We should wait before sending RR, and				 *  also before changing to XMIT_S				 *  state. (note 1, IrLAP p. 82)				 */				irlap_wait_min_turn_around(self, &self->qos_tx);				/*				 * Give higher layers a chance to				 * immediately reply with some data before				 * we decide if we should send a RR frame				 * or not				 */				irlap_data_indication(self, skb, FALSE);				/* Any pending data requests?  */				if (!skb_queue_empty(&self->txq) &&				    (self->window > 0))				{					self->ack_required = TRUE;					del_timer(&self->wd_timer);					irlap_next_state(self, LAP_XMIT_S);				} else {					irlap_send_rr_frame(self, RSP_FRAME);					irlap_start_wd_timer(self,							     self->wd_timeout);					/* Keep the state */					irlap_next_state(self, LAP_NRM_S);				}				break;			}		}		/*		 *  Check for Unexpected next to send (Ns)		 */		if ((ns_status == NS_UNEXPECTED) && (nr_status == NR_EXPECTED))		{			/* Unexpected next to send, with final bit cleared */			if (!info->pf) {				irlap_update_nr_received(self, info->nr);				irlap_start_wd_timer(self, self->wd_timeout);			} else {				/* Update Nr received */				irlap_update_nr_received(self, info->nr);				irlap_wait_min_turn_around(self, &self->qos_tx);				irlap_send_rr_frame(self, RSP_FRAME);				irlap_start_wd_timer(self, self->wd_timeout);			}			break;		}		/*		 *  Unexpected Next to Receive(NR) ?		 */		if ((ns_status == NS_EXPECTED) && (nr_status == NR_UNEXPECTED))		{			if (info->pf) {				IRDA_DEBUG(4, "RECV_I_RSP: frame(s) lost\n");				self->vr = (self->vr + 1) % 8;				/* Update Nr received */				irlap_update_nr_received(self, info->nr);				/* Resend rejected frames */				irlap_resend_rejected_frames(self, RSP_FRAME);				/* Keep state, do not move this line */				irlap_next_state(self, LAP_NRM_S);				irlap_data_indication(self, skb, FALSE);				irlap_start_wd_timer(self, self->wd_timeout);				break;			}			/*			 *  This is not documented in IrLAP!! Unexpected NR			 *  with poll bit cleared			 */			if (!info->pf) {				self->vr = (self->vr + 1) % 8;				/* Update Nr received */				irlap_update_nr_received(self, info->nr);				/* Keep state, do not move this line */				irlap_next_state(self, LAP_NRM_S);				irlap_data_indication(self, skb, FALSE);				irlap_start_wd_timer(self, self->wd_timeout);			}			break;		}		if (ret == NR_INVALID) {			IRDA_DEBUG(0, "NRM_S, NR_INVALID not implemented!\n");		}		if (ret == NS_INVALID) {			IRDA_DEBUG(0, "NRM_S, NS_INVALID not implemented!\n");		}		break;	case RECV_UI_FRAME:		/*		 *  poll bit cleared?		 */		if (!info->pf) {			irlap_data_indication(self, skb, TRUE);			irlap_next_state(self, LAP_NRM_S); /* Keep state */		} else {			/*			 *  Any pending data requests?			 */			if (!skb_queue_empty(&self->txq) &&			    (self->window > 0) && !self->remote_busy)			{				irlap_data_indication(self, skb, TRUE);				del_timer(&self->wd_timer);				irlap_next_state(self, LAP_XMIT_S);			} else {				irlap_data_indication(self, skb, TRUE);				irlap_wait_min_turn_around(self, &self->qos_tx);				irlap_send_rr_frame(self, RSP_FRAME);				self->ack_required = FALSE;				irlap_start_wd_timer(self, self->wd_timeout);				/* Keep the state */				irlap_next_state(self, LAP_NRM_S);			}		}		break;	case RECV_RR_CMD:		self->retry_count = 0;		/*		 *  Nr as expected?		 */		nr_status = irlap_validate_nr_received(self, info->nr);		if (nr_status == NR_EXPECTED) {			if (!skb_queue_empty(&self->txq) &&			    (self->window > 0)) {				self->remote_busy = FALSE;				/* Update Nr received */				irlap_update_nr_received(self, info->nr);				del_timer(&self->wd_timer);				irlap_wait_min_turn_around(self, &self->qos_tx);				irlap_next_state(self, LAP_XMIT_S);			} else {				self->remote_busy = FALSE;				/* Update Nr received */				irlap_update_nr_received(self, info->nr);				irlap_wait_min_turn_around(self, &self->qos_tx);				irlap_start_wd_timer(self, self->wd_timeout);				/* Note : if the link is idle (this case),				 * we never go in XMIT_S, so we never get a				 * chance to process any DISCONNECT_REQUEST.				 * Do it now ! - Jean II */				if (self->disconnect_pending) {					/* Disconnect */					irlap_send_rd_frame(self);					irlap_flush_all_queues(self);					irlap_next_state(self, LAP_SCLOSE);				} else {					/* Just send back pf bit */					irlap_send_rr_frame(self, RSP_FRAME);					irlap_next_state(self, LAP_NRM_S);				}			}		} else if (nr_status == NR_UNEXPECTED) {			self->remote_busy = FALSE;			irlap_update_nr_received(self, info->nr);			irlap_resend_rejected_frames(self, RSP_FRAME);			irlap_start_wd_timer(self, self->wd_timeout);			/* Keep state */			irlap_next_state(self, LAP_NRM_S);		} else {			IRDA_DEBUG(1, "%s(), invalid nr not implemented!\n",				   __FUNCTION__);		}		break;	case RECV_SNRM_CMD:		/* SNRM frame is not allowed to contain an I-field */		if (!info) {			del_timer(&self->wd_timer);			IRDA_DEBUG(1, "%s(), received SNRM cmd\n", __FUNCTION__);			irlap_next_state(self, LAP_RESET_CHECK);			irlap_reset_indication(self);		} else {			IRDA_DEBUG(0,				   "%s(), SNRM frame contained an I-field!\n",				   __FUNCTION__);		}		break;	case RECV_REJ_CMD:		irlap_update_nr_received(self, info->nr);		if (self->remote_busy) {			irlap_wait_min_turn_around(self, &self->qos_tx);			irlap_send_rr_frame(self, RSP_FRAME);		} else			irlap_resend_rejected_frames(self, RSP_FRAME);		irlap_start_wd_timer(self, self->wd_timeout);		break;	case RECV_SREJ_CMD:		irlap_update_nr_received(self, info->nr);		if (self->remote_busy) {			irlap_wait_min_turn_around(self, &self->qos_tx);			irlap_send_rr_frame(self, RSP_FRAME);		} else			irlap_resend_rejected_frame(self, RSP_FRAME);		irlap_start_wd_timer(self, self->wd_timeout);		break;	case WD_TIMER_EXPIRED:		/*		 *  Wait until retry_count * n matches negotiated threshold/		 *  disconnect time (note 2 in IrLAP p. 82)		 *		 * Similar to irlap_state_nrm_p() -> FINAL_TIMER_EXPIRED		 * Note : self->wd_timeout = (self->final_timeout * 2),		 *   which explain why we use (self->N2 / 2) here !!!		 * Jean II		 */		IRDA_DEBUG(1, "%s(), retry_count = %d\n", __FUNCTION__,			   self->retry_count);		if (self->retry_count < (self->N2 / 2)) {			/* No retry, just wait for primary */			irlap_start_wd_timer(self, self->wd_timeout);			self->retry_count++;			if((self->retry_count % (self->N1 / 2)) == 0)				irlap_status_indication(self,							STATUS_NO_ACTIVITY);		} 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;	case RECV_DISC_CMD:		/* Always switch state before calling upper layers */		irlap_next_state(self, LAP_NDM);		/* Send disconnect response */		irlap_wait_min_turn_around(self, &self->qos_tx);		irlap_send_ua_response_frame(self, NULL);		del_timer(&self->wd_timer);		irlap_flush_all_queues(self);		/* Set default link parameters */		irlap_apply_default_connection_parameters(self);		irlap_disconnect_indication(self, LAP_DISC_INDICATION);		break;	case RECV_DISCOVERY_XID_CMD:		irlap_wait_min_turn_around(self, &self->qos_tx);		irlap_send_rr_frame(self, RSP_FRAME);		self->ack_required = TRUE;		irlap_start_wd_timer(self, self->wd_timeout);		irlap_next_state(self, LAP_NRM_S);		break;	case RECV_TEST_CMD:		/* Remove test frame header (only LAP header in NRM) */		skb_pull(skb, LAP_ADDR_HEADER + LAP_CTRL_HEADER);		irlap_wait_min_turn_around(self, &self->qos_tx);		irlap_start_wd_timer(self, self->wd_timeout);		/* Send response (info will be copied) */		irlap_send_test_frame(self, self->caddr, info->daddr, skb);		break;	default:		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,			   event, irlap_event[event]);		ret = -EINVAL;		break;	}	return ret;}/* * Function irlap_state_sclose (self, event, skb, info) */static int irlap_state_sclose(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 -ENODEV;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);	switch (event) {	case RECV_DISC_CMD:		/* Always switch state before calling upper layers */		irlap_next_state(self, LAP_NDM);		/* Send disconnect response */		irlap_wait_min_turn_around(self, &self->qos_tx);		irlap_send_ua_response_frame(self, NULL);		del_timer(&self->wd_timer);		/* Set default link parameters */		irlap_apply_default_connection_parameters(self);		irlap_disconnect_indication(self, LAP_DISC_INDICATION);		break;	case RECV_DM_RSP:		/* IrLAP-1.1 p.82: in SCLOSE, S and I type RSP frames		 * shall take us down into default NDM state, like DM_RSP		 */	case RECV_RR_RSP:	case RECV_RNR_RSP:	case RECV_REJ_RSP:	case RECV_SREJ_RSP:	case RECV_I_RSP:		/* Always switch state before calling upper layers */		irlap_next_state(self, LAP_NDM);		del_timer(&self->wd_timer);		irlap_apply_default_connection_parameters(self);		irlap_disconnect_indication(self, LAP_DISC_INDICATION);		break;	case WD_TIMER_EXPIRED:		/* Always switch state before calling upper layers */		irlap_next_state(self, LAP_NDM);		irlap_apply_default_connection_parameters(self);		irlap_disconnect_indication(self, LAP_DISC_INDICATION);		break;	default:		/* IrLAP-1.1 p.82: in SCLOSE, basically any received frame		 * with pf=1 shall restart the wd-timer and resend the rd:rsp		 */		if (info != NULL  &&  info->pf) {			del_timer(&self->wd_timer);			irlap_wait_min_turn_around(self, &self->qos_tx);			irlap_send_rd_frame(self);			irlap_start_wd_timer(self, self->wd_timeout);			break;		/* stay in SCLOSE */		}		IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __FUNCTION__,			   event, irlap_event[event]);		ret = -EINVAL;		break;	}	return -1;}static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event,				   struct sk_buff *skb,				   struct irlap_info *info){	int ret = 0;	IRDA_DEBUG(1, "%s(), event=%s\n", __FUNCTION__, irlap_event[event]);	IRDA_ASSERT(self != NULL, return -ENODEV;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -EBADR;);	switch (event) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -