Androidadb驱动实现原理

Androidadb的驱动由androidadb.c和f_adb.c实现,androidadb.c的开头会#include “f_adb.c”,最终编译出来的是g_androidadb.ko文件。

这里涉及到Linux USB Composite Framework的知识,下次再整理一下这方面的知识。


创建struct usb_composite_driver

Androidadb属于USB复合设备,注册这样的设备需要使用到USB Composite Framework,因此首先必须要创建一个struct usb_composite_driver并调用usb_composite_probe()向USB Composte Framework注册驱动。

static struct usb_composite_driver android_usb_driver = {
    .name       = "android_usb",
    .dev        = &device_desc,
    .strings    = dev_strings,
    .bind = android_bind, 
    .unbind     = android_usb_unbind,
    .max_speed  = USB_SPEED_HIGH,
};

static int __init init(void)
{
    struct android_dev *dev;
    int err;


    android_class = class_create(THIS_MODULE, "android_usb");
    if (IS_ERR(android_class))
        return PTR_ERR(android_class);

    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;

    dev->disable_depth = 1;
    dev->functions = supported_functions;
    INIT_LIST_HEAD(&dev->enabled_functions);
    INIT_WORK(&dev->work, android_work);
    mutex_init(&dev->mutex);

    err = android_create_device(dev);
    if (err) {
        class_destroy(android_class);
        kfree(dev);
        return err;
    }

    _android_dev = dev;

    /* Override composite driver functions */
    composite_driver_template.setup = android_setup;
    composite_driver_template.disconnect = android_disconnect;

    return usb_composite_probe(&android_usb_driver);
}
module_init(init);

module_init(init)中首先去创建一个名为”android_usb”的sys class。并且调用android_create_device()函数创建”android0”的设备,它的属性文件包括:

static struct device_attribute *android_usb_attributes[] = {
    &dev_attr_idVendor,
    &dev_attr_idProduct,
    &dev_attr_bcdDevice,
    &dev_attr_bDeviceClass,
    &dev_attr_bDeviceSubClass,
    &dev_attr_bDeviceProtocol,
    &dev_attr_iManufacturer,
    &dev_attr_iProduct,
    &dev_attr_iSerial,
    &dev_attr_functions,
    &dev_attr_enable,
    &dev_attr_state,
    NULL
};

其中dev_attr_functions/dev_attr_enable/dev_attr_state三个属性都有对应的show和store函数,这些函数配置Androidadb或者在adbd应用程序中会去使用,通过这三个来添加functions和使能androidadb功能。

  • functions_show()/functions_store()
  • enable_show()/enable_store()
  • state_show()

#insmod g_androidadb.ko之后,在 /sys/class/android_usb/android0/或者 /sys/devices/virtual/android_usb/android0/目录下就可以看到这些属性文件。

-rw-r--r-- 0        0              4096 2017-05-01 18:31 bDeviceClass
-rw-r--r-- 0        0             4096 2017-05-01 18:31 bDeviceProtocol
-rw-r--r-- 0        0          4096 2017-05-01 18:31 bDeviceSubClass
-rw-r--r-- 0        0              4096 2017-05-01 18:31 bcdDevice
-rw-r--r-- 0        0              4096 2017-05-01 18:31 enable
drwxr-xr-x 0        0                   2017-05-01 18:31 f_adb
-rw-r--r-- 0        0              4096 2017-05-01 18:31 functions
-rw-r--r-- 0        0              4096 2017-05-01 18:31 iManufacturer
-rw-r--r-- 0        0              4096 2017-05-01 18:31 iProduct
-rw-r--r-- 0        0              4096 2017-05-01 18:31 iSerial
-rw-r--r-- 0        0              4096 2017-05-01 18:31 idProduct
-rw-r--r-- 0        0              4096 2017-05-01 18:31 idVendor
drwxr-xr-x 0        0                   2017-05-01 18:31 power
-r--r--r-- 0        0              4096 2017-05-01 18:31 state
lrwxrwxrwx 0        0                   2017-05-01 18:31 subsystem -> ../../../../class/android_usb
-rw-r--r-- 0        0              4096 2017-05-01 18:31 uevent

