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

📄 cdcether.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
                /* Too many to filter perfectly -- accept all multicasts. */		info("%s: set too many MC filters, using allmulti", net->name);		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |			MODE_FLAG_DIRECTED |			MODE_FLAG_BROADCAST |			MODE_FLAG_MULTICAST;	} else if (net->flags & IFF_ALLMULTI) {                /* Filter in software */		info("%s: using allmulti", net->name);		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |			MODE_FLAG_DIRECTED |			MODE_FLAG_BROADCAST |			MODE_FLAG_MULTICAST;        } else {		/* do multicast filtering in hardware */                struct dev_mc_list *mclist;		info("%s: set multicast filters", net->name);		ether_dev->mode_flags = MODE_FLAG_ALL_MULTICAST |			MODE_FLAG_DIRECTED |			MODE_FLAG_BROADCAST |			MODE_FLAG_MULTICAST;		buff = kmalloc(6 * net->mc_count, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);                for (i = 0, mclist = net->mc_list;		     mclist && i < net->mc_count;                     i++, mclist = mclist->next) {			memcpy(&mclist->dmi_addr, &buff[i * 6], 6);		}#if 0		usb_control_msg(ether_dev->usb,				usb_sndctrlpipe(ether_dev->usb, 0),				SET_ETHERNET_MULTICAST_FILTER, /* request */				USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_INTERFACE, /* request type */				cpu_to_le16(net->mc_count), /* value */				cpu_to_le16((u16)ether_dev->comm_interface), /* index */				buff,				(6* net->mc_count), /* size */				HZ); /* timeout */#endif		kfree(buff);	}#if 0 	CDC_SetEthernetPacketFilter(ether_dev);#endif	        // Tell the kernel to start giving frames to us again.	netif_wake_queue(net);}//////////////////////////////////////////////////////////////////////////////// Routines used to parse out the Functional Descriptors ///////////////////////////////////////////////////////////////////////////////////////////////////static int parse_header_functional_descriptor( int *bFunctionLength,                                                int bDescriptorType,                                                int bDescriptorSubtype,                                               unsigned char *data,                                               ether_dev_t *ether_dev,                                               int *requirements ){	// Check to make sure we haven't seen one of these already.	if ( (~*requirements) & REQ_HDR_FUNC_DESCR ) {		err( "Multiple Header Functional Descriptors found." );		return -1;	}		// Is it the right size???	if (*bFunctionLength != 5) {		info( "Invalid length in Header Functional Descriptor" );		// This is a hack to get around a particular device (NO NAMES)		// It has this function length set to the length of the		// whole class-specific descriptor		*bFunctionLength = 5;	}		// Nothing extremely useful here.	// We'll keep it for posterity	ether_dev->bcdCDC = data[0] + (data[1] << 8);	dbg( "Found Header descriptor, CDC version %x", ether_dev->bcdCDC);	// We've seen one of these	*requirements &= ~REQ_HDR_FUNC_DESCR;		// It's all good.	return 0;}static int parse_union_functional_descriptor( int *bFunctionLength,                                               int bDescriptorType,                                               int bDescriptorSubtype,                                              unsigned char *data,                                              ether_dev_t *ether_dev,                                              int *requirements ){	// Check to make sure we haven't seen one of these already.	if ( (~*requirements) & REQ_UNION_FUNC_DESCR ) {		err( "Multiple Union Functional Descriptors found." );		return -1;	}	// Is it the right size?	if (*bFunctionLength != 5) {		// It is NOT the size we expected.		err( "Unsupported length in Union Functional Descriptor" );		return -1;	}		// Sanity check of sorts	if (ether_dev->comm_interface != data[0]) {		// This tells us that we are chasing the wrong comm		// interface or we are crazy or something else weird.		if (ether_dev->comm_interface == data[1]) {			info( "Probably broken Union descriptor, fudging data interface" );			// We'll need this in a few microseconds, 			// so guess here, and hope for the best			ether_dev->data_interface = data[0];		} else {			err( "Union Functional Descriptor is broken beyond repair" );			return -1;		}	} else{ // Descriptor is OK       		// We'll need this in a few microseconds!		ether_dev->data_interface = data[1];	}	// We've seen one of these now.	*requirements &= ~REQ_UNION_FUNC_DESCR;		// Done	return 0;}static int parse_ethernet_functional_descriptor( int *bFunctionLength,                                                  int bDescriptorType,                                                  int bDescriptorSubtype,                                                 unsigned char *data,                                                 ether_dev_t *ether_dev,                                                 int *requirements ){	// Check to make sure we haven't seen one of these already.	if ( (~*requirements) & REQ_ETH_FUNC_DESCR ) {		err( "Multiple Ethernet Functional Descriptors found." );		return -1;	}		// Is it the right size?	if (*bFunctionLength != 13) {		err( "Invalid length in Ethernet Networking Functional Descriptor" );		return -1;	}		// Lots of goodies from this one.  They are all important.	ether_dev->iMACAddress = data[0];	ether_dev->bmEthernetStatistics = data[1] + (data[2] << 8) + (data[3] << 16) + (data[4] << 24);	ether_dev->wMaxSegmentSize = data[5] + (data[6] << 8);	ether_dev->wNumberMCFilters = (data[7] + (data[8] << 8)) & 0x00007FFF;	if (ether_dev->wNumberMCFilters > multicast_filter_limit) {		ether_dev->wNumberMCFilters = multicast_filter_limit;		}		ether_dev->bNumberPowerFilters = data[9];		// We've seen one of these now.	*requirements &= ~REQ_ETH_FUNC_DESCR;		// That's all she wrote.	return 0;}static int parse_protocol_unit_functional_descriptor( int *bFunctionLength,                                                       int bDescriptorType,                                                       int bDescriptorSubtype,                                                      unsigned char *data,                                                      ether_dev_t *ether_dev,                                                      int *requirements ){	// There should only be one type if we are sane	if (bDescriptorType != CS_INTERFACE) {		info( "Invalid bDescriptorType found." );		return -1;	}	// The Subtype tells the tale.	switch (bDescriptorSubtype){		case 0x00:	// Header Functional Descriptor			return parse_header_functional_descriptor( bFunctionLength,			                                           bDescriptorType,			                                           bDescriptorSubtype,			                                           data,			                                           ether_dev,			                                           requirements );			break;		case 0x06:	// Union Functional Descriptor			return parse_union_functional_descriptor( bFunctionLength,			                                          bDescriptorType,			                                          bDescriptorSubtype,			                                          data,			                                          ether_dev,			                                          requirements );			break;		case 0x0F:	// Ethernet Networking Functional Descriptor			return parse_ethernet_functional_descriptor( bFunctionLength,			                                             bDescriptorType,			                                             bDescriptorSubtype,			                                             data,			                                             ether_dev,			                                             requirements );			break;		default:	// We don't support this at this time...			// However that doesn't necessarily indicate an error.			dbg( "Unexpected header type %x:", bDescriptorSubtype );			return 0;	}	// How did we get here???	return -1;}static int parse_ethernet_class_information( unsigned char *data, int length, ether_dev_t *ether_dev ){	int loc = 0;	int rc;	int bFunctionLength;	int bDescriptorType;	int bDescriptorSubtype;	int requirements = REQUIREMENTS_TOTAL;	// As long as there is something here, we will try to parse it	while (loc < length) {		// Length		bFunctionLength = data[loc];		loc++;				// Type		bDescriptorType = data[loc];		loc++;				// Subtype		bDescriptorSubtype = data[loc];		loc++;				// ship this off to be processed elsewhere.		rc = parse_protocol_unit_functional_descriptor( &bFunctionLength, 		                                                bDescriptorType, 		                                                bDescriptorSubtype, 		                                                &data[loc],		                                                ether_dev,		                                                &requirements );		// Did it process okay?		if (rc)	{			// Something was hosed somewhere.			// No need to continue;			err("Bad descriptor parsing: %x", rc );			return -1;		}		// We have already taken three bytes.		loc += (bFunctionLength - 3);	}	// Check to see if we got everything we need.	if (requirements) {		// We missed some of the requirements...		err( "Not all required functional descriptors present 0x%08X", requirements );		return -1;	}	// We got everything.	return 0;}//////////////////////////////////////////////////////////////////////////////// Routine to check for the existence of the Functional Descriptors ////////////////////////////////////////////////////////////////////////////////////////static int find_and_parse_ethernet_class_information( struct usb_device *device, ether_dev_t *ether_dev ){	struct usb_config_descriptor *conf = NULL;	struct usb_interface *comm_intf_group = NULL;	struct usb_interface_descriptor *comm_intf = NULL;	int rc = -1;	// The assumption here is that find_ethernet_comm_interface	// and find_valid_configuration 	// have already filled in the information about where to find	// the a valid commication interface.	conf = &( device->config[ether_dev->configuration_num] );	comm_intf_group = &( conf->interface[ether_dev->comm_interface] );	comm_intf = &( comm_intf_group->altsetting[ether_dev->comm_interface_altset_num] );	// Let's check and see if it has the extra information we need...	if (comm_intf->extralen > 0) {		// This is where the information is SUPPOSED to be.		rc = parse_ethernet_class_information( comm_intf->extra, comm_intf->extralen, ether_dev );	} else if (conf->extralen > 0) {		// This is a hack.  The spec says it should be at the interface 		// location checked above.  However I have seen it here also.		// This is the same device that requires the functional descriptor hack above		warn( "Ethernet information found at device configuration.  This is broken." );		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );	} else 	{		// I don't know where else to look.		warn( "No ethernet information found." );		rc = -1;	}	return rc;}//////////////////////////////////////////////////////////////////////////////// Routines to verify the data interface ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////static int get_data_interface_endpoints( struct usb_device *device, ether_dev_t *ether_dev ){	struct usb_config_descriptor *conf = NULL;	struct usb_interface *data_intf_group = NULL;	struct usb_interface_descriptor *data_intf = NULL;		// Walk through and get to the data interface we are checking.	conf = &( device->config[ether_dev->configuration_num] );	data_intf_group = &( conf->interface[ether_dev->data_interface] );	data_intf = &( data_intf_group->altsetting[ether_dev->data_interface_altset_num_with_traffic] );	// Start out assuming we won't find anything we can use	ether_dev->data_ep_in = 0;	ether_dev->data_ep_out = 0;		// If these are not BULK endpoints, we don't want them	if ( data_intf->endpoint[0].bmAttributes != 0x02 ) {		return -1;	} if ( data_intf->endpoint[1].bmAttributes != 0x02 ) {		return -1;	}	// Check the first endpoint to see if it is IN or OUT	if ( data_intf->endpoint[0].bEndpointAddress & 0x80 ) {		// This endpoint is IN		ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;	} else {		// This endpoint is OUT		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress & 0x7F;		ether_dev->data_ep_out_size = data_intf->endpoint[0].wMaxPacketSize;	}	// Check the second endpoint to see if it is IN or OUT	if ( data_intf->endpoint[1].bEndpointAddress & 0x80 ) {		// This endpoint is IN		ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;	} else	{		// This endpoint is OUT		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress & 0x7F;		ether_dev->data_ep_out_size = data_intf->endpoint[1].wMaxPacketSize;	}		// Now make sure we got both an IN and an OUT	if (ether_dev->data_ep_in && ether_dev->data_ep_out) {		// We did get both, we are in good shape...		info( "detected BULK OUT packets of size %d", ether_dev->data_ep_out_size );		return 0;	}	return -1;}static int verify_ethernet_data_interface( struct usb_device *device, ether_dev_t *ether_dev ){	struct usb_config_descriptor *conf = NULL;	struct usb_interface *data_intf_group = NULL;	struct usb_interface_descriptor *data_intf = NULL;	int rc = -1;	int status;	int altset_num;	// The assumption here is that parse_ethernet_class_information()	// and find_valid_configuration() 	// have already filled in the information about where to find	// a data interface	conf = &( device->config[ether_dev->configuration_num] );	data_intf_group = &( conf->interface[ether_dev->data_interface] );	// start out assuming we won't find what we are looking for.	ether_dev->data_interface_altset_num_with_traffic = -1;	ether_dev->data_bAlternateSetting_with_traffic = -1;	ether_dev->data_interface_altset_num_without_traffic = -1;	ether_dev->data_bAlternateSetting_without_traffic = -1;	// Walk through every possible setting for this interface until	// we find what makes us happy.	for ( altset_num = 0; altset_num < data_intf_group->num_altsetting; altset_num++ ) {		data_intf = &( data_intf_group->altsetting[altset_num] );		// Is this a data interface we like?		if ( ( data_intf->bInterfaceClass == 0x0A )		   && ( data_intf->bInterfaceSubClass == 0x00 )		   && ( data_intf->bInterfaceProtocol == 0x00 ) ) {			if ( data_intf->bNumEndpoints == 2 ) {				// We are required to have one of these.				// An interface with 2 endpoints to send Ethernet traffic back and forth				// It actually may be possible that the device might only				// communicate in a vendor specific manner.				// That would not be very nice.				// We can add that one later.				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;				ether_dev->data_interface_altset_num_with_traffic = altset_num;				ether_dev->data_bAlternateSetting_with_traffic = data_intf->bAlternateSetting;				status = get_data_interface_endpoints( device, ether_dev );				if (!status) {					rc = 0;				}			}			if ( data_intf->bNumEndpoints == 0 ) {				// According to the spec we are SUPPOSED to have one of these				// In fact the device is supposed to come up in this state.				// However, I have seen a device that did not have such an interface.				// So it must be just optional for our driver...				ether_dev->data_bInterfaceNumber = data_intf->bInterfaceNumber;				ether_dev->data_interface_altset_num_without_traffic = altset_num;				ether_dev->data_bAlternateSetting_without_traffic = data_intf->bAlternateSetting;			}		}	}	return rc;}//////////////////////////////////////////////////////////////////////////////// Routine to find a communication interface ///////////////////////////////////////////////////////////////////////////////////////////////////////////////static int find_ethernet_comm_interface( struct usb_device *device, ether_dev_t *ether_dev ){	struct usb_config_descriptor *conf = NULL;	struct usb_interface *comm_intf_group = NULL;	struct usb_interface_descriptor *comm_intf = NULL;	int intf_num;	int altset_num;	int rc;	conf = &( device->config[ether_dev->configuration_num] );	// We need to check and see if any of these interfaces are something we want.	// Walk through each interface one at a time	for ( intf_num = 0; intf_num < conf->bNumInterfaces; intf_num++ ) {		comm_intf_group = &( conf->interface[intf_num] );		// Now for each of those interfaces, check every possible		// alternate setting.		for ( altset_num = 0; altset_num < comm_intf_group->num_altsetting; altset_num++ ) {			comm_intf = &( comm_intf_group->altsetting[altset_num] );			// Is this a communication class of interface of the			// ethernet subclass variety.			if ( ( comm_intf->bInterfaceClass == 0x02 )			   && ( comm_intf->bInterfaceSubClass == 0x06 )			   && ( comm_intf->bInterfaceProtocol == 0x00 ) ) {				if ( comm_intf->bNumEndpoints == 1 ) {					// Good, we found one, we will try this one

⌨️ 快捷键说明

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