android usb 分析

android 系统在 linux usb 模块中加入了 adb 功能,具体代码在 drivers/usb/gadget/android.c 中
1. init/exit:

  1. static int __init init(void)  
  2. {  
  3.     struct android_dev *dev;  
  4.     printk(KERN_INFO "android init\n");  
  5.     dev = kzalloc(sizeof(*dev), GFP_KERNEL);      //分配 android_dev 内存   
  6.     if (!dev)  
  7.         return -ENOMEM;  
  8.     /* set default values, which should be overridden by platform data */  
  9.     dev->product_id = PRODUCT_ID;     //product_id   
  10.     _android_dev = dev;                     //_android_dev 是本地的全局变量   
  11.     return platform_driver_register(&android_platform_driver);    //注册platform_driver   
  12. }  
  13. module_init(init);  
  14. static void __exit cleanup(void)  
  15. {  
  16.     usb_composite_unregister(&android_usb_driver);  
  17.     platform_driver_unregister(&android_platform_driver);  
  18.     kfree(_android_dev);  
  19.     _android_dev = NULL;  
  20. }  
  21. module_exit(cleanup);  
    static int __init init(void)
    {
        struct android_dev *dev;
        printk(KERN_INFO "android init\n");
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);      //分配 android_dev 内存
        if (!dev)
            return -ENOMEM;
        /* set default values, which should be overridden by platform data */
        dev->product_id = PRODUCT_ID;     //product_id
        _android_dev = dev;                     //_android_dev 是本地的全局变量
        return platform_driver_register(&android_platform_driver);    //注册platform_driver
    }
    module_init(init);
    static void __exit cleanup(void)
    {
        usb_composite_unregister(&android_usb_driver);
        platform_driver_unregister(&android_platform_driver);
        kfree(_android_dev);
        _android_dev = NULL;
    }
    module_exit(cleanup);
android_dev 定义:

  1. struct android_dev {  
  2.     struct usb_composite_dev *cdev;  
  3.     struct usb_configuration *config;  
  4.     int num_products;  
  5.     struct android_usb_product *products;  
  6.     int num_functions;  
  7.     char **functions;  
  8.     int product_id;  
  9.     int version;  
  10. };  
    struct android_dev {
        struct usb_composite_dev *cdev;
        struct usb_configuration *config;
        int num_products;
        struct android_usb_product *products;
        int num_functions;
        char **functions;
        int product_id;
        int version;
    };
_android_dev 是一个本地定义的全局变量:
  1. static struct android_dev *_android_dev;  
    static struct android_dev *_android_dev;
默认的 product_id 和 vendor_id 定义:
  1. /* Default vendor and product IDs, overridden by platform data */  
  2. #define VENDOR_ID 0x18D1   
  3. #define PRODUCT_ID 0x0001  
    /* Default vendor and product IDs, overridden by platform data */
    #define VENDOR_ID 0x18D1
    #define PRODUCT_ID 0x0001
struct android_platform_driver  定义:
  1. static struct platform_driver android_platform_driver = {  
  2.     .driver = { .name = "android_usb", },  
  3.     .probe = android_probe,  
  4. };  
    static struct platform_driver android_platform_driver = {
        .driver = { .name = "android_usb", },
        .probe = android_probe,
    };
2. android_probe()
  1. static int android_probe(struct platform_device *pdev)  
  2. {  
  3.     struct android_usb_platform_data *pdata = pdev->dev.platform_data;   //从platform_data中获取内容   
  4.     //platform_data中内容定义在board-xxx.c中,通过比较 .name (即android_usb) 来匹配。   
  5.                      
  6.     struct android_dev *dev = _android_dev;  
  7.     printk(KERN_INFO "android_probe pdata: %p\n", pdata);  
  8.     if (pdata) {  
  9.         dev->products = pdata->products;           //android_usb_product   
  10.         dev->num_products = pdata->num_products;  
  11.         dev->functions = pdata->functions;  
  12.         dev->num_functions = pdata->num_functions;  
  13.         if (pdata->vendor_id)  
  14.             device_desc.idVendor =                         //vendor_id   
  15.                 __constant_cpu_to_le16(pdata->vendor_id);  
  16.         if (pdata->product_id) {                           //product_id   
  17.             dev->product_id = pdata->product_id;  
  18.             device_desc.idProduct =  
  19.                 __constant_cpu_to_le16(pdata->product_id);  
  20.         }  
  21.         if (pdata->version)  
  22.             dev->version = pdata->version;  
  23.         if (pdata->product_name)  
  24.             strings_dev[STRING_PRODUCT_IDX].s = pdata->product_name;  
  25.         if (pdata->manufacturer_name)  
  26.             strings_dev[STRING_MANUFACTURER_IDX].s =  
  27.                     pdata->manufacturer_name;  
  28.         if (pdata->serial_number)  
  29.             strings_dev[STRING_SERIAL_IDX].s = pdata->serial_number;  
  30.     }  
  31.     return usb_composite_probe(&android_usb_driver, android_bind);  //注册一个复杂的驱动   
  32. }  
    static int android_probe(struct platform_device *pdev)
    {
        struct android_usb_platform_data *pdata = pdev->dev.platform_data;   //从platform_data中获取内容
        //platform_data中内容定义在board-xxx.c中,通过比较 .name (即android_usb) 来匹配。
                       
        struct android_dev *dev = _android_dev;
        printk(KERN_INFO "android_probe pdata: %p\n", pdata);
        if (pdata) {
            dev->products = pdata->products;           //android_usb_product
            dev->num_products = pdata->num_products;
            dev->functions = pdata->functions;
            dev->num_functions = pdata->num_functions;
            if (pdata->vendor_id)
                device_desc.idVendor =                         //vendor_id
                    __constant_cpu_to_le16(pdata->vendor_id);
            if (pdata->product_id) {                           //product_id
                dev->product_id = pdata->product_id;
                device_desc.idProduct =
                    __constant_cpu_to_le16(pdata->product_id);
            }
            if (pdata->version)
                dev->version = pdata->version;
            if (pdata->product_name)
                strings_dev[STRING_PRODUCT_IDX].s = pdata->product_name;
            if (pdata->manufacturer_name)
                strings_dev[STRING_MANUFACTURER_IDX].s =
                        pdata->manufacturer_name;
            if (pdata->serial_number)
                strings_dev[STRING_SERIAL_IDX].s = pdata->serial_number;
        }
        return usb_composite_probe(&android_usb_driver, android_bind);  //注册一个复杂的驱动
    }
