寫入USB Type-C 連接器驅動程式

在這些案例中,您必須撰寫 USB Type-C 連接器驅動程式:

摘要

  • 類別延伸模組和客戶端驅動程式所使用的 UCM 物件
  • UCM 類別延伸模組所提供的服務
  • 用戶端驅動程式的預期行為

官方規格

適用於

  • Windows 10

WDF 版本

  • KMDF 1.15 版
  • UMDF 2.15 版

重要 API

描述 USB 連接器管理員 (UCM) 管理 USB Type-C 連接器和連接器驅動程式的預期行為。

UCM 是使用 WDF 類別擴充-用戶端驅動程式模型所設計。 類別延伸模組 (UcmCx) 是 Microsoft 提供的 WDF 驅動程式,提供用戶端驅動程式可以呼叫的介面來報告連接器的相關信息。 UCM 用戶端驅動程式會使用連接器的硬體介面,並讓類別延伸模組知道連接器上發生的事件。 相反地,類別延伸模組會叫用用戶端驅動程式所實作的回呼函式,以回應操作系統事件。

若要在系統上啟用 USB Type-C 連接器,您必須撰寫用戶端驅動程式。

usb 連接器管理員。

開始之前

  • 開發電腦上安裝最新的 Windows 驅動程式套件 (WDK) 。 套件具有撰寫 UCM 用戶端驅動程式所需的頭檔和連結庫,特別是您需要:

    • 存根連結庫, (UcmCxstub.lib) 。 連結庫會轉譯客戶端驅動程式所進行的呼叫,並將其傳遞至UcmCx。

    • 頭檔 UcmCx.h。

      您可以撰寫以使用者模式或核心模式執行的 UCM 用戶端驅動程式。 針對使用者模式,它會與UMDF 2.x 連結庫系結;若為核心模式,則為 KMDF 1.15。 任一模式的程式設計介面都相同。

      ucm 的visual Studio組態。

  • 決定您的客戶端驅動程式是否支援 USB Type-C 連接器和 USB 電源傳遞的進階功能。

    此支援可讓您使用USB Type-C連接器、USB Type-C擴充座和配件,以及USB Type-C電源供應器來建置 Windows 裝置。 用戶端驅動程式會報告連接器事件,以允許操作系統在系統中實作USB和耗電量的原則。

  • 在目標計算機上安裝桌面版本的 Windows 10, (家用版、專業版、企業版和教育版) ,或使用USB Type-C 連接器 Windows 10 行動裝置版。

  • 熟悉UCM,以及如何與其他 Windows 驅動程序互動。 請參閱 架構:Windows 系統的 USB Type-C 設計

  • 熟悉 Windows Driver Foundation (WDF) 。 建議閱讀: 使用 Windows Driver Foundation 開發驅動程式,其作者為Peny Orwick 和 Guy Smith。

UCM 類別延伸模組所提供的服務摘要

UCM 類別延伸模組可讓操作系統知道數據與電源角色、充電等級和交涉的 PD 合約變更。 當客戶端驅動程式與硬體互動時,必須在發生這些變更時通知類別延伸模組。 類別延伸模組提供一組方法,可供用戶端驅動程式用來傳送本主題所討論的通知 () 。 以下是所提供的服務:

數據角色設定

在USB Type-C系統上, (主機或函式) 的數據角色取決於連接器的CC針腳狀態。 您的用戶端驅動程式會讀取 CC 行 (請參閱 架構:Windows 系統) 狀態的 USB Type-C 設計 ,以判斷埠是否已解析為上游面向埠 (UFP) 或下游對向埠 (UFP) 。 它會向類別延伸模組報告該資訊,以便向USB角色交換器驅動程序報告目前的角色。

注意

USB 角色交換器驅動程式用於 Windows 10 行動裝置版 系統上。 在傳統型版本的 Windows 10 上,類別延伸模組與角色交換器驅動程式之間的通訊是選擇性的。 這類系統可能不會使用雙重角色控制器,在此情況下,不會使用角色交換器驅動程式。

電源角色和充電

