USB Type-C コネクタ ドライバーを記述する

次のシナリオでは、USB Type-C コネクタ ドライバーを記述する必要があります。

まとめ

  • クラス拡張機能とクライアント ドライバーによって使用される UCM オブジェクト
  • UCM クラス拡張機能によって提供されるサービス
  • クライアント ドライバーの予期される動作

公式の仕様

適用対象

  • Windows 10

WDF バージョン

  • KMDF バージョン 1.15
  • UMDF バージョン 2.15

重要な API

USB Type-C コネクタを管理する USB コネクタ マネージャー (UCM) と、コネクタ ドライバーの想定される動作について説明します。

UCM は、WDF クラス拡張クライアント ドライバー モデルを使用して設計されています。 クラス拡張機能 (UcmCx) は、Microsoft が提供する WDF ドライバーで、クライアント ドライバーがコネクタに関する情報を報告するために呼び出すインターフェイスを提供します。 UCM クライアント ドライバーは、コネクタのハードウェア インターフェイスを使用し、コネクタで発生するイベントをクラス拡張機能に認識します。 逆に、クラス拡張機能は、オペレーティング システム イベントに応答して、クライアント ドライバーによって実装されたコールバック関数を呼び出します。

システムで USB Type-C コネクタを有効にするには、クライアント ドライバーを記述する必要があります。

usb コネクタ マネージャー。

開始する前に

  • 開発 用コンピューターにWindows Driver Kit (WDK) (WDK) をインストールします。 このキットには、UCM クライアント ドライバーを記述するために必要なヘッダー ファイルとライブラリがあります。具体的には、次が必要です。

    • スタブ ライブラリ (UcmCxstub.lib)。 ライブラリは、クライアント ドライバーによって行われた呼び出しを変換し、UcmCx に渡します。

    • ヘッダー ファイル UcmCx.h。

      ユーザー モードまたはカーネル モードで実行される UCM クライアント ドライバーを記述できます。 ユーザー モードの場合は、UMDF 2.x ライブラリにバインドされます。カーネル モードの場合は KMDF 1.15 です。 どちらのモードでも、プログラミング インターフェイスは同じです。

      ucm 用の visual studio 構成。

  • クライアント ドライバーが USB Type-C コネクタと USB Power Delivery の高度な機能をサポート するかどうかを決定します

    このサポートにより、USB Type-C コネクタ、USB Type-C のドックとアクセサリ、USB Type-C アダプターを使用して Windows デバイスを構築できます。 クライアント ドライバーは、オペレーティング システムが USB とシステムの電力消費に関するポリシーを実装できるコネクタ イベントを報告します。

  • 対象Windows 10コンピューターまたは USB Type-C コネクタを使用して、デスクトップ エディション (Home、Pro、Enterprise、Education) 用Windows 10 Mobileをインストールします。

  • UCM と他の Windows ドライバーとのやり取りについて理解します。 「 アーキテクチャ: Windows システムの USB Type-C 設計」を参照してください

  • Windows Driver Foundation (WDF) について理解する。 推奨される読み取り: Penny Orwickと Guy Smith によって作成された、Windows Driver Foundation を使用したドライバーの開発。

UCM クラス拡張機能によって提供されるサービスの概要

UCM クラス拡張機能は、データと電源の役割、課金レベル、ネゴシエートされた PD コントラクトの変更についてオペレーティング システムに通知を保持します。 クライアント ドライバーがハードウェアと対話している間は、それらの変更が発生した場合にクラス拡張機能に通知する必要があります。 クラス拡張機能は、クライアント ドライバーが通知の送信に使用できる一連のメソッドを提供します (このトピックで説明します)。 提供されるサービスを次に示します。

データ ロールの構成

USB Type-C システムでは、データの役割 (ホストまたは機能) は、コネクタの CC ピンの状態によって異なります。 クライアント ドライバーは、ポート コントローラーから CC 行 (「 アーキテクチャ: Windows システムの USB Type-C設計」を参照) の状態を読み取り、ポートがアップストリーム接続ポート (UFP) またはダウンストリーム接続ポート (UFP) に解決されたかどうかを判断します。 その情報をクラス拡張機能に報告して、現在のロールを USB ロールスイッチ ドライバーに報告できます。