在android_bind()中初始化android_usb_function

当调用usb_composite_probe(),最终会触发android_bind()函数的执行。
android_bind()中首先调用android_init_functions()传递进来的参数为struct android_usb_function *supported_functions[],这里面定义了android usb所有的function,根据需要打开某些功能,这里只使用了 adb_function的功能。

static struct android_usb_function adb_function = {
    .name       = "adb",
    .enable     = adb_android_function_enable,
    .disable    = adb_android_function_disable,
    .init       = adb_function_init,
    .cleanup    = adb_function_cleanup,
    .bind_config    = adb_function_bind_config,
};

static struct android_usb_function *supported_functions[] = {
    //&ffs_function,
    &adb_function,
    //&acm_function,
    //&mtp_function,
    //&ptp_function,
    //&rndis_function,
    //&mass_storage_function,
    //&accessory_function,
    //&audio_source_function,
    NULL
};

static int android_init_functions(struct android_usb_function **functions,
                  struct usb_composite_dev *cdev)
{
    ......

    for (; (f = *functions++); index++) {
        f->dev_name = kasprintf(GFP_KERNEL, "f_%s", f->name);
        f->dev = device_create(android_class, dev->dev,
                MKDEV(0, index), f, f->dev_name);
        if (IS_ERR(f->dev)) {
            pr_err("%s: Failed to create dev %s", __func__,
                            f->dev_name);
            err = PTR_ERR(f->dev);
            goto err_create;
        }

        ......
    }
    return 0;

err_out:
    device_destroy(android_class, f->dev->devt);
err_create:
    kfree(f->dev_name);
    return err;
}

android_init_functions()函数中会为function创建一个名为 f_xxx的sys class,比如说这里用到的是adb的function,那么名字就为 f_adb。因此可以在/sys/class/android_usb/android0/看到f_adb的目录。

接下来就会调用struct android_usb_function的.init()函数,这里肯定是adb_function_init()函数,在这里面又会调用adb_setup()函数。这样代码就从androidadb.c调到f_adb.c了。

static int
adb_function_init(struct android_usb_function *f,
        struct usb_composite_dev *cdev)
{

    f->config = kzalloc(sizeof(struct adb_data), GFP_KERNEL);

    if (!f->config)
        return -ENOMEM;

    return adb_setup();
}

if (f->init) {
    err = f->init(f, cdev);
    if (err) {
        pr_err("%s: Failed to init %s", __func__,
                        f->name);
        goto err_out;
    }
}

adb_setup()

在这个函数里面,初始化了读写队列,并且调用misc_register()在 /dev 目录下创建了一个名为” android_adb”的设备节点,这个节点用于与应用空间的数据通信使用。当然,这里面肯定包含对于 /dev/android_adb节点的write()和read()函数。

/* file operations for ADB device /dev/android_adb */
static const struct file_operations adb_fops = {
    .owner = THIS_MODULE,
    .read = adb_read,
    .write = adb_write,
    .open = adb_open,
    .release = adb_release,
};
static struct miscdevice adb_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = adb_shortname,
    .fops = &adb_fops,
};

android_bind()初始化USB设备描述符并分配string ID

/* Allocate string descriptor numbers ... note that string
     * contents can be overridden by the composite_dev glue.
     */
    id = usb_string_id(cdev);

    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;

    /* Default strings - should be updated by userspace */
    strncpy(manufacturer_string, "Android", sizeof(manufacturer_string)-1);
    strncpy(product_string, "Android", sizeof(product_string) - 1);
    strncpy(serial_string, "0123456789ABCDEF", sizeof(serial_string) - 1);

    id = usb_string_id(cdev);

    if (id < 0)
        return id;
    strings_dev[STRING_SERIAL_IDX].id = id;
    device_desc.iSerialNumber = id;

这一步跟多数的struct usb_composite_driver.bind()所要做的工作一样,要去初始化USB设备描述符,不过此时的USB设备描述符还不是完整的。但是这里有一个很关键的地方就是没有初始化USB的configuration和为其添加usb function。正是因为这里没有做这项工作,所以当我们#insmod g_androidadb.ko的时候,此时androidadb还不是一个完整的USB设备,因为它还没有配置描述符和对应的usb function。所以还要通过 sys class中的属性文件做一些配置。

