当前位置: 代码迷 >> 综合 >> 分析android的usb-gadget
  详细解决方案

分析android的usb-gadget

热度:92   发布时间:2023-12-06 18:36:40.0

分析androidgadget:

gadget部分的UDC和API基本上弄懂了,现在开始研究android上的USB-gadget实现,开始读代码

1:首先从init开始。

static int __init init(void)

{

        struct android_dev *dev;

 

        printk(KERN_INFO "android init\n");

 

        dev = kzalloc(sizeof(*dev), GFP_KERNEL);

        if (!dev)

                return -ENOMEM;

 

        /* set default values, which should be overridden by platform data */

        dev->product_id = PRODUCT_ID;

        _android_dev = dev;

 

        return platform_driver_register(&android_platform_driver);

}

它申请了一个dev空间,然后返回platform_driver_register(&android_platform_driver)

platform_driver_registerdrivers/base/platform.c中定义,如下:

int platform_driver_register(struct platform_driver *drv)

{

        drv->driver.bus = &platform_bus_type;

        if (drv->probe)

                drv->driver.probe = platform_drv_probe;

        if (drv->remove)

                drv->driver.remove = platform_drv_remove;

        if (drv->shutdown)

                drv->driver.shutdown = platform_drv_shutdown;

 

        return driver_register(&drv->driver);

}其含义是注册平台上某个控制器驱动。

android_platform_driver的定义在android.c,如下:

static struct platform_driver android_platform_driver = {

        .driver = { .name = "android_usb", },

        .probe = android_probe,

};

它只是定义了驱动的名字和探测程序。

 

