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

📄 irttp.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * a while before it's run... - Jean II */	/*	 * If the peer device has given us some credits and we didn't have	 * anyone from before, then we need to shedule the tx queue.	 * We need to do that because our Tx have stopped (so we may not	 * get any LAP flow indication) and the user may be stopped as	 * well. - Jean II	 */	if (self->send_credit == n) {		/* Restart pushing stuff to LAP */		irttp_run_tx_queue(self);		/* Note : we don't want to schedule the todo timer		 * because it has horrible latency. No tasklets		 * because the tasklet API is broken. - Jean II */	}	return 0;}/* * Function irttp_status_indication (self, reason) * *    Status_indication, just pass to the higher layer... * */static void irttp_status_indication(void *instance,				    LINK_STATUS link, LOCK_STATUS lock){	struct tsap_cb *self;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	self = (struct tsap_cb *) instance;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	/* Check if client has already closed the TSAP and gone away */	if (self->close_pend)		return;	/*	 *  Inform service user if he has requested it	 */	if (self->notify.status_indication != NULL)		self->notify.status_indication(self->notify.instance,					       link, lock);	else		IRDA_DEBUG(2, "%s(), no handler\n", __FUNCTION__);}/* * Function irttp_flow_indication (self, reason) * *    Flow_indication : IrLAP tells us to send more data. * */static void irttp_flow_indication(void *instance, void *sap, LOCAL_FLOW flow){	struct tsap_cb *self;	self = (struct tsap_cb *) instance;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	IRDA_DEBUG(4, "%s(instance=%p)\n", __FUNCTION__, self);	/* We are "polled" directly from LAP, and the LAP want to fill	 * its Tx window. We want to do our best to send it data, so that	 * we maximise the window. On the other hand, we want to limit the	 * amount of work here so that LAP doesn't hang forever waiting	 * for packets. - Jean II */	/* Try to send some packets. Currently, LAP calls us every time	 * there is one free slot, so we will send only one packet.	 * This allow the scheduler to do its round robin - Jean II */	irttp_run_tx_queue(self);	/* Note regarding the interraction with higher layer.	 * irttp_run_tx_queue() may call the client when its queue	 * start to empty, via notify.flow_indication(). Initially.	 * I wanted this to happen in a tasklet, to avoid client	 * grabbing the CPU, but we can't use tasklets safely. And timer	 * is definitely too slow.	 * This will happen only once per LAP window, and usually at	 * the third packet (unless window is smaller). LAP is still	 * doing mtt and sending first packet so it's sort of OK	 * to do that. Jean II */	/* If we need to send disconnect. try to do it now */	if(self->disconnect_pend)		irttp_start_todo_timer(self, 0);}/* * Function irttp_flow_request (self, command) * *    This function could be used by the upper layers to tell IrTTP to stop *    delivering frames if the receive queues are starting to get full, or *    to tell IrTTP to start delivering frames again. */void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow){	IRDA_DEBUG(1, "%s()\n", __FUNCTION__);	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	switch (flow) {	case FLOW_STOP:		IRDA_DEBUG(1, "%s(), flow stop\n", __FUNCTION__);		self->rx_sdu_busy = TRUE;		break;	case FLOW_START:		IRDA_DEBUG(1, "%s(), flow start\n", __FUNCTION__);		self->rx_sdu_busy = FALSE;		/* Client say he can accept more data, try to free our		 * queues ASAP - Jean II */		irttp_run_rx_queue(self);		break;	default:		IRDA_DEBUG(1, "%s(), Unknown flow command!\n", __FUNCTION__);	}}EXPORT_SYMBOL(irttp_flow_request);/* * Function irttp_connect_request (self, dtsap_sel, daddr, qos) * *    Try to connect to remote destination TSAP selector * */int irttp_connect_request(struct tsap_cb *self, __u8 dtsap_sel,			  __u32 saddr, __u32 daddr,			  struct qos_info *qos, __u32 max_sdu_size,			  struct sk_buff *userdata){	struct sk_buff *tx_skb;	__u8 *frame;	__u8 n;	IRDA_DEBUG(4, "%s(), max_sdu_size=%d\n", __FUNCTION__, max_sdu_size);	IRDA_ASSERT(self != NULL, return -EBADR;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -EBADR;);	if (self->connected) {		if(userdata)			dev_kfree_skb(userdata);		return -EISCONN;	}	/* Any userdata supplied? */	if (userdata == NULL) {		tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,				   GFP_ATOMIC);		if (!tx_skb)			return -ENOMEM;		/* Reserve space for MUX_CONTROL and LAP header */		skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);	} else {		tx_skb = userdata;		/*		 *  Check that the client has reserved enough space for		 *  headers		 */		IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,			{ dev_kfree_skb(userdata); return -1; } );	}	/* Initialize connection parameters */	self->connected = FALSE;	self->avail_credit = 0;	self->rx_max_sdu_size = max_sdu_size;	self->rx_sdu_size = 0;	self->rx_sdu_busy = FALSE;	self->dtsap_sel = dtsap_sel;	n = self->initial_credit;	self->remote_credit = 0;	self->send_credit = 0;	/*	 *  Give away max 127 credits for now	 */	if (n > 127) {		self->avail_credit=n-127;		n = 127;	}	self->remote_credit = n;	/* SAR enabled? */	if (max_sdu_size > 0) {		IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),			{ dev_kfree_skb(tx_skb); return -1; } );		/* Insert SAR parameters */		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);		frame[0] = TTP_PARAMETERS | n;		frame[1] = 0x04; /* Length */		frame[2] = 0x01; /* MaxSduSize */		frame[3] = 0x02; /* Value length */		put_unaligned(cpu_to_be16((__u16) max_sdu_size),			      (__be16 *)(frame+4));	} else {		/* Insert plain TTP header */		frame = skb_push(tx_skb, TTP_HEADER);		/* Insert initial credit in frame */		frame[0] = n & 0x7f;	}	/* Connect with IrLMP. No QoS parameters for now */	return irlmp_connect_request(self->lsap, dtsap_sel, saddr, daddr, qos,				     tx_skb);}EXPORT_SYMBOL(irttp_connect_request);/* * Function irttp_connect_confirm (handle, qos, skb) * *    Sevice user confirms TSAP connection with peer. * */static void irttp_connect_confirm(void *instance, void *sap,				  struct qos_info *qos, __u32 max_seg_size,				  __u8 max_header_size, struct sk_buff *skb){	struct tsap_cb *self;	int parameters;	int ret;	__u8 plen;	__u8 n;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);	self = (struct tsap_cb *) instance;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	self->max_seg_size = max_seg_size - TTP_HEADER;	self->max_header_size = max_header_size + TTP_HEADER;	/*	 *  Check if we have got some QoS parameters back! This should be the	 *  negotiated QoS for the link.	 */	if (qos) {		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %02x\n",		       qos->baud_rate.bits);		IRDA_DEBUG(4, "IrTTP, Negotiated BAUD_RATE: %d bps.\n",		       qos->baud_rate.value);	}	n = skb->data[0] & 0x7f;	IRDA_DEBUG(4, "%s(), Initial send_credit=%d\n", __FUNCTION__, n);	self->send_credit = n;	self->tx_max_sdu_size = 0;	self->connected = TRUE;	parameters = skb->data[0] & 0x80;	IRDA_ASSERT(skb->len >= TTP_HEADER, return;);	skb_pull(skb, TTP_HEADER);	if (parameters) {		plen = skb->data[0];		ret = irda_param_extract_all(self, skb->data+1,					     IRDA_MIN(skb->len-1, plen),					     &param_info);		/* Any errors in the parameter list? */		if (ret < 0) {			IRDA_WARNING("%s: error extracting parameters\n",				     __FUNCTION__);			dev_kfree_skb(skb);			/* Do not accept this connection attempt */			return;		}		/* Remove parameters */		skb_pull(skb, IRDA_MIN(skb->len, plen+1));	}	IRDA_DEBUG(4, "%s() send=%d,avail=%d,remote=%d\n", __FUNCTION__,	      self->send_credit, self->avail_credit, self->remote_credit);	IRDA_DEBUG(2, "%s(), MaxSduSize=%d\n", __FUNCTION__,		   self->tx_max_sdu_size);	if (self->notify.connect_confirm) {		self->notify.connect_confirm(self->notify.instance, self, qos,					     self->tx_max_sdu_size,					     self->max_header_size, skb);	} else		dev_kfree_skb(skb);}/* * Function irttp_connect_indication (handle, skb) * *    Some other device is connecting to this TSAP * */void irttp_connect_indication(void *instance, void *sap, struct qos_info *qos,			      __u32 max_seg_size, __u8 max_header_size,			      struct sk_buff *skb){	struct tsap_cb *self;	struct lsap_cb *lsap;	int parameters;	int ret;	__u8 plen;	__u8 n;	self = (struct tsap_cb *) instance;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return;);	IRDA_ASSERT(skb != NULL, return;);	lsap = (struct lsap_cb *) sap;	self->max_seg_size = max_seg_size - TTP_HEADER;	self->max_header_size = max_header_size+TTP_HEADER;	IRDA_DEBUG(4, "%s(), TSAP sel=%02x\n", __FUNCTION__, self->stsap_sel);	/* Need to update dtsap_sel if its equal to LSAP_ANY */	self->dtsap_sel = lsap->dlsap_sel;	n = skb->data[0] & 0x7f;	self->send_credit = n;	self->tx_max_sdu_size = 0;	parameters = skb->data[0] & 0x80;	IRDA_ASSERT(skb->len >= TTP_HEADER, return;);	skb_pull(skb, TTP_HEADER);	if (parameters) {		plen = skb->data[0];		ret = irda_param_extract_all(self, skb->data+1,					     IRDA_MIN(skb->len-1, plen),					     &param_info);		/* Any errors in the parameter list? */		if (ret < 0) {			IRDA_WARNING("%s: error extracting parameters\n",				     __FUNCTION__);			dev_kfree_skb(skb);			/* Do not accept this connection attempt */			return;		}		/* Remove parameters */		skb_pull(skb, IRDA_MIN(skb->len, plen+1));	}	if (self->notify.connect_indication) {		self->notify.connect_indication(self->notify.instance, self,						qos, self->tx_max_sdu_size,						self->max_header_size, skb);	} else		dev_kfree_skb(skb);}/* * Function irttp_connect_response (handle, userdata) * *    Service user is accepting the connection, just pass it down to *    IrLMP! * */int irttp_connect_response(struct tsap_cb *self, __u32 max_sdu_size,			   struct sk_buff *userdata){	struct sk_buff *tx_skb;	__u8 *frame;	int ret;	__u8 n;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == TTP_TSAP_MAGIC, return -1;);	IRDA_DEBUG(4, "%s(), Source TSAP selector=%02x\n", __FUNCTION__,		   self->stsap_sel);	/* Any userdata supplied? */	if (userdata == NULL) {		tx_skb = alloc_skb(TTP_MAX_HEADER + TTP_SAR_HEADER,				   GFP_ATOMIC);		if (!tx_skb)			return -ENOMEM;		/* Reserve space for MUX_CONTROL and LAP header */		skb_reserve(tx_skb, TTP_MAX_HEADER + TTP_SAR_HEADER);	} else {		tx_skb = userdata;		/*		 *  Check that the client has reserved enough space for		 *  headers		 */		IRDA_ASSERT(skb_headroom(userdata) >= TTP_MAX_HEADER,			{ dev_kfree_skb(userdata); return -1; } );	}	self->avail_credit = 0;	self->remote_credit = 0;	self->rx_max_sdu_size = max_sdu_size;	self->rx_sdu_size = 0;	self->rx_sdu_busy = FALSE;	n = self->initial_credit;	/* Frame has only space for max 127 credits (7 bits) */	if (n > 127) {		self->avail_credit = n - 127;		n = 127;	}	self->remote_credit = n;	self->connected = TRUE;	/* SAR enabled? */	if (max_sdu_size > 0) {		IRDA_ASSERT(skb_headroom(tx_skb) >= (TTP_MAX_HEADER + TTP_SAR_HEADER),			{ dev_kfree_skb(tx_skb); return -1; } );		/* Insert TTP header with SAR parameters */		frame = skb_push(tx_skb, TTP_HEADER+TTP_SAR_HEADER);		frame[0] = TTP_PARAMETERS | n;		frame[1] = 0x04; /* Length */		/* irda_param_insert(self, IRTTP_MAX_SDU_SIZE, frame+1,  *//*				  TTP_SAR_HEADER, &param_info) */		frame[2] = 0x01; /* MaxSduSize */		frame[3] = 0x02; /* Value length */		put_unaligned(cpu_to_be16((__u16) max_sdu_size),			      (__be16 *)(frame+4));	} else {		/* Insert TTP header */		frame = skb_push(tx_skb, TTP_HEADER);		frame[0] = n & 0x7f;	}	ret = irlmp_connect_response(self->lsap, tx_skb);	return ret;}EXPORT_SYMBOL(irttp_connect_response);/* * Function irttp_dup (self, instance)

⌨️ 快捷键说明

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