上面的 platform_data 内容定义在 board-xxx.c中:
  1. #ifdef CONFIG_USB_ANDROID      //条件宏,如果没有可以不编译   
  2. #define GOOGLE_VENDOR_ID 0x18d1   
  3. #define GOOGLE_PRODUCT_ID 0x9018   
  4. #define GOOGLE_ADB_PRODUCT_ID 0x9015   
  5. static char *usb_functions_adb[] = {      //所有的 function 只有一个 adb   
  6.     "adb",  
  7. };  
  8. static char *usb_functions_all[] = {  
  9.     "adb",  
  10. };  
  11. static struct android_usb_product usb_products[] = {  
  12.     {  
  13.         .product_id = GOOGLE_PRODUCT_ID,  
  14.         .num_functions = ARRAY_SIZE(usb_functions_adb),  
  15.         .functions = usb_functions_adb,  
  16.     },  
  17. };  
  18. static struct android_usb_platform_data android_usb_pdata = {  
  19.     .vendor_id = GOOGLE_VENDOR_ID,  
  20.     .product_id = GOOGLE_PRODUCT_ID,  
  21.     .functions = usb_functions_all,  
  22.     .products = usb_products,  
  23.     .version = 0x0100,  
  24.     .product_name = "rowboat gadget",  
  25.     .manufacturer_name = "rowboat",  
  26.     .serial_number = "20100720",  
  27.     .num_functions = ARRAY_SIZE(usb_functions_all),  
  28. };  
  29. static struct platform_device androidusb_device = {  
  30.     .name = "android_usb",       //这个名字是device名字,和上面的driver名字必须一样,用来匹配。   
  31.     .id = -1,  
  32.     .dev = {  
  33.         .platform_data = &android_usb_pdata,  //这个就是上面的platform_data   
  34.     },  
  35. };  
  36. static void omap3evm_android_gadget_init(void)  
  37. {  
  38.     platform_device_register(&androidusb_device);   //上面定义,这里注册 platform_device 设备   
  39. }  
  40. #endif  
    #ifdef CONFIG_USB_ANDROID      //条件宏,如果没有可以不编译
    #define GOOGLE_VENDOR_ID 0x18d1
    #define GOOGLE_PRODUCT_ID 0x9018
    #define GOOGLE_ADB_PRODUCT_ID 0x9015
    static char *usb_functions_adb[] = {      //所有的 function 只有一个 adb
        "adb",
    };
    static char *usb_functions_all[] = {
        "adb",
    };
    static struct android_usb_product usb_products[] = {
        {
            .product_id = GOOGLE_PRODUCT_ID,
            .num_functions = ARRAY_SIZE(usb_functions_adb),
            .functions = usb_functions_adb,
        },
    };
    static struct android_usb_platform_data android_usb_pdata = {
        .vendor_id = GOOGLE_VENDOR_ID,
        .product_id = GOOGLE_PRODUCT_ID,
        .functions = usb_functions_all,
        .products = usb_products,
        .version = 0x0100,
        .product_name = "rowboat gadget",
        .manufacturer_name = "rowboat",
        .serial_number = "20100720",
        .num_functions = ARRAY_SIZE(usb_functions_all),
    };
    static struct platform_device androidusb_device = {
        .name = "android_usb",       //这个名字是device名字,和上面的driver名字必须一样,用来匹配。
        .id = -1,
        .dev = {
            .platform_data = &android_usb_pdata,  //这个就是上面的platform_data
        },
    };
    static void omap3evm_android_gadget_init(void)
    {
        platform_device_register(&androidusb_device);   //上面定义,这里注册 platform_device 设备
    }
    #endif
3. usb_composite_probe(&android_usb_driver, android_bind);
这个函数定义在 drivers/usb/gadget/composite.c 中。
  1. /** 
  2.  * usb_composite_probe() - register a composite driver 
  3.  * @driver: the driver to register 
  4.  * @bind: the callback used to allocate resources that are shared across the 
  5.  * whole device, such as string IDs, and add its configurations using 
  6.  * @usb_add_config(). This may fail by returning a negative errno 
  7.  * value; it should return zero on successful initialization. 
  8.  * Context: single threaded during gadget setup 
  9.  * 
  10.  * This function is used to register drivers using the composite driver 
  11.  * framework. The return value is zero, or a negative errno value. 
  12.  * Those values normally come from the driver's @bind method, which does 
  13.  * all the work of setting up the driver to match the hardware. 
  14.  * 
  15.  * On successful return, the gadget is ready to respond to requests from 
  16.  * the host, unless one of its components invokes usb_gadget_disconnect() 
  17.  * while it was binding. That would usually be done in order to wait for 
  18.  * some userspace participation. 
  19.  */  
  20. extern int usb_composite_probe(struct usb_composite_driver *driver,  
  21.                    int (*bind)(struct usb_composite_dev *cdev))  
  22. {  
  23.     if (!driver || !driver->dev || !bind || composite)  
  24.         return -EINVAL;  
  25.       
  26.     if (!driver->iProduct)  
  27.         driver->iProduct = driver->name;  
  28.     if (!driver->name)  
  29.         driver->name = "composite";  
  30.     composite_driver.function = (char *) driver->name;  
  31.     composite_driver.driver.name = driver->name;  
  32.     composite = driver;  
  33.     composite_gadget_bind = bind;  
  34.     driver->class = class_create(THIS_MODULE, "usb_composite");  //建立一新类 usb_composite   
  35.     if (IS_ERR(driver->class))  
  36.         return PTR_ERR(driver->class);  
  37.     driver->class->dev_uevent = composite_uevent;  
  38.       
  39.     return usb_gadget_probe_driver(&composite_driver, composite_bind);   //这里调到了musb模块   
  40. }  
    /**
     * usb_composite_probe() - register a composite driver
     * @driver: the driver to register
     * @bind: the callback used to allocate resources that are shared across the
     * whole device, such as string IDs, and add its configurations using
     * @usb_add_config(). This may fail by returning a negative errno
     * value; it should return zero on successful initialization.
     * Context: single threaded during gadget setup
     *
     * This function is used to register drivers using the composite driver
     * framework. The return value is zero, or a negative errno value.
     * Those values normally come from the driver's @bind method, which does
     * all the work of setting up the driver to match the hardware.
     *
     * On successful return, the gadget is ready to respond to requests from
     * the host, unless one of its components invokes usb_gadget_disconnect()
     * while it was binding. That would usually be done in order to wait for
     * some userspace participation.
     */
    extern int usb_composite_probe(struct usb_composite_driver *driver,
                       int (*bind)(struct usb_composite_dev *cdev))
    {
        if (!driver || !driver->dev || !bind || composite)
            return -EINVAL;
        
        if (!driver->iProduct)
            driver->iProduct = driver->name;
        if (!driver->name)
            driver->name = "composite";
        composite_driver.function = (char *) driver->name;
        composite_driver.driver.name = driver->name;
        composite = driver;
        composite_gadget_bind = bind;
        driver->class = class_create(THIS_MODULE, "usb_composite");  //建立一新类 usb_composite
        if (IS_ERR(driver->class))
            return PTR_ERR(driver->class);
        driver->class->dev_uevent = composite_uevent;
        
        return usb_gadget_probe_driver(&composite_driver, composite_bind);   //这里调到了musb模块
    }
