您的位置:首页 > 其它

USB驱动Suspend&Resume 调用流程分析

2010-02-04 21:29 316 查看
在6.0中,驱动通过USBDFunction类的成员函数SuspendDevice()来调用suspend功能,代码如下所示:

在SuspendDevice函数内部,通过USBD接口函数指针来调用到USBD内的函数中,在USBD内部的suspend功能实现,代码如下图所示:

该函数中,都先通过SetDeviceBit()函数更新SDevcie类内部的Interface的标志位信息。然后通过IsAllBitSet()函数判断该devcie的所有Interface是否都设定了suspend的标志位。只有当该device的所有interface都设定了suspend的标志位,该函数才会调用HCD传过来的函数指针,最终设定该device进入suspend状态。
在CE5中,没有USBDFunction类的封装,用户直接使用的只有USBD导出的SuspendDevcie()函数,该函数实现与CE6的完全一样。这里就不粘贴出来了。
在USBD层通过调用HCD的函数指针来调用HCD的suspended函数,通过追踪发现HCD层的相关实现函数为HcdSuspendResume()函数,代码如下所示:

可以看出该函数完全是为了HCD层的DLL导出而封装的,实际调用到HCD类的SuspendResume()函数,具体代码如下:

在该函数中,SuspendResume()函数又调用到了CRootHub类的函数SuspendResume函数中,另外,这个时候pRoot会不会为空呢?还需要进一步调查。这里假定不为空,继续前进。
CRootHub类自己没有实现SuspendResume函数,直接调用到他的父类Chub函数中,具体代码如下所示:

在该函数中,根据传入的device对应的地址来找到对应的连接在hub具体的那个port上的device,然后调用该port device的SuspendResume函数。
这里需要注意,函数写法好象是对hub上所有的port都进行suspend或者resume的操作,其实不是这样的。在每个port device内部会根据address来判断该device的address是否就是要找的address,如果不是则直接返回requestIgnored。只有就是的时候,才进行实际的suspend或者resume操作。所以这里需要稍微仔细看一下。
另外,这个函数内部,会不会出现address和m_address对等的情况,还需要进一步了解。这里先假定不为空,继续先前。
函数中通过m_ppCDeviceOnPort指针调用CDevice类的SuspendDevcie函数,具体代码如下所示:

从这里代码可以看到我上面解释的并非对多有port的device都进行suspend或者resume操作。该函数又调用m_pAttchedHub的SuspendResumeOffStreamDevice函数,具体的代码如下所示:

跟踪到这里,终于看到实际需要向设备发送的具体指令,真是不容易啊!这个函数内部通过address来判断是否是我们要设定的device,如果是,这通过SetOrclearFeature函数来设定suspend或者resume操作。如果是resume的话,等待20ms后,调用ResumeNotification来回应resume事件。
下面来看看SetOrClearFeature函数具体怎么操作,该函数对于Root hub和external hub的情况处理是不同的。先看一下root hub的处理,具体代码如下所示:

对于Root hub来说,Set or clear feature最终都是通过Read_PORTSC函数读取寄存器然后更改后再设定回去来实现的。而对于external hub来说,它的执行就没有这么方便,具体代码如下所示:

从上述代码可以看出,external hub必须通过发送transfer来实现,具体的transfer追踪留待下一次研究。今天就先研究到这里,第一次写,不到之处见谅。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: