共用方式為


如何從 USB 管道錯誤復原

注意

本文適用於設備驅動器開發人員。 如果您遇到 USB 裝置的困難,請參閱 修正 Windows 中的 USB-C 問題

本文提供當數據傳輸至 USB 管道失敗時,您可以嘗試的步驟相關信息。 本文所述的機制涵蓋大量、中斷和無時針管道上的中止、重設和迴圈埠作業。

USB 用戶端驅動程式會藉由將控制傳輸傳送至預設端點來與其裝置通訊;數據傳輸至裝置的大量、中斷和不時點端點。 有時,這些傳輸可能會因為各種原因而失敗,例如端點中的停滯狀況。 如果傳輸失敗,在清除錯誤狀況之前,相關聯的管道無法處理要求。

針對控制傳輸,USB 驅動程式堆疊會自動清除錯誤狀況。 針對數據傳輸,客戶端必須採取適當的步驟,才能從錯誤狀況中復原。 數據傳輸失敗時,USB 驅動程式堆疊會透過失敗的USBD狀態代碼向客戶端驅動程式報告錯誤。 根據狀態代碼,驅動程式接著可以提供錯誤復原機制。

本文提供透過這些作業進行錯誤復原的指導方針。

  • 重設USB管道
  • 重設裝置所連線的USB埠
  • 迴圈 USB 埠以重新列舉用戶端驅動程式的裝置堆疊

若要清除錯誤狀況,請從重設管道作業開始,並執行更複雜的作業,例如重設埠和迴圈埠,只有在必要的情況下。

關於協調各種復原機制:

用戶端驅動程序必須協調不同的復原作業,並確保在指定時間只使用一個方法。 例如,請考慮具有兩個端點的裝置:大量和中斷。 將一些數據傳輸要求傳送至裝置之後,驅動程式會注意到大量管道上的要求失敗。 若要從這些錯誤復原,驅動程式會重設大量管道。 不過,該作業無法解決傳輸錯誤,而且大量傳輸會繼續失敗。 因此,驅動程式會發出重設USB埠的要求。 同時,傳輸會在中斷管道上開始失敗,然後是重設裝置要求。 若要從中斷傳輸失敗中復原,驅動程式會在中斷管道上發出重設管道要求。 如果未協調這兩項作業,驅動程式可以同時啟動兩個重設裝置作業,因為兩個管道發生失敗。 這些同時作業可能會有問題。

用戶端驅動程式必須確定在指定時間,驅動程式只會執行一個重設埠或迴圈埠作業。 在這些作業期間,重設管道作業不應在任何管道上進行,而且驅動程式不得發出新的重設管道要求。

須知事項

本文使用 內核模式驅動程式架構 (KMDF)

必要條件

  • 用戶端驅動程序必須已建立架構 USB 目標裝置物件。

    如果您使用visual Studio Professional 2012 Microsoft提供的USB樣本,範本程式代碼會執行這些工作。 範本程式代碼會取得目標裝置物件的句柄,並儲存在裝置內容中。

    KMDF 用戶端驅動程式必須藉由呼叫 WdfUsbTargetDeviceCreateWithParameters 方法來取得 WDFUSBDEVICE 句柄。 如需詳細資訊,請參閱瞭解USB用戶端驅動程式程式代碼結構(KMDF)中的

  • 用戶端驅動程序必須具有架構目標管道物件的句柄。 如需詳細資訊,請參閱 如何列舉 USB 管道

步驟 1:判斷錯誤狀況的原因

用戶端驅動程式會使用 USB 要求區塊 (URB) 起始數據傳輸。 要求完成之後,USB 驅動程式堆疊會傳回USBD狀態代碼,指出傳輸成功還是失敗。 在失敗中,USBD 程式代碼會指出失敗的原因。

傳輸失敗可能會導致裝置錯誤,例如USBD_STATUS_STALL_PID或USBD_STATUS_BABBLE_DETECTED。 它們也可能是因為主控制器回報的錯誤所造成,例如USBD_STATUS_XACT_ERROR。

步驟 2:判斷裝置是否已連線到埠

在發出重設管道或裝置的任何要求之前,請確定裝置已連線。 您可以呼叫 WdfUsbTargetDeviceIsConnectedSynchronous 方法來判斷裝置的連線狀態。

步驟 3:取消所有暫止傳送至管道

傳送任何重設管道或埠的要求之前,請先取消所有擱置的傳送要求至管道,USB 驅動程式堆疊尚未完成。 您可以透過下列其中一種方式取消要求:

