1. 程式人生 > >Wince USB otg驅動中關於函式CHub::HubStatusChangeThread

Wince USB otg驅動中關於函式CHub::HubStatusChangeThread

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