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

📄 cdcether.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
			// is using this device, so we will go ahead and give up.			return -1;		}	}	// We made it all the way through.	// I guess no one has claimed any of these interfaces.	return 0;}//////////////////////////////////////////////////////////////////////////////// Routines to ask for and set the kernel network interface's MAC address ////// Used by driver's probe routine //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static inline unsigned char hex2dec( unsigned char digit ){	/* Is there a standard way to do this??? */	/* I have written this code TOO MANY times. */	if ( (digit >= '0') && (digit <= '9') )	{		return (digit - '0');	}	if ( (digit >= 'a') && (digit <= 'f') )	{		return (digit - 'a' + 10);	}	if ( (digit >= 'A') && (digit <= 'F') )	{		return (digit - 'A' + 10);	}	return 16;}/* CDC Ethernet devices provide the MAC address as a string *//* We get an index to the string in the Ethernet functional header *//* This routine retrieves the string, sanity checks it, and sets the *//* MAC address in the network device *//* The encoding is a bit wacky - see CDC Spec Table 41 for details */static void set_ethernet_addr( ether_dev_t *ether_dev ){	unsigned char	mac_addr[6];	int		i;	int 		len;	unsigned char	buffer[13];	/* Let's assume we don't get anything */	mac_addr[0] = 0x00;	mac_addr[1] = 0x00;	mac_addr[2] = 0x00;	mac_addr[3] = 0x00;	mac_addr[4] = 0x00;	mac_addr[5] = 0x00;	/* Let's ask the device */	if (0 > (len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13))) {		err("Attempting to get MAC address failed: %d", -1*len);		return;	}	/* Sanity check */	if (len != 12)	{		/* You gotta love failing sanity checks */		err("Attempting to get MAC address returned %d bytes", len);		return;	}	/* Fill in the mac_addr */	for (i = 0; i < 6; i++)	{		if ((16 == buffer[2 * i]) || (16 == buffer[2 * i + 1])) {			err("Bad value in MAC address");		}		else {			mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );		}	}	/* Now copy it over to our network device structure */	memcpy( ether_dev->net->dev_addr, mac_addr, sizeof(mac_addr) );}//////////////////////////////////////////////////////////////////////////////// Routine to print to syslog information about the driver ///////////////////// Used by driver's probe routine //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////void log_device_info(ether_dev_t *ether_dev){	int len;	int string_num;	unsigned char manu[256];	unsigned char prod[256];	unsigned char sern[256];	unsigned char *mac_addr;	/* Default empty strings in case we don't find a real one */	manu[0] = 0x00;	prod[0] = 0x00;	sern[0] = 0x00;	/*  Try to get the device Manufacturer */	string_num = ether_dev->usb->descriptor.iManufacturer;	if (string_num)	{		// Put it into its buffer		len = usb_string(ether_dev->usb, string_num, manu, 255);		// Just to be safe		manu[len] = 0x00;	}	/* Try to get the device Product Name */	string_num = ether_dev->usb->descriptor.iProduct;	if (string_num)	{		// Put it into its buffer		len = usb_string(ether_dev->usb, string_num, prod, 255);		// Just to be safe		prod[len] = 0x00;	}	/* Try to get the device Serial Number */	string_num = ether_dev->usb->descriptor.iSerialNumber;	if (string_num)	{		// Put it into its buffer		len = usb_string(ether_dev->usb, string_num, sern, 255);		// Just to be safe		sern[len] = 0x00;	}	/* This makes it easier for us to print */	mac_addr = ether_dev->net->dev_addr;	/* Now send everything we found to the syslog */	info( "%s: %s %s %s", ether_dev->net->name, manu, prod, sern);	dbg( "%s: %02X:%02X:%02X:%02X:%02X:%02X",		ether_dev->net->name,		mac_addr[0],		mac_addr[1],		mac_addr[2],		mac_addr[3],		mac_addr[4],		mac_addr[5] );}/* Forward declaration */static struct usb_driver CDCEther_driver ;//////////////////////////////////////////////////////////////////////////////// Module's probe routine ////////////////////////////////////////////////////// claims interfaces if they are for an Ethernet CDC ///////////////////////////////////////////////////////////////////////////////////////////////////////static void * CDCEther_probe( struct usb_device *usb, unsigned int ifnum,			     const struct usb_device_id *id){	struct net_device	*net;	ether_dev_t		*ether_dev;	int 			rc;	// First we should check the active configuration to see if 	// any other driver has claimed any of the interfaces.	if ( check_for_claimed_interfaces( usb->actconfig ) ) {		// Someone has already put there grubby paws on this device.		// We don't want it now...		return NULL;	}	// We might be finding a device we can use.	// We all go ahead and allocate our storage space.	// We need to because we have to start filling in the data that	// we are going to need later.	if(!(ether_dev = kmalloc(sizeof(ether_dev_t), GFP_KERNEL))) {		err("out of memory allocating device structure");		return NULL;	}	// Zero everything out.	memset(ether_dev, 0, sizeof(ether_dev_t));	// Let's see if we can find a configuration we can use.	rc = find_valid_configuration( usb, ether_dev );	if (rc)	{		// Nope we couldn't find one we liked.		// This device was not meant for us to control.		kfree( ether_dev );		return	NULL;	}	// Now that we FOUND a configuration. let's try to make the 	// device go into it.	if ( usb_set_configuration( usb, ether_dev->bConfigurationValue ) ) {		err("usb_set_configuration() failed");		kfree( ether_dev );		return NULL;	}	// Now set the communication interface up as required.	if (usb_set_interface(usb, ether_dev->comm_bInterfaceNumber, ether_dev->comm_bAlternateSetting)) {		err("usb_set_interface() failed");		kfree( ether_dev );		return NULL;	}	// Only turn traffic on right now if we must...	if (ether_dev->data_interface_altset_num_without_traffic >= 0)	{		// We found an alternate setting for the data		// interface that allows us to turn off traffic.		// We should use it.		if (usb_set_interface( usb, 		                       ether_dev->data_bInterfaceNumber, 		                       ether_dev->data_bAlternateSetting_without_traffic)) {			err("usb_set_interface() failed");			kfree( ether_dev );			return NULL;		}	} else	{		// We didn't find an alternate setting for the data		// interface that would let us turn off traffic.		// Oh well, let's go ahead and do what we must...		if (usb_set_interface( usb, 		                       ether_dev->data_bInterfaceNumber, 		                       ether_dev->data_bAlternateSetting_with_traffic)) {			err("usb_set_interface() failed");			kfree( ether_dev );			return NULL;		}	}	// Now we need to get a kernel Ethernet interface.	net = init_etherdev( NULL, 0 );	if ( !net ) {		// Hmm...  The kernel is not sharing today...		// Fine, we didn't want it anyway...		err( "Unable to initialize ethernet device" );		kfree( ether_dev );		return	NULL;	}	// Now that we have an ethernet device, let's set it up	// (And I don't mean "set [it] up the bomb".)	net->priv = ether_dev;	SET_MODULE_OWNER(net);	net->open = CDCEther_open;	net->stop = CDCEther_close;	net->watchdog_timeo = CDC_ETHER_TX_TIMEOUT;	net->tx_timeout = CDCEther_tx_timeout;   // TX timeout function	net->do_ioctl = CDCEther_ioctl;	net->hard_start_xmit = CDCEther_start_xmit;	net->set_multicast_list = CDCEther_set_multicast;	net->get_stats = CDCEther_netdev_stats;	net->mtu = ether_dev->wMaxSegmentSize - 14;	// We'll keep track of this information for later...	ether_dev->usb = usb;	ether_dev->net = net;		// and don't forget the MAC address.	set_ethernet_addr( ether_dev );	// Send a message to syslog about what we are handling	log_device_info( ether_dev );	/* We need to manually claim the data interface, while the comm interface gets claimed in the return */	usb_driver_claim_interface( &CDCEther_driver, 	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]), 	                            ether_dev );	// Does this REALLY do anything???	usb_inc_dev_use( usb );	// Okay, we are finally done...	return ether_dev;}//////////////////////////////////////////////////////////////////////////////// Module's disconnect routine ///////////////////////////////////////////////// Called when the driver is unloaded or the device is unplugged /////////////// (Whichever happens first assuming the driver suceeded at its probe) /////////////////////////////////////////////////////////////////////////////////////static void CDCEther_disconnect( struct usb_device *usb, void *ptr ){	ether_dev_t *ether_dev = ptr;	// Sanity check!!!	if ( !ether_dev || !ether_dev->usb ) {		// We failed.  We are insane!!!		warn("unregistering non-existant device");		return;	}	// Make sure we fail the sanity check if we try this again.	ether_dev->usb = NULL;		// It is possible that this function is called before	// the "close" function.	// This tells the close function we are already disconnected	ether_dev->flags |= CDC_ETHER_UNPLUG;		// We don't need the network device any more	unregister_netdev( ether_dev->net );		// For sanity checks	ether_dev->net = NULL;	// I ask again, does this do anything???	usb_dec_dev_use( usb );	// We are done with this interface	usb_driver_release_interface( &CDCEther_driver, 	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]) );	// We are done with this interface too	usb_driver_release_interface( &CDCEther_driver, 	                              &(usb->config[ether_dev->configuration_num].interface[ether_dev->data_interface]) );	// No more tied up kernel memory	kfree( ether_dev );		// This does no good, but it looks nice!	ether_dev = NULL;}//////////////////////////////////////////////////////////////////////////////// Driver info /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static struct usb_driver CDCEther_driver = {	name:		"CDCEther",	probe:		CDCEther_probe,	disconnect:	CDCEther_disconnect,	id_table:	CDCEther_ids,};//////////////////////////////////////////////////////////////////////////////// init and exit routines called when driver is installed and uninstalled //////////////////////////////////////////////////////////////////////////////////int __init CDCEther_init(void){	dbg( "%s", version );	return usb_register( &CDCEther_driver );}void __exit CDCEther_exit(void){	usb_deregister( &CDCEther_driver );}//////////////////////////////////////////////////////////////////////////////// Module info /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////module_init( CDCEther_init );module_exit( CDCEther_exit );MODULE_AUTHOR("Brad Hards and another");MODULE_DESCRIPTION("USB CDC Ethernet driver");MODULE_LICENSE("GPL");MODULE_DEVICE_TABLE (usb, CDCEther_ids);MODULE_PARM (multicast_filter_limit, "i");MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");//////////////////////////////////////////////////////////////////////////////// End of file /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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