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

📄 irda-usb.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
                      write_bulk_callback, skb);	urb->transfer_buffer_length = skb->len;	/* Note : unlink *must* be Asynchronous because of the code in 	 * irda_usb_net_timeout() -> call in irq - Jean II */	urb->transfer_flags = URB_ASYNC_UNLINK;	/* This flag (URB_ZERO_PACKET) indicates that what we send is not	 * a continuous stream of data but separate packets.	 * In this case, the USB layer will insert an empty USB frame (TD)	 * after each of our packets that is exact multiple of the frame size.	 * This is how the dongle will detect the end of packet - Jean II */	urb->transfer_flags |= URB_ZERO_PACKET;	/* Generate min turn time. FIXME: can we do better than this? */	/* Trying to a turnaround time at this level is trying to measure	 * processor clock cycle with a wrist-watch, approximate at best...	 *	 * What we know is the last time we received a frame over USB.	 * Due to latency over USB that depend on the USB load, we don't	 * know when this frame was received over IrDA (a few ms before ?)	 * Then, same story for our outgoing frame...	 *	 * In theory, the USB dongle is supposed to handle the turnaround	 * by itself (spec 1.0, chater 4, page 6). Who knows ??? That's	 * why this code is enabled only for dongles that doesn't meet	 * the spec.	 * Jean II */	if (self->capability & IUC_NO_TURN) {		mtt = irda_get_mtt(skb);		if (mtt) {			int diff;			do_gettimeofday(&self->now);			diff = self->now.tv_usec - self->stamp.tv_usec;#ifdef IU_USB_MIN_RTT			/* Factor in USB delays -> Get rid of udelay() that			 * would be lost in the noise - Jean II */			diff += IU_USB_MIN_RTT;#endif /* IU_USB_MIN_RTT */			/* If the usec counter did wraparound, the diff will			 * go negative (tv_usec is a long), so we need to			 * correct it by one second. Jean II */			if (diff < 0)				diff += 1000000;		        /* Check if the mtt is larger than the time we have			 * already used by all the protocol processing			 */			if (mtt > diff) {				mtt -= diff;				if (mtt > 1000)					mdelay(mtt/1000);				else					udelay(mtt);			}		}	}		/* Ask USB to send the packet - Irq disabled -> GFP_ATOMIC */	if ((res = usb_submit_urb(urb, GFP_ATOMIC))) {		WARNING("%s(), failed Tx URB\n", __FUNCTION__);		self->stats.tx_errors++;		/* Let USB recover : We will catch that in the watchdog */		/*netif_start_queue(netdev);*/	} else {		/* Increment packet stats */		self->stats.tx_packets++;                self->stats.tx_bytes += skb->len;				netdev->trans_start = jiffies;	}	spin_unlock_irqrestore(&self->lock, flags);		return 0;drop:	/* Drop silently the skb and exit */	dev_kfree_skb(skb);	spin_unlock_irqrestore(&self->lock, flags);	return err;		/* Usually 1 */}/*------------------------------------------------------------------*//* * Note : this function will be called only for tx_urb... */static void write_bulk_callback(struct urb *urb, struct pt_regs *regs){	unsigned long flags;	struct sk_buff *skb = urb->context;	struct irda_usb_cb *self = ((struct irda_skb_cb *) skb->cb)->context;		IRDA_DEBUG(2, "%s()\n", __FUNCTION__);	/* We should always have a context */	ASSERT(self != NULL, return;);	/* We should always be called for the speed URB */	ASSERT(urb == self->tx_urb, return;);	/* Free up the skb */	dev_kfree_skb_any(skb);	urb->context = NULL;	/* Check for timeout and other USB nasties */	if (urb->status != 0) {		/* I get a lot of -ECONNABORTED = -103 here - Jean II */		IRDA_DEBUG(0, "%s(), URB complete status %d, transfer_flags 0x%04X\n", __FUNCTION__, urb->status, urb->transfer_flags);		/* Don't do anything here, that might confuse the USB layer,		 * and we could go in recursion and blow the kernel stack...		 * Instead, we will wait for irda_usb_net_timeout(), the		 * network layer watchdog, to fix the situation.		 * Jean II */		/* A reset of the dongle might be welcomed here - Jean II */		return;	}	/* urb is now available */	//urb->status = 0; -> tested above	/* Make sure we read self->present properly */	spin_lock_irqsave(&self->lock, flags);	/* If the network is closed, stop everything */	if ((!self->netopen) || (!self->present)) {		IRDA_DEBUG(0, "%s(), Network is gone...\n", __FUNCTION__);		spin_unlock_irqrestore(&self->lock, flags);		return;	}	/* If changes to speed or xbofs is pending... */	if ((self->new_speed != -1) || (self->new_xbofs != -1)) {		if ((self->new_speed != self->speed) ||		    (self->new_xbofs != self->xbofs)) {			/* We haven't changed speed yet (because of			 * IUC_SPEED_BUG), so do it now - Jean II */			IRDA_DEBUG(1, "%s(), Changing speed now...\n", __FUNCTION__);			irda_usb_change_speed_xbofs(self);		} else {			/* New speed and xbof is now commited in hardware */			self->new_speed = -1;			self->new_xbofs = -1;			/* Done, waiting for next packet */			netif_wake_queue(self->netdev);		}	} else {		/* Otherwise, allow the stack to send more packets */		netif_wake_queue(self->netdev);	}	spin_unlock_irqrestore(&self->lock, flags);}/*------------------------------------------------------------------*//* * Watchdog timer from the network layer. * After a predetermined timeout, if we don't give confirmation that * the packet has been sent (i.e. no call to netif_wake_queue()), * the network layer will call this function. * Note that URB that we submit have also a timeout. When the URB timeout * expire, the normal URB callback is called (write_bulk_callback()). */static void irda_usb_net_timeout(struct net_device *netdev){	unsigned long flags;	struct irda_usb_cb *self = netdev->priv;	struct urb *urb;	int	done = 0;	/* If we have made any progress */	IRDA_DEBUG(0, "%s(), Network layer thinks we timed out!\n", __FUNCTION__);	ASSERT(self != NULL, return;);	/* Protect us from USB callbacks, net Tx and else. */	spin_lock_irqsave(&self->lock, flags);	/* self->present *MUST* be read under spinlock */	if (!self->present) {		WARNING("%s(), device not present!\n", __FUNCTION__);		netif_stop_queue(netdev);		spin_unlock_irqrestore(&self->lock, flags);		return;	}	/* Check speed URB */	urb = self->speed_urb;	if (urb->status != 0) {		IRDA_DEBUG(0, "%s: Speed change timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags);		switch (urb->status) {		case -EINPROGRESS:			usb_unlink_urb(urb);			/* Note : above will  *NOT* call netif_wake_queue()			 * in completion handler, we will come back here.			 * Jean II */			done = 1;			break;		case -ECONNABORTED:		/* -103 */		case -ECONNRESET:		/* -104 */		case -ETIMEDOUT:		/* -110 */		case -ENOENT:			/* -2 (urb unlinked by us)  */		default:			/* ??? - Play safe */			urb->status = 0;			netif_wake_queue(self->netdev);			done = 1;			break;		}	}	/* Check Tx URB */	urb = self->tx_urb;	if (urb->status != 0) {		struct sk_buff *skb = urb->context;		IRDA_DEBUG(0, "%s: Tx timed out, urb->status=%d, urb->transfer_flags=0x%04X\n", netdev->name, urb->status, urb->transfer_flags);		/* Increase error count */		self->stats.tx_errors++;#ifdef IU_BUG_KICK_TIMEOUT		/* Can't be a bad idea to reset the speed ;-) - Jean II */		if(self->new_speed == -1)			self->new_speed = self->speed;		if(self->new_xbofs == -1)			self->new_xbofs = self->xbofs;		irda_usb_change_speed_xbofs(self);#endif /* IU_BUG_KICK_TIMEOUT */		switch (urb->status) {		case -EINPROGRESS:			usb_unlink_urb(urb);			/* Note : above will  *NOT* call netif_wake_queue()			 * in completion handler, because urb->status will			 * be -ENOENT. We will fix that at the next watchdog,			 * leaving more time to USB to recover...			 * Also, we are in interrupt, so we need to have			 * URB_ASYNC_UNLINK to work properly...			 * Jean II */			done = 1;			break;		case -ECONNABORTED:		/* -103 */		case -ECONNRESET:		/* -104 */		case -ETIMEDOUT:		/* -110 */		case -ENOENT:			/* -2 (urb unlinked by us)  */		default:			/* ??? - Play safe */			if(skb != NULL) {				dev_kfree_skb_any(skb);				urb->context = NULL;			}			urb->status = 0;			netif_wake_queue(self->netdev);			done = 1;			break;		}	}	spin_unlock_irqrestore(&self->lock, flags);	/* Maybe we need a reset */	/* Note : Some drivers seem to use a usb_set_interface() when they	 * need to reset the hardware. Hum...	 */	/* if(done == 0) */}/************************* RECEIVE ROUTINES *************************//* * Receive packets from the USB layer stack and pass them to the IrDA stack. * Try to work around USB failures... *//* * Note : * Some of you may have noticed that most dongle have an interrupt in pipe * that we don't use. Here is the little secret... * When we hang a Rx URB on the bulk in pipe, it generates some USB traffic * in every USB frame. This is unnecessary overhead. * The interrupt in pipe will generate an event every time a packet is * received. Reading an interrupt pipe adds minimal overhead, but has some * latency (~1ms). * If we are connected (speed != 9600), we want to minimise latency, so * we just always hang the Rx URB and ignore the interrupt. * If we are not connected (speed == 9600), there is usually no Rx traffic, * and we want to minimise the USB overhead. In this case we should wait * on the interrupt pipe and hang the Rx URB only when an interrupt is * received. * Jean II *//*------------------------------------------------------------------*//* * Submit a Rx URB to the USB layer to handle reception of a frame * Mostly called by the completion callback of the previous URB. * * Jean II */static void irda_usb_submit(struct irda_usb_cb *self, struct sk_buff *skb, struct urb *urb){	struct irda_skb_cb *cb;	int ret;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);	/* This should never happen */	ASSERT(skb != NULL, return;);	ASSERT(urb != NULL, return;);	/* Save ourselves in the skb */	cb = (struct irda_skb_cb *) skb->cb;	cb->context = self;	/* Reinitialize URB */	usb_fill_bulk_urb(urb, self->usbdev, 		      usb_rcvbulkpipe(self->usbdev, self->bulk_in_ep), 		      skb->data, skb->truesize,                      irda_usb_receive, skb);	/* Note : unlink *must* be synchronous because of the code in 	 * irda_usb_net_close() -> free the skb - Jean II */	urb->status = 0;	/* Can be called from irda_usb_receive (irq handler) -> GFP_ATOMIC */	ret = usb_submit_urb(urb, GFP_ATOMIC);	if (ret) {		/* If this ever happen, we are in deep s***.		 * Basically, the Rx path will stop... */		WARNING("%s(), Failed to submit Rx URB %d\n", __FUNCTION__, ret);	}}/*------------------------------------------------------------------*//* * Function irda_usb_receive(urb) * *     Called by the USB subsystem when a frame has been received * */static void irda_usb_receive(struct urb *urb, struct pt_regs *regs){	struct sk_buff *skb = (struct sk_buff *) urb->context;	struct irda_usb_cb *self; 	struct irda_skb_cb *cb;	struct sk_buff *newskb;	struct sk_buff *dataskb;	int		docopy;	IRDA_DEBUG(2, "%s(), len=%d\n", __FUNCTION__, urb->actual_length);		/* Find ourselves */	cb = (struct irda_skb_cb *) skb->cb;	ASSERT(cb != NULL, return;);	self = (struct irda_usb_cb *) cb->context;	ASSERT(self != NULL, return;);	/* If the network is closed or the device gone, stop everything */	if ((!self->netopen) || (!self->present)) {		IRDA_DEBUG(0, "%s(), Network is gone!\n", __FUNCTION__);		/* Don't re-submit the URB : will stall the Rx path */		return;	}		/* Check the status */	if (urb->status != 0) {		switch (urb->status) {		case -EILSEQ:			self->stats.rx_errors++;			self->stats.rx_crc_errors++;				break;		case -ECONNRESET:		/* -104 */			IRDA_DEBUG(0, "%s(), Connection Reset (-104), transfer_flags 0x%04X \n", __FUNCTION__, urb->transfer_flags);			/* uhci_cleanup_unlink() is going to kill the Rx			 * URB just after we return. No problem, at this			 * point the URB will be idle ;-) - Jean II */			break;		default:			IRDA_DEBUG(0, "%s(), RX status %d,transfer_flags 0x%04X \n", __FUNCTION__, urb->status, urb->transfer_flags);			break;		}		goto done;	}		/* Check for empty frames */	if (urb->actual_length <= USB_IRDA_HEADER) {		WARNING("%s(), empty frame!\n", __FUNCTION__);		goto done;	}	/*  	 * Remember the time we received this frame, so we can	 * reduce the min turn time a bit since we will know	 * how much time we have used for protocol processing	 */        do_gettimeofday(&self->stamp);	/* Check if we need to copy the data to a new skb or not.	 * For most frames, we use ZeroCopy and pass the already	 * allocated skb up the stack.	 * If the frame is small, it is more efficient to copy it	 * to save memory (copy will be fast anyway - that's	 * called Rx-copy-break). Jean II */	docopy = (urb->actual_length < IRDA_RX_COPY_THRESHOLD);	/* Allocate a new skb */	newskb = dev_alloc_skb(docopy ? urb->actual_length : IRDA_SKB_MAX_MTU);	if (!newskb)  {		self->stats.rx_dropped++;

⌨️ 快捷键说明

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