4. usb_gadget_probe_driver(&composite_driver, composite_bind); 
这个函数定义在 drivers/usb/musb/musb_gadget.c 中.
musb是am3715中集成的usb模块,这usb模块好象是从Mentor Graphic Corporation公司买去的。
这个留到musb模块里去讨论了。
  1. /* 
  2.  * Register the gadget driver. Used by gadget drivers when 
  3.  * registering themselves with the controller. 
  4.  * 
  5.  * -EINVAL something went wrong (not driver) 
  6.  * -EBUSY another gadget is already using the controller 
  7.  * -ENOMEM no memory to perform the operation 
  8.  * 
  9.  * @param driver the gadget driver 
  10.  * @param bind the driver's bind function 
  11.  * @return <0 if error, 0 if everything is fine 
  12.  */  
  13. int usb_gadget_probe_driver(struct usb_gadget_driver *driver,  
  14.         int (*bind)(struct usb_gadget *))  
  15. {  
  16.     int retval;  
  17.     unsigned long flags;  
  18.     struct musb *musb = the_gadget;  
  19. D_ENTER  
  20.     printk(KERN_INFO "xxha: --- enter musb");  
  21.     if (!driver  
  22.             || driver->speed != USB_SPEED_HIGH  
  23.             || !bind || !driver->setup)  
  24.         return -EINVAL;  
  25.     /* driver must be initialized to support peripheral mode */  
  26.     if (!musb) {  
  27.         DBG(1, "%s, no dev??\n", __func__);  
  28.         return -ENODEV;  
  29.     }  
  30.     DBG(3, "registering driver %s\n", driver->function);  
  31.     spin_lock_irqsave(&musb->lock, flags);  
  32.     if (musb->gadget_driver) {  
  33.         DBG(1, "%s is already bound to %s\n",  
  34.                 musb_driver_name,  
  35.                 musb->gadget_driver->driver.name);  
  36.         retval = -EBUSY;  
  37.     } else {  
  38.         musb->gadget_driver = driver;  
  39.         musb->g.dev.driver = &driver->driver;  
  40.         driver->driver.bus = NULL;  
  41.         musb->softconnect = 1;  
  42.         retval = 0;  
  43.     }  
  44.     spin_unlock_irqrestore(&musb->lock, flags);  
  45.     if (retval == 0) {  
  46.         retval = bind(&musb->g);  
  47.         if (retval != 0) {  
  48.             DBG(3, "bind to driver %s failed --> %d\n",  
  49.                     driver->driver.name, retval);  
  50.             musb->gadget_driver = NULL;  
  51.             musb->g.dev.driver = NULL;  
  52.         }  
  53.         spin_lock_irqsave(&musb->lock, flags);  
  54.         otg_set_peripheral(musb->xceiv, &musb->g);  
  55.         musb->xceiv->state = OTG_STATE_B_IDLE;  
  56.         musb->is_active = 1;  
  57.         /* FIXME this ignores the softconnect flag. Drivers are 
  58.          * allowed hold the peripheral inactive until for example 
  59.          * userspace hooks up printer hardware or DSP codecs, so 
  60.          * hosts only see fully functional devices. 
  61.          */  
  62.         if (!is_otg_enabled(musb))  
  63.             musb_start(musb);  
  64.         otg_set_peripheral(musb->xceiv, &musb->g);  
  65.         spin_unlock_irqrestore(&musb->lock, flags);  
  66.         if (is_otg_enabled(musb)) {  
  67.             struct usb_hcd *hcd = musb_to_hcd(musb);  
  68.             DBG(3, "OTG startup...\n");  
  69.             /* REVISIT: funcall to other code, which also 
  70.              * handles power budgeting ... this way also 
  71.              * ensures HdrcStart is indirectly called. 
  72.              */  
  73.             retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);  
  74.             if (retval < 0) {  
  75.                 DBG(1, "add_hcd failed, %d\n", retval);  
  76.                 spin_lock_irqsave(&musb->lock, flags);  
  77.                 otg_set_peripheral(musb->xceiv, NULL);  
  78.                 musb->gadget_driver = NULL;  
  79.                 musb->g.dev.driver = NULL;  
  80.                 spin_unlock_irqrestore(&musb->lock, flags);  
  81.             } else {  
  82.                 hcd->self.uses_pio_for_control = 1;  
  83.             }  
  84.         }  
  85.     }  
  86.     return retval;  
  87. }  
  88. EXPORT_SYMBOL(usb_gadget_probe_driver); 

 

这里继续分析android_usb_driver 和 android_bind。

1. android_usb_driver

  1. static struct usb_composite_driver android_usb_driver = {  
  2.     .name = "android_usb",   //driver名   
  3.     .dev = &device_desc,     //usb_device_descriptor 内容   
  4.     .strings = dev_strings,  
  5.     .enable_function = android_enable_function,  
  6. };  
    static struct usb_composite_driver android_usb_driver = {
        .name = "android_usb",   //driver名
        .dev = &device_desc,     //usb_device_descriptor 内容
        .strings = dev_strings,
        .enable_function = android_enable_function,
    };