2:接下来看android_probe,(android.c

static int __init android_probe(struct platform_device *pdev)

{

        struct android_usb_platform_data *pdata = pdev->dev.platform_data;

        struct android_dev *dev = _android_dev;

 

        printk(KERN_INFO "android_probe pdata: %p\n", pdata);

 

        if (pdata) {

                dev->products = pdata->products;

                dev->num_products = pdata->num_products;

                dev->functions = pdata->functions;

                dev->num_functions = pdata->num_functions;

                if (pdata->vendor_id)

                        device_desc.idVendor =

                                __constant_cpu_to_le16(pdata->vendor_id);

                if (pdata->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_register(&android_usb_driver);

}

这个函数初始化了android_dev *dev,并在最后调用了usb_composite_register

include/linux/platform_device.h中,有platform_device的定义:

struct platform_device {

        const char      * name;

        int             id;

        struct device   dev;

        u32             num_resources;

        struct resource * resource;

 

        struct platform_device_id       *id_entry;

 

        /* arch specific additions */

        struct pdev_archdata    archdata;

};

在探测程序中,大部分工作都是初始化一些数据,或者是数据转换吧,但是最后调用了return usb_composite_register(&android_usb_driver);,即将android_usb_driver注册了。

android.c文件中,android_usb_driver的定义如下:

static struct usb_composite_driver android_usb_driver = {

        .name           = "android_usb",

        .dev            = &device_desc,

        .strings        = dev_strings,

        .bind           = android_bind,

        .enable_function = android_enable_function,

};

 

3usb_composite_register函数定义在drivers/usb/gadget/composite.c中:

int __init usb_composite_register(struct usb_composite_driver *driver)

{

        if (!driver || !driver->dev || !driver->bind || composite)

                return -EINVAL;

 

        if (!driver->name)

                driver->name = "composite";

        composite_driver.function =  (char *) driver->name;

        composite_driver.driver.name = driver->name;

        composite = driver;

 

        driver->class = class_create(THIS_MODULE, "usb_composite");

        if (IS_ERR(driver->class))

                return PTR_ERR(driver->class);

        driver->class->dev_uevent = composite_uevent;

 

        return usb_gadget_register_driver(&composite_driver);

}

这个函数也很简单,就是使用usb_gadget_register_driver注册而已,至此,就算到了UDC层了。

4:我们再回头看看android_usb_driver。重点看下面三行代码。

        .dev            = &device_desc,

        .bind           = android_bind,

        .enable_function = android_enable_function

先看device_desc,在android.c中:

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,

};

没什么可说的,都是比较底层的描述性定义。

再看android_bind,在android.c中定义,比较长,重要的如下:

static int __init android_bind(struct usb_composite_dev *cdev)

{

        struct android_dev *dev = _android_dev;

        struct usb_gadget       *gadget = cdev->gadget;

        if (gadget->ops->wakeup)

                android_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;

 

        /* register our configuration */

        ret = usb_add_config(cdev, &android_config_driver);

        if (ret) {

                printk(KERN_ERR "usb_add_config failed\n");

                return ret;

        }

        usb_gadget_set_selfpowered(gadget);

        dev->cdev = cdev;

 

。。。。

}

函数bind负责完成Gadget驱动和下层设备控

制器的关联,并开启设备的功能

 

最后看看android_enable_function,在android.c中定义,

if (!strcmp(f->name, "rndis")) {

                        struct usb_function             *func;

 

                        /* We need to specify the COMM class in the device descriptor

                         * if we are using RNDIS.

                         */

                        if (enable)

                        list_for_each_entry(func, &android_config_driver.functions, list) {

                                if (!strcmp(func->name, "usb_mass_storage")) {

                                        usb_function_set_enabled(func, !enable);

                                        break;

                                }

                        }

                usb_composite_force_reset(dev->cdev);

将列表中的所有功能全部开启,除了usb_mass_storage

composite.c中定义了usb_function_set_enabled函数。

void usb_function_set_enabled(struct usb_function *f, int enabled)

{

        f->disabled = !enabled;

        kobject_uevent(&f->dev->kobj, KOBJ_CHANGE);

}

 

这里涉及两个概念,一个是usb_function,一个是android_config_driverusb_configuration

static struct usb_configuration android_config_driver = {

        .label          = "android",

        .bind           = android_bind_config,

        .setup          = android_setup_config,

        .bConfigurationValue = 1,

        .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,

        .bMaxPower      = 0xFA, /* 500ma */

};

 

先看看usb_configuration,在include/linux/usb/composite.h中,

struct usb_configuration {

        const char                      *label;

        struct usb_gadget_strings       **strings;

        const struct usb_descriptor_header **descriptors;

 

        /* REVISIT:  bind() functions can be marked __init, which

         * makes trouble for section mismatch analysis.  See if

         * we can't restructure things to avoid mismatching...

         */

 

        /* configuration management:  bind/unbind */

        int                     (*bind)(struct usb_configuration *);

        void                    (*unbind)(struct usb_configuration *);

        int                     (*setup)(struct usb_configuration *,

                                        const struct usb_ctrlrequest *);

 

        /* fields in the config descriptor */

        u8                      bConfigurationValue;

        u8                      iConfiguration;

        u8                      bmAttributes;

        u8                      bMaxPower;

 

        struct usb_composite_dev        *cdev;

 

        /* private: */

        /* internals */

        struct list_head        list;

        struct list_head        functions;

        u8                      next_interface_id;

        unsigned                highspeed:1;

        unsigned                fullspeed:1;

        struct usb_function     *interface[MAX_CONFIG_INTERFACES];

};

 

再看看usb_function,在include/linux/usb/composite.h

struct usb_function {

        const char                      *name;

        struct usb_gadget_strings       **strings;

        struct usb_descriptor_header    **descriptors;

        struct usb_descriptor_header    **hs_descriptors;

 

        struct usb_configuration        *config;

 

        /* disabled is zero if the function is enabled */

        int                             disabled;

 

        /* REVISIT:  bind() functions can be marked __init, which

         * makes trouble for section mismatch analysis.  See if

         * we can't restructure things to avoid mismatching.

         * Related:  unbind() may kfree() but bind() won't...

         */

 

        /* configuration management:  bind/unbind */

        int                     (*bind)(struct usb_configuration *,

                                        struct usb_function *);

        void                    (*unbind)(struct usb_configuration *,

                                        struct usb_function *);

 

        /* runtime state management */

        int                     (*set_alt)(struct usb_function *,

                                        unsigned interface, unsigned alt);

        int                     (*get_alt)(struct usb_function *,

                                        unsigned interface);

        void                    (*disable)(struct usb_function *);

        int                     (*setup)(struct usb_function *,

                                        const struct usb_ctrlrequest *);

        void                    (*suspend)(struct usb_function *);

        void                    (*resume)(struct usb_function *);

 

        /* private: */

        /* internals */

        struct list_head                list;

        struct device                   *dev;

};

我没看出个所以然来,只知道这里有复杂的链表关系,不明白,于是回头看看,在android_config_driver中,注意这两个函数:

        .bind           = android_bind_config,

        .setup          = android_setup_config,

他们都在android.c文件中。

static int __init android_bind_config(struct usb_configuration *c)

{

        struct android_dev *dev = _android_dev;

 

        printk(KERN_DEBUG "android_bind_config\n");

        dev->config = c;

 

        /* bind our functions if they have all registered */

        if (_registered_function_count == dev->num_functions)

                bind_functions(dev);

 

        return 0;

}

 

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;

}

 

看下bind_functions

static void bind_functions(struct android_dev *dev)

{

        struct android_usb_function     *f;

        char **functions = dev->functions;

        int i;

 

        for (i = 0; i < dev->num_functions; i++) {

                char *name = *functions++;

                f = get_function(name);

                if (f)

                        f->bind_config(dev->config);

                else

                        printk(KERN_ERR "function %s not found in bind_functions\n", name);

        }

}

 

再看get_function

static struct android_usb_function *get_function(const char *name)

{

        struct android_usb_function     *f;

        list_for_each_entry(f, &_functions, list) {

                if (!strcmp(name, f->name))

                        return f;

        }

        return 0;

}

 

 

到此为止,没有什么思路了,我察看了下android.c,大部分函数都用到了,唯有android_usb_set_connected没有使用 ,经搜索,在arch/arm/mach-omap2/board-sholes.c中使用了这个函数。

 

 

static int cpcap_usb_connected_probe(struct platform_device *pdev)

{

        /* Wake up MUSB from lowpower state */

        musb_disable_idle(1);

        android_usb_set_connected(1);

        return 0;

}

 

static int cpcap_usb_connected_remove(struct platform_device *pdev)

{

        /* Enable low power state for MUSB */

        musb_disable_idle(0);

        android_usb_set_connected(0);

        return 0;

}

 

 

 

终于知道function是哪来的了。

注意android_register_function,它在arch/arm/mach-omap2/board-sholes-usbnet.cdrivers/usb/gadget/f_acm.cdrivers/usb/gadget/f_adb.c:drivers/usb/gadget/f_rndis.cdrivers/usb/gadget/f_mass_storage.c,中调用过,也就是说,总共就有这么几个function.简单查看了一下f_adb.c,看到了关于gadget的内容,哦也!!!终于弄通了!!!!!!!!!

 

 

 

 

(上面那句话是最后写的,下面的内容为设备与驱动的关联部分)

 

昨天基本上没有什么线索了,不知道android.c是怎么与gadget联系上的,不知道那些function是怎样关联,定义的。今天早上重新看,注意了一下最开始的platform_driver_register(&android_platform_driver);

int platform_driver_register(struct platform_driver *drv)

{

        drv->driver.bus = &platform_bus_type;

        if (drv->probe)

                drv->driver.probe = platform_drv_probe;

        if (drv->remove)

                drv->driver.remove = platform_drv_remove;

        if (drv->shutdown)

                drv->driver.shutdown = platform_drv_shutdown;

 

        return driver_register(&drv->driver);

}其含义是注册平台上某个控制器驱动。

platform_driver定义在include/linux/platform_device.h里:

struct platform_driver {

        int (*probe)(struct platform_device *);

        int (*remove)(struct platform_device *);

        void (*shutdown)(struct platform_device *);

        int (*suspend)(struct platform_device *, pm_message_t state);

        int (*resume)(struct platform_device *);

        struct device_driver driver;

        struct platform_device_id *id_table;

};

device_driver定义在include/linux/device.h

struct device_driver {

        const char              *name;

        struct bus_type         *bus;

 

        struct module           *owner;

        const char              *mod_name;      /* used for built-in modules */

 

        bool suppress_bind_attrs;       /* disables bind/unbind via sysfs */

 

        int (*probe) (struct device *dev);

        int (*remove) (struct device *dev);

        void (*shutdown) (struct device *dev);

        int (*suspend) (struct device *dev, pm_message_t state);

        int (*resume) (struct device *dev);

        const struct attribute_group **groups;

 

        const struct dev_pm_ops *pm;

 

        struct driver_private *p;

};

platform_drv_probe定义在drivers/base/platform.c中定义,如下:

static int platform_drv_probe(struct device *_dev)

{

        struct platform_driver *drv = to_platform_driver(_dev->driver);

        struct platform_device *dev = to_platform_device(_dev);

 

        return drv->probe(dev);

}

 

在这里,to_platform_driver是一个宏

#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \

                                 driver))

