USB子系統gadget analyse

來源:互聯網
上載者:User
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.
 */

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.