android usb 分析1

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

    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 定义:

    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 是一个本地定义的全局变量:
    static struct android_dev *_android_dev;
默认的 product_id 和 vendor_id 定义:
    /* Default vendor and product IDs, overridden by platform data */
    #define VENDOR_ID 0x18D1
    #define PRODUCT_ID 0x0001
struct android_platform_driver  定义:
    static struct platform_driver android_platform_driver = {
        .driver = { .name = "android_usb", },
        .probe = android_probe,
    };
2. android_probe()
    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中:
    #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 中。
    /**
     * 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模块里去讨论了。
    /*
     * Register the gadget driver. Used by gadget drivers when
     * registering themselves with the controller.
     *
     * -EINVAL something went wrong (not driver)
     * -EBUSY another gadget is already using the controller
     * -ENOMEM no memory to perform the operation
     *
     * @param driver the gadget driver
     * @param bind the driver's bind function
     * @return <0 if error, 0 if everything is fine
     */
    int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
            int (*bind)(struct usb_gadget *))
    {
        int retval;
        unsigned long flags;
        struct musb *musb = the_gadget;
    D_ENTER
        printk(KERN_INFO "xxha: --- enter musb");
        if (!driver
                || driver->speed != USB_SPEED_HIGH
                || !bind || !driver->setup)
            return -EINVAL;
        /* driver must be initialized to support peripheral mode */
        if (!musb) {
            DBG(1, "%s, no dev??\n", __func__);
            return -ENODEV;
        }
        DBG(3, "registering driver %s\n", driver->function);
        spin_lock_irqsave(&musb->lock, flags);
        if (musb->gadget_driver) {
            DBG(1, "%s is already bound to %s\n",
                    musb_driver_name,
                    musb->gadget_driver->driver.name);
            retval = -EBUSY;
        } else {
            musb->gadget_driver = driver;
            musb->g.dev.driver = &driver->driver;
            driver->driver.bus = NULL;
            musb->softconnect = 1;
            retval = 0;
        }
        spin_unlock_irqrestore(&musb->lock, flags);
        if (retval == 0) {
            retval = bind(&musb->g);
            if (retval != 0) {
                DBG(3, "bind to driver %s failed --> %d\n",
                        driver->driver.name, retval);
                musb->gadget_driver = NULL;
                musb->g.dev.driver = NULL;
            }
            spin_lock_irqsave(&musb->lock, flags);
            otg_set_peripheral(musb->xceiv, &musb->g);
            musb->xceiv->state = OTG_STATE_B_IDLE;
            musb->is_active = 1;
            /* FIXME this ignores the softconnect flag. Drivers are
             * allowed hold the peripheral inactive until for example
             * userspace hooks up printer hardware or DSP codecs, so
             * hosts only see fully functional devices.
             */
            if (!is_otg_enabled(musb))
                musb_start(musb);
            otg_set_peripheral(musb->xceiv, &musb->g);
            spin_unlock_irqrestore(&musb->lock, flags);
            if (is_otg_enabled(musb)) {
                struct usb_hcd *hcd = musb_to_hcd(musb);
                DBG(3, "OTG startup...\n");
                /* REVISIT: funcall to other code, which also
                 * handles power budgeting ... this way also
                 * ensures HdrcStart is indirectly called.
                 */
                retval = usb_add_hcd(musb_to_hcd(musb), -1, 0);
                if (retval < 0) {
                    DBG(1, "add_hcd failed, %d\n", retval);
                    spin_lock_irqsave(&musb->lock, flags);
                    otg_set_peripheral(musb->xceiv, NULL);
                    musb->gadget_driver = NULL;
                    musb->g.dev.driver = NULL;
                    spin_unlock_irqrestore(&musb->lock, flags);
                } else {
                    hcd->self.uses_pio_for_control = 1;
                }
            }
        }
        return retval;
    }
    EXPORT_SYMBOL(usb_gadget_probe_driver);


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值