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

📄 irlap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 *    Receive Ultra data. This is data that is received outside any connection * */#ifdef CONFIG_IRDA_ULTRAvoid irlap_unitdata_indication(struct irlap_cb *self, struct sk_buff *skb){	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	/* Hide LAP header from IrLMP layer */	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);	irlmp_link_unitdata_indication(self->notify.instance, skb);}#endif /* CONFIG_IRDA_ULTRA *//* * Function irlap_disconnect_request (void) * *    Request to disconnect connection by service user */void irlap_disconnect_request(struct irlap_cb *self){	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	/* Don't disconnect until all data frames are successfully sent */	if (!skb_queue_empty(&self->txq)) {		self->disconnect_pending = TRUE;		return;	}	/* Check if we are in the right state for disconnecting */	switch (self->state) {	case LAP_XMIT_P:        /* FALLTROUGH */	case LAP_XMIT_S:        /* FALLTROUGH */	case LAP_CONN:          /* FALLTROUGH */	case LAP_RESET_WAIT:    /* FALLTROUGH */	case LAP_RESET_CHECK:		irlap_do_event(self, DISCONNECT_REQUEST, NULL, NULL);		break;	default:		IRDA_DEBUG(2, "%s(), disconnect pending!\n", __FUNCTION__);		self->disconnect_pending = TRUE;		break;	}}/* * Function irlap_disconnect_indication (void) * *    Disconnect request from other device * */void irlap_disconnect_indication(struct irlap_cb *self, LAP_REASON reason){	IRDA_DEBUG(1, "%s(), reason=%s\n", __FUNCTION__, lap_reasons[reason]);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	/* Flush queues */	irlap_flush_all_queues(self);	switch (reason) {	case LAP_RESET_INDICATION:		IRDA_DEBUG(1, "%s(), Sending reset request!\n", __FUNCTION__);		irlap_do_event(self, RESET_REQUEST, NULL, NULL);		break;	case LAP_NO_RESPONSE:	   /* FALLTROUGH */	case LAP_DISC_INDICATION:  /* FALLTROUGH */	case LAP_FOUND_NONE:       /* FALLTROUGH */	case LAP_MEDIA_BUSY:		irlmp_link_disconnect_indication(self->notify.instance, self,						 reason, NULL);		break;	default:		IRDA_ERROR("%s: Unknown reason %d\n", __FUNCTION__, reason);	}}/* * Function irlap_discovery_request (gen_addr_bit) * *    Start one single discovery operation. * */void irlap_discovery_request(struct irlap_cb *self, discovery_t *discovery){	struct irlap_info info;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(discovery != NULL, return;);	IRDA_DEBUG(4, "%s(), nslots = %d\n", __FUNCTION__, discovery->nslots);	IRDA_ASSERT((discovery->nslots == 1) || (discovery->nslots == 6) ||		    (discovery->nslots == 8) || (discovery->nslots == 16),		    return;);	/* Discovery is only possible in NDM mode */	if (self->state != LAP_NDM) {		IRDA_DEBUG(4, "%s(), discovery only possible in NDM mode\n",			   __FUNCTION__);		irlap_discovery_confirm(self, NULL);		/* Note : in theory, if we are not in NDM, we could postpone		 * the discovery like we do for connection request.		 * In practice, it's not worth it. If the media was busy,		 * it's likely next time around it won't be busy. If we are		 * in REPLY state, we will get passive discovery info & event.		 * Jean II */		return;	}	/* Check if last discovery request finished in time, or if	 * it was aborted due to the media busy flag. */	if (self->discovery_log != NULL) {		hashbin_delete(self->discovery_log, (FREE_FUNC) kfree);		self->discovery_log = NULL;	}	/* All operations will occur at predictable time, no need to lock */	self->discovery_log = hashbin_new(HB_NOLOCK);	if (self->discovery_log == NULL) {		IRDA_WARNING("%s(), Unable to allocate discovery log!\n",			     __FUNCTION__);		return;	}	info.S = discovery->nslots; /* Number of slots */	info.s = 0; /* Current slot */	self->discovery_cmd = discovery;	info.discovery = discovery;	/* sysctl_slot_timeout bounds are checked in irsysctl.c - Jean II */	self->slot_timeout = sysctl_slot_timeout * HZ / 1000;	irlap_do_event(self, DISCOVERY_REQUEST, NULL, &info);}/* * Function irlap_discovery_confirm (log) * *    A device has been discovered in front of this station, we *    report directly to LMP. */void irlap_discovery_confirm(struct irlap_cb *self, hashbin_t *discovery_log){	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(self->notify.instance != NULL, return;);	/*	 * Check for successful discovery, since we are then allowed to clear	 * the media busy condition (IrLAP 6.13.4 - p.94). This should allow	 * us to make connection attempts much faster and easier (i.e. no	 * collisions).	 * Setting media busy to false will also generate an event allowing	 * to process pending events in NDM state machine.	 * Note : the spec doesn't define what's a successful discovery is.	 * If we want Ultra to work, it's successful even if there is	 * nobody discovered - Jean II	 */	if (discovery_log)		irda_device_set_media_busy(self->netdev, FALSE);	/* Inform IrLMP */	irlmp_link_discovery_confirm(self->notify.instance, discovery_log);}/* * Function irlap_discovery_indication (log) * *    Somebody is trying to discover us! * */void irlap_discovery_indication(struct irlap_cb *self, discovery_t *discovery){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(discovery != NULL, return;);	IRDA_ASSERT(self->notify.instance != NULL, return;);	/* A device is very likely to connect immediately after it performs	 * a successful discovery. This means that in our case, we are much	 * more likely to receive a connection request over the medium.	 * So, we backoff to avoid collisions.	 * IrLAP spec 6.13.4 suggest 100ms...	 * Note : this little trick actually make a *BIG* difference. If I set	 * my Linux box with discovery enabled and one Ultra frame sent every	 * second, my Palm has no trouble connecting to it every time !	 * Jean II */	irda_device_set_media_busy(self->netdev, SMALL);	irlmp_link_discovery_indication(self->notify.instance, discovery);}/* * Function irlap_status_indication (quality_of_link) */void irlap_status_indication(struct irlap_cb *self, int quality_of_link){	switch (quality_of_link) {	case STATUS_NO_ACTIVITY:		IRDA_MESSAGE("IrLAP, no activity on link!\n");		break;	case STATUS_NOISY:		IRDA_MESSAGE("IrLAP, noisy link!\n");		break;	default:		break;	}	irlmp_status_indication(self->notify.instance,				quality_of_link, LOCK_NO_CHANGE);}/* * Function irlap_reset_indication (void) */void irlap_reset_indication(struct irlap_cb *self){	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	if (self->state == LAP_RESET_WAIT)		irlap_do_event(self, RESET_REQUEST, NULL, NULL);	else		irlap_do_event(self, RESET_RESPONSE, NULL, NULL);}/* * Function irlap_reset_confirm (void) */void irlap_reset_confirm(void){	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);}/* * Function irlap_generate_rand_time_slot (S, s) * *    Generate a random time slot between s and S-1 where *    S = Number of slots (0 -> S-1) *    s = Current slot */int irlap_generate_rand_time_slot(int S, int s){	static int rand;	int slot;	IRDA_ASSERT((S - s) > 0, return 0;);	rand += jiffies;	rand ^= (rand << 12);	rand ^= (rand >> 20);	slot = s + rand % (S-s);	IRDA_ASSERT((slot >= s) || (slot < S), return 0;);	return slot;}/* * Function irlap_update_nr_received (nr) * *    Remove all acknowledged frames in current window queue. This code is *    not intuitive and you should not try to change it. If you think it *    contains bugs, please mail a patch to the author instead. */void irlap_update_nr_received(struct irlap_cb *self, int nr){	struct sk_buff *skb = NULL;	int count = 0;	/*	 * Remove all the ack-ed frames from the window queue.	 */	/*	 *  Optimize for the common case. It is most likely that the receiver	 *  will acknowledge all the frames we have sent! So in that case we	 *  delete all frames stored in window.	 */	if (nr == self->vs) {		while ((skb = skb_dequeue(&self->wx_list)) != NULL) {			dev_kfree_skb(skb);		}		/* The last acked frame is the next to send minus one */		self->va = nr - 1;	} else {		/* Remove all acknowledged frames in current window */		while ((skb_peek(&self->wx_list) != NULL) &&		       (((self->va+1) % 8) != nr))		{			skb = skb_dequeue(&self->wx_list);			dev_kfree_skb(skb);			self->va = (self->va + 1) % 8;			count++;		}	}	/* Advance window */	self->window = self->window_size - skb_queue_len(&self->wx_list);}/* * Function irlap_validate_ns_received (ns) * *    Validate the next to send (ns) field from received frame. */int irlap_validate_ns_received(struct irlap_cb *self, int ns){	/*  ns as expected?  */	if (ns == self->vr)		return NS_EXPECTED;	/*	 *  Stations are allowed to treat invalid NS as unexpected NS	 *  IrLAP, Recv ... with-invalid-Ns. p. 84	 */	return NS_UNEXPECTED;	/* return NR_INVALID; */}/* * Function irlap_validate_nr_received (nr) * *    Validate the next to receive (nr) field from received frame. * */int irlap_validate_nr_received(struct irlap_cb *self, int nr){	/*  nr as expected?  */	if (nr == self->vs) {		IRDA_DEBUG(4, "%s(), expected!\n", __FUNCTION__);		return NR_EXPECTED;	}	/*	 *  unexpected nr? (but within current window), first we check if the	 *  ns numbers of the frames in the current window wrap.	 */	if (self->va < self->vs) {		if ((nr >= self->va) && (nr <= self->vs))			return NR_UNEXPECTED;	} else {		if ((nr >= self->va) || (nr <= self->vs))			return NR_UNEXPECTED;	}	/* Invalid nr!  */	return NR_INVALID;}/* * Function irlap_initiate_connection_state () * *    Initialize the connection state parameters * */void irlap_initiate_connection_state(struct irlap_cb *self){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	/* Next to send and next to receive */	self->vs = self->vr = 0;	/* Last frame which got acked (0 - 1) % 8 */	self->va = 7;	self->window = 1;	self->remote_busy = FALSE;	self->retry_count = 0;}/* * Function irlap_wait_min_turn_around (self, qos) * *    Wait negotiated minimum turn around time, this function actually sets *    the number of BOS's that must be sent before the next transmitted *    frame in order to delay for the specified amount of time. This is *    done to avoid using timers, and the forbidden udelay! */void irlap_wait_min_turn_around(struct irlap_cb *self, struct qos_info *qos){	__u32 min_turn_time;	__u32 speed;	/* Get QoS values.  */	speed = qos->baud_rate.value;	min_turn_time = qos->min_turn_time.value;	/* No need to calculate XBOFs for speeds over 115200 bps */	if (speed > 115200) {

⌨️ 快捷键说明

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