• USB子系统gadget analyse


    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)
    {
    	int	value = -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;
    		}
    	} else
    		value = 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.
     */

  • 相关阅读:
    elasticsearch 6.x.x 获取客户端方法
    struts2+spring 配置404和500错误页面
    linux 部署redis集群 碰到的坑
    Linux下安装redis
    struts加载spring
    有关struts中DispatchAction的用法小结
    spring AOP原理
    struts2.0的工作原理?
    Spring MVC的实现原理
    spring 的单例模式
  • 原文地址:https://www.cnblogs.com/yuzaipiaofei/p/4124135.html
Copyright © 2020-2023  润新知