注意

USB ロールスイッチ ドライバーは、システム上Windows 10 Mobileされます。 デスクトップ Windows 10システムの場合、クラス拡張機能とロールスイッチ ドライバー間の通信は省略可能です。 このようなシステムでは、デュアル ロール コントローラーを使用しない場合があります。その場合、ロールスイッチ ドライバーは使用されません。

電源ロールと課金

クライアント ドライバーが USB Type-C の現在のアドバタイズを読み取ったか、パートナー コネクタと PD 電源コントラクトをネゴシエートします。

  • ソフトウェア システムWindows 10 Mobile適切なオプションを選択する決定はソフトウェア支援です。 クライアント ドライバーは、クラス拡張機能にコントラクト情報を報告して、課金レベルを充電中の調書ドライバー (CAD.sys) に送信できます。 CAD は、使用する現在のレベルを選択し、バッテリ サブシステムに充電レベル情報を転送します。
  • デスクトップ エディション Windows 10システムでは、ハードウェアによって適切なオプションが選択されます。 クライアント ドライバーは、その情報を取得し、それをクラス拡張機能に転送することができます。 また、そのロジックは別のドライバーによって実装される場合があります。

データとパワー ロールの変更

PD コントラクトがネゴシエートされた後、データ ロールと電源ロールが変更される可能性があります。 この変更は、クライアント ドライバーまたはパートナー コネクタによって開始される可能性があります。 クライアント ドライバーは、その情報をクラス拡張機能に報告して、必要に応じて構成を変更できます。

データや電源ロールの更新

オペレーティング システムは、現在のデータ ロールが正しくはないと判断する場合があります。 その場合、クラス拡張機能はドライバーのコールバック関数を呼び出して、必要なロールスワップ操作を実行します。

Microsoft 提供の USB Type-C ポリシー マネージャーは、USB Type-C コネクタのアクティビティを監視します。 Windows バージョン 1809 には、ポリシー マネージャーにクライアント ドライバーを書き込むのに使用できる一連のプログラミング インターフェイスが導入されています。 クライアント ドライバーは、USB Type-C コネクタのポリシー決定に参加できます。 このセットを使用すると、カーネル モード のエクスポート ドライバーまたはユーザー モード ドライバーを作成できます。 詳細については 、「USB Type-C Policy Manager クライアント ドライバーを作成する」を参照してください

クライアント ドライバーの予期される動作

クライアント ドライバーは、次のタスクを担当します。

  • CC 行の変更を検出し、UFP、DFP などのパートナーの種類を決定します。 これを行うには、ドライバーは USB Type-C 仕様で定義されている完全な Type-C ステート マシンを実装する必要があります。
  • CC 行で検出された向きに基づいて Mux を構成します。 これには、PD 送信/受信機能のオンと、PD メッセージの処理と応答が含まれます。 これを行うには、ドライバーは、USB Power Delivery 2.0 仕様で定義されている完全な PD レシーバーおよび送信状態マシンを実装する必要があります。
  • コントラクトのネゴシエート (ソースまたはシンク)、ロールのスワップなど、PD ポリシーの決定を行います。 クライアント ドライバーは、最も適切なコントラクトを決定する役割を担います。
  • 代替モードをアドバタイズおよびネゴシエートし、代替モードが検出された場合は Mux を構成します。 クライアント ドライバーは、ネゴシエートする代替モードを決定する必要があります。
  • コネクタに対する VBus/VConn の制御。

1.UCM コネクタ オブジェクト (UCMCONNECTOR) を初期化する

UCM コネクタ オブジェクト (UCMCONNECTOR) は USB Type-C コネクタを表し、UCM クラス拡張機能とクライアント ドライバーの間のメイン ハンドルです。 オブジェクトは、コネクタの動作モードと電源供給機能を追跡します。