to_platform_device也是一个宏(定义在include/linux/platform_device.h

#define to_platform_device(x) container_of((x), struct platform_device, dev)

 

现在的关键就是怎么确定使用哪个device呢?即struct device *_dev

 

 

看了些资料,现在重点看一下driver_register

platform_driver_register()函数

在文件drivers/base/platform.c中,实现出了platform_driver_register()函数,以便使其他模中的函数可以用此函数。它在完成简单的包装后,用了driver_register()函数,完成了从平台实现Linux内核实现

    在此,我需要注一下platform_match()platform_drv_probe()函数。platform_match() 函数确定驱动设备关联,而platform_drv_probe()函数会在随后介绍的函数中被

driver_register()函数定义在drivers/base/driver.c中。

int driver_register(struct device_driver *drv)

{

        int ret;

        struct device_driver *other;

        BUG_ON(!drv->bus->p);

        if ((drv->bus->probe && drv->probe) ||

            (drv->bus->remove && drv->remove) ||

            (drv->bus->shutdown && drv->shutdown))

                printk(KERN_WARNING "Driver '%s' needs updating - please use "

                        "bus_type methods\n", drv->name);

 

        other = driver_find(drv->name, drv->bus);

        if (other) {

                put_driver(other);

                printk(KERN_ERR "Error: Driver '%s' is already registered, "

                        "aborting...\n", drv->name);

                return -EBUSY;

        }

 

        ret = bus_add_driver(drv);

        if (ret)

                return ret;

        ret = driver_add_groups(drv, drv->groups);

        if (ret)

                bus_remove_driver(drv);

        return ret;

}

再看bus_add_driverdrivers/base/bus.c中。

int bus_add_driver(struct device_driver *drv)

{

        struct bus_type *bus;

        struct driver_private *priv;

        int error = 0;

 

        bus = bus_get(drv->bus);

        if (!bus)

                return -EINVAL;

 

        pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

 

        priv = kzalloc(sizeof(*priv), GFP_KERNEL);

        if (!priv) {

                error = -ENOMEM;

                goto out_put_bus;

        }

        klist_init(&priv->klist_devices, NULL, NULL);

        priv->driver = drv;

        drv->p = priv;

        priv->kobj.kset = bus->p->drivers_kset;

        error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,

                                     "%s", drv->name);

        if (error)

                goto out_unregister;

 

        if (drv->bus->p->drivers_autoprobe) {

                error = driver_attach(drv);

                if (error)

                        goto out_unregister;

        }

        klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);

        module_add_driver(drv->owner, drv);

        error = driver_create_file(drv, &driver_attr_uevent);

        if (error) {

                printk(KERN_ERR "%s: uevent attr (%s) failed\n",

                        __func__, drv->name);

        }

        error = driver_add_attrs(bus, drv);

        if (error) {

                /* How the hell do we get out of this pickle? Give up */

                printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",

                        __func__, drv->name);

        }

 

        if (!drv->suppress_bind_attrs) {

                error = add_bind_files(drv);

                if (error) {

                        /* Ditto */

                        printk(KERN_ERR "%s: add_bind_files(%s) failed\n",

                                __func__, drv->name);

                }

        }

 

        kobject_uevent(&priv->kobj, KOBJ_ADD);

        return 0;

 

