高通Android9.0_Kernel4.9 USB主从切换检测调试总结

一、主要问题

       本项目采用的是高通的SDM450平台,单USB口出来后接了USB HUB 同时可以连接电脑等,这就有个问题,当我同时连接电脑并将USB HUB上电后,在主从切换之间就有问题,也就是当处于主模式的时候,通过拉高USB_ID管脚进入从模式,这时候就会切换失败;或者处于从模式的时候,将USB_ID管脚拉低进入主模式的时候,也会切换失败。

二、原理图

主控部分原理图

 

usb_ID 控制部分原理图

Vbus电路原理图

 

通过原理图可以很清晰的看出,通过HOST_EN管脚可以控制USB_ID管脚,然后进行主从的状态切换

三、原理

高通Android9.0 kernel4.9 USB主从检测代码里面可以找到两个方面的信息,一是通过OTG_ID 管脚的高低电平产生中断然后将主模式的状态设置为1或者0;一是通过VBUS电压检测中断将从模式的状态设置为1或者0,当将状态设置为0的时候并没有完全退出相应的模式(注意这里只是相应模式的状态设置为1或者0,跟状态切换无关)

四、软件分析过程

用于VBUS和OTG_ID检测相关驱动

kernel/msm-4.9/drivers/platform/msm/gpio-usbdetect.c

用于设置主从状态相关驱动

kernel/msm-4.9/drivers/extcon/extcon.c

kernel/msm-4.9/drivers/extcon/driver.c

 

驱动简单分析

USB驱动器状态控制模块(extcon)主要做两件事
A、    注册extcon设备类
B、    提供相关的状态注册,状态设置等接口
状态检测驱动(gpio-usbdetect.c) 主要做三件事
A、    获取相关管脚并注册对应的中断处理函数
B、    向USB驱动器状态控制模块(extcon) 申请状态监听
C、    应对相关中断产生并向USB驱动器状态控制模块(extcon) 设置相应的状态用于上报
 

相关代码gpio-usbdetect.c

gpio_usbdetect_probe()
A、        获取id管脚并注册对应的中断处理函数

B、    向USB驱动器状态控制模块(extcon) 申请状态监听

C、应对相关中断产生并向USB驱动器状态控制模块(extcon) 设置相应的状态用于上报

Extcon.c驱动
注册 extcon类

还有一些其他相关的接口,不再一一贴出来

int extcon_dev_register(struct extcon_dev *edev)

int extcon_set_property_sync(struct extcon_dev *edev, unsigned int id,
                unsigned int prop,
                union extcon_property_value prop_val)
int extcon_get_property_capability(struct extcon_dev *edev, unsigned int id,
                    unsigned int prop)
int extcon_set_property(struct extcon_dev *edev, unsigned int id,
                unsigned int prop,
                union extcon_property_value prop_val)
 

int extcon_set_state_sync(struct extcon_dev *edev, unsigned int id,
                bool cable_state)

说明: Extcon 主要是实现usb驱动器的管理,提供包括USB状态器的注册,同步等,具体可以查看文件

kernel/msm-4.9/drivers/extcon/extcon.c

 

在我们的项目中对于USB驱动器状态管理模块来说,USB的状态有三种
EXTCON_USB
EXTCON_USB_HOST
EXTCON_NONE
当然实际不止这三种状态

根据调试过程log分析,得到以下一个问题
任何的一个切换都必须先USB退出当前状态,此时USB处于 EXTCON_NONE状态,然后再切换到HOST或者USB模式,否则就会有切换不过去的情况,而这些动作只是在两个中断处理函数里面做:

static irqreturn_t gpio_usbdetect_id_irq_thread(int irq, void *data)

static irqreturn_t gpio_usbdetect_vbus_irq(int irq, void *data)

这两个函数主要是处理VBUS产生中断和USB_ID产生中断,我们要做的就是修改里面的逻辑,使得当退出主模式时,不仅仅是将EXTCON_USB_HOST状态设置为0;当退出从模式的时候,不仅仅是将EXTCON_USB设置为0,而是完整的退出相应的模式。通过对比修改前后大概可以知道

gpio_usbdetect_id_irq_thread处理函数修改前

gpio_usbdetect_id_irq_thread处理函数修改后

由于我们的硬件设计时候,没有考虑到VBUS中断管脚的连接,使得VBUS的中断无法产生,我们只能在usb_id的中断处理函数里面通过一个 work来处理,若果插拔USB线可以产生VBUS中断的话,就可以把这个work的内容换到gpio_usbdetect_vbus_irq 里面,以下是work的处理

 

这两部分主要是进入EXTCON_USB_HOST 或者EXTCON_USB模式,只是在中断处理函数里面已经通过          extcon_set_property函数来完全退出上一个模式,然后再调用相应的work来进入一个新的模式

例如完全退出 EXTCON_USB 模式

        val.intval = false;
        extcon_set_property(usb->extcon_dev, EXTCON_USB,
                    EXTCON_PROP_USB_SS, val);
        extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB, 0);

完全退出EXTCON_USB_HOST模式

        val.intval = false;
        extcon_set_property(usb->extcon_dev, EXTCON_USB_HOST,
                    EXTCON_PROP_USB_SS, val);
        extcon_set_cable_state_(usb->extcon_dev, EXTCON_USB_HOST, 0);

五、adb调试查看状态

上面是查看extcon 对应的USB驱动器状态
USB=0   代表从模式下USB线断开
USB=1   代表从模式下USB线连接上

USB_HOST=0 代表不处于HOST 状态
USB_HOST=1 代表处于HOST状态

所以这里就会有个问题 当 USB=1 且USB_HOST=1时,主控处于什么状态? 此时处于不确定状态,会导致主从切换失败。这也是文章第四步要解决的问题
 

 

  • 1
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值