您的用戶端驅動程式會讀取USB Type-C目前的公告,或與合作夥伴連接器交涉 PD 電源合約。

  • 在 Windows 10 行動裝置版 系統上,選擇適當措施的決策是軟體輔助的。 用戶端驅動程式會將合約資訊回報給類別延伸模組,以便將充電等級傳送至充電仲裁驅動程式 (CAD.sys) 。 CAD 會選取要使用的目前層級,並將充電等級資訊轉送至電池子系統。
  • 在桌面版本的 Windows 10 系統上,硬體會選取適當的電源。 用戶端驅動程式可以選擇取得該資訊,並將其轉送到類別延伸模組。 或者,該邏輯可由不同的驅動程序實作。

數據和電源角色變更

交涉 PD 合約之後,數據角色和電源角色可能會變更。 您的用戶端驅動程式或合作夥伴連接器可能會起始該變更。 用戶端驅動程式會向類別延伸模組報告該資訊,以便據以重新設定專案。

數據和/或電源角色更新

操作系統可能會決定目前的數據角色不正確。 在此情況下,類別擴充功能會呼叫驅動程式的回呼函式,以執行必要的角色交換作業。

Microsoft 提供的 USB Type-C 原則管理員會監視 USB Type-C 連接器的活動。 Windows 1809 版引進了一組程式設計介面,可用來將用戶端驅動程式寫入原則管理員。 用戶端驅動程式可以參與 USB Type-C 連接器的原則決策。 透過此集合,您可以選擇撰寫內核模式導出驅動程式或使用者模式驅動程式。 如需詳細資訊,請參閱 撰寫USB Type-C原則管理員客戶端驅動程式

用戶端驅動程式的預期行為

您的用戶端驅動程式負責下列工作:

  • 偵測 CC 行上的變更,並判斷合作夥伴的類型,例如 UFP、DFP 和其他專案。 若要這樣做,驅動程式必須實作USB Type-C規格中所定義的完整 Type-C 狀態機器。
  • 根據在 CC 行上偵測到的方向設定您的 Mux。 這包括開啟您的 PD 傳輸器/接收者,以及處理和回應 PD 訊息。 若要這樣做,驅動程式必須實作 USB 電源傳遞 2.0 規格中所定義的完整 PD 接收器和傳輸器狀態機器。
  • 進行 PD 原則決策,例如交涉合約 (作為來源或接收) 、角色交換和其他專案。 用戶端驅動程式負責判斷最適當的合約。
  • 公告並交涉替代模式,並在偵測到替代模式時設定 Mux。 用戶端驅動程式負責決定要交涉的替代模式。
  • 透過連接器控制 VBus/VConn。

1. (UCMCONNECTOR) 初始化 UCM 連接器物件

UCM 連接器物件 (UCMCONNECTOR) 代表 USB Type-C 連接器,而且是 UCM 類別延伸模組與用戶端驅動程式之間的主要句柄。 對象會追蹤連接器的作業模式和電源功能。

以下是客戶端驅動程式擷取連接器 UCMCONNECTOR 句柄的順序摘要。 在驅動程式的 中執行這些工作

  1. 藉由將參考傳遞至UCM_MANAGER_CONFIG結構,呼叫 UcmInitializeDevice。 驅動程式必須在 EVT_WDF_DRIVER_DEVICE_ADD回 呼函式中呼叫這個方法,才能呼叫 WdfDeviceCreate

  2. UCM_CONNECTOR_TYPEC_CONFIG 結構中指定USB Type-C連接器的初始化參數。 這包括連接器的作業模式,無論是下游面向的埠、上游面向的埠,還是具備雙重角色功能。 當連接器是電源來源時,它也會指定USB Type-C目前層級。 USB Type-C 連接器可以設計成可以執行 3.5 公厘音訊插孔。 如果硬體支援此功能,則必須據以初始化連接器物件。

    在結構中,您也必須註冊客戶端驅動程式的回呼函式來處理數據角色。

    這個回呼函式會與 UCM 類別延伸模組叫用的連接器對象相關聯。 用戶端驅動程序必須實作此函式。

    EVT_UCM_CONNECTOR_SET_DATA_ROLE 連接到夥伴連接器時,將連接器的數據角色交換至指定的角色。

  3. 如果您的用戶端驅動程式想要具備 PD 功能,也就是處理連接器的 Power Delivery 2.0 硬體實作,您也必須初始化指定 PD 初始化參數 的UCM_CONNECTOR_PD_CONFIG 結構。 這包括電源流程,無論是連接器是電源接收或來源。

    在結構中,您也必須註冊客戶端驅動程式的回呼函式來處理電源角色。

    這個回呼函式會與 UCM 類別延伸模組叫用的連接器對象相關聯。 用戶端驅動程序必須實作此函式。

    EVT_UCM_CONNECTOR_SET_POWER_ROLE 將連接器的電源角色設定為附加至夥伴連接器時的指定角色。

  4. 呼叫 UcmConnectorCreate 並擷取連接器的 UCMCONNECTOR 句柄。 呼叫 WdfDeviceCreate,確定您在用戶端驅動程式建立架構裝置對象之後呼叫此方法。 此呼叫的適當位置可以是驅動程式 的EVT_WDF_DEVICE_PREPARE_HARDWAREEVT_WDF_DEVICE_D0_ENTRY

