前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >高通SDX55平台:adb功能异常

高通SDX55平台:adb功能异常

作者头像
四儿家的小祖宗
发布2022-11-15 16:19:41
3.4K0
发布2022-11-15 16:19:41
举报

展锐UDX710:LAN7800 PHY驱动调试

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总线类型如下图:
在这里插入图片描述
在这里插入图片描述
  1. 注册USB总线通知链
在这里插入图片描述
在这里插入图片描述
  1. 初始化usb主控器字符设备:cat /proc/devices可以看到(#define USB_MAJOR 180)
  2. 注册usbfs驱动:注册后的驱动将在/sys/bus/usb/drivers创建节点,该节点可以看到哪些设备加载usbfs,当前模块adb使用的便是usbfs。usbfs为提供了在用户空间直接访问usb硬件设备接口的能力。usbfs驱动不需要host进行加载,当上层应用调用的时候usbfs驱动自动加载识别设备。
在这里插入图片描述
在这里插入图片描述
  1. usb字符设备初始化(#define USB_DEVICE_MAJOR 189)
  2. usb hub初始化
  3. 将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/

{bus_id}/

{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工具问题根据实际情况分析。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-05-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 展锐UDX710:LAN7800 PHY驱动调试
  • 1. 问题描述
  • 2. 问题分析
    • 2.1 测试环境
      • 2.2 初步分析
        • 2.3 USB驱动初始化
          • 2.3.1 USB驱动加载流程
          • 2.3.2 adb请求后usbfs设备驱动初始化流程
        • 2.4 adb接口枚举流程分析
          • 2.4.1 adb架构
          • 2.4.2 adb devices流程
        • 2.5 关键log解读
        • 3 问题小结
          • 3.1 问题根因
            • 3.2 解决方法
              • 3.3 小结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档