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

📄 irlap_event.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ifdef CONFIG_IRDA_ULTRA		/* Send any pending Ultra frames if any */		if (!skb_queue_empty(&self->txq_ultra)) {			/* We don't send the frame, just post an event.			 * Also, previously this code was in timer.c...			 * Jean II */			ret = (*state[self->state])(self, SEND_UI_FRAME,						    NULL, NULL);		}#endif /* CONFIG_IRDA_ULTRA */		/* Check if we should try to connect.		 * This code was previously in irlap_do_event() */		if (self->connect_pending) {			self->connect_pending = FALSE;			/* This one *should* not pend in this state, except			 * if a socket try to connect and immediately			 * disconnect. - clear - Jean II */			if (self->disconnect_pending)				irlap_disconnect_indication(self, LAP_DISC_INDICATION);			else				ret = (*state[self->state])(self,							    CONNECT_REQUEST,							    NULL, NULL);			self->disconnect_pending = FALSE;		}		/* Note : one way to test if this code works well (including		 * media busy and small busy) is to create a user space		 * application generating an Ultra packet every 3.05 sec (or		 * 2.95 sec) and to see how it interact with discovery.		 * It's fairly easy to check that no packet is lost, that the		 * packets are postponed during discovery and that after		 * discovery indication you have a 100ms "gap".		 * As connection request and Ultra are now processed the same		 * way, this avoid the tedious job of trying IrLAP connection		 * in all those cases...		 * Jean II */		break;#ifdef CONFIG_IRDA_ULTRA	case SEND_UI_FRAME:	{		int i;		/* Only allowed to repeat an operation twice */		for (i=0; ((i<2) && (self->media_busy == FALSE)); i++) {			skb = skb_dequeue(&self->txq_ultra);			if (skb)				irlap_send_ui_frame(self, skb, CBROADCAST,						    CMD_FRAME);			else				break;			/* irlap_send_ui_frame() won't increase skb reference			 * count, so no dev_kfree_skb() - Jean II */		}		if (i == 2) {			/* Force us to listen 500 ms again */			irda_device_set_media_busy(self->netdev, TRUE);		}		break;	}	case RECV_UI_FRAME:		/* Only accept broadcast frames in NDM mode */		if (info->caddr != CBROADCAST) {			IRDA_DEBUG(0, "%s(), not a broadcast frame!\n",				   __FUNCTION__);		} else			irlap_unitdata_indication(self, skb);		break;#endif /* CONFIG_IRDA_ULTRA */	case RECV_TEST_CMD:		/* Remove test frame header */		skb_pull(skb, sizeof(struct test_frame));		/*		 * Send response. This skb will not be sent out again, and		 * will only be used to send out the same info as the cmd		 */		irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);		break;	case RECV_TEST_RSP:		IRDA_DEBUG(0, "%s() not implemented!\n", __FUNCTION__);		break;	default:		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,			   irlap_event[event]);		ret = -1;		break;	}	return ret;}/* * Function irlap_state_query (event, skb, info) * *    QUERY state * */static int irlap_state_query(struct irlap_cb *self, IRLAP_EVENT event,			     struct sk_buff *skb, struct irlap_info *info){	int ret = 0;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);	switch (event) {	case RECV_DISCOVERY_XID_RSP:		IRDA_ASSERT(info != NULL, return -1;);		IRDA_ASSERT(info->discovery != NULL, return -1;);		IRDA_DEBUG(4, "%s(), daddr=%08x\n", __FUNCTION__,			   info->discovery->data.daddr);		if (!self->discovery_log) {			IRDA_WARNING("%s: discovery log is gone! "				     "maybe the discovery timeout has been set"				     " too short?\n", __FUNCTION__);			break;		}		hashbin_insert(self->discovery_log,			       (irda_queue_t *) info->discovery,			       info->discovery->data.daddr, NULL);		/* Keep state */		/* irlap_next_state(self, LAP_QUERY);  */		break;	case RECV_DISCOVERY_XID_CMD:		/* Yes, it is possible to receive those frames in this mode.		 * Note that most often the last discovery request won't		 * occur here but in NDM state (see my comment there).		 * What should we do ?		 * Not much. We are currently performing our own discovery,		 * therefore we can't answer those frames. We don't want		 * to change state either. We just pass the info to		 * IrLMP who will put it in the log (and post an event).		 * Jean II		 */		IRDA_ASSERT(info != NULL, return -1;);		IRDA_DEBUG(1, "%s(), Receiving discovery request (s = %d) while performing discovery :-(\n", __FUNCTION__, info->s);		/* Last discovery request ? */		if (info->s == 0xff)			irlap_discovery_indication(self, info->discovery);		break;	case SLOT_TIMER_EXPIRED:		/*		 * Wait a little longer if we detect an incoming frame. This		 * is not mentioned in the spec, but is a good thing to do,		 * since we want to work even with devices that violate the		 * timing requirements.		 */		if (irda_device_is_receiving(self->netdev) && !self->add_wait) {			IRDA_DEBUG(2, "%s(), device is slow to answer, "				   "waiting some more!\n", __FUNCTION__);			irlap_start_slot_timer(self, msecs_to_jiffies(10));			self->add_wait = TRUE;			return ret;		}		self->add_wait = FALSE;		if (self->s < self->S) {			irlap_send_discovery_xid_frame(self, self->S,						       self->s, TRUE,						       self->discovery_cmd);			self->s++;			irlap_start_slot_timer(self, self->slot_timeout);			/* Keep state */			irlap_next_state(self, LAP_QUERY);		} else {			/* This is the final slot! */			irlap_send_discovery_xid_frame(self, self->S, 0xff,						       TRUE,						       self->discovery_cmd);			/* Always switch state before calling upper layers */			irlap_next_state(self, LAP_NDM);			/*			 *  We are now finished with the discovery procedure,			 *  so now we must return the results			 */			irlap_discovery_confirm(self, self->discovery_log);			/* IrLMP should now have taken care of the log */			self->discovery_log = NULL;		}		break;	default:		IRDA_DEBUG(2, "%s(), Unknown event %s\n", __FUNCTION__,			   irlap_event[event]);		ret = -1;		break;	}	return ret;}/* * Function irlap_state_reply (self, event, skb, info) * *    REPLY, we have received a XID discovery frame from a device and we *    are waiting for the right time slot to send a response XID frame * */static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event,			     struct sk_buff *skb, struct irlap_info *info){	discovery_t *discovery_rsp;	int ret=0;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);	switch (event) {	case QUERY_TIMER_EXPIRED:		IRDA_DEBUG(0, "%s(), QUERY_TIMER_EXPIRED <%ld>\n",			   __FUNCTION__, jiffies);		irlap_next_state(self, LAP_NDM);		break;	case RECV_DISCOVERY_XID_CMD:		IRDA_ASSERT(info != NULL, return -1;);		/* Last frame? */		if (info->s == 0xff) {			del_timer(&self->query_timer);			/* info->log.condition = REMOTE; */			/* Always switch state before calling upper layers */			irlap_next_state(self, LAP_NDM);			irlap_discovery_indication(self, info->discovery);		} else {			/* If it's our slot, send our reply */			if ((info->s >= self->slot) && (!self->frame_sent)) {				discovery_rsp = irlmp_get_discovery_response();				discovery_rsp->data.daddr = info->daddr;				irlap_send_discovery_xid_frame(self, info->S,							       self->slot,							       FALSE,							       discovery_rsp);				self->frame_sent = TRUE;			}			/* Readjust our timer to accomodate devices			 * doing faster or slower discovery than us...			 * Jean II */			irlap_start_query_timer(self, info->S, info->s);			/* Keep state */			//irlap_next_state(self, LAP_REPLY);		}		break;	default:		IRDA_DEBUG(1, "%s(), Unknown event %d, %s\n", __FUNCTION__,			   event, irlap_event[event]);		ret = -1;		break;	}	return ret;}/* * Function irlap_state_conn (event, skb, info) * *    CONN, we have received a SNRM command and is waiting for the upper *    layer to accept or refuse connection * */static int irlap_state_conn(struct irlap_cb *self, IRLAP_EVENT event,			    struct sk_buff *skb, struct irlap_info *info){	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 CONNECT_RESPONSE:		skb_pull(skb, sizeof(struct snrm_frame));		IRDA_ASSERT(self->netdev != NULL, return -1;);		irlap_qos_negotiate(self, skb);		irlap_initiate_connection_state(self);		/*		 * Applying the parameters now will make sure we change speed		 * *after* we have sent the next frame		 */		irlap_apply_connection_parameters(self, FALSE);		/*		 * Sending this frame will force a speed change after it has		 * been sent (i.e. the frame will be sent at 9600).		 */		irlap_send_ua_response_frame(self, &self->qos_rx);#if 0		/*		 * We are allowed to send two frames, but this may increase		 * the connect latency, so lets not do it for now.		 */		/* This is full of good intentions, but doesn't work in		 * practice.		 * After sending the first UA response, we switch the		 * dongle to the negotiated speed, which is usually		 * different than 9600 kb/s.		 * From there, there is two solutions :		 * 1) The other end has received the first UA response :		 * it will set up the connection, move to state LAP_NRM_P,		 * and will ignore and drop the second UA response.		 * Actually, it's even worse : the other side will almost		 * immediately send a RR that will likely collide with the		 * UA response (depending on negotiated turnaround).		 * 2) The other end has not received the first UA response,		 * will stay at 9600 and will never see the second UA response.		 * Jean II */		irlap_send_ua_response_frame(self, &self->qos_rx);#endif		/*		 *  The WD-timer could be set to the duration of the P-timer		 *  for this case, but it is recommended to use twice the		 *  value (note 3 IrLAP p. 60).		 */		irlap_start_wd_timer(self, self->wd_timeout);		irlap_next_state(self, LAP_NRM_S);		break;	case RECV_DISCOVERY_XID_CMD:		IRDA_DEBUG(3, "%s(), event RECV_DISCOVER_XID_CMD!\n",			   __FUNCTION__);		irlap_next_state(self, LAP_NDM);		break;	case DISCONNECT_REQUEST:		IRDA_DEBUG(0, "%s(), Disconnect request!\n", __FUNCTION__);		irlap_send_dm_frame(self);		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_setup (event, skb, frame) * *    SETUP state, The local layer has transmitted a SNRM command frame to *    a remote peer layer and is awaiting a reply . * */static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event,			     struct sk_buff *skb, struct irlap_info *info){	int ret = 0;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return -1;);	switch (event) {	case FINAL_TIMER_EXPIRED:		if (self->retry_count < self->N3) {/* *  Perform random backoff, Wait a random number of time units, minimum *  duration half the time taken to transmitt a SNRM frame, maximum duration *  1.5 times the time taken to transmit a SNRM frame. So this time should *  between 15 msecs and 45 msecs. */			irlap_start_backoff_timer(self, msecs_to_jiffies(20 +							(jiffies % 30)));		} else {			/* Always switch state before calling upper layers */			irlap_next_state(self, LAP_NDM);			irlap_disconnect_indication(self, LAP_FOUND_NONE);		}		break;	case BACKOFF_TIMER_EXPIRED:		irlap_send_snrm_frame(self, &self->qos_rx);		irlap_start_final_timer(self, self->final_timeout);		self->retry_count++;		break;	case RECV_SNRM_CMD:		IRDA_DEBUG(4, "%s(), SNRM battle!\n", __FUNCTION__);		IRDA_ASSERT(skb != NULL, return 0;);		IRDA_ASSERT(info != NULL, return 0;);		/*		 *  The device with the largest device address wins the battle		 *  (both have sent a SNRM command!)		 */		if (info &&(info->daddr > self->saddr)) {			del_timer(&self->final_timer);			irlap_initiate_connection_state(self);			IRDA_ASSERT(self->netdev != NULL, return -1;);			skb_pull(skb, sizeof(struct snrm_frame));			irlap_qos_negotiate(self, skb);			/* Send UA frame and then change link settings */			irlap_apply_connection_parameters(self, FALSE);			irlap_send_ua_response_frame(self, &self->qos_rx);			irlap_next_state(self, LAP_NRM_S);			irlap_connect_confirm(self, skb);			/*			 *  The WD-timer could be set to the duration of the			 *  P-timer for this case, but it is recommended			 *  to use twice the value (note 3 IrLAP p. 60).			 */			irlap_start_wd_timer(self, self->wd_timeout);		} else {			/* We just ignore the other device! */			irlap_next_state(self, LAP_SETUP);		}		break;	case RECV_UA_RSP:		/* Stop F-timer */		del_timer(&self->final_timer);		/* Initiate connection state */		irlap_initiate_connection_state(self);		/* Negotiate connection parameters */		IRDA_ASSERT(skb->len > 10, return -1;);		skb_pull(skb, sizeof(struct ua_frame));		IRDA_ASSERT(self->netdev != NULL, return -1;);		irlap_qos_negotiate(self, skb);		/* Set the new link setting *now* (before the rr frame) */		irlap_apply_connection_parameters(self, TRUE);

⌨️ 快捷键说明

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