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

📄 irda-usb.c

📁 是关于linux2.5.1的完全源码
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (!new) {			self->stats.rx_dropped++;			goto done;  		}		/* Make sure IP header get aligned (IrDA header is 5 bytes) */		skb_reserve(new, 1);				/* Copy packet, so we can recycle the original */		memcpy(skb_put(new, skb->len), skb->data, skb->len);		/* We will cleanup the skb in irda_usb_submit() */	} else {		/* Deliver the original skb */		new = skb;		skb = NULL;	}		self->stats.rx_bytes += new->len;	self->stats.rx_packets++;	/* Ask the networking layer to queue the packet for the IrDA stack */        new->dev = self->netdev;        new->mac.raw  = new->data;        new->protocol = htons(ETH_P_IRDA);        netif_rx(new);		self->netdev->last_rx = jiffies;done:	/* Note : at this point, the URB we've just received (urb)	 * is still referenced by the USB layer. For example, if we	 * have received a -ECONNRESET, uhci_cleanup_unlink() will	 * continue to process it (in fact, cleaning it up).	 * If we were to submit this URB, disaster would ensue.	 * Therefore, we submit our idle URB, and put this URB in our	 * idle slot....	 * Jean II */	/* Note : with this scheme, we could submit the idle URB before	 * processing the Rx URB. Another time... Jean II */	/* Submit the idle URB to replace the URB we've just received */	irda_usb_submit(self, skb, self->idle_rx_urb);	/* Recycle Rx URB : Now, the idle URB is the present one */	urb->context = NULL;	self->idle_rx_urb = urb;}/*------------------------------------------------------------------*//* * Callbak from IrDA layer. IrDA wants to know if we have * started receiving anything. */static int irda_usb_is_receiving(struct irda_usb_cb *self){	/* Note : because of the way UHCI works, it's almost impossible	 * to get this info. The Controller DMA directly to memory and	 * signal only when the whole frame is finished. To know if the	 * first TD of the URB has been filled or not seems hard work...	 *	 * The other solution would be to use the "receiving" command	 * on the default decriptor with a usb_control_msg(), but that	 * would add USB traffic and would return result only in the	 * next USB frame (~1ms).	 *	 * I've been told that current dongles send status info on their	 * interrupt endpoint, and that's what the Windows driver uses	 * to know this info. Unfortunately, this is not yet in the spec...	 *	 * Jean II	 */	return 0; /* For now */}/********************** IRDA DEVICE CALLBACKS **********************//* * Main calls from the IrDA/Network subsystem. * Mostly registering a new irda-usb device and removing it.... * We only deal with the IrDA side of the business, the USB side will * be dealt with below... *//*------------------------------------------------------------------*//* * Callback when a new IrDA device is created. */static int irda_usb_net_init(struct net_device *dev){	IRDA_DEBUG(1, __FUNCTION__ "()\n");		/* Set up to be a normal IrDA network device driver */	irda_device_setup(dev);	/* Insert overrides below this line! */	return 0;}/*------------------------------------------------------------------*//* * Function irda_usb_net_open (dev) * *    Network device is taken up. Usually this is done by "ifconfig irda0 up"  *    * Note : don't mess with self->netopen - Jean II */static int irda_usb_net_open(struct net_device *netdev){	struct irda_usb_cb *self;	char	hwname[16];	int i;		IRDA_DEBUG(1, __FUNCTION__ "()\n");	ASSERT(netdev != NULL, return -1;);	self = (struct irda_usb_cb *) netdev->priv;	ASSERT(self != NULL, return -1;);	/* Can only open the device if it's there */	if(!self->present) {		WARNING(__FUNCTION__ "(), device not present!\n");		return -1;	}	/* Initialise default speed and xbofs value	 * (IrLAP will change that soon) */	self->speed = -1;	self->xbofs = -1;	self->new_speed = -1;	self->new_xbofs = -1;	/* To do *before* submitting Rx urbs and starting net Tx queue	 * Jean II */	self->netopen = 1;	/* 	 * Now that everything should be initialized properly,	 * Open new IrLAP layer instance to take care of us...	 * Note : will send immediately a speed change...	 */	sprintf(hwname, "usb#%d", self->usbdev->devnum);	self->irlap = irlap_open(netdev, &self->qos, hwname);	ASSERT(self->irlap != NULL, return -1;);	/* Allow IrLAP to send data to us */	netif_start_queue(netdev);	/* We submit all the Rx URB except for one that we keep idle.	 * Need to be initialised before submitting other USBs, because	 * in some cases as soon as we submit the URBs the USB layer	 * will trigger a dummy receive - Jean II */	self->idle_rx_urb = self->rx_urb[IU_MAX_ACTIVE_RX_URBS];	self->idle_rx_urb->context = NULL;	/* Now that we can pass data to IrLAP, allow the USB layer	 * to send us some data... */	for (i = 0; i < IU_MAX_ACTIVE_RX_URBS; i++)		irda_usb_submit(self, NULL, self->rx_urb[i]);	/* Ready to play !!! */	MOD_INC_USE_COUNT;	return 0;}/*------------------------------------------------------------------*//* * Function irda_usb_net_close (self) * *    Network device is taken down. Usually this is done by  *    "ifconfig irda0 down"  */static int irda_usb_net_close(struct net_device *netdev){	struct irda_usb_cb *self;	int	i;	IRDA_DEBUG(1, __FUNCTION__ "()\n");	ASSERT(netdev != NULL, return -1;);	self = (struct irda_usb_cb *) netdev->priv;	ASSERT(self != NULL, return -1;);	/* Clear this flag *before* unlinking the urbs and *before*	 * stopping the network Tx queue - Jean II */	self->netopen = 0;	/* Stop network Tx queue */	netif_stop_queue(netdev);	/* Deallocate all the Rx path buffers (URBs and skb) */	for (i = 0; i < IU_MAX_RX_URBS; i++) {		struct urb *urb = self->rx_urb[i];		struct sk_buff *skb = (struct sk_buff *) urb->context;		/* Cancel the receive command */		usb_unlink_urb(urb);		/* The skb is ours, free it */		if(skb) {			dev_kfree_skb(skb);			urb->context = NULL;		}	}	/* Cancel Tx and speed URB - need to be synchronous to avoid races */	self->tx_urb->transfer_flags &= ~USB_ASYNC_UNLINK;	usb_unlink_urb(self->tx_urb);	self->speed_urb->transfer_flags &= ~USB_ASYNC_UNLINK;	usb_unlink_urb(self->speed_urb);	/* Stop and remove instance of IrLAP */	if (self->irlap)		irlap_close(self->irlap);	self->irlap = NULL;	MOD_DEC_USE_COUNT;	return 0;}/*------------------------------------------------------------------*//* * IOCTLs : Extra out-of-band network commands... */static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){	unsigned long flags;	struct if_irda_req *irq = (struct if_irda_req *) rq;	struct irda_usb_cb *self;	int ret = 0;	ASSERT(dev != NULL, return -1;);	self = dev->priv;	ASSERT(self != NULL, return -1;);	IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);	switch (cmd) {	case SIOCSBANDWIDTH: /* Set bandwidth */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		/* Protect us from USB callbacks, net watchdog and else. */		spin_lock_irqsave(&self->lock, flags);		/* Check if the device is still there */		if(self->present) {			/* Set the desired speed */			self->new_speed = irq->ifr_baudrate;			irda_usb_change_speed_xbofs(self);		}		spin_unlock_irqrestore(&self->lock, flags);		break;	case SIOCSMEDIABUSY: /* Set media busy */		if (!capable(CAP_NET_ADMIN))			return -EPERM;		/* Check if the IrDA stack is still there */		if(self->netopen)			irda_device_set_media_busy(self->netdev, TRUE);		break;	case SIOCGRECEIVING: /* Check if we are receiving right now */		irq->ifr_receiving = irda_usb_is_receiving(self);		break;	default:		ret = -EOPNOTSUPP;	}		return ret;}/*------------------------------------------------------------------*//* * Get device stats (for /proc/net/dev and ifconfig) */static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev){	struct irda_usb_cb *self = dev->priv;	return &self->stats;}/********************* IRDA CONFIG SUBROUTINES *********************//* * Various subroutines dealing with IrDA and network stuff we use to * configure and initialise each irda-usb instance. * These functions are used below in the main calls of the driver... *//*------------------------------------------------------------------*//* * Set proper values in the IrDA QOS structure */static inline void irda_usb_init_qos(struct irda_usb_cb *self){	struct irda_class_desc *desc;	IRDA_DEBUG(3, __FUNCTION__ "()\n");		desc = self->irda_desc;		/* Initialize QoS for this device */	irda_init_max_qos_capabilies(&self->qos);	self->qos.baud_rate.bits       = desc->wBaudRate;	self->qos.min_turn_time.bits   = desc->bmMinTurnaroundTime;	self->qos.additional_bofs.bits = desc->bmAdditionalBOFs;	self->qos.window_size.bits     = desc->bmWindowSize;	self->qos.data_size.bits       = desc->bmDataSize;	IRDA_DEBUG(0, __FUNCTION__ "(), dongle says speed=0x%X, size=0x%X, window=0x%X, bofs=0x%X, turn=0x%X\n", self->qos.baud_rate.bits, self->qos.data_size.bits, self->qos.window_size.bits, self->qos.additional_bofs.bits, self->qos.min_turn_time.bits);	/* Don't always trust what the dongle tell us */	if(self->capability & IUC_SIR_ONLY)		self->qos.baud_rate.bits	&= 0xff;	if(self->capability & IUC_SMALL_PKT)		self->qos.data_size.bits	 = 0x07;	if(self->capability & IUC_NO_WINDOW)		self->qos.window_size.bits	 = 0x01;	if(self->capability & IUC_MAX_WINDOW)		self->qos.window_size.bits	 = 0x7f;	if(self->capability & IUC_MAX_XBOFS)		self->qos.additional_bofs.bits	 = 0x01;#if 1	/* Module parameter can override the rx window size */	if (qos_mtt_bits)		self->qos.min_turn_time.bits = qos_mtt_bits;#endif	    	/* 	 * Note : most of those values apply only for the receive path,	 * the transmit path will be set differently - Jean II 	 */	irda_qos_bits_to_value(&self->qos);	self->flags |= IFF_SIR;	if (self->qos.baud_rate.value > 115200)		self->flags |= IFF_MIR;	if (self->qos.baud_rate.value > 1152000)		self->flags |= IFF_FIR;	if (self->qos.baud_rate.value > 4000000)		self->flags |= IFF_VFIR;}/*------------------------------------------------------------------*//* * Initialise the network side of the irda-usb instance * Called when a new USB instance is registered in irda_usb_probe() */static inline int irda_usb_open(struct irda_usb_cb *self){	struct net_device *netdev;	int err;	IRDA_DEBUG(1, __FUNCTION__ "()\n");	spin_lock_init(&self->lock);	irda_usb_init_qos(self);		/* Initialise list of skb beeing curently transmitted */	self->tx_list = hashbin_new(HB_GLOBAL);	/* Allocate the buffer for speed changes */	/* Don't change this buffer size and allocation without doing	 * some heavy and complete testing. Don't ask why :-(	 * Jean II */	self->speed_buff = (char *) kmalloc(IRDA_USB_SPEED_MTU, GFP_KERNEL);	if (self->speed_buff == NULL) 		return -1;	memset(self->speed_buff, 0, IRDA_USB_SPEED_MTU);	/* Create a network device for us */	if (!(netdev = dev_alloc("irda%d", &err))) {		ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");		return -1;	}	self->netdev = netdev; 	netdev->priv = (void *) self;	/* Override the network functions we need to use */	netdev->init            = irda_usb_net_init;	netdev->hard_start_xmit = irda_usb_hard_xmit;	netdev->tx_timeout	= irda_usb_net_timeout;	netdev->watchdog_timeo  = 250*HZ/1000;	/* 250 ms > USB timeout */	netdev->open            = irda_usb_net_open;	netdev->stop            = irda_usb_net_close;	netdev->get_stats	= irda_usb_net_get_stats;	netdev->do_ioctl        = irda_usb_net_ioctl;	rtnl_lock();	err = register_netdevice(netdev);	rtnl_unlock();	if (err) {		ERROR(__FUNCTION__ "(), register_netdev() failed!\n");		return -1;	}	MESSAGE("IrDA: Registered device %s\n", netdev->name);	return 0;}/*------------------------------------------------------------------*//* * Cleanup the network side of the irda-usb instance * Called when a USB instance is removed in irda_usb_disconnect() */static inline int irda_usb_close(struct irda_usb_cb *self){	IRDA_DEBUG(1, __FUNCTION__ "()\n");	ASSERT(self != NULL, return -1;);	/* Remove netdevice */	if (self->netdev) {		rtnl_lock();		unregister_netdevice(self->netdev);		self->netdev = NULL;		rtnl_unlock();	}	/* Delete all pending skbs */	hashbin_delete(self->tx_list, (FREE_FUNC) &dev_kfree_skb_any);	/* Remove the speed buffer */	if (self->speed_buff != NULL) {		kfree(self->speed_buff);		self->speed_buff = NULL;

⌨️ 快捷键说明

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