該函數是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。
該函數是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。