a. usb_composite_driver 数据结构原型定义在 include/linux/usb/composite.h 中

  1. /** 
  2.  * struct usb_composite_driver - groups configurations into a gadget 
  3.  * @name: For diagnostics, identifies the driver. 
  4.  * @iProduct: Used as iProduct override if @dev->iProduct is not set. 
  5.  * If NULL value of @name is taken. 
  6.  * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is 
  7.  * not set. If NULL a default "<system> <release> with <udc>" value 
  8.  * will be used. 
  9.  * @dev: Template descriptor for the device, including default device 
  10.  * identifiers. 
  11.  * @strings: tables of strings, keyed by identifiers assigned during bind() 
  12.  * and language IDs provided in control requests 
  13.  * @needs_serial: set to 1 if the gadget needs userspace to provide 
  14.  * a serial number. If one is not provided, warning will be printed. 
  15.  * @unbind: Reverses bind; called as a side effect of unregistering 
  16.  * this driver. 
  17.  * @disconnect: optional driver disconnect method 
  18.  * @suspend: Notifies when the host stops sending USB traffic, 
  19.  * after function notifications 
  20.  * @resume: Notifies configuration when the host restarts USB traffic, 
  21.  * before function notifications 
  22.  * 
  23.  * Devices default to reporting self powered operation. Devices which rely 
  24.  * on bus powered operation should report this in their @bind() method. 
  25.  * 
  26.  * Before returning from bind, various fields in the template descriptor 
  27.  * may be overridden. These include the idVendor/idProduct/bcdDevice values 
  28.  * normally to bind the appropriate host side driver, and the three strings 
  29.  * (iManufacturer, iProduct, iSerialNumber) normally used to provide user 
  30.  * meaningful device identifiers. (The strings will not be defined unless 
  31.  * they are defined in @dev and @strings.) The correct ep0 maxpacket size 
  32.  * is also reported, as defined by the underlying controller driver. 
  33.  */  
  34. struct usb_composite_driver {  
  35.     const char *name;  
  36.     const char *iProduct;  
  37.     const char *iManufacturer;  
  38.     const struct usb_device_descriptor *dev;  
  39.     struct usb_gadget_strings **strings;  
  40.     unsigned needs_serial:1;  
  41.     struct class *class;  
  42.     atomic_t function_count;  
  43.     int (*unbind)(struct usb_composite_dev *);  
  44.     void (*disconnect)(struct usb_composite_dev *);  
  45.     /* global suspend hooks */  
  46.     void (*suspend)(struct usb_composite_dev *);  
  47.     void (*resume)(struct usb_composite_dev *);  
  48.     void (*enable_function)(struct usb_function *f, int enable);  
  49. };  
    /**
     * struct usb_composite_driver - groups configurations into a gadget
     * @name: For diagnostics, identifies the driver.
     * @iProduct: Used as iProduct override if @dev->iProduct is not set.
     * If NULL value of @name is taken.
     * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is
     * not set. If NULL a default "<system> <release> with <udc>" value
     * will be used.
     * @dev: Template descriptor for the device, including default device
     * identifiers.
     * @strings: tables of strings, keyed by identifiers assigned during bind()
     * and language IDs provided in control requests
     * @needs_serial: set to 1 if the gadget needs userspace to provide
     * a serial number. If one is not provided, warning will be printed.
     * @unbind: Reverses bind; called as a side effect of unregistering
     * this driver.
     * @disconnect: optional driver disconnect method
     * @suspend: Notifies when the host stops sending USB traffic,
     * after function notifications
     * @resume: Notifies configuration when the host restarts USB traffic,
     * before function notifications
     *
     * Devices default to reporting self powered operation. Devices which rely
     * on bus powered operation should report this in their @bind() method.
     *
     * Before returning from bind, various fields in the template descriptor
     * may be overridden. These include the idVendor/idProduct/bcdDevice values
     * normally to bind the appropriate host side driver, and the three strings
     * (iManufacturer, iProduct, iSerialNumber) normally used to provide user
     * meaningful device identifiers. (The strings will not be defined unless
     * they are defined in @dev and @strings.) The correct ep0 maxpacket size
     * is also reported, as defined by the underlying controller driver.
     */
    struct usb_composite_driver {
        const char *name;
        const char *iProduct;
        const char *iManufacturer;
        const struct usb_device_descriptor *dev;
        struct usb_gadget_strings **strings;
        unsigned needs_serial:1;
        struct class *class;
        atomic_t function_count;
        int (*unbind)(struct usb_composite_dev *);
        void (*disconnect)(struct usb_composite_dev *);
        /* global suspend hooks */
        void (*suspend)(struct usb_composite_dev *);
        void (*resume)(struct usb_composite_dev *);
        void (*enable_function)(struct usb_function *f, int enable);
    };

b. device_desc 设备描述声明:

  1. static struct usb_device_descriptor device_desc = {  
  2.     .bLength = sizeof(device_desc),  
  3.     .bDescriptorType = USB_DT_DEVICE,  
  4.     .bcdUSB = __constant_cpu_to_le16(0x0200),  
  5.     .bDeviceClass = USB_CLASS_PER_INTERFACE,  
  6.     .idVendor = __constant_cpu_to_le16(VENDOR_ID),  
  7.     .idProduct = __constant_cpu_to_le16(PRODUCT_ID),  
  8.     .bcdDevice = __constant_cpu_to_le16(0xffff),  
  9.     .bNumConfigurations = 1,  
  10. };  
    static struct usb_device_descriptor device_desc = {
        .bLength = sizeof(device_desc),
        .bDescriptorType = USB_DT_DEVICE,
        .bcdUSB = __constant_cpu_to_le16(0x0200),
        .bDeviceClass = USB_CLASS_PER_INTERFACE,
        .idVendor = __constant_cpu_to_le16(VENDOR_ID),
        .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
        .bcdDevice = __constant_cpu_to_le16(0xffff),
        .bNumConfigurations = 1,
    };

c. dev_strings 设备的字符内容 声明:

  1. static struct usb_gadget_strings *dev_strings[] = {  //多个usb_gadget_string集合   
  2.     &stringtab_dev,    //具体一个usb_gadget_string   
  3.     NULL,  
  4. };  
  5.   
  6. static struct usb_gadget_strings stringtab_dev = {  
  7.     .language = 0x0409, /* en-us */  
  8.     .strings = strings_dev,  
  9. };  
  10.   
  11. /* String Table */  
  12. static struct usb_string strings_dev[] = {  
  13.     /* These dummy values should be overridden by platform data */  
  14.     [STRING_MANUFACTURER_IDX].s = "Android",  
  15.     [STRING_PRODUCT_IDX].s = "Android",  
  16.     [STRING_SERIAL_IDX].s = "0123456789ABCDEF",  
  17.     { } /* end of list */  
  18. };  
    static struct usb_gadget_strings *dev_strings[] = {  //多个usb_gadget_string集合
        &stringtab_dev,    //具体一个usb_gadget_string
        NULL,
    };

    static struct usb_gadget_strings stringtab_dev = {
        .language = 0x0409, /* en-us */
        .strings = strings_dev,
    };

    /* String Table */
    static struct usb_string strings_dev[] = {
        /* These dummy values should be overridden by platform data */
        [STRING_MANUFACTURER_IDX].s = "Android",
        [STRING_PRODUCT_IDX].s = "Android",
        [STRING_SERIAL_IDX].s = "0123456789ABCDEF",
        { } /* end of list */
    };

