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

📄 cdcether.c

📁 S3C2440ARM9开发板的USB驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		err( "Invalid bDescriptorType found." );		return -1;	}	/* The Subtype tells the tale - CDC spec Table 25 */	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; /* We init to our needs, and then clear						* bits as we find the descriptors */	/* As long as there is something here, we will try to parse it */	/* All of the functional descriptors start with the same 3 byte pattern */	while (loc < length) {		/* Length */		bFunctionLength = data[loc];		loc++;		/* Type */		bDescriptorType = data[loc];		loc++;		/* Subtype */		bDescriptorSubtype = data[loc];		loc++;				/* ship this off to be processed */		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 move the loc pointer along, remembering		 * that 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 */		dbg( "Ethernet information found at device configuration.  Trying to use it anyway." );		rc = parse_ethernet_class_information( conf->extra, conf->extralen, ether_dev );	} else 	{		/* I don't know where else to look */		err( "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 != USB_ENDPOINT_XFER_BULK ) {		return -1;	}	if ( data_intf->endpoint[1].bmAttributes != USB_ENDPOINT_XFER_BULK ) {		return -1;	}	/* Check the first endpoint to see if it is IN or OUT */	if ( data_intf->endpoint[0].bEndpointAddress & USB_DIR_IN ) {		ether_dev->data_ep_in = data_intf->endpoint[0].bEndpointAddress & 0x7F;	} else {		ether_dev->data_ep_out = data_intf->endpoint[0].bEndpointAddress;		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 & USB_DIR_IN ) {		ether_dev->data_ep_in = data_intf->endpoint[1].bEndpointAddress & 0x7F;	} else	{		ether_dev->data_ep_out = data_intf->endpoint[1].bEndpointAddress;		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) {		dbg( "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] );			/* Good, we found one, we will try this one */			/* 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;			}			/* It is a bit ambiguous whether the Ethernet model really requires			 * the notification element (usually an interrupt endpoint) or not			 * And some products (eg Sharp Zaurus) don't support it, so we			 * only use the notification element if present */			/* We check for a sane endpoint before using it */			if ( (comm_intf->bNumEndpoints == 1) &&				(comm_intf->endpoint[0].bEndpointAddress & USB_DIR_IN) &&				(comm_intf->endpoint[0].bmAttributes == USB_ENDPOINT_XFER_INT)) {					ether_dev->properties |= HAVE_NOTIFICATION_ELEMENT;					ether_dev->comm_ep_in = (comm_intf->endpoint[0].bEndpointAddress & 0x7F);					dbg("interrupt address: %x",ether_dev->comm_ep_in);					ether_dev->intr_interval = (comm_intf->endpoint[0].bInterval);					dbg("interrupt interval: %d",ether_dev->intr_interval);			}			// This communication interface seems to give us everything			// we require.  We have all the ethernet info we need.			return 0;		} // 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

⌨️ 快捷键说明

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