EVT_UCM_CONNECTOR_SET_DATA_ROLE     EvtSetDataRole;

NTSTATUS
EvtDevicePrepareHardware(
    WDFDEVICE Device,
    WDFCMRESLIST ResourcesRaw,
    WDFCMRESLIST ResourcesTranslated
    )
{
    NTSTATUS status = STATUS_SUCCESS;
    PDEVICE_CONTEXT devCtx;
    UCM_MANAGER_CONFIG ucmCfg;
    UCM_CONNECTOR_CONFIG connCfg;
    UCM_CONNECTOR_TYPEC_CONFIG typeCConfig;
    UCM_CONNECTOR_PD_CONFIG pdConfig;
    WDF_OBJECT_ATTRIBUTES attr;
    PCONNECTOR_CONTEXT connCtx;

    UNREFERENCED_PARAMETER(ResourcesRaw);
    UNREFERENCED_PARAMETER(ResourcesTranslated);

    TRACE_FUNC_ENTRY();

    devCtx = GetDeviceContext(Device);

    if (devCtx->Connector)
    {
        goto Exit;
    }

    //
    // Initialize UCM Manager
    //
    UCM_MANAGER_CONFIG_INIT(&ucmCfg);

    status = UcmInitializeDevice(Device, &ucmCfg);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(
            "UcmInitializeDevice failed with %!STATUS!.",
            status);
        goto Exit;
    }

    TRACE_INFO("UcmInitializeDevice() succeeded.");

    //
    // Create a USB Type-C connector #0 with PD
    //
    UCM_CONNECTOR_CONFIG_INIT(&connCfg, 0);

    UCM_CONNECTOR_TYPEC_CONFIG_INIT(
        &typeCConfig,
        UcmTypeCOperatingModeDrp,
        UcmTypeCCurrentDefaultUsb | UcmTypeCCurrent1500mA | UcmTypeCCurrent3000mA);

    typeCConfig.EvtSetDataRole = EvtSetDataRole;

    UCM_CONNECTOR_PD_CONFIG_INIT(&pdConfig, UcmPowerRoleSink | UcmPowerRoleSource);

    connCfg.TypeCConfig = &typeCConfig;
    connCfg.PdConfig = &pdConfig;

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attr, CONNECTOR_CONTEXT);

    status = UcmConnectorCreate(Device, &connCfg, &attr, &devCtx->Connector);
    if (!NT_SUCCESS(status))
    {
        TRACE_ERROR(
            "UcmConnectorCreate failed with %!STATUS!.",
            status);
        goto Exit;
    }

    connCtx = GetConnectorContext(devCtx->Connector);

    UcmEventInitialize(&connCtx->EventSetDataRole);

    TRACE_INFO("UcmConnectorCreate() succeeded.");

Exit:

    TRACE_FUNC_EXIT();
    return status;
}

2.回報合作夥伴連接器附加事件

偵測到夥伴連接器的連線時,客戶端驅動程序必須呼叫 UcmConnectorTypeCAttach 。 此呼叫會通知 UCM 類別延伸模組,以進一步通知作業系統。 此時,系統可能會開始在USB Type-C 層級充電。

