高通SDX55平台:adb功能异常

1. 问题描述

在Linux环境上使用SDX55模块时出现无法识别adb端口,但可以识别手机adb端口。

2. 问题分析

2.1 测试环境

内核:Linux 4.19.26
系统:CentOS Linux release 7.8.2003
Modem:高通SDX55
连接方式:USB3.0(M.2)

2.2 初步分析

通过分析dmesg log发现,手机与Linux设备连接使用的端口是USB2.0,而模块与Linux设备连接的端口是USB3.0。初步分析可能由于USB2.0和USB3.0的差异或者客户USB3.0的硬件有问题导致。再次对比测试,将SDX55模块通过USB2.0方式连接到Linux设备,发现可以正常识别adb端口。进一步确认我们的分析。由于adb涉及到的问题主要从主机侧驱动、主机侧adb、模块adbd状态来排查。接下来我们将对这些情况进行一一排查来确定问题:

  1. USB驱动初始化是否正常
  2. 主机侧adb是否正常
  3. 模块侧adbd确定是否正常

2.3 USB驱动初始化

由于对adb流程不熟悉,因此先排查一下USB内核驱动相关的初始化是否正常。

2.3.1 USB驱动加载流程

2.3.1.1 USB_init初始化

USB内核框架的代码在linux-4.19.26/drivers/usb目录下,入口函数为usb_init,在内核启动过程中加载执行,其代码如下图:
kernel\drivers\usb\core\usb.c:在这里插入图片描述
usb_init用于初始化usb内核框架,主要进行以下初始化:

  1. USB debugfs初始化:创建字符设备/sys/kernel/debug/usb/devices,读取该字符设备可以得到usb总线拓扑结构、带宽、设备描述信息、产品标识信息、serialnumber信息、配置描述信息和端点描述信息。在lsusb命令不可用的时候,可以为usb驱动提供丰富的调试信息。
  2. 总线注册:这个就是将usb总线注册到系统总线上,注册的USB总线类型如下图:
    在这里插入图片描述
  3. 注册USB总线通知链
    在这里插入图片描述
  4. 初始化usb主控器字符设备:cat /proc/devices可以看到(#define USB_MAJOR 180)
  5. 注册usbfs驱动:注册后的驱动将在/sys/bus/usb/drivers创建节点,该节点可以看到哪些设备加载usbfs,当前模块adb使用的便是usbfs。usbfs为提供了在用户空间直接访问usb硬件设备接口的能力。usbfs驱动不需要host进行加载,当上层应用调用的时候usbfs驱动自动加载识别设备。
    在这里插入图片描述
  6. usb字符设备初始化(#define USB_DEVICE_MAJOR 189)
  7. usb hub初始化
  8. 将generic.c里面的 usb_generic_driver 加入到usb总线下的驱动链表里

usb驱动的匹配过程主要在hub初始化里面实现,接下里看一下hub初始化的流程。

2.3.1.2 usb_hub_init

kernel\drivers\usb\core\hub.c:在这里插入图片描述
usb_hub_init主要做了以下事情:

  1. 将hub driver注册到usb驱动列表
  2. 创建hub_wq:这个worker跟usb hub event处理相关联,用来处理usb总线上的设备状态,连接状态事件。

usb_hub_init调用usb_register将hub_driver注册到usb总线驱动的列表里。然后调用hub_driver.probe加载hub驱动,hub_driver如下图:
在这里插入图片描述
hub_probe调用hub_configure注册了中断,一旦接入新的usb设备就会调用hub_irq
在这里插入图片描述
然后hub_irq中断处理完成后,开启hub_wq线程(kick_hub_wq(hub);)调用hub_event处理usb插入事件。下面详细介绍一下。

2.3.1.3 usb设备插入后usbufs驱动加载

当usb设备插入之后usb总线会识别出adb端口,并且找到匹配的usbfs驱动加载,从而你完成adb设备的驱动初始化。当设备插入中断触发后,hub_irq处理中断后开启workqueue hub_wq调用hub_event处理插入事件。下面梳理一下流程。
hub_event调用遍历所有的port处理port event:
在这里插入图片描述
port_event调用hub_port_status进而调用hub_ext_port_status来处理端口事件:
在这里插入图片描述
如hub_ext_port_status获取到的hub port状态为0x203,即表示当前port有设备连接:
在这里插入图片描述
从port_event调用hub_port_connect_change最后调用到hub_port_connect,hub_port_connect主要作用是创建设备、给新设备选择新的编号,获取设备的各种描述符,然后调用usb_new_device注册新设备。
hub_port_connect
->choose_devnum 给新设备选择新的编号(地址)
->hub_port_init 把编号(地址)告诉USB设备,以后就使用这个地址了
->usb_new_device
usb_new_device调用usb_enumerate_device获取usb描述符
在这里插入图片描述
注:设备描述符在hub_port_init里面获取

如下图获取配置描述符,usb_get_configuration首先从设备描述符里面获取配置描述符的数量,然后遍历所有配置描述符并获取,将获取到描述符格式化到dev->rawdescriptors[cfgno]里面。
在这里插入图片描述
其他描述符这里不多赘述,只讲一下usb3.0和usb2.0的差异。usb3.0有超高速伙伴描述符usb_ss_ep_comp_descriptor,所以只有usb3.0会获取它,usb2.0是不会获取这个描述符的。如下图:
在这里插入图片描述
由于usb超高速伙伴描述符sizeof()=USB_DT_SS_EP_COMP_SIZE=6,保存该描述符后将buffer+6:
在这里插入图片描述
此时,所有的usb描述符都获取完毕,并解析保存完毕。

接下来回到usb_new_device,接下来调用add_device,此时usb总线匹配设备驱动,此时新插入的usb将于usb_init注册的驱动usb_generic_driver匹配,总线接下来加载该驱动识别并加载usb interface和驱动。

generic_probe做了两件事1、获取设备配置,2、应用配置。对usb设备的interface、endpoint进行设备注册与配置。
在这里插入图片描述
usb_set_configuration设置interface属性:
在这里插入图片描述
然后将interface设备加入到系统,然后初始化每个 interface对应的endpoint。add_device将match对应的interface设备驱动,总线将自动加载对应的驱动。
在这里插入图片描述
接下来编译interface的每个endpoint进行配置,将设备添加进系统中
在这里插入图片描述
至此内核驱动的初始化就完成了,当上层adb应用请求连接建立时将动态将usbfs设备驱动与设备进行关联,并加载驱动。也可以看一下usbfs驱动在usb_init时已经注册,他的probe函数是一个空函数,只有当上层adb设备请求的时候才会进行设备匹配。

2.3.2 adb请求后usbfs设备驱动初始化流程

当adb向usbfs驱动发起USBDEVFS_CLAIMINTERFACE请求后,此时将进行USB设备与usbfs驱动设备的绑定。
如下图为usb devio注册的函数,adb server发起的请求由usb devio进行处理:
在这里插入图片描述
adb的请求由usbdev_ioctl进行处理:
在这里插入图片描述
最终调用到claimintf,claimintf函数将进行ad端口与usbfs驱动进行绑定:
在这里插入图片描述
至此所有的驱动侧就完成了。

2.4 adb接口枚举流程分析

adb源码:https://android.googlesource.com/platform/system/core/
可在以上链接获取adb源码集成到项目中。本次问题出现在adb server端,本文后续内容只对host侧adb server的相关代码进行解读,不涉及adbd和adb clinet。

2.4.1 adb架构

adb由两个物理文件组成adb和adbd。adb client和adb server运行在host端,adbd守护进程运行在device侧,host和device通过tcp连接。
在这里插入图片描述

2.4.2 adb devices流程

adb main函数调用adb_commandline对adb参数进行拼接组成adb command line。
在这里插入图片描述
adb_commandline调用adb_query_command然后调用adb_query查询adb server状态,如果adb server未运行则启动adb server:
在这里插入图片描述
launch_server在5037端口运行adb server,此时adb进程fork一个子进程,此时adb devices返回。子进程执行“adb –P 5037 fork-server server”启动adb server:
在这里插入图片描述
在这里插入图片描述
adb判断子进程需要启动server,调用adb_main启动adb server:
在这里插入图片描述
然后启动线程find usb devices:
在这里插入图片描述
在这里插入图片描述
如上图,find_usb_device读取字符设备/dev/bus/usb/ b u s i d / {bus_id}/ busid/{device_id}获取设备各种描述符:
在这里插入图片描述
在这里插入图片描述
然后跳过设备描述符和配置描述符:
在这里插入图片描述接下来在interface描述符里面查找adb端口,adb对应的interface描述符为endpoint为2,bInterfaceClass为255,bInterfaceSubClass为66,bInterfaceProtocol为1。当查找到adb接口的时候,遍历endpoint描述符,由于usb3.0 endpoint描述符后面会增加usb超高速伙伴描述符,且sizeof()=6,所以usb3.0需要在找到endpoint描述符后将指针偏移+6,USB2.0则不需要。具体的描述符解释请参考usb规范。
在这里插入图片描述
查找到adb interface后再调用驱动接口注册驱动。
在这里插入图片描述
自此adb server与usb驱动的绑定就完成了。

2.5 关键log解读

当执行adb devices的时候,adb log打印endpoints not found,对应代码如下图:
在这里插入图片描述
如下图的interface descriptor配置为对应的interface为adb设备的interface:
在这里插入图片描述
adb端口对应的usb interface有两个endpoint,ep5和ep89。对应的bInterfaceClass为255,bInterfaceSubClass为66,bInterfaceProtocol为1。adb设备在插入到主机后通过读取主机侧USB设备的descriptor找到对应的interface,其查找的条件满足以上4个条件即认为找到正确的adb设备,否则失败。

3 问题小结

3.1 问题根因

adb代码里面find_usb_device,当adb server在读取到的usb设备描述符里面查找adb对应的interface和endpoint描述符来注册adb,由于usb3.0在设备描述符里面会加入usb高速端点伙伴描述符,而在usb2.0的设备描述符里面没有。在usb3.0的情况下adb需要在查找到每一个endpoint描述服务后,将缓冲区偏移一个高速端点伙伴描述符的长度。由于客户的adb代码没有进行这个补丁的修改,导致usb2.0在查找endpoint描述符的时候出现问题,从而导致问题出现。

3.2 解决方法

修改adb代码在Linux环境上,编译成adb二进制文件,进一步验证,问题不再复现。

3.3 小结

确认ep个数为2,bInterfaceClass为255,bInterfaceSubClass为66,bInterfaceProtocol为1,即可确定usb驱动和模块adb端口是没有问题的,问题一定出现在主机侧。具体的主机侧问题或者adb工具问题根据实际情况分析。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
高通SDX12是一种移动芯片平台,支持最新的USB连接技术。在使用USB连接设备时,为了达到更高的数据传输效率和稳定性,可以进行USB眼图调优。 USB眼图是通过观察USB信号的时域波形来评估数据传输的质量。当接收端正确接收到数据时,眼图的开口足够大,表示数据传输质量良好;反之,如果眼图的开口较小,可能导致数据传输错误或丢失。 要进行USB眼图调优,可以采取以下措施: 1. 保持良好的信号完整性:使用高质量的USB连接线和连接器,尽量减少信号的损耗和失真。确保信号线不过长,避免干扰和干扰。 2. 优化供电环境:提供稳定的供电电源,减少功率波动和干扰。使用优质的电源适配器或电池供电,避免共地和干扰。 3. 适当调整传输速率:根据设备和系统的性能要求,选择适当的USB传输速率。较高的传输速率可能导致数据传输质量下降,因此在保证速度的同时,需要权衡信号质量。 4. 确保正确的数据编码和解码:在设备端和主机端使用正确的数据编码和解码协议,以确保数据传输的正确性和一致性。 5. 消除干扰源:降低共地干扰和电磁干扰对USB信号的影响。确保设备和连接线远离其他电磁辐射源,如无线电设备、电源适配器等。 总之,通过技术手段优化USB眼图,可以提高USB连接的数据传输效能和稳定性,提升设备的整体性能和用户体验。高通SDX12作为一种先进的移动芯片平台,可为USB连接提供高质量的信号和传输效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四儿家的小祖宗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值