分析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 圆形头像—— android开源系列:CircleImageView自定义圆
  2. 自定义Android菜单背景
  3. android调用camera实现自定义照相
  4. android 单例
  5. 学习Android中的Adapter
  6. Android百分比布局(PercentRelativeLayout)嵌套NavigationView自
  7. Android自带Music播放器更新播放时间和进度条的方法
  8. Android架构分析之使用自定义硬件抽象层(HAL)模块
  9. 箭头函数的基础使用

随机推荐

  1. PS合成技巧、改日期时间、修图改字、换背
  2. 在虚拟机中运行 Linux 的十大优点
  3. js对象、函数、日期对象----简易日历
  4. JavaScript格式的计算器以及乘法表
  5. JS 简单计算器、九九乘法表实例演示
  6. 文件本质与作用、关键字的学习
  7. Unity程序结合云渲染技术在手机中使用要
  8. CSS:模态框定位实战
  9. Android的自动测试研究--Robotium
  10. Qt on Android(安卓)Episode 3(翻译)