分析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;

intid;

struct devicedev;

u32num_resources;

struct resource * resource;

struct platform_device_id*id_entry;

/* arch specific additions */

struct pdev_archdataarchdata;

};

在探测程序中,大部分工作都是初始化一些数据,或者是数据转换吧,但是最后调用了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 */

u8bConfigurationValue;

u8iConfiguration;

u8bmAttributes;

u8bMaxPower;

struct usb_composite_dev*cdev;

/* private: */

/* internals */

struct list_headlist;

struct list_headfunctions;

u8next_interface_id;

unsignedhighspeed:1;

unsignedfullspeed: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 */

intdisabled;

/* 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_headlist;

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;

}


更多相关文章

  1. android调用camera实现自定义照相
  2. android 圆形头像—— android开源系列:CircleImageView自定义圆
  3. Android百分比布局(PercentRelativeLayout)嵌套NavigationView自
  4. Android中自定义控件之飞入飞出布局及随机布局实现方式
  5. Android Studio3.0自定义apk输出路径和文件名
  6. 自定义Android菜单背景
  7. Android色彩空间像素格式定义及设定

随机推荐

  1. Android(安卓)Matrix详解
  2. Android(安卓)NDK初识
  3. 怎么让 Android(安卓)程序一直后台运行,像
  4. Android(安卓)imageView图片按比例缩放
  5. 深入理解Android消息处理系统——Looper
  6. 简析Android对Linux内核的改动
  7. 详解 Android(安卓)的 Activity 组件
  8. Android布局之LinearLayout与RelativeLay
  9. Android十日学习路线
  10. Android(安卓)滑动效果高级篇(七)—— 华丽