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 + -
显示快捷键?