步驟 4:重設 USB 管道

重設管道以啟動錯誤復原。 您可以呼叫下列其中一種方法來傳送重設管道要求:

注意

在重設管道作業完成之前,請勿傳送任何新的傳輸要求。

重設管道要求會清除裝置和主機控制器硬體中的錯誤狀況。 若要清除裝置錯誤,USB 驅動程式堆疊會使用ENDPOINT_HALT功能選取器,將CLEAR_FEATURE控制要求傳送給裝置。 要求的收件者是與管道相關聯的端點。 如果錯誤狀況發生在不時針管道上,則驅動程式堆疊不會採取任何動作來清除裝置,因為若發生錯誤,系統會自動清除不時點端點。

若要清除主控制器錯誤,驅動程式堆疊會清除管道的 HALT 狀態,並將管道的數據切換重設為 0。

步驟 5:重設 USB 埠

如果重設管道作業無法清除錯誤狀況,且數據傳輸會繼續失敗,請傳送重設埠要求。

  1. 取消所有傳輸至裝置。 若要這樣做,請列舉目前組態中的所有管道,並取消針對每個管道排程的擱置要求。

  2. 停止裝置的 I/O 目標。

    呼叫 WdfUsbTargetDeviceGetIoTarget 方法,以取得與架構目標裝置對象相關聯的 WDFIOTARGET 句柄。 然後,呼叫 WdfIoTargetStop 並指定 WDFIOTARGET 句柄。 在呼叫中,將動作設定為 WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION)。

  3. 呼叫 WdfUsbTargetDeviceResetPortSynchronously 方法來傳送重設埠要求。

重設埠作業會導致裝置在USB總線上重新列舉。 USB 驅動程式堆疊會在 列舉之後保留裝置組態。 用戶端驅動程式可以使用先前取得的管道句柄,因為驅動程式堆疊可確保現有的管道控點保持有效。

您無法重設複合裝置的個別功能。 針對複合裝置,當特定函式的用戶端驅動程式傳送重設埠要求時,會重設整個裝置。 如果 USB 裝置維持狀態,重設埠要求可能會影響其他功能的用戶端驅動程式。 因此,客戶端驅動程式在重設埠之前,請務必先嘗試重設管道。

步驟 6:迴圈 USB 埠

迴圈埠作業類似於未插接並插回埠的裝置,但裝置未以電力中斷連線。 裝置已中斷連線,並在軟體中重新連線。 此作業會導致裝置重設和列舉。 因此,PnP 管理員會重建裝置節點。

如果重設埠作業無法清除錯誤狀況,且數據傳輸會繼續失敗,請傳送迴圈埠要求。

  1. 取消所有傳輸至裝置。 請確定您取消針對目前組態中每個管道排程的擱置要求(請參閱步驟 3)。

  2. 停止裝置的 I/O 目標。

    呼叫 WdfUsbTargetDeviceGetIoTarget 方法,以取得與架構目標裝置對象相關聯的 WDFIOTARGET 句柄。 然後,呼叫 WdfIoTargetStop 並指定 WDFIOTARGET 句柄。 在呼叫中,將動作設定為 WdfIoTargetCancelSentIo (WDF_IO_TARGET_SENT_IO_ACTION)。

  3. 呼叫下列其中一種方法來傳送迴圈埠要求:

用戶端驅動程式只有在週期埠要求完成之後,才能將傳送要求傳送至裝置。 這是因為當 USB 驅動程式堆疊處理循環埠要求時,裝置節點會移除。

迴圈埠要求會導致裝置重新列舉。 USB 驅動程式堆疊會通知 PnP 管理員裝置已中斷連線。 PnP 管理員會卸除與客戶端驅動程式相關聯的裝置堆疊。 驅動程式堆疊會重設裝置、在USB總線上重新列舉它,並通知 PnP 管理員裝置已連線。 然後,PnP 管理員會重建 USB 裝置的裝置堆疊。

由於迴圈埠作業,任何已開啟裝置句柄的應用程式都會取得裝置移除通知(如果應用程式已註冊這類通知)。 回應中,應用程式可能會向用戶回報裝置中斷連線的訊息。 因為它會影響用戶體驗,所以只有在其他復原機制無法解決錯誤狀況時,用戶端驅動程式才應該選擇使用週期埠要求。

類似於重設埠作業(如步驟 6 所述),對於複合裝置,迴圈埠作業會影響整個裝置,而不是裝置的個別功能。