UCM 類別延伸模組也會通知 USB 角色切換驅動程式 (URS) 。 根據合作夥伴的類型,URS 會在主機角色或函式角色中設定控制器。 在呼叫此方法之前,請確定系統上的 Mux 已正確設定。 否則,如果系統處於函式角色,則會以不正確的速度連線, (高速而非 SuperSpeed) 。

        UCM_CONNECTOR_TYPEC_ATTACH_PARAMS attachParams;

        UCM_CONNECTOR_TYPEC_ATTACH_PARAMS_INIT(
            &attachParams,
            UcmTypeCPortStateDfp);
        attachParams.CurrentAdvertisement = UcmTypeCCurrent1500mA;

        status = UcmConnectorTypeCAttach(
                    Connector,
                    &attachParams);
        if (!NT_SUCCESS(status))
        {
            TRACE_ERROR(
                "UcmConnectorTypeCAttach() failed with %!STATUS!.",
                status);
            goto Exit;
        }

        TRACE_INFO("UcmConnectorTypeCAttach() succeeded.");

3.報告 USB Type-C 公告變更

在初始附加事件中,合作夥伴連接器會傳送目前的公告。 如果公告在合作夥伴是 USB Type-C 下游面向埠時,指定合作夥伴連接器的目前層級。 否則,公告會指定本機連接器的目前層級,由 UCMCONNECTOR 句柄 (本機連接器) 表示。 此初始公告可能會在連線存留期期間變更。 用戶端驅動程序必須監視這些變更。

如果本機連接器是電源接收器,且目前的公告變更,用戶端驅動程序必須偵測目前公告中的變更,並將其回報給類別延伸模組。 在 Windows 10 行動裝置版 系統上,CAD.sys 和電池子系統會使用該資訊來調整從來源繪製的目前數量。 若要向類別延伸模塊報告目前層級的變更,用戶端驅動程序必須呼叫 UcmConnectorTypeCCurrentAdChanged

4.回報新的交涉 PD 合約