不清楚为啥androidadb不直接将configuration和usb function都初始化完毕和添加完毕,还要手动去做配置。
现在想想,因为Android usb支持很多function,都在supported_functions[]中明确的定义了。

static struct android_usb_function *supported_functions[] = {
    //&ffs_function,
    &adb_function,
    //&acm_function,
    //&mtp_function,
    //&ptp_function,
    //&rndis_function,
    //&mass_storage_function,
    //&accessory_function,
    //&audio_source_function,
    NULL
};

这里有可能选择多种function,使得驱动支持多种fucntion。但是至于要使用何种function,那么需要用户来选择,所以会提供 /sys/class/android_usb/android0/functions接口让用户选择使用何种function,最后再使用/sys/class/android_usb/android0/enable使之与usb configuration绑定。此时这个USB设备的功能就已经明确下来了,可以正常的被枚举。


添加functions到list中

这一步需要用户手动配置,因为我们是使用adb的功能,因此需要输入以下命令:#echo adb > /sys/class/android_usb/android0/functions

对应的驱动接口是 functions_store()函数,这个函数的内容是先解析传进来的字符串,然后调用android_enable_function(),根据解析出来的字符串是否与之前
android_init_functions()中设定的名字(也就是该驱动现在支持哪些function)是否有相匹配的,如果有,那么就将名字添加到enabled_list中。

static int android_enable_function(struct android_dev *dev, char *name)
{
    struct android_usb_function **functions = dev->functions;
    struct android_usb_function *f;
    while ((f = *functions++)) {
        if (!strcmp(name, f->name)) {
            list_add_tail(&f->enabled_list,
                        &dev->enabled_functions);
            return 0;
        }
    }
    return -EINVAL;
}

使能androidadb

#echo 1 > /sys/class/android_usb/android0/enable

对应的驱动接口是enable_store(),在这个函数里面会去完善USB设备描述符,然后从enabled_list中找出与之对应的struct android_usb_function,并执行它的.enable()成员函数,这里当然是会去执行adb_android_function_enable()函数。注意,在adb_android_function_enable()函数中会去先执行一次android_disable()。执行完这一步还没绑定USB configuration和USB function。函数调用如下:

[  348.556864] [xxx-adb] in enable_store, line 561
[  348.561705] [xxx-adb] in adb_android_function_enable, line 278
[  348.567577] [xxx-adb] in android_disable, line 227
[  348.572379] [xxx-adb] in android_enable, line 215, disable_depth 2
if (enabled && !dev->enabled) {
        /*
         * Update values in composite driver's copy of
         * device descriptor.
         */
        cdev->desc.idVendor = device_desc.idVendor;
        cdev->desc.idProduct = device_desc.idProduct;
        cdev->desc.bcdDevice = device_desc.bcdDevice;
        cdev->desc.bDeviceClass = device_desc.bDeviceClass;
        cdev->desc.bDeviceSubClass = device_desc.bDeviceSubClass;
        cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
        list_for_each_entry(f, &dev->enabled_functions, enabled_list) {
            if (f->enable)
                f->enable(f);
        }
        android_enable(dev);
        dev->enabled = true;
    }

static void adb_android_function_enable(struct android_usb_function *f)
{
    struct android_dev *dev = _android_dev;
    struct adb_data *data = f->config;

    data->enabled = true;

    /* Disable the gadget until adbd is ready */
    if (!data->opened)
        android_disable(dev);
}

启动adbd进程

启动adbd进程,那么首先会去调用adb_open(),最终会调用usb_add_config()adb_bind_config()函数将USB configuration和USB function绑定起来。此时,这个USB设备已经配置完整了,可以接受USB Host的枚举。

[  497.782451] adb_open
[  497.784725] [xxx-adb] in adb_open, line 366
[  497.788928] [xxx-adb] in adb_ready_callback, line 308
[  497.794358] [xxx-adb] in android_enable, line 215, disable_depth 1
[  497.800601] [xxx-adb] in android_enable, line 217, invoke usb_add_config()
[  497.807475] adb_bind_config
  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值