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

📄 irlap_frame.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static void irlap_recv_discovery_xid_cmd(struct irlap_cb *self,					 struct sk_buff *skb,					 struct irlap_info *info){	struct xid_frame *xid;	discovery_t *discovery = NULL;	__u8 *discovery_info;	char *text;	if (!pskb_may_pull(skb, sizeof(struct xid_frame))) {		IRDA_ERROR("%s: frame too short!\n", __FUNCTION__);		return;	}	xid = (struct xid_frame *) skb->data;	info->daddr = le32_to_cpu(xid->saddr);	info->saddr = le32_to_cpu(xid->daddr);	/* Make sure frame is addressed to us */	if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {		IRDA_DEBUG(0, "%s(), frame is not addressed to us!\n",			   __FUNCTION__);		return;	}	switch (xid->flags & 0x03) {	case 0x00:		info->S = 1;		break;	case 0x01:		info->S = 6;		break;	case 0x02:		info->S = 8;		break;	case 0x03:		info->S = 16;		break;	default:		/* Error!! */		return;	}	info->s = xid->slotnr;	discovery_info = skb_pull(skb, sizeof(struct xid_frame));	/*	 *  Check if last frame	 */	if (info->s == 0xff) {		/* Check if things are sane at this point... */		if((discovery_info == NULL) ||		   !pskb_may_pull(skb, 3)) {			IRDA_ERROR("%s: discovery frame too short!\n",				   __FUNCTION__);			return;		}		/*		 *  We now have some discovery info to deliver!		 */		discovery = kmalloc(sizeof(discovery_t), GFP_ATOMIC);		if (!discovery) {			IRDA_WARNING("%s: unable to malloc!\n", __FUNCTION__);			return;		}		discovery->data.daddr = info->daddr;		discovery->data.saddr = self->saddr;		discovery->timestamp = jiffies;		discovery->data.hints[0] = discovery_info[0];		if (discovery_info[0] & HINT_EXTENSION) {			discovery->data.hints[1] = discovery_info[1];			discovery->data.charset = discovery_info[2];			text = (char *) &discovery_info[3];		} else {			discovery->data.hints[1] = 0;			discovery->data.charset = discovery_info[1];			text = (char *) &discovery_info[2];		}		/*		 *  Terminate string, should be safe since this is where the		 *  FCS bytes resides.		 */		skb->data[skb->len] = '\0';		strncpy(discovery->data.info, text, NICKNAME_MAX_LEN);		discovery->name_len = strlen(discovery->data.info);		info->discovery = discovery;	} else		info->discovery = NULL;	irlap_do_event(self, RECV_DISCOVERY_XID_CMD, skb, info);}/* * Function irlap_send_rr_frame (self, command) * *    Build and transmit RR (Receive Ready) frame. Notice that it is currently *    only possible to send RR frames with the poll bit set. */void irlap_send_rr_frame(struct irlap_cb *self, int command){	struct sk_buff *tx_skb;	struct rr_frame *frame;	tx_skb = alloc_skb(sizeof(struct rr_frame), GFP_ATOMIC);	if (!tx_skb)		return;	frame = (struct rr_frame *)skb_put(tx_skb, 2);	frame->caddr = self->caddr;	frame->caddr |= (command) ? CMD_FRAME : 0;	frame->control = RR | PF_BIT | (self->vr << 5);	irlap_queue_xmit(self, tx_skb);}/* * Function irlap_send_rd_frame (self) * *    Request disconnect. Used by a secondary station to request the *    disconnection of the link. */void irlap_send_rd_frame(struct irlap_cb *self){	struct sk_buff *tx_skb;	struct rd_frame *frame;	tx_skb = alloc_skb(sizeof(struct rd_frame), GFP_ATOMIC);	if (!tx_skb)		return;	frame = (struct rd_frame *)skb_put(tx_skb, 2);	frame->caddr = self->caddr;	frame->caddr = RD_RSP | PF_BIT;	irlap_queue_xmit(self, tx_skb);}/* * Function irlap_recv_rr_frame (skb, info) * *    Received RR (Receive Ready) frame from peer station, no harm in *    making it inline since its called only from one single place *    (irlap_driver_rcv). */static inline void irlap_recv_rr_frame(struct irlap_cb *self,				       struct sk_buff *skb,				       struct irlap_info *info, int command){	info->nr = skb->data[1] >> 5;	/* Check if this is a command or a response frame */	if (command)		irlap_do_event(self, RECV_RR_CMD, skb, info);	else		irlap_do_event(self, RECV_RR_RSP, skb, info);}/* * Function irlap_recv_rnr_frame (self, skb, info) * *    Received RNR (Receive Not Ready) frame from peer station * */static void irlap_recv_rnr_frame(struct irlap_cb *self, struct sk_buff *skb,				 struct irlap_info *info, int command){	info->nr = skb->data[1] >> 5;	IRDA_DEBUG(4, "%s(), nr=%d, %ld\n", __FUNCTION__, info->nr, jiffies);	if (command)		irlap_do_event(self, RECV_RNR_CMD, skb, info);	else		irlap_do_event(self, RECV_RNR_RSP, skb, info);}static void irlap_recv_rej_frame(struct irlap_cb *self, struct sk_buff *skb,				 struct irlap_info *info, int command){	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);	info->nr = skb->data[1] >> 5;	/* Check if this is a command or a response frame */	if (command)		irlap_do_event(self, RECV_REJ_CMD, skb, info);	else		irlap_do_event(self, RECV_REJ_RSP, skb, info);}static void irlap_recv_srej_frame(struct irlap_cb *self, struct sk_buff *skb,				  struct irlap_info *info, int command){	IRDA_DEBUG(0, "%s()\n", __FUNCTION__);	info->nr = skb->data[1] >> 5;	/* Check if this is a command or a response frame */	if (command)		irlap_do_event(self, RECV_SREJ_CMD, skb, info);	else		irlap_do_event(self, RECV_SREJ_RSP, skb, info);}static void irlap_recv_disc_frame(struct irlap_cb *self, struct sk_buff *skb,				  struct irlap_info *info, int command){	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);	/* Check if this is a command or a response frame */	if (command)		irlap_do_event(self, RECV_DISC_CMD, skb, info);	else		irlap_do_event(self, RECV_RD_RSP, skb, info);}/* * Function irlap_recv_ua_frame (skb, frame) * *    Received UA (Unnumbered Acknowledgement) frame * */static inline void irlap_recv_ua_frame(struct irlap_cb *self,				       struct sk_buff *skb,				       struct irlap_info *info){	irlap_do_event(self, RECV_UA_RSP, skb, info);}/* * Function irlap_send_data_primary(self, skb) * *    Send I-frames as the primary station but without the poll bit set * */void irlap_send_data_primary(struct irlap_cb *self, struct sk_buff *skb){	struct sk_buff *tx_skb;	if (skb->data[1] == I_FRAME) {		/*		 *  Insert frame sequence number (Vs) in control field before		 *  inserting into transmit window queue.		 */		skb->data[1] = I_FRAME | (self->vs << 1);		/*		 *  Insert frame in store, in case of retransmissions		 *  Increase skb reference count, see irlap_do_event()		 */		skb_get(skb);		skb_queue_tail(&self->wx_list, skb);		/* Copy buffer */		tx_skb = skb_clone(skb, GFP_ATOMIC);		if (tx_skb == NULL) {			return;		}		self->vs = (self->vs + 1) % 8;		self->ack_required = FALSE;		self->window -= 1;		irlap_send_i_frame( self, tx_skb, CMD_FRAME);	} else {		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);		irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);		self->window -= 1;	}}/* * Function irlap_send_data_primary_poll (self, skb) * *    Send I(nformation) frame as primary with poll bit set */void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb){	struct sk_buff *tx_skb;	int transmission_time;	/* Stop P timer */	del_timer(&self->poll_timer);	/* Is this reliable or unreliable data? */	if (skb->data[1] == I_FRAME) {		/*		 *  Insert frame sequence number (Vs) in control field before		 *  inserting into transmit window queue.		 */		skb->data[1] = I_FRAME | (self->vs << 1);		/*		 *  Insert frame in store, in case of retransmissions		 *  Increase skb reference count, see irlap_do_event()		 */		skb_get(skb);		skb_queue_tail(&self->wx_list, skb);		/* Copy buffer */		tx_skb = skb_clone(skb, GFP_ATOMIC);		if (tx_skb == NULL) {			return;		}		/*		 *  Set poll bit if necessary. We do this to the copied		 *  skb, since retransmitted need to set or clear the poll		 *  bit depending on when they are sent.		 */		tx_skb->data[1] |= PF_BIT;		self->vs = (self->vs + 1) % 8;		self->ack_required = FALSE;		irlap_next_state(self, LAP_NRM_P);		irlap_send_i_frame(self, tx_skb, CMD_FRAME);	} else {		IRDA_DEBUG(4, "%s(), sending unreliable frame\n", __FUNCTION__);		if (self->ack_required) {			irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);			irlap_next_state(self, LAP_NRM_P);			irlap_send_rr_frame(self, CMD_FRAME);			self->ack_required = FALSE;		} else {			skb->data[1] |= PF_BIT;			irlap_next_state(self, LAP_NRM_P);			irlap_send_ui_frame(self, skb_get(skb), self->caddr, CMD_FRAME);		}	}	/* How much time we took for transmission of all frames.	 * We don't know, so let assume we used the full window. Jean II */	transmission_time = self->final_timeout;	/* Reset parameter so that we can fill next window */	self->window = self->window_size;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW	/* Remove what we have not used. Just do a prorata of the	 * bytes left in window to window capacity.	 * See max_line_capacities[][] in qos.c for details. Jean II */	transmission_time -= (self->final_timeout * self->bytes_left			      / self->line_capacity);	IRDA_DEBUG(4, "%s() adjusting transmission_time : ft=%d, bl=%d, lc=%d -> tt=%d\n", __FUNCTION__, self->final_timeout, self->bytes_left, self->line_capacity, transmission_time);	/* We are allowed to transmit a maximum number of bytes again. */	self->bytes_left = self->line_capacity;#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */	/*	 * The network layer has a intermediate buffer between IrLAP	 * and the IrDA driver which can contain 8 frames. So, even	 * though IrLAP is currently sending the *last* frame of the	 * tx-window, the driver most likely has only just started	 * sending the *first* frame of the same tx-window.	 * I.e. we are always at the very begining of or Tx window.	 * Now, we are supposed to set the final timer from the end	 * of our tx-window to let the other peer reply. So, we need	 * to add extra time to compensate for the fact that we	 * are really at the start of tx-window, otherwise the final timer	 * might expire before he can answer...	 * Jean II	 */	irlap_start_final_timer(self, self->final_timeout + transmission_time);	/*	 * The clever amongst you might ask why we do this adjustement	 * only here, and not in all the other cases in irlap_event.c.	 * In all those other case, we only send a very short management	 * frame (few bytes), so the adjustement would be lost in the	 * noise...	 * The exception of course is irlap_resend_rejected_frame().	 * Jean II */}/* * Function irlap_send_data_secondary_final (self, skb) * *    Send I(nformation) frame as secondary with final bit set * */void irlap_send_data_secondary_final(struct irlap_cb *self,				     struct sk_buff *skb){	struct sk_buff *tx_skb = NULL;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	/* Is this reliable or unreliable data? */	if (skb->data[1] == I_FRAME) {		/*		 *  Insert frame sequence number (Vs) in control field before		 *  inserting into transmit window queue.		 */		skb->data[1] = I_FRAME | (self->vs << 1);		/*		 *  Insert frame in store, in case of retransmissions		 *  Increase skb reference count, see irlap_do_event()		 */		skb_get(skb);		skb_queue_tail(&self->wx_list, skb);		tx_skb = skb_clone(skb, GFP_ATOMIC);		if (tx_skb == NULL) {			return;		}		tx_skb->data[1] |= PF_BIT;		self->vs = (self->vs + 1) % 8;		self->ack_required = FALSE;		irlap_send_i_frame(self, tx_skb, RSP_FRAME);	} else {		if (self->ack_required) {			irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);			irlap_send_rr_frame(self, RSP_FRAME);			self->ack_required = FALSE;		} else {			skb->data[1] |= PF_BIT;			irlap_send_ui_frame(self, skb_get(skb), self->caddr, RSP_FRAME);		}	}	self->window = self->window_size;#ifdef CONFIG_IRDA_DYNAMIC_WINDOW	/* We are allowed to transmit a maximum number of bytes again. */	self->bytes_left = self->line_capacity;#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */	irlap_start_wd_timer(self, self->wd_timeout);}/* * Function irlap_send_data_secondary (self, skb) * *    Send I(nformation) frame as secondary without final bit set * */void irlap_send_data_secondary(struct irlap_cb *self, struct sk_buff *skb){	struct sk_buff *tx_skb = NULL;	/* Is this reliable or unreliable data? */	if (skb->data[1] == I_FRAME) {		/*		 *  Insert frame sequence number (Vs) in control field before		 *  inserting into transmit window queue.		 */		skb->data[1] = I_FRAME | (self->vs << 1);		/*		 *  Insert frame in store, in case of retransmissions		 *  Increase skb reference count, see irlap_do_event()		 */		skb_get(skb);		skb_queue_tail(&self->wx_list, skb);		tx_skb = skb_clone(skb, GFP_ATOMIC);		if (tx_skb == NULL) {			return;		}		self->vs = (self->vs + 1) % 8;		self->ack_required = FALSE;		self->window -= 1;

⌨️ 快捷键说明

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