2. android_enable_function() :

  1. void android_enable_function(struct usb_function *f, int enable)  
  2. {  
  3.     struct android_dev *dev = _android_dev;   //获得全局变量 _android_dev   
  4.     int disable = !enable;  
  5.     int product_id;  
  6.     if (!!f->disabled != disable) {  
  7.         usb_function_set_enabled(f, !disable);    //使能usb function.   
  8. #ifdef CONFIG_USB_ANDROID_RNDIS   
  9.         if (!strcmp(f->name, "rndis")) {  
  10.             struct usb_function *func;  
  11.             /* Windows does not support other interfaces when RNDIS is enabled, 
  12.              * so we disable UMS and MTP when RNDIS is on. 
  13.              */  
  14.             list_for_each_entry(func, &android_config_driver.functions, list) {  
  15.                 if (!strcmp(func->name, "usb_mass_storage")  
  16.                     || !strcmp(func->name, "mtp")) {  
  17.                     usb_function_set_enabled(func, !enable);  
  18.                 }  
  19.             }  
  20.         }  
  21. #endif   
  22.         update_dev_desc(dev);  //更新设备描述   
  23.         product_id = get_product_id(dev);  
  24.         device_desc.idProduct = __constant_cpu_to_le16(product_id);  
  25.         if (dev->cdev)  
  26.             dev->cdev->desc.idProduct = device_desc.idProduct;  
  27.         usb_composite_force_reset(dev->cdev);    //reset   
  28.     }  
  29. }  
    void android_enable_function(struct usb_function *f, int enable)
    {
        struct android_dev *dev = _android_dev;   //获得全局变量 _android_dev
        int disable = !enable;
        int product_id;
        if (!!f->disabled != disable) {
            usb_function_set_enabled(f, !disable);    //使能usb function.
    #ifdef CONFIG_USB_ANDROID_RNDIS
            if (!strcmp(f->name, "rndis")) {
                struct usb_function *func;
                /* Windows does not support other interfaces when RNDIS is enabled,
                 * so we disable UMS and MTP when RNDIS is on.
                 */
                list_for_each_entry(func, &android_config_driver.functions, list) {
                    if (!strcmp(func->name, "usb_mass_storage")
                        || !strcmp(func->name, "mtp")) {
                        usb_function_set_enabled(func, !enable);
                    }
                }
            }
    #endif
            update_dev_desc(dev);  //更新设备描述
            product_id = get_product_id(dev);
            device_desc.idProduct = __constant_cpu_to_le16(product_id);
            if (dev->cdev)
                dev->cdev->desc.idProduct = device_desc.idProduct;
            usb_composite_force_reset(dev->cdev);    //reset
        }
    }

a. usb_function_set_enabled():

  1. void usb_function_set_enabled(struct usb_function *f, int enabled)  
  2. {  
  3.     f->disabled = !enabled;  
  4.     kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);  
  5. }  
    void usb_function_set_enabled(struct usb_function *f, int enabled)
    {
        f->disabled = !enabled;
        kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);
    }

b. update_dev_desc() : 更新设备描述符

  1. void update_dev_desc(struct android_dev *dev)  
  2. {  
  3.     struct usb_function *f;  
  4.     struct usb_function *last_enabled_f = NULL;  
  5.     int num_enabled = 0;  
  6.     int has_iad = 0;  
  7.           
  8.     dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;  
  9.     dev->cdev->desc.bDeviceSubClass = 0x00;  
  10.     dev->cdev->desc.bDeviceProtocol = 0x00;  
  11.     list_for_each_entry(f, &android_config_driver.functions, list) {  
  12.         if (!f->disabled) {  
  13.             num_enabled++;  
  14.             last_enabled_f = f;  
  15.             if (f->descriptors[0]->bDescriptorType ==  
  16.                     USB_DT_INTERFACE_ASSOCIATION)  
  17.                 has_iad = 1;  
  18.         }  
  19.         if (num_enabled > 1 && has_iad) {  
  20.             dev->cdev->desc.bDeviceClass = USB_CLASS_MISC;  
  21.             dev->cdev->desc.bDeviceSubClass = 0x02;  
  22.             dev->cdev->desc.bDeviceProtocol = 0x01;  
  23.             break;  
  24.         }  
  25.     }  
  26.     if (num_enabled == 1) {  
  27. #ifdef CONFIG_USB_ANDROID_RNDIS   
  28.         if (!strcmp(last_enabled_f->name, "rndis")) {  
  29. #ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS   
  30.             dev->cdev->desc.bDeviceClass =  
  31.                     USB_CLASS_WIRELESS_CONTROLLER;  
  32. #else   
  33.             dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;  
  34. #endif   
  35.         }  
  36. #endif   
  37.     }  
  38. }  
    void update_dev_desc(struct android_dev *dev)
    {
        struct usb_function *f;
        struct usb_function *last_enabled_f = NULL;
        int num_enabled = 0;
        int has_iad = 0;
            
        dev->cdev->desc.bDeviceClass = USB_CLASS_PER_INTERFACE;
        dev->cdev->desc.bDeviceSubClass = 0x00;
        dev->cdev->desc.bDeviceProtocol = 0x00;
        list_for_each_entry(f, &android_config_driver.functions, list) {
            if (!f->disabled) {
                num_enabled++;
                last_enabled_f = f;
                if (f->descriptors[0]->bDescriptorType ==
                        USB_DT_INTERFACE_ASSOCIATION)
                    has_iad = 1;
            }
            if (num_enabled > 1 && has_iad) {
                dev->cdev->desc.bDeviceClass = USB_CLASS_MISC;
                dev->cdev->desc.bDeviceSubClass = 0x02;
                dev->cdev->desc.bDeviceProtocol = 0x01;
                break;
            }
        }
        if (num_enabled == 1) {
    #ifdef CONFIG_USB_ANDROID_RNDIS
            if (!strcmp(last_enabled_f->name, "rndis")) {
    #ifdef CONFIG_USB_ANDROID_RNDIS_WCEIS
                dev->cdev->desc.bDeviceClass =
                        USB_CLASS_WIRELESS_CONTROLLER;
    #else
                dev->cdev->desc.bDeviceClass = USB_CLASS_COMM;
    #endif
            }
    #endif
        }
    }

c. usb_composite_force_reset():  重置usb gadget.

  1. void usb_composite_force_reset(struct usb_composite_dev *cdev)  
  2. {  
  3.     unsigned long flags;  
  4.     spin_lock_irqsave(&cdev->lock, flags);  
  5.     /* force reenumeration */  
  6.     if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {  
  7.         spin_unlock_irqrestore(&cdev->lock, flags);  
  8.         usb_gadget_disconnect(cdev->gadget);  
  9.         msleep(10);  
  10.         usb_gadget_connect(cdev->gadget);  
  11.     } else {  
  12.         spin_unlock_irqrestore(&cdev->lock, flags);  
  13.     }  
  14. }  
    void usb_composite_force_reset(struct usb_composite_dev *cdev)
    {
        unsigned long flags;
        spin_lock_irqsave(&cdev->lock, flags);
        /* force reenumeration */
        if (cdev && cdev->gadget && cdev->gadget->speed != USB_SPEED_UNKNOWN) {
            spin_unlock_irqrestore(&cdev->lock, flags);
            usb_gadget_disconnect(cdev->gadget);
            msleep(10);
            usb_gadget_connect(cdev->gadget);
        } else {
            spin_unlock_irqrestore(&cdev->lock, flags);
        }
    }