out_unregister:

        kfree(drv->p);

        drv->p = NULL;

        kobject_put(&priv->kobj);

out_put_bus:

        bus_put(bus);

        return error;

}

 

1.5 dd.c文件

在文件drivers/base/dd.c中,实现设备驱动交互的核心函数

1.5.1 driver_attach()函数

函数driver_attach()返回bus_for_each_dev()函数的运行果。bus_for_each_dev()函数的原型如下:

int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,

    int (*fn) (struct device *, void *));

函数迭代了在总线上的设备,将相device传递给fn,同时传递data。如果startNULL,将从总线上的第一个设备开始迭代;否将从start后的第一个设备开始迭代。如果fn返回一个非零,将停止迭代,而也会从函数返回(摘自<<Linux设备驱动程序>>第三版)。

函数是如何知道总线上的设备的呢?在设备注册程中,我会详细

/*

 *  drivers/base/dd.c - The core device/driver interactions.

 *

 * This file contains the (sometimes tricky) code that controls the

 *  interactions between devices and drivers, which primarily includes

 *  driver binding and unbinding.

 */

 

/**

 *  driver_attach - try to bind driver to devices.

 *  @drv:  driver.

 *

 *  Walk the list of devices that the bus has on it and try to

 *  match the driver with each one.  If driver_probe_device()

 *  returns 0 and the @dev->driver is set, we've found a

 *  compatible pair.

 */

