usbd-func.c

来自「Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码」· C语言 代码 · 共 1,206 行 · 第 1/3 页

C
1,206
字号
	for (i = 0; i < alternates; i++) {		struct usb_alternate_description *alternate_description = alternate_description_array + i;		struct usb_alternate_instance *alternate_instance = alternate_instance_array + i;		struct usb_interface_descriptor *interface_descriptor;		dbg_init (1, "alternate: %d:%d", i, alternates);		// allocate a descriptor for this interface		if (!(interface_descriptor = usbd_alloc_descriptor (USB_DT_INTERFACE, 0, 0))) {			return NULL;		}		interface_descriptor->bInterfaceNumber = bInterfaceNumber;	// XXX		interface_descriptor->bInterfaceClass = interface_description->bInterfaceClass;		interface_descriptor->bInterfaceSubClass = interface_description->bInterfaceSubClass;		interface_descriptor->bInterfaceProtocol = interface_description->bInterfaceProtocol;		interface_descriptor->bAlternateSetting = alternate_description->bAlternateSetting;		interface_descriptor->bNumEndpoints = alternate_description->endpoints;		interface_descriptor->iInterface = usbd_alloc_string (alternate_description->iInterface ? alternate_description->iInterface : interface_description->iInterface);		// XXX Classes		alternate_instance->classes_descriptor_array =			alloc_function_classes(				alternate_description->classes,				alternate_description->class_list);		alternate_instance->reports_descriptor_array =			alloc_function_reports(				alternate_description->classes,				alternate_description->class_list);		alternate_instance->classes = alternate_description->classes;		// XXX it should be possible to collapse the next two functions into one.		alternate_instance->endpoints_descriptor_array = alloc_function_endpoints (alternate_description->endpoints, alternate_description->endpoint_list);		alternate_instance->endpoint_transfersize_array = alloc_endpoint_transfer (alternate_description->endpoints, alternate_description->endpoint_list);		// save number of alternates, classes and endpoints for this alternate		alternate_instance->endpoints = alternate_description->endpoints;		alternate_instance->interface_descriptor = interface_descriptor;	}	return alternate_instance_array;}/* * * alloc_function_interfaces - allocate interface instance array * @interfaces: number of interfaces * @interface_description_array: pointer to an array of interface descriptions * * Return a pointer to an array of interface instances. Each instance contains a pointer * to a filled in interface descriptor and a pointer to the endpoint descriptor array. * * Returning NULL will cause the caller to cleanup all previously allocated memory. */__devinit static struct usb_interface_instance *alloc_function_interfaces (int interfaces, struct usb_interface_description *interface_description_array){	int interface;	struct usb_interface_instance *interface_instance_array;	// allocate array of interface instances	if (!(interface_instance_array = ckmalloc (sizeof (struct usb_interface_instance) * interfaces, GFP_KERNEL))) {		return NULL;	}	// iterate across the interface descriptions	for (interface = 0; interface < interfaces; interface++) {		struct usb_interface_description *interface_description = interface_description_array + interface;		struct usb_interface_instance *interface_instance = interface_instance_array + interface;		dbg_init (1, "_");		dbg_init (1, "interface: %d:%d   alternates: %d", interface, interfaces, interface_description->alternates);		// save the interface description in the interface instance array		//interface_instance_array[interface].interface_descriptor = interface_descriptor;		interface_instance->alternates_instance_array = alloc_function_alternates (interface, interface_description, interface_description->alternates, interface_description->alternate_list);		interface_instance->alternates = interface_description->alternates;	}	return interface_instance_array;}/* * * alloc_function_configurations - allocate configuration instance array * @configurations: number of configurations * @configuration_description_array: pointer to an array of configuration descriptions * * Return a pointer to an array of configuration instances. Each instance contains a pointer * to a filled in configuration descriptor and a pointer to the interface instances array. * * Returning NULL will cause the caller to cleanup all previously allocated memory. */__devinit static struct usb_configuration_instance *alloc_function_configurations (int configurations, struct usb_configuration_description *configuration_description_array){	int i;	struct usb_configuration_instance *configuration_instance_array;	// allocate array	if (!(configuration_instance_array = ckmalloc (sizeof (struct usb_configuration_instance) * configurations, GFP_KERNEL))) {		return NULL;	}	// fill in array	for (i = 0; i < configurations; i++) {		int j;		int length;		struct usb_configuration_description *configuration_description = configuration_description_array + i;		struct usb_configuration_descriptor *configuration_descriptor;		dbg_init (1, "configurations: %d:%d", i, configurations);		// allocate a descriptor		if (!(configuration_descriptor = usbd_alloc_descriptor (USB_DT_CONFIG, 0, 0))) {			return NULL;		}		// setup fields in configuration descriptor		// XXX c.f. 9.4.7 zero is default, so config MUST BE 1 to n, not 0 to n-1		// XXX N.B. the configuration itself is fetched 0 to n-1.		//		configuration_descriptor->bConfigurationValue = i + 1;		configuration_descriptor->wTotalLength = 0;		configuration_descriptor->bNumInterfaces = configuration_description->interfaces;		configuration_descriptor->iConfiguration = usbd_alloc_string (configuration_description->iConfiguration);		configuration_descriptor->bmAttributes = configuration_description->bmAttributes;		configuration_descriptor->bMaxPower = configuration_description->bMaxPower;		// save the configuration descriptor in the configuration instance array		configuration_instance_array[i].configuration_descriptor = configuration_descriptor;		if (!(configuration_instance_array[i].interface_instance_array = alloc_function_interfaces (configuration_description->interfaces, configuration_description->interface_list))		    ) {			// XXX			return NULL;		}		for (length = 0, j = 0; j < configuration_descriptor->bNumInterfaces; j++) {			int alternate;			struct usb_interface_instance *interface_instance = configuration_instance_array[i].interface_instance_array + j;			for (alternate = 0; alternate < interface_instance->alternates; alternate++) {				int class;				struct usb_alternate_instance *alternate_instance = interface_instance->alternates_instance_array + alternate;				for (class = 0; class < alternate_instance->classes; class++) {					struct usb_class_descriptor *class_descriptor = alternate_instance->classes_descriptor_array[class];					length += class_descriptor->descriptor.generic.bFunctionLength;				}				length += sizeof (struct usb_interface_descriptor) + alternate_instance->endpoints * sizeof (struct usb_endpoint_descriptor);			}		}		configuration_descriptor->wTotalLength = cpu_to_le16 (sizeof (struct usb_configuration_descriptor) + length);		dbg_init (1, "-------> [%d] %d %d %d length: %d", i,			  configuration_descriptor->bNumInterfaces, configuration_descriptor->bConfigurationValue, configuration_descriptor->iConfiguration, length);		configuration_instance_array[i].interfaces = configuration_description->interfaces;	}	return configuration_instance_array;}/* * * usbd_dealloc_function - deallocate a function driver * @function_driver: pointer to a function driver structure * * Find and free all descriptor structures associated with a function structure. */static void __devexit usbd_dealloc_function (struct usb_function_driver *function_driver){	int configuration;	struct usb_configuration_instance *configuration_instance_array = function_driver->configuration_instance_array;	dbg_init (1, "%s", function_driver->name);	// iterate across the descriptors list and de-allocate all structures	if (function_driver->configuration_instance_array) {		for (configuration = 0; configuration < function_driver->configurations; configuration++) {			int interface;			struct usb_configuration_instance *configuration_instance = configuration_instance_array + configuration;			dbg_init (1, "%s configuration: %d", function_driver->name, configuration);			for (interface = 0; interface < configuration_instance->interfaces; interface++) {				int alternate;				struct usb_interface_instance *interface_instance = configuration_instance->interface_instance_array + interface;				dbg_init (1, "%s configuration: %d interface: %d", function_driver->name, configuration, interface);				for (alternate = 0; alternate < interface_instance->alternates; alternate++) {					int class;					int endpoint;					struct usb_alternate_instance *alternate_instance = interface_instance->alternates_instance_array + alternate;					dbg_init (1, "%s configuration: %d interface: %d alternate: %d", function_driver->name, configuration, interface, alternate);					for (class = 0; class < alternate_instance->classes; class++) {						dbg_init (1, "%s configuration: %d interface: %d alternate: %d class: %d", function_driver->name, configuration, interface, alternate, class);						usbd_dealloc_descriptor ((struct usb_descriptor *)									 alternate_instance->classes_descriptor_array[class]);					}					for (endpoint = 0; endpoint < alternate_instance->endpoints; endpoint++) {						dbg_init (1, "%s configuration: %d interface: %d alternate: %d endpoint: %d", function_driver->name, configuration, interface, alternate, endpoint);						usbd_dealloc_descriptor ((struct usb_descriptor *)									 alternate_instance->endpoints_descriptor_array[endpoint]);					}					lkfree (alternate_instance->endpoints_descriptor_array);					lkfree (alternate_instance->endpoint_transfersize_array);					lkfree (alternate_instance->classes_descriptor_array);					usbd_dealloc_descriptor ((struct usb_descriptor *) alternate_instance->interface_descriptor);				}				lkfree (interface_instance->alternates_instance_array);			}			lkfree (configuration_instance->interface_instance_array);			usbd_dealloc_descriptor ((struct usb_descriptor *)						 configuration_instance_array[configuration].configuration_descriptor);		}	}	usbd_dealloc_descriptor ((struct usb_descriptor *) function_driver->device_descriptor);	lkfree (configuration_instance_array);}__devinit static int usbd_strings_init (void){	if (maxstrings > 254) {		dbg_init (1, "setting maxstrings to maximum value of 254");		maxstrings = 254;	}	if (!(usb_strings = ckmalloc (sizeof (struct usb_string_descriptor *) * maxstrings, GFP_KERNEL))) {		return -1;	}	if (usbd_alloc_string_zero (LANGIDs) != 0) {		lkfree (usb_strings);		return -1;	}	return 0;}/* * * usbd_register_function - register a usb function driver * @function_driver: pointer to function driver structure * * Used by a USB Function driver to register itself with the usb device layer. * * It will create a usb_function_instance structure. * * The user friendly configuration/interface/endpoint descriptions are compiled into * the equivalent ready to use descriptor records. * * All function drivers must register before any bus interface drivers. * */EXPORT_SYMBOL(usbd_register_function);__devinit int usbd_register_function (struct usb_function_driver *function_driver){	//struct usb_device_descriptor *device_descriptor;	/* Create a function driver structure, copy the configuration,	 * interface and endpoint descriptions into descriptors, add to the	 * function drivers list.	 */	dbg_init (1, "--");	if (registered_devices) {		dbg_init (1, "cannot register after device created: %s", function_driver->name);		return -EINVAL;	}	// initialize the strings pool	if (usbd_strings_init ()) {		dbg_init (0, "usbd_strings_init failed");		return -EINVAL;	}	dbg_init (9, "USE_COUNT %d", GET_USE_COUNT (THIS_MODULE));	list_add_tail (&function_driver->drivers, &function_drivers);	registered_functions++;	dbg_init (1, "registered_functions: %d", registered_functions);	dbg_init (1, "--------------");	return 0;}/* * * usbd_deregister_function - called by a USB FUNCTION driver to deregister itself * @function_driver: pointer to struct usb_function_driver * * Called by a USB Function driver De-register a usb function driver. */EXPORT_SYMBOL(usbd_deregister_function);void __devexit usbd_deregister_function (struct usb_function_driver *function_driver){	dbg_init (1, "%s", function_driver->name);	list_del (&function_driver->drivers);	registered_functions--;	//usbd_dealloc_function(function_driver);	dbg_init (9, "USE_COUNT %d", GET_USE_COUNT (THIS_MODULE));}void usbd_function_init (struct usb_bus_instance *bus, struct usb_device_instance *device, struct usb_function_driver *function_driver){	struct usb_device_descriptor *device_descriptor;	dbg_init (1, "-");	if (function_driver->ops->function_init) {		function_driver->ops->function_init (bus, device, function_driver);	}	if (!(device_descriptor = usbd_alloc_descriptor (USB_DT_DEVICE, 0, 0))) {		return;	}	device_descriptor->bcdUSB = cpu_to_le16(USB_BCD_VERSION);	device_descriptor->bDeviceClass = function_driver->device_description->bDeviceClass;	device_descriptor->bDeviceSubClass = function_driver->device_description->bDeviceSubClass;	device_descriptor->bDeviceProtocol = function_driver->device_description->bDeviceProtocol;	//device_descriptor->bMaxPacketSize0 = 0;             // this will be set in ep0	// XXX test that this works, should be able to remove from ep0	device_descriptor->bMaxPacketSize0 = bus->driver->maxpacketsize;	device_descriptor->idVendor =		cpu_to_le16(function_driver->device_description->idVendor);	device_descriptor->idProduct =		cpu_to_le16(function_driver->device_description->idProduct);	device_descriptor->bcdDevice = 0;	// XXX	device_descriptor->iManufacturer = usbd_alloc_string (function_driver->device_description->iManufacturer);	device_descriptor->iProduct = usbd_alloc_string (function_driver->device_description->iProduct);	dbg_init (1, "*      *       *       *");#ifdef CONFIG_USBD_SERIAL_NUMBER_STR	dbg_init (1, "SERIAL_NUMBER");	if (bus->serial_number_str && strlen (bus->serial_number_str)) {		dbg_init (0, "bus->serial_number_str: %s", bus->serial_number_str);		device_descriptor->iSerialNumber = usbd_alloc_string (bus->serial_number_str);	} else {		dbg_init (0, "function_driver->device_description->iSerialNumber: %s", function_driver->device_description->iSerialNumber);		device_descriptor->iSerialNumber = usbd_alloc_string (function_driver->device_description->iSerialNumber);	}	dbg_init (1, "device_descriptor->iSerialNumber: %d", device_descriptor->iSerialNumber);#else	// XXX should not need to do anything here#endif	device_descriptor->bNumConfigurations = function_driver->configurations;	dbg_init (3, "configurations: %d", device_descriptor->bNumConfigurations);	// allocate the configuration descriptor array	if (!(function_driver->configuration_instance_array = alloc_function_configurations (function_driver->configurations, function_driver->configuration_description))) {		dbg_init (1, "failed during function configuration %s", function_driver->name);		usbd_dealloc_descriptor ((struct usb_descriptor *) device_descriptor);		return;	}	function_driver->device_descriptor = device_descriptor;	dbg_init (1, "- finished");}void usbd_function_close (struct usb_device_instance *device){	struct usb_function_instance *function;	if ((function = usbd_device_function_instance (device, 0))) {		if (function->function_driver->ops->function_exit) {			function->function_driver->ops->function_exit (device);		}	}	usbd_dealloc_function (function->function_driver);}

⌨️ 快捷键说明

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