3. android_bind():

  1. static int android_bind(struct usb_composite_dev *cdev)  
  2. {  
  3.     struct android_dev *dev = _android_dev;  
  4.     struct usb_gadget *gadget = cdev->gadget;  
  5.     int gcnum, id, product_id, ret;  
  6.     printk(KERN_INFO "android_bind\n");  
  7.     /* Allocate string descriptor numbers ... note that string 
  8.      * contents can be overridden by the composite_dev glue. 
  9.      */  
  10.     id = usb_string_id(cdev); //allocate an unused string ID   
  11.     if (id < 0)  
  12.         return id;  
  13.     strings_dev[STRING_MANUFACTURER_IDX].id = id;  
  14.     device_desc.iManufacturer = id;  
  15.     id = usb_string_id(cdev);  
  16.     if (id < 0)  
  17.         return id;  
  18.     strings_dev[STRING_PRODUCT_IDX].id = id;  
  19.     device_desc.iProduct = id;  
  20.     id = usb_string_id(cdev);  
  21.     if (id < 0)  
  22.         return id;  
  23.     strings_dev[STRING_SERIAL_IDX].id = id;  
  24.     device_desc.iSerialNumber = id;  
  25.     /* register our configuration */  
  26.     ret = usb_add_config(cdev, &android_config_driver, android_bind_config); //add a configuration to a device.   
  27.     if (ret) {  
  28.         printk(KERN_ERR "usb_add_config failed\n");  
  29.         return ret;  
  30.     }  
  31.     gcnum = usb_gadget_controller_number(gadget); //support bcdDevice id convention.   
  32.     if (gcnum >= 0)  
  33.         device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);  
  34.     else {  
  35.         /* gadget zero is so simple (for now, no altsettings) that 
  36.          * it SHOULD NOT have problems with bulk-capable hardware. 
  37.          * so just warn about unrcognized controllers -- don't panic. 
  38.          * 
  39.          * things like configuration and altsetting numbering 
  40.          * can need hardware-specific attention though. 
  41.          */  
  42.         pr_warning("%s: controller '%s' not recognized\n",  
  43.             longname, gadget->name);  
  44.         device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);  
  45.     }  
  46.     usb_gadget_set_selfpowered(gadget);   
  47.     dev->cdev = cdev;  
  48.     product_id = get_product_id(dev);  
  49.     device_desc.idProduct = __constant_cpu_to_le16(product_id);  
  50.     cdev->desc.idProduct = device_desc.idProduct;  
  51.     return 0;  
  52. }  
    static int android_bind(struct usb_composite_dev *cdev)
    {
        struct android_dev *dev = _android_dev;
        struct usb_gadget *gadget = cdev->gadget;
        int gcnum, id, product_id, ret;
        printk(KERN_INFO "android_bind\n");
        /* Allocate string descriptor numbers ... note that string
         * contents can be overridden by the composite_dev glue.
         */
        id = usb_string_id(cdev); //allocate an unused string ID
        if (id < 0)
            return id;
        strings_dev[STRING_MANUFACTURER_IDX].id = id;
        device_desc.iManufacturer = id;
        id = usb_string_id(cdev);
        if (id < 0)
            return id;
        strings_dev[STRING_PRODUCT_IDX].id = id;
        device_desc.iProduct = id;
        id = usb_string_id(cdev);
        if (id < 0)
            return id;
        strings_dev[STRING_SERIAL_IDX].id = id;
        device_desc.iSerialNumber = id;
        /* register our configuration */
        ret = usb_add_config(cdev, &android_config_driver, android_bind_config); //add a configuration to a device.
        if (ret) {
            printk(KERN_ERR "usb_add_config failed\n");
            return ret;
        }
        gcnum = usb_gadget_controller_number(gadget); //support bcdDevice id convention.
        if (gcnum >= 0)
            device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
        else {
            /* gadget zero is so simple (for now, no altsettings) that
             * it SHOULD NOT have problems with bulk-capable hardware.
             * so just warn about unrcognized controllers -- don't panic.
             *
             * things like configuration and altsetting numbering
             * can need hardware-specific attention though.
             */
            pr_warning("%s: controller '%s' not recognized\n",
                longname, gadget->name);
            device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
        }
        usb_gadget_set_selfpowered(gadget); 
        dev->cdev = cdev;
        product_id = get_product_id(dev);
        device_desc.idProduct = __constant_cpu_to_le16(product_id);
        cdev->desc.idProduct = device_desc.idProduct;
        return 0;
    }

a. usb_string_id() :

  1. /** 
  2.  * usb_string_id() - allocate an unused string ID 
  3.  * @cdev: the device whose string descriptor IDs are being allocated 
  4.  * Context: single threaded during gadget setup 
  5.  * 
  6.  * @usb_string_id() is called from bind() callbacks to allocate 
  7.  * string IDs. Drivers for functions, configurations, or gadgets will 
  8.  * then store that ID in the appropriate descriptors and string table. 
  9.  * 
  10.  * All string identifier should be allocated using this, 
  11.  * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure 
  12.  * that for example different functions don't wrongly assign different 
  13.  * meanings to the same identifier. 
  14.  */  
  15. int usb_string_id(struct usb_composite_dev *cdev)  
  16. {  
  17.     if (cdev->next_string_id < 254) {  
  18.         /* string id 0 is reserved by USB spec for list of 
  19.          * supported languages */  
  20.         /* 255 reserved as well? -- mina86 */  
  21.         cdev->next_string_id++;  
  22.         return cdev->next_string_id;  
  23.     }  
  24.     return -ENODEV;  
  25. }  
    /**
     * usb_string_id() - allocate an unused string ID
     * @cdev: the device whose string descriptor IDs are being allocated
     * Context: single threaded during gadget setup
     *
     * @usb_string_id() is called from bind() callbacks to allocate
     * string IDs. Drivers for functions, configurations, or gadgets will
     * then store that ID in the appropriate descriptors and string table.
     *
     * All string identifier should be allocated using this,
     * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure
     * that for example different functions don't wrongly assign different
     * meanings to the same identifier.
     */
    int usb_string_id(struct usb_composite_dev *cdev)
    {
        if (cdev->next_string_id < 254) {
            /* string id 0 is reserved by USB spec for list of
             * supported languages */
            /* 255 reserved as well? -- mina86 */
            cdev->next_string_id++;
            return cdev->next_string_id;
        }
        return -ENODEV;
    }

