struct usb_gadget_driver { char *function; enum usb_device_speed speed; void (*unbind)(struct usb_gadget *); int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *); void (*disconnect)(struct usb_gadget *); void (*suspend)(struct usb_gadget *); void (*resume)(struct usb_gadget *); /* FIXME support safe rmmod */ struct device_driver driver;};struct s3c2410_udc {spinlock_t lock;struct s3c2410_ep ep[S3C2410_ENDPOINTS];int address;struct usb_gadget gadget;struct usb_gadget_driver *driver;struct s3c2410_request fifo_req;u8 fifo_buf[EP_FIFO_SIZE];u16 devstatus;u32 port_status;int ep0state;unsigned got_irq : 1;unsigned req_std : 1;unsigned req_config : 1;unsigned req_pending : 1;u8 vbus;struct dentry *regs_info;};USB從裝置測分析. 首先我們要知道把usb 運行於client角色時, 它的USB控制器是運行在otg模式, USB OTG標準在完全相容USB2.0標準的基礎之上, 它允許裝置既可以做為主機, 也可作為外設操作,而此時控制USB裝置控制器的驅動稱之為UDC驅動, 我們記得HOST模式下控制USB裝置控制器的是:USB主機控制器驅動.這些概念比較多.只要我們理清楚就容易理解了.UDC之上就是Gadget api .再之上就是gadeget 驅動. USB OTG的裝置控制器被抽象為:"struct s3c2410_udc { spinlock_t lock; struct s3c2410_ep ep[S3C2410_ENDPOINTS]; int address; struct usb_gadget gadget; struct usb_gadget_driver *driver; struct s3c2410_request fifo_req; u8 fifo_buf[EP_FIFO_SIZE]; u16 devstatus; u32 port_status; int ep0state; unsigned got_irq : 1; unsigned req_std : 1; unsigned req_config : 1; unsigned req_pending : 1; u8 vbus; struct dentry *regs_info;};/*---------------------------------------------------------------------------*/static struct s3c2410_udc memory = { .gadget = { .ops = &s3c2410_ops, .ep0 = &memory.ep[0].ep, .name = gadget_name, .dev = { .init_name = "gadget", }, }, /* control endpoint */ .ep[0] = { .num = 0, .ep = { .name = ep0name, .ops = &s3c2410_ep_ops, .maxpacket = EP0_FIFO_SIZE, }, .dev = &memory, }, /* first group of endpoints */ .ep[1] = { .num = 1, .ep = { .name = "ep1-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, .bEndpointAddress = 1, .bmAttributes = USB_ENDPOINT_XFER_BULK, }, .ep[2] = { .num = 2, .ep = { .name = "ep2-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, .bEndpointAddress = 2, .bmAttributes = USB_ENDPOINT_XFER_BULK, }, .ep[3] = { .num = 3, .ep = { .name = "ep3-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, .bEndpointAddress = 3, .bmAttributes = USB_ENDPOINT_XFER_BULK, }, .ep[4] = { .num = 4, .ep = { .name = "ep4-bulk", .ops = &s3c2410_ep_ops, .maxpacket = EP_FIFO_SIZE, }, .dev = &memory, .fifo_size = EP_FIFO_SIZE, .bEndpointAddress = 4, .bmAttributes = USB_ENDPOINT_XFER_BULK, }};
usb_add_function .
為configuration 添加一個或一個以上的functions, 添加過程條用@bind 函數.
比如下面添加下面的adb
static int adb_bind_config(struct usb_configuration *c){struct adb_dev *dev = _adb_dev;printk(KERN_INFO "adb_bind_config\n");dev->cdev = c->cdev;dev->function.name = "adb";dev->function.descriptors = fs_adb_descs;dev->function.hs_descriptors = hs_adb_descs;dev->function.bind = adb_function_bind;dev->function.unbind = adb_function_unbind;dev->function.set_alt = adb_function_set_alt;dev->function.disable = adb_function_disable;return usb_add_function(c, &dev->function);}
這裡dev->function.bind = adb_function_bind; 把bind函數的進行了賦值
下面在調用
usb_add_function
這個函數時會調用這個bind函數 ,不信往下看
/** * usb_add_function() - add a function to a configuration * @config: the configuration * @function: the function being added * Context: single threaded during gadget setup * * After initialization, each configuration must have one or more * functions added to it. Adding a function involves calling its @bind() * method to allocate resources such as interface and string identifiers * and endpoints. * * This function returns the value of the function's bind(), which is * zero for success else a negative errno value. */int usb_add_function(struct usb_configuration *config,struct usb_function *function){intvalue = -EINVAL;DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",function->name, function,config->label, config);if (!function->set_alt || !function->disable)goto done;function->config = config;list_add_tail(&function->list, &config->functions);/* REVISIT *require* function->bind? */
/*這裡就在調用bind 函數就行configuration和 usb_function的綁定*/
if (function->bind) {value = function->bind(config, function); //調用開始if (value < 0) {list_del(&function->list);function->config = NULL;}} elsevalue = 0;/* We allow configurations that don't work at both speeds. * If we run into a lowspeed Linux system, treat it the same * as full speed ... it's the function drivers that will need * to avoid bulk and ISO transfers. */if (!config->fullspeed && function->descriptors)config->fullspeed = true;if (!config->highspeed && function->hs_descriptors)config->highspeed = true;if (!config->superspeed && function->ss_descriptors)config->superspeed = true;done:if (value)DBG(config->cdev, "adding '%s'/%p --> %d\n",function->name, function, value);return value;}
看上面的這部分代碼,. 就是調用了dev->function.bind = adb_function_bind; 這個函數進行functions 和configuration的綁定.
再看下 usb_function .
那這個 usb_function 是什麼作用呢?
看下面的介紹
/**
* struct usb_function - describes one function of a configuration
* @name: For diagnostics, identifies the function.
* @strings: tables of strings, keyed by identifiers assigned during bind()
* and by language IDs provided in control requests
* @descriptors: Table of full (or low) speed descriptors, using interface and
* string identifiers assigned during @bind(). If this pointer is null,
* the function will not be available at full speed (or at low speed).
* @hs_descriptors: Table of high speed descriptors, using interface and
* string identifiers assigned during @bind(). If this pointer is null,
* the function will not be available at high speed.
* @ss_descriptors: Table of super speed descriptors, using interface and
* string identifiers assigned during @bind(). If this
* pointer is null after initiation, the function will not
* be available at super speed.
* @config: assigned when @usb_add_function() is called; this is the
* configuration with which this function is associated.
* @bind: Before the gadget can register, all of its functions bind() to the
* available resources including string and interface identifiers used
* in interface or class descriptors; endpoints; I/O buffers; and so on.
* @unbind: Reverses @bind; called as a side effect of unregistering the
* driver which added this function.
* @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
* initialize usb_ep.driver data at this time (when it is used).
* Note that setting an interface to its current altsetting resets
* interface state, and that all interfaces have a disabled state.
* @get_alt: Returns the active altsetting. If this is not provided,
* then only altsetting zero is supported.
* @disable: (REQUIRED) Indicates the function should be disabled. Reasons
* include host resetting or reconfiguring the gadget, and disconnection.
* @setup: Used for interface-specific control requests.
* @suspend: Notifies functions when the host stops sending USB traffic.
* @resume: Notifies functions when the host restarts USB traffic.
* @get_status: Returns function status as a reply to
* GetStatus() request when the recepient is Interface.
* @func_suspend: callback to be called when
* SetFeature(FUNCTION_SUSPEND) is reseived
*
* A single USB function uses one or more interfaces, and should in most
* cases support operation at both full and high speeds. Each function is
* associated by @usb_add_function() with a one configuration; that function
* causes @bind() to be called so resources can be allocated as part of
* setting up a gadget driver. Those resources include endpoints, which
* should be allocated using @usb_ep_autoconfig().
*
* To support dual speed operation, a function driver provides descriptors
* for both high and full speed operation. Except in rare cases that don't
* involve bulk endpoints, each speed needs different endpoint descriptors.
*
* Function drivers choose their own strategies for managing instance data.
* The simplest strategy just declares it "static', which means the function
* can only be activated once. If the function needs to be exposed in more
* than one configuration at a given speed, it needs to support multiple
* usb_function structures (one for each configuration).
*
* A more complex strategy might encapsulate a @usb_function structure inside
* a driver-specific instance structure to allows multiple activations. An
* example of multiple activations might be a CDC ACM function that supports
* two or more distinct instances within the same configuration, providing
* several independent logical data links to a USB host.
*/