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

📄 cdcether.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
					// Fill in the structure...					ether_dev->comm_interface = intf_num;					ether_dev->comm_bInterfaceNumber = comm_intf->bInterfaceNumber;					ether_dev->comm_interface_altset_num = altset_num;					ether_dev->comm_bAlternateSetting = comm_intf->bAlternateSetting;					// Look for the Ethernet Functional Descriptors					rc = find_and_parse_ethernet_class_information( device, ether_dev );					if (rc) {						// Nope this was no good after all.						continue;					}					// Check that we really can talk to the data					// interface 					// This includes # of endpoints, protocols,					// etc.					rc = verify_ethernet_data_interface( device, ether_dev );					if (rc)	{						// We got something we didn't like						continue;					}					// This communication interface seems to give us everything					// we require.  We have all the ethernet info we need.					// Let's get out of here and go home right now.					return 0;				} else {                                        // bNumEndPoints != 1					// We found an interface that had the wrong number of 					// endpoints but would have otherwise been okay				} // end bNumEndpoints check.			} // end interface specifics check.		} // end for altset_num	} // end for intf_num	return -1;}//////////////////////////////////////////////////////////////////////////////// Routine to go through all configurations and find one that ////////////////// is an Ethernet Networking Device ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static int find_valid_configuration( struct usb_device *device, ether_dev_t *ether_dev ){	struct usb_config_descriptor *conf = NULL;	int conf_num;	int rc;	// We will try each and every possible configuration	for ( conf_num = 0; conf_num < device->descriptor.bNumConfigurations; conf_num++ ) {		conf = &( device->config[conf_num] );		// Our first requirement : 2 interfaces		if ( conf->bNumInterfaces != 2 ) {			// I currently don't know how to handle devices with any number of interfaces			// other than 2.			continue;		}		// This one passed our first check, fill in some 		// useful data		ether_dev->configuration_num = conf_num;		ether_dev->bConfigurationValue = conf->bConfigurationValue;		// Now run it through the ringers and see what comes		// out the other side.		rc = find_ethernet_comm_interface( device, ether_dev );		// Check if we found an ethernet Communcation Device		if ( !rc ) {			// We found one.			return 0;		}	}	// None of the configurations suited us.	return -1;}//////////////////////////////////////////////////////////////////////////////// Routine that checks a given configuration to see if any driver ////////////// has claimed any of the devices interfaces ///////////////////////////////////////////////////////////////////////////////////////////////////////////////static int check_for_claimed_interfaces( struct usb_config_descriptor *config ){	struct usb_interface *comm_intf_group;	int intf_num;	// Go through all the interfaces and make sure none are 	// claimed by anybody else.	for ( intf_num = 0; intf_num < config->bNumInterfaces; intf_num++ ) {		comm_intf_group = &( config->interface[intf_num] );		if ( usb_interface_claimed( comm_intf_group ) )	{			// Somebody has beat us to this guy.			// We can't change the configuration out from underneath of whoever			// 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 0;}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...	len = usb_string(ether_dev->usb, ether_dev->iMACAddress, buffer, 13);	// 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++)	{		mac_addr[i] = ( hex2dec( buffer[2 * i] ) << 4 ) + hex2dec( buffer[2 * i + 1] );	}	// Now copy it over to the kernel's network driver.	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 %02X:%02X:%02X:%02X:%02X:%02X", 	      ether_dev->net->name, manu, prod, sern, 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 );	// I claim this interface to be a CDC Ethernet Networking device	usb_driver_claim_interface( &CDCEther_driver, 	                            &(usb->config[ether_dev->configuration_num].interface[ether_dev->comm_interface]), 	                            ether_dev );	// I claim this interface to be a CDC Ethernet Networking device	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 );	// TODO - last minute HACK	ether_dev->comm_ep_in = 5;	// Okay, we are finally done...	return NULL;}//////////////////////////////////////////////////////////////////////////////// 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){	info( "%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_PARM (multicast_filter_limit, "i");MODULE_PARM_DESC (multicast_filter_limit, "CDCEther maximum number of filtered multicast addresses");MODULE_DEVICE_TABLE (usb, CDCEther_ids);//////////////////////////////////////////////////////////////////////////////// End of file /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

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