b. usb_add_config()

  1. /** 
  2.  * usb_add_config() - add a configuration to a device. 
  3.  * @cdev: wraps the USB gadget 
  4.  * @config: the configuration, with bConfigurationValue assigned 
  5.  * @bind: the configuration's bind function 
  6.  * Context: single threaded during gadget setup 
  7.  * 
  8.  * One of the main tasks of a composite @bind() routine is to 
  9.  * add each of the configurations it supports, using this routine. 
  10.  * 
  11.  * This function returns the value of the configuration's @bind(), which 
  12.  * is zero for success else a negative errno value. Binding configurations 
  13.  * assigns global resources including string IDs, and per-configuration 
  14.  * resources such as interface IDs and endpoints. 
  15.  */  
  16. int usb_add_config(struct usb_composite_dev *cdev,  
  17.         struct usb_configuration *config,  
  18.         int (*bind)(struct usb_configuration *))  
  19. {  
  20.     int status = -EINVAL;  
  21.     struct usb_configuration *c;  
  22.     DBG(cdev, "adding config #%u '%s'/%p\n",  
  23.             config->bConfigurationValue,  
  24.             config->label, config);  
  25.       
  26.     if (!config->bConfigurationValue || !bind)  
  27.         goto done;  
  28.       
  29.     /* Prevent duplicate configuration identifiers */  
  30.     list_for_each_entry(c, &cdev->configs, list) {  
  31.         if (c->bConfigurationValue == config->bConfigurationValue) {  
  32.             status = -EBUSY;  
  33.             goto done;  
  34.         }  
  35.     }  
  36.       
  37.     config->cdev = cdev;  
  38.     list_add_tail(&config->list, &cdev->configs);  
  39.     INIT_LIST_HEAD(&config->functions);  
  40.     config->next_interface_id = 0;  
  41.     status = bind(config);  
  42.     if (status < 0) {  
  43.         list_del(&config->list);  
  44.         config->cdev = NULL;  
  45.     } else {  
  46.         unsigned i;  
  47.         DBG(cdev, "cfg %d/%p speeds:%s%s\n",  
  48.             config->bConfigurationValue, config,  
  49.             config->highspeed ? " high" : "",  
  50.             config->fullspeed  
  51.                 ? (gadget_is_dualspeed(cdev->gadget)  
  52.                     ? " full"  
  53.                     : " full/low")  
  54.                 : "");  
  55.         for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {  
  56.             struct usb_function *f = config->interface[i];  
  57.             if (!f)  
  58.                 continue;  
  59.             DBG(cdev, " interface %d = %s/%p\n",  
  60.                 i, f->name, f);  
  61.         }  
  62.     }  
  63.     /* set_alt(), or next bind(), sets up 
  64.      * ep->driver_data as needed. 
  65.      */  
  66.     usb_ep_autoconfig_reset(cdev->gadget);  
  67. done:  
  68.     if (status)  
  69.         DBG(cdev, "added config '%s'/%u --> %d\n", config->label,  
  70.                 config->bConfigurationValue, status);  
  71.     return status;  
  72. }  
    /**
     * usb_add_config() - add a configuration to a device.
     * @cdev: wraps the USB gadget
     * @config: the configuration, with bConfigurationValue assigned
     * @bind: the configuration's bind function
     * Context: single threaded during gadget setup
     *
     * One of the main tasks of a composite @bind() routine is to
     * add each of the configurations it supports, using this routine.
     *
     * This function returns the value of the configuration's @bind(), which
     * is zero for success else a negative errno value. Binding configurations
     * assigns global resources including string IDs, and per-configuration
     * resources such as interface IDs and endpoints.
     */
    int usb_add_config(struct usb_composite_dev *cdev,
            struct usb_configuration *config,
            int (*bind)(struct usb_configuration *))
    {
        int status = -EINVAL;
        struct usb_configuration *c;
        DBG(cdev, "adding config #%u '%s'/%p\n",
                config->bConfigurationValue,
                config->label, config);
        
        if (!config->bConfigurationValue || !bind)
            goto done;
        
        /* Prevent duplicate configuration identifiers */
        list_for_each_entry(c, &cdev->configs, list) {
            if (c->bConfigurationValue == config->bConfigurationValue) {
                status = -EBUSY;
                goto done;
            }
        }
        
        config->cdev = cdev;
        list_add_tail(&config->list, &cdev->configs);
        INIT_LIST_HEAD(&config->functions);
        config->next_interface_id = 0;
        status = bind(config);
        if (status < 0) {
            list_del(&config->list);
            config->cdev = NULL;
        } else {
            unsigned i;
            DBG(cdev, "cfg %d/%p speeds:%s%s\n",
                config->bConfigurationValue, config,
                config->highspeed ? " high" : "",
                config->fullspeed
                    ? (gadget_is_dualspeed(cdev->gadget)
                        ? " full"
                        : " full/low")
                    : "");
            for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
                struct usb_function *f = config->interface[i];
                if (!f)
                    continue;
                DBG(cdev, " interface %d = %s/%p\n",
                    i, f->name, f);
            }
        }
        /* set_alt(), or next bind(), sets up
         * ep->driver_data as needed.
         */
        usb_ep_autoconfig_reset(cdev->gadget);
    done:
        if (status)
            DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
                    config->bConfigurationValue, status);
        return status;
    }

