shiftc / android-usb

https://github.com/shiftc/android-usb/blob/master/1.usb_framwork_in_android.md

553 lines (469 sloc) 17.8 KB

 

 

code path

java:

frameworks/base/services/usb/java/com/android/server/usb
frameworks/base/core/java/android/hardware/usb/

jni:

frameworks/base/services/core/jni/com_android_server_UsbHostManager.cpp (host)
frameworks/base/services/core/jni/com_android_server_UsbDeviceManager.cpp (accessory)

native(host):

system/core/libusbhost

initrc(gadget):

system/core/rootdir/init.usb{.configfs}.rc
device/fsl/imx6{78}/etc/init.usb.rc

kernel(gadget):

drivers/usb/gadget/

 

usb host

check this

 

device detection

 

 

communicating with a device

TODO

 

usb gadgets

 

usbDeviceManager

// create UsbDeviceManager
UsbService -> UsbDeviceManager

// create UsbHandler
mHandler = new UsbHandler(FgThread.get().getLooper());

/**
 * The persistent property which stores whether adb is enabled or not.
 * May also contain vendor-specific default functions for testing purposes.
 */
USB_PERSISTENT_CONFIG_PROPERTY = "persist.sys.usb.config";

/**
 * The non-persistent property which stores the current USB settings.
 */
USB_CONFIG_PROPERTY = "sys.usb.config";

/**
 * The non-persistent property which stores the current USB actual state.
 */
USB_STATE_PROPERTY = "sys.usb.state";

###1. restore default

// Restore default functions, current usb function is stored in mCurrentFunctions
mCurrentFunctions = SystemProperties.get(USB_CONFIG_PROPERTY,
        UsbManager.USB_FUNCTION_NONE);
if (UsbManager.USB_FUNCTION_NONE.equals(mCurrentFunctions)) {
    mCurrentFunctions = UsbManager.USB_FUNCTION_MTP;
}
// check if adb is enabled
mAdbEnabled = UsbManager.containsFunction(getDefaultFunctions(),
        UsbManager.USB_FUNCTION_ADB);
// set the default functions
setEnabledFunctions(null, false);

###2. setEnabledFunctions(functions, forceRestart)

trySetEnabledFunctions(functions, forceRestart)
// 判断adb是否使能,给functions加上adb
setUsbConfig(NONE) -> setUsbConfig(functions)
setUsbConfig(String config) {
    SystemProperties.set(USB_CONFIG_PROPERTY, config);
    return waitForState(config);
}

设置的这个USB_CONFIG_PROPERTY会触发init.usb{.configfs}.rc内的相关动作 使kernel usb gadget driver做相应的function切换操作

###3. UEvent observer 监听两个,一个是usb gadget state的,一个是accessory setup的

// Watch for USB configuration changes
mUEventObserver.startObserving(USB_STATE_MATCH);
mUEventObserver.startObserving(ACCESSORY_START_MATCH);

当usb otg线插入时,kernel发出UEVENT, mUEventObserver接收到

onUEvent() {
    String state = event.get("USB_STATE");
    String accessory = event.get("ACCESSORY");
    if (state != null) {
        mHandler.updateState(state);
    } else if ("START".equals(accessory)) {
        startAccessoryMode();
    }
}

对于usb gadget function切换的uevent来说,走mHandler.updateState这条路

updateState()把uevent里的"DISCONNECT"/"CONNECTED"/"CONFIGURED"作为MSG_UPDATE_STATE的参数发出

###4. handleMessage()

case MSG_UPDATE_STATE:
    // usb function 改变的时候
    updateNotification();
    // 若DISCONNECT, setEnabledFunctions(null, false);
    // 否则broadcast intent UsbManager.ACTION_USB_STATE
case MSG_SET_CURRENT_FUNCTIONS:
    // 上层(DevelopmentSettings)调用setCurrentFunctions()做function切换的时候
   setEnabledFunctions(functions, false); //见2