クライアント ドライバーがコネクタの UCMCONNECTOR ハンドルを取得するシーケンスの概要を次に示します。 ドライバーでこれらのタスクを実行する

  1. UCM MANAGER CONFIG 構造体への参照を渡して、UcmInitializeDevice _ を _ 呼び出 します。 ドライバーは、WdfDeviceCreate を呼び出す前 、EVT_WDF_DRIVER_DEVICE_ADDコールバック関数でこのメソッド を呼び出す必要があります

  2. UCM コネクタ TYPEC CONFIG 構造体で USB Type-C コネクタの _ _ 初期化パラメーターを _ 指定 します。 これには、コネクタの動作モードが含まれます。コネクタがダウンストリーム向けポート、アップストリーム向けポート、デュアル ロール対応かどうか。 コネクタが電源の場合は、USB Type-C の現在のレベルも指定します。 USB Type-C コネクタは、3.5 mm オーディオ ジャックを機能するように設計できます。 ハードウェアで機能がサポートされている場合は、コネクタ オブジェクトを必要に応じて初期化する必要があります。

    構造体では、データ ロールを処理するクライアント ドライバーのコールバック関数も登録する必要があります。

    このコールバック関数は、UCM クラス拡張機能によって呼び出されるコネクタ オブジェクトに関連付けられている。 この関数は、クライアント ドライバーによって実装される必要があります。

    EVT _ UCM _ コネクタ セット _ _ のデータ _ ロール
    パートナー コネクタにアタッチするときに、コネクタのデータ ロールを指定したロールにスワップします。

  3. クライアント ドライバーが PD 対応である必要がある場合、つまり、コネクタの Power Delivery 2.0 ハードウェア実装を処理する場合は、PD 初期化パラメーターを指定する UCM _ CONNECTOR PD _ _ CONFIG 構造体も初期化する必要があります。 これには、コネクタが電源シンクでもソースでも、電源のフローが含まれます。

    構造では、電源ロールを処理するクライアント ドライバーのコールバック関数も登録する必要があります。

    このコールバック関数は、UCM クラス拡張機能によって呼び出されるコネクタ オブジェクトに関連付けられている。 この関数は、クライアント ドライバーによって実装される必要があります。

    EVT _ UCM _ コネクタセット _ _ の電源 _ ロール
    パートナー コネクタにアタッチするときに、コネクタの電源ロールを指定したロールに設定します。

  4. UcmConnectorCreate を呼び出し、コネクタの UCMCONNECTOR ハンドルを取得します。 クライアント ドライバーが WdfDeviceCreateを呼び出してフレームワーク デバイス オブジェクトを作成した後に、このメソッドを呼び出してください。 この呼び出しに適した場所は、ドライバーの呼び 出しEVT_WDF_DEVICE_PREPARE_HARDWAREまたはEVT_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 Mobile、その情報は、CAD.sys とバッテリ サブシステムによって使用され、ソースから描画される現在の量を調整します。 現在のレベルの変更をクラス拡張機能に報告するには、クライアント ドライバーが UcmConnectorTypeCCurrentAdChangedを呼び出す必要があります。

4.新しいネゴシエートされた PD コントラクトを報告する

コネクタが PD をサポートしている場合、最初のアタッチ イベントの後に、コネクタとそのパートナー コネクタの間で転送される PD メッセージがあります。 両方のパートナー間で、コネクタが描画できる現在のレベルを決定する PD コントラクトがネゴシエートされ、パートナーが描画を許可します。 PD コントラクトが変更されるたび、クライアント ドライバーは、これらのメソッドを呼び出して、クラス拡張機能に変更を報告する必要があります。

  • クライアント ドライバーは、パートナーからソース機能の提供情報 (要求されていないか、それ以外の場合) を取得するたびに、これらのメソッドを呼び出す必要があります。 ローカル コネクタ (シンク) は、パートナーがソースである場合にのみ、パートナーから未承諾のアドバタイズを取得します。 また、ローカル コネクタは、(パートナーが現在シンクである場合でも) ソースに対応できるソース機能をパートナーに明示的に要求できます。 交換は、ソース キャップの取得メッセージ をパートナーに _ _ 送信 することで行われます。
  • 逆に、クライアント ドライバーは、ローカル コネクタ (ソース) がソース機能をパートナーにアドバタイズするたび、これらのメソッドを呼び出す必要があります。 また、ローカル コネクタがパートナーから ソース _ _ キャップの取得メッセージを受信すると、ローカル コネクタのソース機能で応答する必要があります。

5.バッテリの充電状態を報告する