如果您的連接器支援 PD,在初始附加事件之後,連接器與其夥伴連接器之間會傳送 PD 訊息。 這兩個合作夥伴之間會交涉 PD 合約,決定連接器可以繪製或允許合作夥伴繪製的目前層級。 每次 PD 合約變更時,用戶端驅動程式都必須呼叫這些方法,以向類別延伸模組報告變更。

  • 每當客戶端驅動程式取得來源功能公告時,用戶端驅動程序必須呼叫這些方法, (未經要求或從合作夥伴) 。 只有在合作夥伴是來源時,本機連接器 (接收) 才會從合作夥伴取得未經請求的公告。 此外,即使合作夥伴目前是接收) ,本機連接器也可以明確地向合作夥伴要求能夠成為來源 (的來源功能。 交換的方法是將 Get_Source_Caps 訊息傳送給合作夥伴。
  • 相反地,每次本機連接器 (來源) 向合作夥伴公告來源功能時,用戶端驅動程式都必須呼叫這些方法。 此外,當本機連接器收到來自合作夥伴 的Get_Source_Caps 訊息時,它必須回應本機連接器的來源功能。

5.報告電池充電狀態

如果充電等級不足,客戶端驅動程式可以通知UCM類別延伸模組。 類別延伸模組會將此資訊報告給操作系統。 系統會使用該資訊來顯示使用者通知,指出充電器未以最佳方式充電系統。 這些方法可以報告充電狀態:

這些方法會指定充電狀態。 如果回報的層級為 UcmChargingStateSlowChargingUcmChargingStateTrickleCharging (請參閱 UCM_CHARGING_STATE) ,操作系統會顯示使用者通知。

6.報告PR_Swap/DR_Swap事件

如果連接器收到電源角色 (PR_Swap) 或數據角色, (DR_Swap) 從合作夥伴交換訊息,用戶端驅動程序必須通知 UCM 類別延伸模組。

  • UcmConnectorDataDirectionChanged

    在處理 PD DR_Swap訊息之後呼叫此方法。 在此呼叫之後,操作系統會將新角色回報給 URS,這會終止現有的角色驅動程式,並載入新角色的驅動程式。

  • UcmConnectorPowerDirectionChanged

    處理 PD PR_Swap訊息之後,呼叫這個方法。 PR_Swap之後,必須重新交涉 PD 合約。 用戶端驅動程序必須呼叫 步驟 4 中所述的方法來報告 PD 合約交涉。

7.實作回呼函式來處理電源和數據角色交換要求

UCM 類別延伸模組可能會取得變更連接器數據或電源方向的要求。 在此情況下,如果連接器實作 PD) ,它會叫用用戶端驅動程式的 EVT_UCM_CONNECTOR_SET_DATA_ROLE 實作,並 EVT_UCM_CONNECTOR_SET_POWER_ROLE 回呼函式 (。 用戶端驅動程式先前已在呼叫 UcmConnectorCreate 中註冊這些函式。

用戶端驅動程式會使用硬體介面來執行角色交換作業。

  • EVT_UCM_CONNECTOR_SET_DATA_ROLE

    在回呼實作中,用戶端驅動程序應該會:

    1. 將 PD DR_Swap訊息傳送至埠夥伴。
    2. 呼叫 UcmConnectorDataDirectionChanged 以通知類別延伸模組訊息序列已成功或失敗。
    EVT_UCM_CONNECTOR_SET_DATA_ROLE     EvtSetDataRole;
    
    NTSTATUS
    EvtSetDataRole(
        UCMCONNECTOR  Connector,
        UCM_TYPE_C_PORT_STATE DataRole
        )
    {
        PCONNECTOR_CONTEXT connCtx;
    
        TRACE_INFO("EvtSetDataRole(%!UCM_TYPE_C_PORT_STATE!) Entry", DataRole);
    
        connCtx = GetConnectorContext(Connector);
    
        TRACE_FUNC_EXIT();
    
        return STATUS_SUCCESS;
    }
    
  • EVT_UCM_CONNECTOR_SET_POWER_ROLE

    在回呼實作中,用戶端驅動程序應該會:

    1. 將 PD PR_Swap訊息傳送至埠夥伴。
    2. 呼叫 UcmConnectorPowerDirectionChanged 以通知類別延伸模組訊息序列已成功或失敗。
    EVT_UCM_CONNECTOR_SET_POWER_ROLE     EvtSetPowerRole;
    
    NTSTATUS
    EvtSetPowerRole(
        UCMCONNECTOR Connector,
        UCM_POWER_ROLE PowerRole
        )
    {
        PCONNECTOR_CONTEXT connCtx;
    
        TRACE_INFO("EvtSetPowerRole(%!UCM_POWER_ROLE!) Entry", PowerRole);
    
        connCtx = GetConnectorContext(Connector);
    
        //PR_Swap operation.
    
        TRACE_FUNC_EXIT();
    
        return STATUS_SUCCESS;
    }
    

注意

用戶端驅動程式可以異步呼叫 UcmConnectorDataDirectionChangedUcmConnectorPowerDirectionChanged ,而不是從回呼線程呼叫。 在一般實作中,類別延伸模組會叫用回呼函式,導致客戶端驅動程式起始硬體交易以傳送訊息。 當交易完成時,硬體會通知驅動程式。 驅動程式會呼叫這些方法來通知類別延伸模組。

8.回報合作夥伴連接器中斷連結事件

當與夥伴連接器的連線結束時,用戶端驅動程序必須呼叫 UcmConnectorTypeCDetach 。 此呼叫會通知 UCM 類別延伸模組,以進一步通知作業系統。

使用案例範例:連線到計算機的行動裝置

當執行 Windows 10 行動裝置版 的裝置透過 USB Type-C 連線連接到執行傳統型版本 Windows 10 的電腦時,操作系統可確保行動裝置是上游面向埠 (UFP) ,因為 MTP 僅適用於該方向。 在此案例中,以下是數據角色更正的順序:

  1. 在行動裝置上執行的用戶端驅動程式會呼叫 UcmConnectorTypeCAttach 回報附加事件,並將合作夥伴連接器回報為下游面向埠 (UFP) 。
  2. 用戶端驅動程式會呼叫 UcmConnectorPdPartnerSourceCapsUcmConnectorPdConnectionStateChanged 來報告 PD 合約。
  3. UCM 類別延伸模組會通知 USB 裝置端驅動程式,導致這些驅動程式回應主機的列舉。 操作系統資訊會透過USB交換。
  4. UCM 類別延伸模組 UcmCx 會叫用用戶端驅動程式的回呼函式來變更角色: EVT_UCM_CONNECTOR_SET_DATA_ROLEEVT_UCM_CONNECTOR_SET_POWER_ROLE

注意

如果兩個 Windows 10 行動裝置版 裝置彼此連線,則不會執行角色交換,而且使用者會收到連線不是有效連線的通知。