其他的看代码

 

init.usb{.configfs}.rc

板子相关的init.usb.rc是对system/core/rootdir内的补充

on property:sys.usb.config=none
    ...
    setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=adb
    ...
    setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=mtp
    ...
    setprop sys.usb.state ${sys.usb.config}

当sys.usb.config这个property改变时,对操作kernel的node切换不同的usb gadget function 开始重新bind, setup

切换完成后设置sys.usb.state

这个过程由setUsbConfig()触发

 

kernel related gadget driver

3.18以后 configfs based gadget framework

 

configfs

configfs是一种ram based文件系统,跟sysfs比较像,都可在用户空间配置内核对象。

与sysfs不同的是,sysfs主要是kernel export node给用户,而configfs则是用户创建或删除kernel node

主要用在需要创建内核对象并且内核对象需要修改配置时

对于usb gadget来说,configfs的特性符合gadget动态配置的要求,

configfs_subsystem
| .config_group su_group //抽象的容器,递归的包含config_group
| | .config_item cg_item //表示容器下的目录
| | | .char ci_namebuf[] //目录的名称
| | | .config_group ci_group
| | | .config_item_type ci_type //目录下的属性(文件)和属性的操作
| | | | .configfs_item_operations ct_item_ops //属性文件的操作方法
| | | | .configfs_attribute ct_attrs //属性文件数组
| | | | .configfs_group_opetations  ct_group_ops //目录下目录的操作方法

init.usb.{vendor}.rc内,基于configfs的usb gadget的init:

on fs
    mkdir /dev/usb-ffs 0770 shell shell
    mkdir /dev/usb-ffs/adb 0770 shell shell
    # mount the configfs on /config
    mount configfs none /config mode=0755
    mkdir /config/usb_gadget/g1
    mkdir /config/usb_gadget/g1/configs/b.1
    # mkdir for functions needed
    # this will call each gadget's alloc_inst()
    mkdir /config/usb_gadget/g1/functions/ffs.adb
    mkdir /config/usb_gadget/g1/functions/mtp.gs0
    mkdir /config/usb_gadget/g1/functions/ptp.gs1
    mkdir /config/usb_gadget/g1/functions/accessory.gs2
    mkdir /config/usb_gadget/g1/functions/audio_source.gs3
    mkdir /config/usb_gadget/g1/functions/rndis.gs4
    mkdir /config/usb_gadget/g1/functions/midi.gs5
    mkdir /config/usb_gadget/g1/strings/0x409
    mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409
    # The mount of functionfs for adb must be put AFTER the mkdir for functions in configfs
    mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=2000
    # ci_hdrc.0 is the fixed UDC name
    setprop sys.usb.controller ci_hdrc.0

 

gadget configfs的建立

对于usb gadget:

// 在模块初始化地方调用子系统注册函数后,会凋ci_types->ci_group_ops->make_group
// 建立在/sys/kernel/config/下的子系统目录
static struct configfs_subsystem gadget_subsys = {
    .su_group = {
        .cg_item = {
            .ci_namebuf = "usb_gadget",
            .ci_type = &gadgets_type,
        },
    },
};
static struct config_item_type gadgets_type = {
    .ct_group_ops   = &gadgets_ops,
    .ct_owner       = THIS_MODULE,
};
static struct configfs_group_operations gadgets_ops = {
    .make_group     = &gadgets_make,
    .drop_item      = &gadgets_drop,
};

struct gadget_info {
    struct config_group group;
    //保存的子group
    struct config_group functions_group;
    struct config_group configs_group;
    struct config_group strings_group;
    struct config_group os_desc_group;
    struct config_group *default_groups[5];
    ...
}

static const struct usb_gadget_driver configfs_driver_template = {
    .bind           = configfs_composite_bind,
    .unbind         = configfs_composite_unbind,
    .setup          = android_setup,
    .reset          = android_disconnect,
    .disconnect     = android_disconnect,
    .suspend    = composite_suspend,
    .resume     = composite_resume,

    .max_speed  = USB_SPEED_SUPER,
    .driver = {
        .owner          = THIS_MODULE,
        .name       = "configfs-gadget",
    },
};