c. usb_gadget_controller_number() : support bcdDevice id convention.

  1. /** 
  2.  * usb_gadget_controller_number - support bcdDevice id convention 
  3.  * @gadget: the controller being driven 
  4.  * 
  5.  * Return a 2-digit BCD value associated with the peripheral controller, 
  6.  * suitable for use as part of a bcdDevice value, or a negative error code. 
  7.  * 
  8.  * NOTE: this convention is purely optional, and has no meaning in terms of 
  9.  * any USB specification. If you want to use a different convention in your 
  10.  * gadget driver firmware -- maybe a more formal revision ID -- feel free. 
  11.  * 
  12.  * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) 
  13.  * to change their behavior accordingly. For example it might help avoiding 
  14.  * some chip bug. 
  15.  */  
  16. static inline int usb_gadget_controller_number(struct usb_gadget *gadget)  
  17. {  
  18.     if (gadget_is_net2280(gadget))  
  19.         return 0x01;  
  20.     else if (gadget_is_dummy(gadget))  
  21.         return 0x02;  
  22.     else if (gadget_is_pxa(gadget))  
  23.         return 0x03;  
  24.     else if (gadget_is_goku(gadget))  
  25.         return 0x06;  
  26.     else if (gadget_is_omap(gadget))  
  27.         return 0x08;  
  28.     else if (gadget_is_lh7a40x(gadget))  
  29.         return 0x09;  
  30.     else if (gadget_is_pxa27x(gadget))  
  31.         return 0x11;  
  32.     else if (gadget_is_s3c2410(gadget))  
  33.         return 0x12;  
  34.     else if (gadget_is_at91(gadget))  
  35.         return 0x13;  
  36.     else if (gadget_is_imx(gadget))  
  37.         return 0x14;  
  38.     else if (gadget_is_musbhdrc(gadget))  
  39.         return 0x16;  
  40.     else if (gadget_is_atmel_usba(gadget))  
  41.         return 0x18;  
  42.     else if (gadget_is_fsl_usb2(gadget))  
  43.         return 0x19;  
  44.     else if (gadget_is_amd5536udc(gadget))  
  45.         return 0x20;  
  46.     else if (gadget_is_m66592(gadget))  
  47.         return 0x21;  
  48.     else if (gadget_is_fsl_qe(gadget))  
  49.         return 0x22;  
  50.     else if (gadget_is_ci13xxx(gadget))  
  51.         return 0x23;  
  52.     else if (gadget_is_langwell(gadget))  
  53.         return 0x24;  
  54.     else if (gadget_is_r8a66597(gadget))  
  55.         return 0x25;  
  56.     else if (gadget_is_s3c_hsotg(gadget))  
  57.         return 0x26;  
  58.     return -ENOENT;  
  59. }  
    /**
     * usb_gadget_controller_number - support bcdDevice id convention
     * @gadget: the controller being driven
     *
     * Return a 2-digit BCD value associated with the peripheral controller,
     * suitable for use as part of a bcdDevice value, or a negative error code.
     *
     * NOTE: this convention is purely optional, and has no meaning in terms of
     * any USB specification. If you want to use a different convention in your
     * gadget driver firmware -- maybe a more formal revision ID -- feel free.
     *
     * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!)
     * to change their behavior accordingly. For example it might help avoiding
     * some chip bug.
     */
    static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
    {
        if (gadget_is_net2280(gadget))
            return 0x01;
        else if (gadget_is_dummy(gadget))
            return 0x02;
        else if (gadget_is_pxa(gadget))
            return 0x03;
        else if (gadget_is_goku(gadget))
            return 0x06;
        else if (gadget_is_omap(gadget))
            return 0x08;
        else if (gadget_is_lh7a40x(gadget))
            return 0x09;
        else if (gadget_is_pxa27x(gadget))
            return 0x11;
        else if (gadget_is_s3c2410(gadget))
            return 0x12;
        else if (gadget_is_at91(gadget))
            return 0x13;
        else if (gadget_is_imx(gadget))
            return 0x14;
        else if (gadget_is_musbhdrc(gadget))
            return 0x16;
        else if (gadget_is_atmel_usba(gadget))
            return 0x18;
        else if (gadget_is_fsl_usb2(gadget))
            return 0x19;
        else if (gadget_is_amd5536udc(gadget))
            return 0x20;
        else if (gadget_is_m66592(gadget))
            return 0x21;
        else if (gadget_is_fsl_qe(gadget))
            return 0x22;
        else if (gadget_is_ci13xxx(gadget))
            return 0x23;
        else if (gadget_is_langwell(gadget))
            return 0x24;
        else if (gadget_is_r8a66597(gadget))
            return 0x25;
        else if (gadget_is_s3c_hsotg(gadget))
            return 0x26;
        return -ENOENT;
    }

d. usb_gadget_set_selfpowered()

  1. /** 
  2.  * usb_gadget_set_selfpowered - sets the device selfpowered feature. 
  3.  * @gadget:the device being declared as self-powered 
  4.  * 
  5.  * this affects the device status reported by the hardware driver 
  6.  * to reflect that it now has a local power supply. 
  7.  * 
  8.  * returns zero on success, else negative errno. 
  9.  */  
  10. static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)  
  11. {  
  12.     if (!gadget->ops->set_selfpowered)  
  13.         return -EOPNOTSUPP;  
  14.     return gadget->ops->set_selfpowered(gadget, 1);  
  15. }  
    /**
     * usb_gadget_set_selfpowered - sets the device selfpowered feature.
     * @gadget:the device being declared as self-powered
     *
     * this affects the device status reported by the hardware driver
     * to reflect that it now has a local power supply.
     *
     * returns zero on success, else negative errno.
     */
    static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
    {
        if (!gadget->ops->set_selfpowered)
            return -EOPNOTSUPP;
        return gadget->ops->set_selfpowered(gadget, 1);
    }

4. android_config_driver

  1. static struct usb_configuration android_config_driver = {  
  2.     .label = "android",  
  3.     .setup = android_setup_config,  
  4.     .bConfigurationValue = 1,  
  5.     .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,  
  6.     .bMaxPower = 0xFA, /* 500ma */  
  7. };  
    static struct usb_configuration android_config_driver = {
        .label = "android",
        .setup = android_setup_config,
        .bConfigurationValue = 1,
        .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
        .bMaxPower = 0xFA, /* 500ma */
    };

android_setup_config()

  1. static int android_setup_config(struct usb_configuration *c,  
  2.         const struct usb_ctrlrequest *ctrl)  
  3. {  
  4.     int i;  
  5.     int ret = -EOPNOTSUPP;  
  6.     for (i = 0; i < android_config_driver.next_interface_id; i++) {  
  7.         if (android_config_driver.interface[i]->setup) {  
  8.             ret = android_config_driver.interface[i]->setup(  
  9.                 android_config_driver.interface[i], ctrl);  
  10.             if (ret >= 0)  
  11.                 return ret;  
  12.         }  
  13.     }  
  14.     return ret;  
  15. }  
    static int android_setup_config(struct usb_configuration *c,
            const struct usb_ctrlrequest *ctrl)
    {
        int i;
        int ret = -EOPNOTSUPP;
        for (i = 0; i < android_config_driver.next_interface_id; i++) {
            if (android_config_driver.interface[i]->setup) {
                ret = android_config_driver.interface[i]->setup(
                    android_config_driver.interface[i], ctrl);
                if (ret >= 0)
                    return ret;
            }
        }
        return ret;
    }

5. android_bind_config()

  1. static int android_bind_config(struct usb_configuration *c)  
  2. {  
  3.     struct android_dev *dev = _android_dev;  
  4.     printk(KERN_DEBUG "android_bind_config\n");  
  5.     dev->config = c;  
  6.     if (should_bind_functions(dev))  
  7.         bind_functions(dev);  
  8.     return 0;  
  9. }  
    static int android_bind_config(struct usb_configuration *c)
    {
        struct android_dev *dev = _android_dev;
        printk(KERN_DEBUG "android_bind_config\n");
        dev->config = c;
        if (should_bind_functions(dev))
            bind_functions(dev);
        return 0;
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值