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,触发相应的处理