// functions 子group的ops
static struct configfs_group_operations functions_ops = {
    .make_group     = &function_make,
    .drop_item      = &function_drop,
};

static struct config_item_type functions_type = {
    .ct_group_ops   = &functions_ops,
    .ct_owner       = THIS_MODULE,
};

// config_desc子group的ops
static struct configfs_group_operations config_desc_ops = {
    .make_group     = &config_desc_make,
    .drop_item      = &config_desc_drop,
};

static struct config_item_type config_desc_type = {
    .ct_group_ops   = &config_desc_ops,
    .ct_owner       = THIS_MODULE,
};

//等等还有其他的子group

static struct config_group *gadgets_make(
        struct config_group *group,
        const char *name)
{
    struct gadget_info *gi;

    gi = kzalloc(sizeof(*gi), GFP_KERNEL);
    if (!gi)
        return ERR_PTR(-ENOMEM);
    gi->group.default_groups = gi->default_groups;
    gi->group.default_groups[0] = &gi->functions_group;
    gi->group.default_groups[1] = &gi->configs_group;
    gi->group.default_groups[2] = &gi->strings_group;
    gi->group.default_groups[3] = &gi->os_desc_group;

    //建立这几个子group对应的目录
    config_group_init_type_name(&gi->functions_group, "functions",
            &functions_type);
    config_group_init_type_name(&gi->configs_group, "configs",
            &config_desc_type);
    config_group_init_type_name(&gi->strings_group, "strings",
            &gadget_strings_strings_type);
    config_group_init_type_name(&gi->os_desc_group, "os_desc",
            &os_desc_type);

    gi->composite.bind = configfs_do_nothing;
    gi->composite.unbind = configfs_do_nothing;
    gi->composite.suspend = NULL;
    gi->composite.resume = NULL;
    gi->composite.max_speed = USB_SPEED_SUPER;

    mutex_init(&gi->lock);
    INIT_LIST_HEAD(&gi->string_list);
    INIT_LIST_HEAD(&gi->available_func);

    composite_init_dev(&gi->cdev);
    gi->cdev.desc.bLength = USB_DT_DEVICE_SIZE;
    gi->cdev.desc.bDescriptorType = USB_DT_DEVICE;
    gi->cdev.desc.bcdDevice = cpu_to_le16(get_default_bcdDevice());

    //gadget driver
    gi->composite.gadget_driver = configfs_driver_template;

    gi->composite.gadget_driver.function = kstrdup(name, GFP_KERNEL);
    gi->composite.name = gi->composite.gadget_driver.function;

    if (!gi->composite.gadget_driver.function)
        goto err;

    if (android_device_create(gi) < 0)
        goto err;

    //除了上面的几个子group之外,这个gadget根目录下还有一些属性文件
    //在gadget_root_type里
    config_group_init_type_name(&gi->group, name,
                &gadget_root_type);
    return &gi->group;
}

static struct config_item_type gadget_root_type = {
    .ct_item_ops    = &gadget_root_item_ops,
    .ct_attrs   = gadget_root_attrs,
    .ct_owner   = THIS_MODULE,
};

GI_DEVICE_DESC_ITEM_ATTR(bDeviceClass);
GI_DEVICE_DESC_ITEM_ATTR(bDeviceSubClass);
GI_DEVICE_DESC_ITEM_ATTR(bDeviceProtocol);
GI_DEVICE_DESC_ITEM_ATTR(bMaxPacketSize0);
GI_DEVICE_DESC_ITEM_ATTR(idVendor);
GI_DEVICE_DESC_ITEM_ATTR(idProduct);
GI_DEVICE_DESC_ITEM_ATTR(bcdDevice);
GI_DEVICE_DESC_ITEM_ATTR(bcdUSB);
GI_DEVICE_DESC_ITEM_ATTR(UDC);

static struct configfs_attribute *gadget_root_attrs[] = {
    &gadget_cdev_desc_bDeviceClass.attr,
    &gadget_cdev_desc_bDeviceSubClass.attr,
    &gadget_cdev_desc_bDeviceProtocol.attr,
    &gadget_cdev_desc_bMaxPacketSize0.attr,
    &gadget_cdev_desc_idVendor.attr,
    &gadget_cdev_desc_idProduct.attr,
    &gadget_cdev_desc_bcdDevice.attr,
    &gadget_cdev_desc_bcdUSB.attr,
    &gadget_cdev_desc_UDC.attr,
    NULL,
};

这样init之后生成的目录结构:

127|sabresd_6dq:/config/usb_gadget/g1 # ls -al
total 0
drwxr-xr-x 6 root root    0 1970-01-01 00:01 .
drwxr-xr-x 3 root root    0 1970-01-01 00:00 ..
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 UDC
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bDeviceClass
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bDeviceProtocol
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bDeviceSubClass
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bMaxPacketSize0
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bcdDevice
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 bcdUSB
drwxr-xr-x 3 root root    0 1970-01-01 00:00 configs
drwxr-xr-x 9 root root    0 1970-01-01 00:00 functions
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 idProduct
-rw-r--r-- 1 root root 4096 1970-01-01 00:13 idVendor
drwxr-xr-x 2 root root    0 1970-01-01 00:00 os_desc
drwxr-xr-x 3 root root    0 1970-01-01 00:00 strings

在其中的各个子group(functions, configs, os_desc, strings) 内,还有他们自己的属性文件,实现方式和root的属性文件类似。

 

gadget configfs的bind/setup过程

当在functions内做mkdir ffs.adb时 会调到config_item_type->ct_group_ops->make_group, 也就是 function_make, 通过usb_get_function_inst找到function_inst, 会凋相应usb function的alloc_inst()方法,得到fi 将其加入到gi->avaiable_func链表中

当在configs内做mkdir b.1时 会调到config_desc_make

static struct config_group *config_desc_make(
        struct config_group *group,
        const char *name)
{
    ...
    config_group_init_type_name(&cfg->group, name,
                &gadget_config_type);
    config_group_init_type_name(&cfg->strings_group, "strings",
            &gadget_config_name_strings_type);

    //把cfg->c(usb_configuration)加入到gi->cdev->configs链表
	//表示当前所使能的usb_configuration
    ret = usb_add_config_only(&gi->cdev, &cfg->c);
    ...
}

对于gadget_config_type这个config_item_type,其config_item_type-> ct_item_ops为

static struct configfs_item_operations gadget_config_item_ops = {
    .release                = gadget_config_attr_release,
    .show_attribute         = config_usb_cfg_attr_show,
    .store_attribute        = config_usb_cfg_attr_store,
    .allow_link             = config_usb_cfg_link,
    .drop_link              = config_usb_cfg_unlink,
};

注意到其中的allow_link字段,这部分在做

symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1

操作的时候调用,根据target的ffs.adb找到group,再找到function_inst,与gi->avaiable_func链表内 比对,如果匹配且这个function_inst之前没有被添加,则usb_function = usb_get_function(usb_function_inst) 会凋到usb function的alloc_func()方法 得到usb_function并链入cfg->func_list链表

以上包括了gi->avaiable_func链表,代表了板子上能够用到的usb_function, 在function内的mkdir链入;

cfg->func_list链表,代表当前要做bind的usb_function, 在symlink的时候链入

这样建立了fi, f等需要的结构之后,真正开始做bind和枚举setup是通过

write /config/usb_gadget/g1/UDC ${sys.usb.controller}

其中sys.usb.controller是soc的gadget udc controller的name,这里是"ci_hdrc.0"