int driver_attach(struct device_driver * drv)

{

    return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);

}

1.5.2 __driver_attach()函数

函数__driver_attach()driver_probe_device()函数前,需要线的互斥

static int __driver_attach(struct device * dev, void * data)

{

    struct device_driver * drv = data;

 

    /*

     * Lock device and try to bind to it. We drop the error

     * here and always return 0, because we need to keep trying

     * to bind to devices and some drivers will return an error

     * simply if it didn't support the device.

     *

     * driver_probe_device() will spit a warning if there

     * is an error.

     */

 

    if (dev->parent)  /* Needed for USB */

       down(&dev->parent->sem);

    down(&dev->sem);

    if (!dev->driver)

       driver_probe_device(drv, dev);

    up(&dev->sem);

    if (dev->parent)

       up(&dev->parent->sem);

 

    return 0;

}

 

1.5.3 driver_probe_device()函数

driver_probe_device()函数中,用了device_is_registered,如果它返回0,表示驱动设备不一致,函数返回;否really_probe()函数。

 /**

 * driver_probe_device - attempt to bind device & driver together

 * @drv: driver to bind a device to

 * @dev: device to try to bind to the driver

 *

 * This function returns -ENODEV if the device is not registered,

 * 1 if the device is bound sucessfully and 0 otherwise.

 *

 * This function must be called with @dev->sem held.  When called for a

 * USB interface, @dev->parent->sem must be held as well.

 */

int driver_probe_device(struct device_driver *drv, struct device *dev)

{

        int ret = 0;

 

        if (!device_is_registered(dev))

                return -ENODEV;

 

        pr_debug("bus: '%s': %s: matched device %s with driver %s\n",

                 drv->bus->name, __func__, dev_name(dev), drv->name);

 

        pm_runtime_get_noresume(dev);

        pm_runtime_barrier(dev);

        ret = really_probe(dev, drv);

        pm_runtime_put_sync(dev);

 

        return ret;

}

在文件include/linux/device.h中定义device_is_registered

static inline int device_is_registered(struct device *dev)

{

        return dev->kobj.state_in_sysfs;

}

 

really_probe()函数

really_probe()函数中,实现设备驱动定。句如下:dev->driver = drv;

ret = drv->probe(dev); probe()函数的实现如下

 

 

 

 

static int really_probe(struct device *dev, struct device_driver *drv)

{

        int ret = 0;

 

        atomic_inc(&probe_count);

        pr_debug("bus: '%s': %s: probing driver %s with device %s\n",

                 drv->bus->name, __func__, drv->name, dev_name(dev));

        WARN_ON(!list_empty(&dev->devres_head));

 

        dev->driver = drv;

        if (driver_sysfs_add(dev)) {

                printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",

                        __func__, dev_name(dev));

                goto probe_failed;

        }

 

        if (dev->bus->probe) {

                ret = dev->bus->probe(dev);

                if (ret)

                        goto probe_failed;

        } else if (drv->probe) {

                ret = drv->probe(dev);

                if (ret)

                        goto probe_failed;

        }

 

        driver_bound(dev);

        ret = 1;

        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",

                 drv->bus->name, __func__, dev_name(dev), drv->name);

        goto done;

probe_failed:

        devres_release_all(dev);

        driver_sysfs_remove(dev);

        dev->driver = NULL;

 

        if (ret != -ENODEV && ret != -ENXIO) {

                /* driver matched but the probe failed */

                printk(KERN_WARNING

                       "%s: probe of %s failed with error %d\n",

                       drv->name, dev_name(dev), ret);

        }

        /*

         * Ignore errors returned by ->probe so that the next driver can try

         * its luck.

         */

        ret = 0;

done:

        atomic_dec(&probe_count);

        wake_up(&probe_waitqueue);

        return ret;

}


  相关解决方案