该函数是USB驱动中,监视hub状态改变的线程函数。
Root hub的监视线程在OTG_Init函数被调用时创建。
External Hub的监视线程在External Hub插入到Root Hub时被创建。
在线程刚启动的时候(在线程循环体之外),需要进行一些操作。
// before we can process port changes, we need
// to power all ports
// 函数PowerAllHubPorts在CRootHub类中的实现为空。
// 在类CExternalHub中,遍历Hub上的所有Port,
// 调用函数SetOrClearFeature设置各个Port的Feature。
// 函数SetOrClearFeature中,调用Control Pipe的IssueTransfer函数进行设置
// status = m_ppCPipe[ ENDPOINT0_CONTROL_PIPE ]->IssueTransfer
// 然后等待设置的完成
// WaitForSingleObject( m_hHubStatusChangeEvent, INFINITE );
// 然后调用Control Pipe的AbortTransfer函数结束传输
// m_ppCPipe[ ENDPOINT0_CONTROL_PIPE ]->AbortTransfer
fSuccess = PowerAllHubPorts();
// Sleep 一段时间,等待Hub上电完成。
Sleep( 2 * m_usbHubDescriptor.bPowerOnToPowerGood );
// 设置External Hub的remove wakeup feature。
// 因为该设置只是针对External Hub的,所以Root Hub中该函数为空
// External Hub中,调用Control Pipe的IssueTransfer函数进行设置
// status = m_ppCPipe[ ENDPOINT0_CONTROL_PIPE ]->IssueTransfer
// 然后等待设置的完成
// WaitForSingleObject( m_hHubStatusChangeEvent, INFINITE );
// 然后调用Control Pipe的AbortTransfer函数结束传输
// m_ppCPipe[ ENDPOINT0_CONTROL_PIPE ]->AbortTransfer
// 下面进入线程循环体
// m_fHubThreadClosing在函数CHub::HandleDetach中被设置为True
while ( !m_fHubThreadClosing )
// 等待事件m_hHubSuspendBlockEvent
// 该事件在函数CHub::HandleDetach和函数CHub::ResumeNotification中被设置
fSuccess = (WaitForSingleObject(m_hHubSuspendBlockEvent,INFINITE) == WAIT_OBJECT_0);
// 调用函数WaitForPortStatusChange等待Port状态改变
// 函数WaitForPortStatusChange在Root Hub和External Hub中有不同的实现。
// 在Root Hub中,首先看HCD中是否支持Root Hub Status Change,若不支持,则在此处等待m_hHubStatusChangeEvent。
// 然后遍历Hub上的每个Port,调用函数CHW::DidPortStatusChange检查Port状态是否改变。
// 若改变,调用函数GetStatus获取Port状态。
// 在External Hub中,首先调用函数GetStatusChangeBitmap等待直到Port状态改变的发生
// (通过调用control Pipe的IssueTransfer函数)。
// 通过获取的BitMap处理所有的状态改变。
// 调用函数GetStatus获取状态改变port的状态,然后调用函数SetOrClearFeature清除Feature。
fSuccess = WaitForPortStatusChange( port, hubStatus );
// 判断Port是否为over current(过电流)
if (hubStatus.change.port.OverCurrentChange ) {
if ( hubStatus.status.port.PortOverCurrent ) {
// 如果port为over current,调用函数DetachDevice去Detach port上的device
DetachDevice( port );
// 然后调用函数SetOrClearFeature清除Feature
SetOrClearFeature( port, USB_REQUEST_CLEAR_FEATURE, USB_HUB_FEATURE_PORT_POWER );
else
// 如果port为over current
hubStatus.change.port.ConnectStatusChange = 1;
// 判断是否为suspend change,若是,进行Resume Notification
m_ppCDeviceOnPort[port-1]->ResumeNotification();
// 判断是否是Enable change
if ( hubStatus.change.port.PortEnableChange &&
!hubStatus.status.port.PortEnabled &&
hubStatus.status.port.PortConnected ) {
// 若是,并且Device is present,调用函数DetachDevice,并设置ConnectStatusChange
DetachDevice( port );
hubStatus.change.port.ConnectStatusChange = 1;
// 检查connect changes
// 如果是连接change,并且设备已经存在,需要调用DetachDevice函数
DetachDevice(port);
// 在一个循环体中调用函数GetStatus获取Port状态(防抖动处理de-bouncing)
// 如果获取失败,设置port connect状态,并退出循环
hubStatus.status.port.PortConnected = FALSE;
// 如果获取成功,并且为连接状态改变,调用函数SetOrClearFeature清除Feature,并且继续循环
// ack the status change and wait again
// 否则,跳出循环
// 接下来需要Reset port并重新获取speed information
// 函数ResetAndEnablePort在root hub和external hub中的实现不同
// root hub中,直接调用了HCD对象的ResetAndEnablePort函数
// BOOL fSuccess = m_pCHcd->ResetAndEnablePort( port );
// external hub中,调用SetOrClearFeature函数,
// 首先,设置USB_HUB_FEATURE_PORT_RESET
// 然后,清除USB_HUB_FEATURE_C_PORT_RESET
// 函数ResetAndEnablePort的注释:
// reset/enable device on the given port so that when this
// function completes, the device is listening on address 0
ResetAndEnablePort( port );
Sleep(20);
GetStatus(port , hubStatus);
// 判断获取的状态是否为连接状态
if ( hubStatus.status.port.PortConnected ) {
// 若是
// 判断是否为root hub上的otg port
// 若是
::OTGHNP_EventNotify(HNP_EVENT_HOST_CONNECT);
// 调用函数AttachDevice
AttachDevice( port,
hubStatus.status.port.DeviceIsLowSpeed,
m_fIsHighSpeed?hubStatus.status.port.DeviceIsHighSpeed:FALSE );
追加个参考结构体:
typedef struct _USB_HUB_DESCRIPTOR {
UCHAR bDescriptorLength; // Length of this descriptor
UCHAR bDescriptorType; // Hub configuration type
UCHAR bNumberOfPorts; // number of ports on this hub
USHORT wHubCharacteristics; // Hub Charateristics
UCHAR bPowerOnToPowerGood; // port power on till power good in 2ms
UCHAR bHubControlCurrent; // max current in mA
//
// room for 255 ports power control and removable bitmask
UCHAR bRemoveAndPowerMask[64];
} USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;
成员变量m_usbHubDescriptor的赋值是在构造函数中进行的。
Root Hub的该成员,是在函数CEhcd::DeviceInitialize中初始化结构体的各成员,然后以其为参数创建Root Hub对象。
External Hub的该成员,是在函数CHub::AttachDevice中,调用函数CHub::GetDescriptor获取,然后以其为参数创建External Hub对象。函数CHub::GetDescriptor中通过调用Control Pipe的函数IssueTransfer来获取Descriptor。