write UDC这个操作实际上是调用了gadget_cdev_desc_UDC.attr这个root属性文件的store方法 也就是gadget_dev_desc_UDC_store

static ssize_t gadget_dev_desc_UDC_store(struct gadget_info *gi,
        const char *page, size_t len)
{
    ...
    gi->composite.gadget_driver.udc_name = name;
    ret = usb_gadget_probe_driver(&gi->composite.gadget_driver);
    ...
}

通过usb_gadget_probe_driver()=> udc_bind_to_driver()=> gadget_driver->bind() 调到了configfs_driver_template这个gadget的bind(), 也就是configfs_composite_bind()

static int configfs_composite_bind(struct usb_gadget *gadget,
        struct usb_gadget_driver *gdriver)
{
    ...
    //遍历cfg->func_list链表,分别usb_add_function
    list_for_each_entry_safe(f, tmp, &cfg->func_list, list) {
        list_del(&f->list);
        ret = usb_add_function(c, f);
    }
    ...
}

usb_add_function()=> f->bind()

开始枚举后会调到configfs_driver_template这个gadget driver的setup(),也就是android_setup()

static int android_setup(struct usb_gadget *gadget,
            const struct usb_ctrlrequest *c)
{
    ...
    //触发android_work发送uevent
    spin_lock_irqsave(&cdev->lock, flags);
    if (!gi->connected) {
        wake_lock(&wakelock);
        gi->connected = 1;
        schedule_work(&gi->work);
    }
    spin_unlock_irqrestore(&cdev->lock, flags);

    //遍历gi->avaiable_func链表调用f->setup()开始枚举
    list_for_each_entry(fi, &gi->available_func, cfs_list) {
        if (fi != NULL && fi->f != NULL && fi->f->setup != NULL) {
            value = fi->f->setup(fi->f, c);
        }
    }
    ...
}

###Uevent的发送 对于Uevent的发送,通过上面的work queue在setup/disconnect的时候触发android_work发送

static void android_work(struct work_struct *data)
{
    struct gadget_info *gi = container_of(data, struct gadget_info, work);
    struct usb_composite_dev *cdev = &gi->cdev;
    char *disconnected[2] = { "USB_STATE=DISCONNECTED", NULL };
    char *connected[2]    = { "USB_STATE=CONNECTED", NULL };
    char *configured[2]   = { "USB_STATE=CONFIGURED", NULL };
    /* 0-connected 1-configured 2-disconnected*/
    bool status[3] = { false, false, false };
    unsigned long flags;
    bool uevent_sent = false;

    spin_lock_irqsave(&cdev->lock, flags);
    if (cdev->config)
        status[1] = true;

    if (gi->connected != gi->sw_connected) {
        if (gi->connected)
            status[0] = true;
        else
            status[2] = true;
        gi->sw_connected = gi->connected;
    }
    spin_unlock_irqrestore(&cdev->lock, flags);

    if (status[0]) {
        kobject_uevent_env(&android_device->kobj,
                    KOBJ_CHANGE, connected);
        pr_info("%s: sent uevent %s\n", __func__, connected[0]);
        uevent_sent = true;
    }

    if (status[1]) {
        kobject_uevent_env(&android_device->kobj,
                    KOBJ_CHANGE, configured);
        pr_info("%s: sent uevent %s\n", __func__, configured[0]);
        uevent_sent = true;
    }

    if (status[2]) {
        kobject_uevent_env(&android_device->kobj,
                    KOBJ_CHANGE, disconnected);
        pr_info("%s: sent uevent %s\n", __func__, disconnected[0]);
        uevent_sent = true;
    }

    if (!uevent_sent) {
        pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
            gi->connected, gi->sw_connected, cdev->config);
    }
}

在每次插拔otg线的时候,console里打印的usb uevent就是在android_work里面打印的
这样,如上面讲的,usbDeviceManager的UeventObserver会监听这些uevent,触发相应的处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值