課金レベルが適切ではない場合、クライアント ドライバーは UCM クラス拡張機能に通知できます。 クラス拡張機能は、この情報をオペレーティング システムに報告します。 システムは、その情報を使用して、装置がシステムに最適に充電されていないというユーザー通知を表示します。 課金状態は、次の方法で報告できます。

これらのメソッドは、課金状態を指定します。 報告されるレベルが UcmChargingStateSlowCharging または UcmChargingStateTrickleCharging (UCM _ CHARGING _ STATEを参照) の場合、オペレーティング システムにはユーザー通知が表示されます。

6.PR スワップ _ /DR スワップ イベント _ を報告する

コネクタがパートナーから電源ロール (PR スワップ) またはデータ ロール (DR スワップ) スワップ メッセージを受け取った場合、クライアント ドライバーは UCM クラス拡張機能に通知 _ _ する必要があります。

  • UcmConnectorDataDirectionChanged

    PD DR スワップ メッセージが処理された後 _ に、このメソッドを呼び出します。 この呼び出しの後、オペレーティング システムは URS に新しいロールを報告します。これにより、既存のロール ドライバーが破損し、新しいロールのドライバーが読み込まれます。

  • UcmConnectorPowerDirectionChanged

    PD PR スワップ メッセージが処理された後 _ に、このメソッドを呼び出します。 PR スワップ後 _ 、PD コントラクトを再ネゴシエーションする必要があります。 クライアント ドライバーは、手順 4 で説明したメソッドを呼び出して、その PD コントラクト ネゴシエーション を報告する必要があります

7.機能とデータ ロールのスワップ要求を処理するコールバック関数を実装する

UCM クラス拡張機能は、コネクタのデータまたは電源の方向を変更する要求を受け取る場合があります。 その場合 、EVT _ UCM CONNECTOR SET _ DATA _ _ _ ROLE および EVT _ UCM CONNECTOR SET POWER _ _ _ _ ROLE コールバック関数のクライアント ドライバーの実装が呼び出されます (コネクタが PD を実装している場合)。 クライアント ドライバーは、以前に UcmConnectorCreateの呼び出しでこれらの関数を登録しました。

クライアント ドライバーは、ハードウェア インターフェイスを使用して役割のスワップ操作を実行します。

  • EVT _ UCM _ コネクタ セット _ _ のデータ _ ロール

    コールバックの実装では、クライアント ドライバーは次の処理を行う必要があります。

    1. PD DR スワップ メッセージ _ をポート パートナーに送信します。
    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 _ コネクタセット _ _ の電源 _ ロール

    コールバックの実装では、クライアント ドライバーは次の処理を行う必要があります。

    1. PD PR スワップ メッセージ _ をポート パートナーに送信します。
    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 クラス拡張機能に通知します。

使用事例の例: PC に接続されているモバイル デバイス

Windows 10 Mobile を実行しているデバイスが、USB Type-C 接続を使用してデスクトップ エディション用に Windows 10 を実行している PC に接続されている場合、MTP は、その方向でのみ機能するために、モバイル デバイスがアップストリーム接続ポート (UFP) である必要があります。 このシナリオでは、データ ロールの修正のシーケンスを次に示します。

  1. モバイル デバイスで実行されているクライアント ドライバーは 、UcmConnectorTypeCAttach を呼び出してアタッチ イベントを報告し、パートナー コネクタをダウンストリーム接続ポート (UFP) として報告します。
  2. クライアント ドライバーは 、UcmConnectorPdPartnerSourceCapsUcmConnectorPdConnectionStateChangedを呼び出して PD コントラクトを報告します。
  3. UCM クラス拡張機能は、USB デバイス側ドライバーに通知して、それらのドライバーがホストからの列挙に応答するようにします。 オペレーティング システム情報は USB を使用して交換されます。
  4. UCM クラス拡張機能 UcmCx は、クライアント ドライバーのコールバック関数を呼び出してロールを変更します 。EVT _ UCM _ CONNECTOR SET _ DATA _ _ ROLEEVT _ UCM CONNECTOR SET POWER _ _ _ _ ROLE

注意

2 Windows 10 Mobileデバイスが互いに接続されている場合、ロールのスワップは実行されません。接続が有効な接続ではないという通知がユーザーに表示されます。

USB Type-C コネクタ用 Windows ドライバーの開発