Android14 init.qcom.usb.rc详解
本文以高通平台为例,介绍其USB子系统启动以及USB各种配置动态切换的逻辑,它是以configfs架构实现动态配置USB。
相关文档
1. USB子系统的启动
1.1 on boot阶段
1.1.1 重启恢复用户选择的USB配置
当设备重启时恢复用户选择的USB配置,避免每次重启都回到默认模式,如果是第一次开机,则persist.vendor.usb.config为空,则使用默认值(MTP,文件传输)。
恢复的原理:当用户选择了对应的USB配置,例如MTP+adb调试,则系统会设置:setprop persist.vendor.usb.config mtp,adb,该属性被写入 /data/property/persist.vendor.usb.config,而persist属性重启时是不会丢失的。
on bootsetprop sys.usb.config ${persist.vendor.usb.config}
1.1.2 启用USB gadget HAL来控制USB功能
on boot && property:vendor.usb.use_gadget_hal=1setprop sys.usb.configfs 2
✅property:vendor.usb.use_gadget_hal=1表示启动USB gadget HAL来控制USB功能。该属性是高通平台特有的系统属性,取值1表示把USB配置由init.rc交给了Gadget HAL 服务来实现。
✅可以通过以下指令验证是否生效,当前设备的configfs=2,而且usb.gadget的HAL层服务android.hardware.usb.gadget@1.2-service-qti也在运行。
✅何时设置了该属性vendor.usb.use_gadget_hal,在高通平台下是由vendor_product.mk文件中设置该属性值:
// path: Vendor/android/vendor/qcom/opensource/usb/vendor_product.mk
ifneq ($(filter taro kalama neo parrot anorak,$(TARGET_BOARD_PLATFORM)),)PRODUCT_PROPERTY_OVERRIDES += vendor.usb.use_gadget_hal=1PRODUCT_PACKAGES += android.hardware.usb.gadget@1.2-service-qtiPRODUCT_PACKAGES += usb_compositions.conf
elsePRODUCT_PROPERTY_OVERRIDES += vendor.usb.use_gadget_hal=0
endif
如果当前设备的芯片平台是枚举中的其中之一,则设置vendor.usb.use_gadget_hal=1,并打包android.hardware.usb.gadget@1.2-service-qti服务和USB模式配置文件usb_compositions.conf。
✅usb_compositions.conf介绍
该文件列举了vendor支持的VID-PID组合USB
# /vendor/etc/usb_compositions.conf: HSUSB VID PID supported compositions# <properties> <vid> <pid> <actual order of properties>
mass_storage 0x05C6 0xF000
mass_storage,adb 0x05C6 0x9015 adb,mass_storage
...
diag,qdss,rmnet 0x05C6 0x9083 diag,qdss_debug,rmnet
diag,qdss,rmnet,adb 0x05C6 0x9084 diag,qdss_debug,adb,rmnet
...
rndis,diag,diag_mdm,diag_mdm2,qdss,qdss_mdm,serial_cdev,dpl,adb 0x05C6 0x90F9
1.2 on post-fs阶段
1.2.1 只有on post-fs条件
on post-fs:在/data,/dev等关键文件系统挂在完成后执行,主要完成的动作如下:
- 将内核的configfs文件系统挂载到/config
- 创建Gadget实例g1(主设备)和g2(备用设备,例如反向充电时用)
- 设置设备描述符(Strings相关操作)
- 设置USB协议版本,0x200表示USB2.0,0x300表示USB3.0
- 启用该Microsoft OS描述符,让 Windows 自动识别设备并加载正确驱动
- 创建各种USB功能
- 创建配置#1
- FunctionFS挂载(用户空间)
- 设置MTP设备类型为3
- 执行脚本/vendor/bin/init.qcom.usb.sh
on post-fs// 将内核的configfs文件系统挂载到/config mount configfs none /config//创建Gadget实例g1(主设备)和g2(备用设备,例如反向充电时用)mkdir /config/usb_gadget/g1 0770mkdir /config/usb_gadget/g2 0770//设置设备描述符,序列号-厂商-产品名mkdir /config/usb_gadget/g1/strings/0x409 0770mkdir /config/usb_gadget/g2/strings/0x409 0770write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}write /config/usb_gadget/g2/strings/0x409/serialnumber ${ro.serialno}write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}write /config/usb_gadget/g2/strings/0x409/manufacturer ${ro.product.manufacturer}write /config/usb_gadget/g1/strings/0x409/product ${vendor.usb.product_string}write /config/usb_gadget/g2/strings/0x409/product ${vendor.usb.product_string}//设置USB协议版本,0x200表示USB2.0,0x300表示USB3.0write /config/usb_gadget/g1/bcdUSB 0x0200write /config/usb_gadget/g2/bcdUSB 0x0200//启用该Microsoft OS描述符,让 Windows 自动识别设备并加载正确驱动//MSFT100是微软的签名write /config/usb_gadget/g1/os_desc/use 1write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1write /config/usb_gadget/g1/os_desc/qw_sign "MSFT100"//创建各种USB功能mkdir /config/usb_gadget/g1/functions/mass_storage.0mkdir /config/usb_gadget/g1/functions/mtp.gs0mkdir /config/usb_gadget/g1/functions/ptp.gs1mkdir /config/usb_gadget/g1/functions/accessory.gs2mkdir /config/usb_gadget/g1/functions/audio_source.gs3mkdir /config/usb_gadget/g1/functions/midi.gs5mkdir /config/usb_gadget/g1/functions/ffs.adbmkdir /config/usb_gadget/g1/functions/ffs.diagmkdir /config/usb_gadget/g1/functions/ffs.diag_mdmmkdir /config/usb_gadget/g1/functions/ffs.diag_mdm2mkdir /config/usb_gadget/g1/functions/diag.diagmkdir /config/usb_gadget/g1/functions/diag.diag_mdmmkdir /config/usb_gadget/g1/functions/diag.diag_mdm2mkdir /config/usb_gadget/g1/functions/cser.dun.0mkdir /config/usb_gadget/g1/functions/cser.nmea.1mkdir /config/usb_gadget/g1/functions/cser.dun.2mkdir /config/usb_gadget/g1/functions/gsi.rmnetmkdir /config/usb_gadget/g1/functions/gsi.rndismkdir /config/usb_gadget/g1/functions/gsi.dplmkdir /config/usb_gadget/g1/functions/qdss.qdssmkdir /config/usb_gadget/g1/functions/qdss.qdss_mdmmkdir /config/usb_gadget/g1/functions/qdss.qdss_swmkdir /config/usb_gadget/g1/functions/rndis_bam.rndismkdir /config/usb_gadget/g1/functions/rndis.rndismkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnetmkdir /config/usb_gadget/g1/functions/rmnet_bam.dplmkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnet_bam_dmuxmkdir /config/usb_gadget/g1/functions/rmnet_bam.dpl_bam_dmuxmkdir /config/usb_gadget/g1/functions/ncm.gs6mkdir /config/usb_gadget/g1/functions/ccid.ccidmkdir /config/usb_gadget/g1/functions/uac2.0mkdir /config/usb_gadget/g1/functions/uvc.0write /config/usb_gadget/g1/functions/diag.diag/serial ${ro.serialno}//创建配置#1mkdir /config/usb_gadget/g1/configs/b.1 0770mkdir /config/usb_gadget/g2/configs/b.1 0770mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770mkdir /config/usb_gadget/g2/configs/b.1/strings/0x409 0770//设置功率write /config/usb_gadget/g1/configs/b.1/MaxPower 900//FunctionFS挂载(用户空间)mkdir /dev/usb-ffs 0775 shell systemmkdir /dev/usb-ffs/adb 0770 shell systemmount functionfs adb /dev/usb-ffs/adb uid=2000,gid=1000,rmode=0770,fmode=0660mkdir /dev/ffs-diag 0770 shell systemmount functionfs diag /dev/ffs-diag uid=2000,gid=1000,rmode=0770,fmode=0660,no_disconnect=1mkdir /dev/ffs-diag-1 0770 shell systemmount functionfs diag_mdm /dev/ffs-diag-1 uid=2000,gid=1000,rmode=0770,fmode=0660,no_disconnect=1mkdir /dev/ffs-diag-2 0770 shell systemmount functionfs diag_mdm2 /dev/ffs-diag-2 uid=2000,gid=1000,rmode=0770,fmode=0660,no_disconnect=1//设置MTP设备类型为3setprop sys.usb.mtp.device_type 3//执行脚本exec u:r:vendor_qti_init_shell:s0 -- /vendor/bin/init.qcom.usb.sh
1.2.2 在post-fs和vendor.usb.use_ffs属性为1的条件
on post-fs && property:vendor.usb.use_ffs_mtp=1mkdir /config/usb_gadget/g1/functions/ffs.mtpmkdir /config/usb_gadget/g1/functions/ffs.ptpmkdir /dev/usb-ffs/mtp 0770 mtp mtpmount functionfs mtp /dev/usb-ffs/mtp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1mkdir /dev/usb-ffs/ptp 0770 mtp mtpmount functionfs ptp /dev/usb-ffs/ptp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1
- post-fs阶段是文件系统已挂载,可以创建设备节点。
- vendor.usb.use_ffs_mtp=1表示仅当启用FFS版的MTP时才支持。
- 主要操作:
- 创建usb_gadget/g1实例下的功能目录functions/ffs.mtp和functions/ffs.ptp
- 创建用户空间访问目录/dev/usb-ffs/mtp,权限是rwxrwx---,所属用户和组均是mtp
- mount functionfs mtp /dev/usb-ffs/mtp ...:mount把内核functions把USB底层时间打包成文件交给用户空间。
- 同理ptp配置
参数 含义 mount
Linux 系统调用,挂载一个文件系统 functionfs
特殊文件系统,用于用户空间与 USB Gadget 通信 mtp
挂载源(对应 /config/usb_gadget/g1/functions/ffs.mtp
)/dev/usb-ffs/mtp
挂载点 rmode=0770
目录权限 fmode=0660
文件权限 uid=1024,gid=1024
强制所有者(通常是 mtp
用户)no_disconnect=1
关键参数:防止用户空间服务重启时USB断开
1.2.3 各种 USB 功能(Functions)
功能 | 类型 | 用途 |
---|---|---|
mass_storage.0 | 内核态 | 大容量存储(U盘模式) |
mtp.gs0 , ptp.gs1 | 内核态 | 文件传输(MTP)、相机传输(PTP) |
accessory.gs2 | 内核态 | Android Accessory 模式(AOA) |
audio_source.gs3 | 内核态 | 音频输入(如 USB 麦克风) |
midi.gs5 | 内核态 | MIDI 设备 |
uac2.0 | 内核态 | USB Audio Class 2.0 |
uvc.0 | 内核态 | USB Video Class(摄像头) |
ffs.adb | 用户态 | ADB 调试(通过 FunctionFS) |
ffs.diag , ffs.diag_mdm | 用户态 | 高通诊断端口(diag) |
cser.dun.0 , cser.nmea.1 | 内核态 | 串口功能(DUN 拨号、NMEA GPS) |
gsi.rmnet , gsi.rndis , gsi.dpl | 内核态 | GSI(Generic Signaling Interface)网络 |
qdss.qdss , qdss.qdss_mdm | 内核态 | QDSS( Qualcomm Debug Support) |
rndis.rndis , rndis_bam.rndis | 内核态 | RNDIS(以太网) |
rmnet_bam.rmnet , rmnet_bam.dpl | 内核态 | RMNET(高通专有网络) |
ncm.gs6 | 内核态 | NCM(网络控制模型) |
ccid.ccid | 内核态 | 智能卡接口设备 |
2 充电模式下USB子系统的启动
适用场景:手机关机但插 USB 线充电,电量极低自动进入充电模式,长按电源键 + 音量下进入“充电画面”。此时 Zygote、System Server、SurfaceFlinger 等核心服务未启动,系统处于极简状态。
- 将内核的configfs文件系统挂载到/config
- 只创建Gadget实例g1
- 设置设备描述符(Strings相关操作)
- 设置USB协议版本,0x200表示USB2.0,0x300表示USB3.0
- 只创建mass_storage.0大容量存储功能
- 创建配置#1
- 执行脚本/vendor/bin/init.qcom.usb.sh
- 启用USB大容量存储功能和设置configfs标志
on chargermount configfs none /configmkdir /config/usb_gadget/g1 0770mkdir /config/usb_gadget/g1/strings/0x409 0770write /config/usb_gadget/g1/bcdUSB 0x0200write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}mkdir /config/usb_gadget/g1/functions/mass_storage.0mkdir /config/usb_gadget/g1/configs/b.1 0770mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770write /config/usb_gadget/g1/configs/b.1/MaxPower 900exec u:r:vendor_qti_init_shell:s0 -- /vendor/bin/init.qcom.usb.shwrite /config/usb_gadget/g1/strings/0x409/product ${vendor.usb.product_string}setprop sys.usb.config mass_storagesetprop sys.usb.configfs 1
3 USB配置切换
高通的usb配置和谷歌默认的init.usb.configfs.rc中动态配置USB状态的方式基本上是一致的,差别有:QC多了很好USB功能,常规功能参考init.usb.configfs.rc的USB动态配置中5.1 sys.usb.config取值。
3.1 高通专有的USB配置
取值 | 含义 | 用途 |
---|---|---|
diag | Qualcomm Diagnostics Port,诊断 | 读取 Modem、AP、BP 的日志( 发送诊断命令(如重启、读寄存器) 获取电池、温度、电压等传感器数据 刷写 EFS、NV 数据 |
| Diag for CNSS (Connectivity SubSystem) | 专门用于 Wi-Fi / Bluetooth / GNSS(GPS)子系统 的诊断。 用于wifi驱动调试,蓝牙连接、GPS定位、射频校准等问题 |
diag_mdm | Diag for Modem (mdm=Mobile Data Modem) | 专门用于与基带处理器(modem)通信的诊断通道 读取 Modem 的 获取蜂窝网络日志(RRC、NAS、PHY 层) 抓取通话、短信、注册过程日志 |
diag_mdm2 | Diag for Modem (mdm=Mobile Data Modem) | 同diag_mdm,多个诊断是为了支持多SIM卡或者多Modem实例。 diag_mdm:主modem,通常是SIM1 diag_mdm2:副modem,通常是SIM2 |
| cser (Character Serial) | 创建一个虚拟串口设备, 提供类似 UART 的字符设备接口,类似插入一个USB转串口设备 |
rmnet | Remote Networking | 高通专有的网络传输通道,这是“通过 USB 使用蜂窝数据上网”的底层通道 |
dpl | Device Porting Layer | 高通专有的高速数据下载通道 刷机(Flashing):下载 固件升级 |
| Qualcomm Debug Support Subsystem | 芯片级性能分析和跟踪 抓取 CPU 执行轨迹(Instruction Trace) 监控内存访问 分析功耗热点 实时性能 profiling |
qdss_mdm | QDSS for Modem | 为 Modem 处理器 提供 芯片级性能跟踪和调试 抓取 Modem CPU 的指令执行流 监控内存访问 分析 Modem 任务调度延迟 定位 5G PHY 层性能瓶颈 |
3.2 高通SOC中多处理器介绍
高通芯片SOC中有多个独立的处理器,运行不同的OS,通过共享内存和IPC通信。
处理器 | 代号 | 作用 |
---|---|---|
AP | Apps Processor (A55/A7xx) | 运行 Android 系统 |
MP | Modem Processor (MDM) | 处理 2G/3G/4G/5G 通信 |
LPASS | Audio Subsystem | 处理音频 |
CNSS | Connectivity Subsystem | 处理 Wi-Fi/蓝牙 |
SPSS | Security Subsystem | 处理安全加密 |
3.3 USB动态配置
以diag,adb的配置为例
- 更新configuration为”diag_adb“
- 删除配置#1中链接到functions的符号f1-f9
- 创建配置#1的软连接,将os_desc/b.1指向configs/b.1
- 配置USB描述符,将os_desc/b.1指向configs/b.1
- 将b.1/f1执行内核的diag function
- 将b.1/f2指向内核的ffs.adb function
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=diag,adb && property:sys.usb.configfs=1write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "diag_adb"rm /config/usb_gadget/g1/configs/b.1/f1rm /config/usb_gadget/g1/configs/b.1/f2rm /config/usb_gadget/g1/configs/b.1/f3rm /config/usb_gadget/g1/configs/b.1/f4rm /config/usb_gadget/g1/configs/b.1/f5rm /config/usb_gadget/g1/configs/b.1/f6rm /config/usb_gadget/g1/configs/b.1/f7rm /config/usb_gadget/g1/configs/b.1/f8rm /config/usb_gadget/g1/configs/b.1/f9symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1write /config/usb_gadget/g1/idVendor 0x05C6write /config/usb_gadget/g1/idProduct 0x901Dwrite /config/usb_gadget/g1/functions/diag.diag/pid 0x901dsymlink /config/usb_gadget/g1/functions/${vendor.usb.diag.func.name}.diag /config/usb_gadget/g1/configs/b.1/f1symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2write /config/usb_gadget/g1/UDC ${sys.usb.controller}setprop sys.usb.state ${sys.usb.config}